aa
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useReducer, useTransition } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
makeInitialState,
|
||||
reducer,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
import { AppDataProvider, type AppData } from "@/lib/app-context";
|
||||
import type { Place } from "@/lib/types";
|
||||
import { deleteCollection, deletePlace } from "@/lib/db/actions";
|
||||
import { loadSnapshot, saveSnapshot } from "@/lib/offline-cache";
|
||||
import { TabBar } from "@/components/ui-primitives";
|
||||
import { Icons } from "@/components/icons";
|
||||
import { PlacesListScreen } from "@/screens/places-list-screen";
|
||||
@@ -31,8 +33,59 @@ export function PlacesApp({
|
||||
initialPlaces: Place[];
|
||||
data: AppData;
|
||||
}) {
|
||||
const [state, dispatch] = useReducer(reducer, initialPlaces, makeInitialState);
|
||||
// If we boot up offline, prefer the cached snapshot so the UI has *some*
|
||||
// data to show. When network returns, the visibility/focus effect refreshes.
|
||||
const bootData: { places: Place[]; data: AppData } = (() => {
|
||||
if (typeof window === "undefined") return { places: initialPlaces, data };
|
||||
if (!navigator.onLine) {
|
||||
const snap = loadSnapshot(data.me.id);
|
||||
if (snap) {
|
||||
return {
|
||||
places: snap.places,
|
||||
data: { me: snap.me, users: snap.users, collections: snap.collections },
|
||||
};
|
||||
}
|
||||
}
|
||||
return { places: initialPlaces, data };
|
||||
})();
|
||||
|
||||
const [state, dispatch] = useReducer(reducer, bootData.places, makeInitialState);
|
||||
const [, startTransition] = useTransition();
|
||||
const router = useRouter();
|
||||
|
||||
// Mirror the latest server snapshot to localStorage so it's available next
|
||||
// time the user boots up offline. Only writes when we trust the data
|
||||
// (i.e. currently online).
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
if (!navigator.onLine) return;
|
||||
saveSnapshot({
|
||||
v: 1,
|
||||
savedAt: Date.now(),
|
||||
me: data.me,
|
||||
users: data.users,
|
||||
collections: data.collections,
|
||||
places: state.places,
|
||||
});
|
||||
}, [data, state.places]);
|
||||
|
||||
// Realtime-lite sync: re-fetch server data when the tab regains focus or
|
||||
// network comes back. Cheap proxy for true realtime — catches changes other
|
||||
// members made while this tab was inactive. CLAUDE.md Phase 2.
|
||||
useEffect(() => {
|
||||
const refresh = () => router.refresh();
|
||||
const onVisible = () => {
|
||||
if (document.visibilityState === "visible") refresh();
|
||||
};
|
||||
document.addEventListener("visibilitychange", onVisible);
|
||||
window.addEventListener("focus", refresh);
|
||||
window.addEventListener("online", refresh);
|
||||
return () => {
|
||||
document.removeEventListener("visibilitychange", onVisible);
|
||||
window.removeEventListener("focus", refresh);
|
||||
window.removeEventListener("online", refresh);
|
||||
};
|
||||
}, [router]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.toast) return;
|
||||
@@ -78,7 +131,7 @@ export function PlacesApp({
|
||||
if (screen === "place")
|
||||
return (
|
||||
<PlaceDetailScreen
|
||||
state={{ ...state, placeId: top.placeId }}
|
||||
state={{ ...state, placeId: top.placeId, collectionId: top.collectionId }}
|
||||
dispatch={dispatch}
|
||||
/>
|
||||
);
|
||||
@@ -99,11 +152,11 @@ export function PlacesApp({
|
||||
: null;
|
||||
const collectionForDelete =
|
||||
m?.type === "confirmDeleteCollection"
|
||||
? data.collections.find((c) => c.id === m.collectionId)
|
||||
? bootData.data.collections.find((c) => c.id === m.collectionId)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<AppDataProvider value={data}>
|
||||
<AppDataProvider value={bootData.data}>
|
||||
<div className="app-frame">
|
||||
{renderScreen(top.screen)}
|
||||
<TabBar
|
||||
@@ -144,7 +197,7 @@ export function PlacesApp({
|
||||
/>
|
||||
)}
|
||||
{m?.type === "editCollection" && (() => {
|
||||
const c = data.collections.find((x) => x.id === m.collectionId);
|
||||
const c = bootData.data.collections.find((x) => x.id === m.collectionId);
|
||||
return c ? (
|
||||
<CollectionFormSheet
|
||||
mode="edit"
|
||||
|
||||
Reference in New Issue
Block a user