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
This commit is contained in:
@@ -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;
|
||||
};
|
||||
@@ -3,12 +3,14 @@ import './index.css'
|
||||
import App from './App.tsx'
|
||||
import { ThemeProvider } from './components/ThemeProvider'
|
||||
import { Toaster } from './components/ui/sonner'
|
||||
import { PwaUpdater } from './components/PwaUpdater'
|
||||
|
||||
const root = document.getElementById('root')
|
||||
|
||||
render(() => {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<PwaUpdater />
|
||||
<App />
|
||||
<Toaster />
|
||||
</ThemeProvider>
|
||||
|
||||
+3
-1
@@ -221,10 +221,12 @@ export const startContextPolling = () => {
|
||||
}
|
||||
};
|
||||
|
||||
createEffect(() => {
|
||||
createRoot(() => {
|
||||
createEffect(() => {
|
||||
// Re-run whenever ctx changes
|
||||
currentTaskContext();
|
||||
startContextPolling();
|
||||
});
|
||||
});
|
||||
|
||||
export interface FilterTemplate {
|
||||
|
||||
@@ -77,7 +77,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-col gap-12">
|
||||
<div class="flex flex-col gap-12 mt-4">
|
||||
|
||||
|
||||
{/* Resources Category (Mostly for Mobile) */}
|
||||
@@ -1086,6 +1086,23 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="pt-40 pb-20 flex flex-col items-center gap-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="h-8 gap-2 text-[0.625rem] font-bold uppercase tracking-widest text-muted-foreground hover:text-foreground opacity-30 hover:opacity-100 transition-opacity"
|
||||
onClick={async () => {
|
||||
const { forceServiceWorkerUpdate } = await import('@/components/PwaUpdater');
|
||||
forceServiceWorkerUpdate();
|
||||
toast.success("Checking for updates...");
|
||||
}}
|
||||
>
|
||||
<Upload class="rotate-180" size={14} />
|
||||
Check for Updates
|
||||
</Button>
|
||||
<p class="text-[0.5rem] font-mono text-muted-foreground/30 uppercase tracking-[0.2em]">Tasgrid v1.0.0</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+3
-1
@@ -10,7 +10,9 @@
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"types": [
|
||||
"vite/client"
|
||||
"vite/client",
|
||||
"vite-plugin-pwa/client",
|
||||
"vite-plugin-pwa/solid"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ export default defineConfig({
|
||||
solid(),
|
||||
tailwindcss(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
registerType: 'prompt',
|
||||
includeAssets: ['icon.webp', 'vite.svg'],
|
||||
manifest: {
|
||||
name: 'Tasgrid',
|
||||
|
||||
Reference in New Issue
Block a user