watchFloor method
- String layerName
Watches cached geometry for one published layerName.
A missing or 14-day-old floor refreshes once per subscription. Errors retain cached spaces; CampusMapFloorData.hasCache distinguishes an empty floor from a failed first load. Other buildings and floors are never fetched.
Implementation
Stream<CampusMapFloorData> watchFloor(String layerName) {
var attempted = false;
final query = _db.select(_db.campusMapFloors).join([
innerJoin(
_db.campusMapBuildings,
_db.campusMapBuildings.code.equalsExp(_db.campusMapFloors.building),
),
leftOuterJoin(
_db.campusMapRooms,
_db.campusMapRooms.layerName.equalsExp(_db.campusMapFloors.layerName),
),
])..where(_db.campusMapFloors.layerName.equals(layerName));
List<(MapFloorRecord, MapBuildingRecord, MapRoomRecord?)> snapshot(
List<TypedResult> rows,
) => [
for (final row in rows)
(
row.readTable(_db.campusMapFloors),
row.readTable(_db.campusMapBuildings),
row.readTableOrNull(_db.campusMapRooms),
),
];
// Stream transforms propagate cancellation to Drift even while idle.
// Filtering inside async* would leave an idle await-for waiting forever
// after an unrelated-floor update was discarded.
return query
.watch()
.asyncMap((rows) async {
final floor = rows.firstOrNull?.readTable(_db.campusMapFloors);
if (floor?.fetchedAt == null && !attempted) {
attempted = true;
try {
await refreshFloor(layerName);
return await query.get();
} catch (_) {
// Retain hasCache=false so the screen offers a retry.
}
}
final stamp = floor?.fetchedAt;
if (!attempted &&
(stamp == null || _now().difference(stamp) >= _cacheTtl)) {
attempted = true;
unawaited(
refreshFloor(layerName).catchError((Object _) {
// Retain stale geometry already in this snapshot.
}),
);
}
return rows;
})
.distinct(
(previous, next) =>
const ListEquality().equals(snapshot(previous), snapshot(next)),
)
.map(
(rows) => CampusMapFloorData(
rooms: [
for (final row in rows)
if (row.readTableOrNull(_db.campusMapRooms)?.geometry != null)
_room(row),
],
hasCache:
rows.firstOrNull?.readTable(_db.campusMapFloors).fetchedAt !=
null,
),
);
}