Add service worker implementation and tests for PWA caching strategy
- Implemented a service worker (sw.js) that handles installation, activation, and fetch events. - Added caching logic for public assets and a fallback for offline navigation. - Created unit tests (sw.test.ts) to validate service worker behavior, including asset caching, navigation handling, and activation logic. - Ensured that private API routes and third-party requests are excluded from caching.
This commit is contained in:
43
src/components/PwaControls.tsx
Normal file
43
src/components/PwaControls.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useState } from "react";
|
||||
import { applyUpdate, installApp, useOnline, usePwa } from "../pwa/client";
|
||||
import { Button } from "./design-system/primitives";
|
||||
import { Modal } from "./design-system/Modal";
|
||||
|
||||
export function InstallApp() {
|
||||
const { enabled, installed, installPrompt } = usePwa();
|
||||
const [help, setHelp] = useState(false);
|
||||
if (!enabled || installed) return null;
|
||||
return <>
|
||||
<Button variant="text" onClick={() => { if (installPrompt) void installApp(); else setHelp(true); }}>Install app</Button>
|
||||
{help && <Modal id="install-app" size="compact" title="Keep Mina Habits close." onClose={() => setHelp(false)}>
|
||||
<div className="ds-form-stack">
|
||||
<p>Open Mina Habits from your home screen or dock.</p>
|
||||
<p><strong>iPhone or iPad:</strong> open the Share menu, then choose Add to Home Screen.</p>
|
||||
<p><strong>Mac Safari:</strong> choose File → Add to Dock.</p>
|
||||
<p><strong>Chrome or Edge:</strong> use the install icon in the address bar, or Install app in the browser menu.</p>
|
||||
<p className="ds-supporting-copy">Installation options depend on your browser. Your habits still need a connection to load and save.</p>
|
||||
<div className="ds-actions"><Button onClick={() => setHelp(false)}>Got it</Button></div>
|
||||
</div>
|
||||
</Modal>}
|
||||
</>;
|
||||
}
|
||||
|
||||
export function PwaStatus() {
|
||||
const online = useOnline();
|
||||
const { updateReady, error } = usePwa();
|
||||
const [confirmUpdate, setConfirmUpdate] = useState(false);
|
||||
return <>
|
||||
{!online && <div className="ds-form-feedback" role="status">You’re offline. Reconnect to load or save your habits. Changes are not queued.</div>}
|
||||
{error && <div className="ds-form-feedback" role="status">{error}</div>}
|
||||
{updateReady && <div className="ds-action-row" role="status">
|
||||
<span>A new version of Mina Habits is ready.</span>
|
||||
<Button variant="secondary" onClick={() => setConfirmUpdate(true)}>Update app</Button>
|
||||
</div>}
|
||||
{confirmUpdate && <Modal id="update-app" size="compact" title="Ready to update?" onClose={() => setConfirmUpdate(false)}>
|
||||
<div className="ds-form-stack">
|
||||
<p>This window will reload. Save any unfinished changes first.</p>
|
||||
<div className="ds-actions"><Button onClick={applyUpdate}>Reload and update</Button><Button variant="text" onClick={() => setConfirmUpdate(false)}>Later</Button></div>
|
||||
</div>
|
||||
</Modal>}
|
||||
</>;
|
||||
}
|
||||
Reference in New Issue
Block a user