Versioning and Updating improvements
CI / build (push) Has been skipped
CI / deploy (push) Successful in 1m3s

This commit is contained in:
2026-03-13 12:21:25 -05:00
parent b89e6ca2c3
commit 3ebc43ef72
5 changed files with 95 additions and 16 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "tasgrid",
"private": true,
"version": "0.0.0",
"version": "1.1.0",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0 --port 4001",
+38
View File
@@ -1,8 +1,10 @@
import { type Component, createEffect, onCleanup } from 'solid-js';
import { useRegisterSW } from 'virtual:pwa-register/solid';
import { toast } from 'solid-sonner';
// We export a function so other parts of the app can manually trigger an update
let manualUpdateFn: (() => void) | undefined;
let updateAndReloadFn: (() => void) | undefined;
export const forceServiceWorkerUpdate = () => {
if (manualUpdateFn) {
@@ -12,6 +14,15 @@ export const forceServiceWorkerUpdate = () => {
}
};
export const updateAndReloadApp = () => {
if (updateAndReloadFn) {
updateAndReloadFn();
} else {
console.warn("PWA Updater not initialized yet; reloading directly.");
window.location.reload();
}
};
export const PwaUpdater: Component = () => {
let registration: ServiceWorkerRegistration | undefined;
@@ -47,6 +58,33 @@ export const PwaUpdater: Component = () => {
registration.update();
}
};
updateAndReloadFn = () => {
if (needRefresh()) {
console.log('Update ready. Reloading now...');
updateServiceWorker(true);
return;
}
if (registration) {
console.log('Checking for updates before reload...');
registration.update();
}
const start = Date.now();
const timeoutMs = 5000;
const poll = window.setInterval(() => {
if (needRefresh()) {
console.log('Update found. Reloading with new SW...');
window.clearInterval(poll);
updateServiceWorker(true);
} else if (Date.now() - start > timeoutMs) {
console.log('No update detected quickly. Reloading now...');
window.clearInterval(poll);
toast.info("No update found");
}
}, 250);
};
});
createEffect(() => {
+36 -6
View File
@@ -1088,20 +1088,50 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
</div>
<footer class="pt-40 pb-20 flex flex-col items-center gap-4">
<div class="flex items-center gap-2">
<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"
class="h-8 gap-2 text-[0.625rem] font-bold uppercase tracking-widest text-muted-foreground hover:text-foreground opacity-70 hover:opacity-100 transition-opacity"
onClick={async () => {
const { forceServiceWorkerUpdate } = await import('@/components/PwaUpdater');
forceServiceWorkerUpdate();
toast.success("Checking for updates...");
const { updateAndReloadApp } = await import('@/components/PwaUpdater');
toast.success("Updating app...");
updateAndReloadApp();
}}
>
<Upload class="rotate-180" size={14} />
Check for Updates
Update App
</Button>
<p class="text-[0.5rem] font-mono text-muted-foreground/30 uppercase tracking-[0.2em]">Tasgrid v1.0.1</p> {/* Versioning System: v[breaking update].[user-facing update].[patch/backend updated] */}
<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-70 hover:opacity-100 transition-opacity"
onClick={async () => {
if (!confirm("Reset PWA? This will clear offline data and reload.")) return;
try {
const registrations = await navigator.serviceWorker?.getRegistrations?.();
if (registrations) {
await Promise.all(registrations.map(r => r.unregister()));
}
if ('caches' in window) {
const keys = await caches.keys();
await Promise.all(keys.map(k => caches.delete(k)));
}
toast.success("PWA reset. Reloading...");
window.location.reload();
} catch (err) {
console.error("Failed to reset PWA", err);
toast.error("Failed to reset PWA");
}
}}
>
<Trash2 size={14} />
Reset PWA
</Button>
</div>
<p class="text-[0.5rem] font-mono text-muted-foreground/60 uppercase tracking-[0.2em]">
Tasgrid v{__APP_VERSION__}
</p> {/* Versioning System: v[breaking update].[user-facing update].[patch/backend updated] */}
</footer>
</div>
);
+3
View File
@@ -0,0 +1,3 @@
/// <reference types="vite/client" />
declare const __APP_VERSION__: string;
+8
View File
@@ -3,8 +3,16 @@ import solid from 'vite-plugin-solid'
import { VitePWA } from 'vite-plugin-pwa'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'
import { readFileSync } from 'fs'
const packageJson = JSON.parse(
readFileSync(new URL('./package.json', import.meta.url), 'utf-8')
);
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify(packageJson.version),
},
plugins: [
solid(),
tailwindcss(),