Added custom PWA reloading - 10 minutes of idle or when moved to the background or when loading initially or manually with the new button in settings
CI / build (push) Has been skipped
CI / deploy_prod (push) Successful in 1m19s
CI / deploy_dev (push) Has been skipped

This commit is contained in:
2026-03-04 19:29:18 -06:00
parent 4ebd0b5f61
commit 6a963a32fd
6 changed files with 140 additions and 7 deletions
+110
View File
@@ -0,0 +1,110 @@
import { type Component, createEffect, onCleanup } from 'solid-js';
import { useRegisterSW } from 'virtual:pwa-register/solid';
// We export a function so other parts of the app can manually trigger an update
let manualUpdateFn: (() => void) | undefined;
export const forceServiceWorkerUpdate = () => {
if (manualUpdateFn) {
manualUpdateFn();
} else {
console.warn("PWA Updater not initialized yet");
}
};
export const PwaUpdater: Component = () => {
let registration: ServiceWorkerRegistration | undefined;
const {
needRefresh: [needRefresh],
updateServiceWorker,
} = useRegisterSW({
onRegistered(r: ServiceWorkerRegistration | undefined) {
console.log('SW Registered:', r);
registration = r;
// Periodically check for updates (every 1 hour)
if (r) {
setInterval(() => {
console.log('Periodic SW update check...');
r.update();
}, 60 * 60 * 1000);
}
},
onRegisterError(error: Error | any) {
console.error('SW registration error', error);
},
});
createEffect(() => {
// Expose function globally
manualUpdateFn = () => {
if (needRefresh()) {
console.log('User manually forced an update. Reloading now...');
updateServiceWorker(true);
} else if (registration) {
console.log('User manually asked to check for updates...');
registration.update();
}
};
});
createEffect(() => {
// Check for updates when the app regains focus/visibility
const handleVisibilityFocus = () => {
if (document.visibilityState === 'visible' && registration) {
console.log('App became visible, checking for SW updates...');
registration.update();
}
};
document.addEventListener('visibilitychange', handleVisibilityFocus);
window.addEventListener('focus', handleVisibilityFocus);
onCleanup(() => {
document.removeEventListener('visibilitychange', handleVisibilityFocus);
window.removeEventListener('focus', handleVisibilityFocus);
});
});
createEffect(() => {
if (needRefresh()) {
console.log('New PWA version available. Monitoring for idle/hidden state to update...');
let idleTimeout: number | undefined;
const triggerUpdate = () => {
console.log('Triggering PWA update...');
updateServiceWorker(true);
};
const resetIdle = () => {
if (idleTimeout) window.clearTimeout(idleTimeout);
// 10 minutes idle
idleTimeout = window.setTimeout(triggerUpdate, 10 * 60 * 1000);
};
const handleVisibility = () => {
if (document.visibilityState === 'hidden') {
triggerUpdate();
}
};
// Start idle timer
resetIdle();
// Listen for user activity
const events = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart'];
events.forEach(e => window.addEventListener(e, resetIdle, { passive: true }));
document.addEventListener('visibilitychange', handleVisibility);
onCleanup(() => {
if (idleTimeout) window.clearTimeout(idleTimeout);
events.forEach(e => window.removeEventListener(e, resetIdle));
document.removeEventListener('visibilitychange', handleVisibility);
});
}
});
return null;
};