Skip to content

Commit 9861e63

Browse files
authored
Merge pull request #44 from openpatch/copilot/integrate-vitepwa
Integrate VitePWA prompt mode with ReloadPrompt component
2 parents ebcd481 + 8632f09 commit 9861e63

7 files changed

Lines changed: 130 additions & 2 deletions

File tree

platforms/web/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { LearningMapEditor } from '@learningmap/learningmap';
44
import "@learningmap/learningmap/index.css";
55
import Learn from './Learn';
66
import Landing from './Landing';
7+
import ReloadPrompt from './ReloadPrompt';
78

89
function App() {
910
return (
@@ -13,6 +14,7 @@ function App() {
1314
<Route path="/create" element={<LearningMapEditor jsonStore="https://json.openpatch.org" />} />
1415
<Route path="/learn" element={<Learn />} />
1516
</Routes>
17+
<ReloadPrompt />
1618
</BrowserRouter>
1719
)
1820
}

platforms/web/src/ReloadPrompt.css

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
.ReloadPrompt-container {
2+
padding: 0;
3+
margin: 0;
4+
width: 0;
5+
height: 0;
6+
}
7+
8+
.ReloadPrompt-toast {
9+
position: fixed;
10+
transition: all 0.3s ease;
11+
right: 0;
12+
bottom: 0;
13+
margin: 32px;
14+
padding: 12px;
15+
border: 1px solid #8885;
16+
border-radius: 8px;
17+
z-index: 1;
18+
text-align: left;
19+
box-shadow: 3px 4px 5px 0 #8885;
20+
}
21+
22+
.ReloadPrompt-toast.info {
23+
background-color: #F0FFFF;
24+
border-color: #4682B4;
25+
color: #4682B4;
26+
27+
button {
28+
transition: all 0.3s ease;
29+
background-color: #4682B4;
30+
color: #F0FFFF;
31+
}
32+
33+
button:hover {
34+
background-color: #315f7d;
35+
border-color: #315f7d;
36+
}
37+
38+
button.close {
39+
background-color: transparent;
40+
color: #4682B4;
41+
border: 1px solid #4682B4;
42+
}
43+
44+
button.close:hover {
45+
background-color: #315f7d;
46+
color: #F0FFFF;
47+
border-color: #315f7d;
48+
}
49+
}
50+
51+
.ReloadPrompt-message {
52+
margin-bottom: 8px;
53+
}
54+
55+
.ReloadPrompt-buttons {
56+
display: flex;
57+
justify-content: flex-end;
58+
gap: 8px;
59+
}
60+
61+
.ReloadPrompt-toast-button {
62+
border: 1px solid #8885;
63+
outline: none;
64+
margin-right: 5px;
65+
border-radius: 8px;
66+
padding: 6px 12px;
67+
cursor: pointer;
68+
}

platforms/web/src/ReloadPrompt.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import './ReloadPrompt.css'
2+
3+
import { useRegisterSW } from 'virtual:pwa-register/react'
4+
5+
const UPDATE_CHECK_INTERVAL_MS = 60 * 60 * 1000 // Check for updates every hour
6+
7+
function ReloadPrompt() {
8+
const {
9+
offlineReady: [offlineReady, setOfflineReady],
10+
needRefresh: [needRefresh, setNeedRefresh],
11+
updateServiceWorker,
12+
} = useRegisterSW({
13+
onRegistered(r) {
14+
console.log(`SW Registered: ${r}`)
15+
// Implement periodic SW updates (check every hour)
16+
if (r) {
17+
setInterval(() => {
18+
r.update()
19+
}, UPDATE_CHECK_INTERVAL_MS)
20+
}
21+
},
22+
onRegisterError(error) {
23+
console.log('SW registration error', error)
24+
},
25+
})
26+
27+
const close = () => {
28+
setOfflineReady(false)
29+
setNeedRefresh(false)
30+
}
31+
32+
return (
33+
<div className="ReloadPrompt-container">
34+
{(offlineReady || needRefresh)
35+
&& <div className="ReloadPrompt-toast info">
36+
<div className="ReloadPrompt-message">
37+
{offlineReady
38+
? <span>App ready to work offline</span>
39+
: <span>New content available, click on reload button to update.</span>
40+
}
41+
</div>
42+
<div className="ReloadPrompt-buttons">
43+
{needRefresh && <button className="ReloadPrompt-toast-button" onClick={() => updateServiceWorker(true)}>Reload</button>}
44+
<button className="ReloadPrompt-toast-button close" onClick={() => close()}>Close</button>
45+
</div>
46+
</div>
47+
}
48+
</div>
49+
)
50+
}
51+
52+
export default ReloadPrompt

platforms/web/src/vite-env.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/// <reference types="vite/client" />
2+
/// <reference types="vite-plugin-pwa/react" />

platforms/web/tsconfig.app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"useDefineForClassFields": true,
66
"lib": ["ES2022", "DOM", "DOM.Iterable"],
77
"module": "ESNext",
8-
"types": ["vite/client"],
8+
"types": ["vite/client", "vite-plugin-pwa/react"],
99
"skipLibCheck": true,
1010

1111
/* Bundler mode */

platforms/web/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default defineConfig({
77
plugins: [
88
react(),
99
VitePWA({
10-
registerType: 'autoUpdate',
10+
registerType: 'prompt',
1111
includeAssets: ['logo.svg', 'concert_one_latin.woff2'],
1212
manifest: {
1313
name: 'Learningmap - Interactive Visual Maps for Teaching and Learning',

pnpm-workspace.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ packages:
22
- packages/*
33
- platforms/*
44
- '!**/test/**'
5+
6+
onlyBuiltDependencies:
7+
- '@vscode/vsce-sign'
8+
- keytar

0 commit comments

Comments
 (0)