Internal
Public Access
Refresh the page automatically after a pending offline sync completes
The real dashboard is server-rendered before any client JS runs, so the first page load after reconnecting always reflects the pre-sync database state -- the background sync then completes silently, but nothing told that already-rendered page to update. A task created offline would appear to vanish until the next navigation happened to load fresh data. runBackgroundSync() now reports whether it pushed pending changes, and both places that trigger it automatically reload the page when it did. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
a6f227e931
commit
ae9ab596bb
+5
-2
@@ -11,8 +11,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
maybeBackgroundSync();
|
||||
});
|
||||
|
||||
window.addEventListener('online', function() {
|
||||
runBackgroundSync();
|
||||
window.addEventListener('online', async function() {
|
||||
const pushedChanges = await runBackgroundSync();
|
||||
if (pushedChanges) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
/* ============================================
|
||||
|
||||
@@ -92,10 +92,14 @@ async function mergeAndResolveEntity({ entityType, dirtyLocal, serverRows, confl
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if locally-queued offline changes were successfully pushed up
|
||||
// this call - meaning the current (server-rendered) page was rendered before
|
||||
// those changes existed and is now stale, so the caller should refresh it.
|
||||
// Returns false if there was nothing to push, or the sync didn't complete.
|
||||
async function runBackgroundSync() {
|
||||
const csrfToken = getCsrfToken();
|
||||
if (!csrfToken) {
|
||||
return; // Not on an authenticated page (e.g. login/register).
|
||||
return false; // Not on an authenticated page (e.g. login/register).
|
||||
}
|
||||
|
||||
const deviceId = await ensureDeviceId();
|
||||
@@ -104,6 +108,7 @@ async function runBackgroundSync() {
|
||||
const dirtyTasks = await getDirtyTasks();
|
||||
const dirtyTags = await getDirtyTags();
|
||||
const dirtyTimeEntries = await getDirtyTimeEntries();
|
||||
const hadPendingChanges = dirtyTasks.length + dirtyTags.length + dirtyTimeEntries.length > 0;
|
||||
|
||||
let response;
|
||||
try {
|
||||
@@ -124,11 +129,11 @@ async function runBackgroundSync() {
|
||||
}),
|
||||
});
|
||||
} catch (err) {
|
||||
return; // Offline or network error - retry next time, nothing to clean up.
|
||||
return false; // Offline or network error - retry next time, nothing to clean up.
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return; // Includes 429 throttled - retry next time.
|
||||
return false; // Includes 429 throttled - retry next time.
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
@@ -149,6 +154,8 @@ async function runBackgroundSync() {
|
||||
|
||||
await setMeta('last_sync_token', data.sync_token);
|
||||
await setMeta('last_sync_at', new Date().toISOString());
|
||||
|
||||
return hadPendingChanges;
|
||||
}
|
||||
|
||||
async function maybeBackgroundSync() {
|
||||
@@ -156,5 +163,8 @@ async function maybeBackgroundSync() {
|
||||
if (lastSyncAt && Date.now() - new Date(lastSyncAt).getTime() < BACKGROUND_SYNC_MIN_INTERVAL_MS) {
|
||||
return;
|
||||
}
|
||||
runBackgroundSync();
|
||||
const pushedChanges = await runBackgroundSync();
|
||||
if (pushedChanges) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user