diff --git a/platforms/web/src/App.tsx b/platforms/web/src/App.tsx index 34cbfa8..4fd4371 100644 --- a/platforms/web/src/App.tsx +++ b/platforms/web/src/App.tsx @@ -4,6 +4,7 @@ import { LearningMapEditor } from '@learningmap/learningmap'; import "@learningmap/learningmap/index.css"; import Learn from './Learn'; import Landing from './Landing'; +import ReloadPrompt from './ReloadPrompt'; function App() { return ( @@ -13,6 +14,7 @@ function App() { } /> } /> + ) } diff --git a/platforms/web/src/ReloadPrompt.css b/platforms/web/src/ReloadPrompt.css new file mode 100644 index 0000000..7954413 --- /dev/null +++ b/platforms/web/src/ReloadPrompt.css @@ -0,0 +1,68 @@ +.ReloadPrompt-container { + padding: 0; + margin: 0; + width: 0; + height: 0; +} + +.ReloadPrompt-toast { + position: fixed; + transition: all 0.3s ease; + right: 0; + bottom: 0; + margin: 32px; + padding: 12px; + border: 1px solid #8885; + border-radius: 8px; + z-index: 1; + text-align: left; + box-shadow: 3px 4px 5px 0 #8885; +} + +.ReloadPrompt-toast.info { + background-color: #F0FFFF; + border-color: #4682B4; + color: #4682B4; + + button { + transition: all 0.3s ease; + background-color: #4682B4; + color: #F0FFFF; + } + + button:hover { + background-color: #315f7d; + border-color: #315f7d; + } + + button.close { + background-color: transparent; + color: #4682B4; + border: 1px solid #4682B4; + } + + button.close:hover { + background-color: #315f7d; + color: #F0FFFF; + border-color: #315f7d; + } +} + +.ReloadPrompt-message { + margin-bottom: 8px; +} + +.ReloadPrompt-buttons { + display: flex; + justify-content: flex-end; + gap: 8px; +} + +.ReloadPrompt-toast-button { + border: 1px solid #8885; + outline: none; + margin-right: 5px; + border-radius: 8px; + padding: 6px 12px; + cursor: pointer; +} diff --git a/platforms/web/src/ReloadPrompt.tsx b/platforms/web/src/ReloadPrompt.tsx new file mode 100644 index 0000000..555ec9d --- /dev/null +++ b/platforms/web/src/ReloadPrompt.tsx @@ -0,0 +1,52 @@ +import './ReloadPrompt.css' + +import { useRegisterSW } from 'virtual:pwa-register/react' + +const UPDATE_CHECK_INTERVAL_MS = 60 * 60 * 1000 // Check for updates every hour + +function ReloadPrompt() { + const { + offlineReady: [offlineReady, setOfflineReady], + needRefresh: [needRefresh, setNeedRefresh], + updateServiceWorker, + } = useRegisterSW({ + onRegistered(r) { + console.log(`SW Registered: ${r}`) + // Implement periodic SW updates (check every hour) + if (r) { + setInterval(() => { + r.update() + }, UPDATE_CHECK_INTERVAL_MS) + } + }, + onRegisterError(error) { + console.log('SW registration error', error) + }, + }) + + const close = () => { + setOfflineReady(false) + setNeedRefresh(false) + } + + return ( +
+ {(offlineReady || needRefresh) + &&
+
+ {offlineReady + ? App ready to work offline + : New content available, click on reload button to update. + } +
+
+ {needRefresh && } + +
+
+ } +
+ ) +} + +export default ReloadPrompt diff --git a/platforms/web/src/vite-env.d.ts b/platforms/web/src/vite-env.d.ts new file mode 100644 index 0000000..ec878b7 --- /dev/null +++ b/platforms/web/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/platforms/web/tsconfig.app.json b/platforms/web/tsconfig.app.json index a9b5a59..177d3d7 100644 --- a/platforms/web/tsconfig.app.json +++ b/platforms/web/tsconfig.app.json @@ -5,7 +5,7 @@ "useDefineForClassFields": true, "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", - "types": ["vite/client"], + "types": ["vite/client", "vite-plugin-pwa/react"], "skipLibCheck": true, /* Bundler mode */ diff --git a/platforms/web/vite.config.ts b/platforms/web/vite.config.ts index 223ee57..16f42eb 100644 --- a/platforms/web/vite.config.ts +++ b/platforms/web/vite.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ plugins: [ react(), VitePWA({ - registerType: 'autoUpdate', + registerType: 'prompt', includeAssets: ['logo.svg', 'concert_one_latin.woff2'], manifest: { name: 'Learningmap - Interactive Visual Maps for Teaching and Learning', diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 962d171..90599f1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,3 +2,7 @@ packages: - packages/* - platforms/* - '!**/test/**' + +onlyBuiltDependencies: + - '@vscode/vsce-sign' + - keytar