Attention cues review fixes (#238)

- NEW lane: Gate A notice pinned below the rows (it scrolled off with >3
  entries, same rule as the rail, #46); rows at text-xs for the wall.
- Mobile chip moved off MapView's centred "Live" chip, which it covered.
- Keyword cues re-resolve to the incident once correlation links the call,
  so the lane row is clickable and the pin pulses.
- Enabling notifications sends one confirmation notification; a browser
  that grants permission but throws on construct (mobile Chrome) now shows
  "unsupported" instead of a switched-on control that never delivers.
- useActiveIncidentsState: includeMetadataChanges so `loaded` flips on a
  metadata-only server sync (quiet org / offline start) instead of waiting
  for the first incident change and swallowing it into the baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-10-05 03:52:02 -04:00
co-authored by Claude Opus 5.5
parent eb0faf2aea
commit 292c4fffd9
4 changed files with 53 additions and 17 deletions
+10 -2
View File
@@ -157,7 +157,16 @@ export function useActiveIncidentsState(): { incidents: IncidentRecord[]; loaded
}
const q = query(collection(db, "incidents"), where("org_id", "==", orgId), where("status", "==", "active"));
unsubFirestore = onSnapshot(q, (snap) => {
// includeMetadataChanges: the fromCache → server flip arrives as a
// metadata-only snapshot when the data didn't change (e.g. an org with
// nothing active, or a start while offline). Without it `loaded` would
// stay false until some incident changed, and that change would be
// swallowed into the baseline instead of cued.
let first = true;
unsubFirestore = onSnapshot(q, { includeMetadataChanges: true }, (snap) => {
if (!snap.metadata.fromCache) setLoaded(true);
if (!first && snap.docChanges().length === 0) return; // metadata only — no new array, no re-render storm
first = false;
setIncidents(snap.docs.map((d) => {
const data = d.data();
return {
@@ -166,7 +175,6 @@ export function useActiveIncidentsState(): { incidents: IncidentRecord[]; loaded
updated_at: toISO(data.updated_at),
} as IncidentRecord;
}));
if (!snap.metadata.fromCache) setLoaded(true);
}, (err: FirestoreError) => { console.error("useActiveIncidents:", err); });
});