Improved initial loading. Uses on device cach first

This commit is contained in:
2026-01-30 17:47:08 -06:00
parent c38892b1ae
commit 40f09b796f
2 changed files with 60 additions and 14 deletions
+32 -7
View File
@@ -1,9 +1,9 @@
// ... (imports)
import { createStore } from "solid-js/store";
import { createSignal } from "solid-js";
import { createStore, reconcile } from "solid-js/store";
import { createSignal, createEffect, createRoot } from "solid-js";
import { pb, TASGRID_COLLECTION } from "@/lib/pocketbase";
import { toast } from "solid-sonner";
const STORAGE_KEY = "tasgrid_data_v1";
export const [now, setNow] = createSignal(Date.now());
export const [activeTaskId, setActiveTaskId] = createSignal<string | null>(null);
@@ -30,12 +30,31 @@ interface TaskStore {
prefId?: string; // ID of the user_preferences record
}
// Initial state
export const [store, setStore] = createStore<TaskStore>({
// Synchronous hydration from localStorage for "instant" first paint
const getInitialState = (): TaskStore => {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
try {
return JSON.parse(saved);
} catch (e) {
console.error("Failed to parse cached data", e);
}
}
return {
tasks: [],
pWeight: 1.0,
uWeight: 1.0,
matrixScaleDays: 30, // Default requested by user
matrixScaleDays: 30,
};
};
export const [store, setStore] = createStore<TaskStore>(getInitialState());
// Auto-persist changes to localStorage (wrapped in root to avoid console warning)
createRoot(() => {
createEffect(() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
});
});
// -- Calibration --
@@ -126,11 +145,17 @@ export const initStore = async () => {
deletedAt: r.deletedAt ? new Date(r.deletedAt).getTime() : undefined
}));
setStore("tasks", loadedTasks);
// Use reconcile for efficient store update (keeps observers happy)
setStore("tasks", reconcile(loadedTasks));
} catch (err) {
// If we fail but have cached data, don't toast an error unless it's a hard failure
if (store.tasks.length === 0) {
console.error("Failed to load data:", err);
toast.error("Failed to sync with server.");
} else {
console.warn("Sync failed, using cached data", err);
}
}
};
+23 -2
View File
@@ -20,12 +20,33 @@ export default defineConfig({
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
type: 'image/png',
purpose: 'any maskable'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
type: 'image/png',
purpose: 'any maskable'
}
]
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/pocketbase\.ccllc\.pro\/api\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
expiration: {
maxEntries: 100,
maxAgeSeconds: 60 * 60 * 24 * 7 // 1 week
},
cacheableResponse: {
statuses: [0, 200]
}
}
}
]
}