feat: Implement PWA install prompt with platform-specific handling and dismissal persistence.
All checks were successful
Build and Deploy / build (push) Successful in 1m25s
All checks were successful
Build and Deploy / build (push) Successful in 1m25s
This commit is contained in:
@@ -90,3 +90,6 @@
|
||||
- [Customizable Deck Builder Layout](./devlog/2025-12-17-170000_customizable_deck_builder.md): Completed. Implemented switchable Vertical (Side-by-Side) and Horizontal (Top-Bottom) layouts, with an integrated, improved Land Station.
|
||||
- [Draft View Layout Selection](./devlog/2025-12-17-185000_draft_view_layout.md): Completed. Implemented Vertical/Horizontal layout selection for Draft View to match Deck Builder, optimizing screen space and preventing overlap.
|
||||
- [Fix Cube Sidebar Scrolling](./devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md): Completed. Adjusted sidebar max-height to ensure autonomous scrolling and button accessibility on tablet screens.
|
||||
- [PWA Install Prompt](./devlog/2025-12-18-004600_pwa_install_prompt.md): Completed. Implemented `PWAInstallPrompt` component in `App.tsx` and enabled PWA dev options.
|
||||
- [Fix PWA Install Prompt](./devlog/2025-12-18-005000_fix_pwa_prompt.md): Completed. Implemented global event capture, iOS detection, and explicit service worker registration to ensure install prompt appears.
|
||||
- [Persist PWA Dismissal](./devlog/2025-12-18-005300_persist_pwa_dismissal.md): Completed. Implemented logic to remember user's choice to dismiss or install the PWA, preventing repeated prompts.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# PWA Install Prompt Implementation Plan
|
||||
|
||||
## Objective
|
||||
Implement a user interface that prompts the user to install the application as a PWA on supported devices (primarily Android/Chrome).
|
||||
|
||||
## Tasks
|
||||
1. Create `src/client/src/components/PWAInstallPrompt.tsx` that:
|
||||
- Listens for `beforeinstallprompt` event.
|
||||
- Displays a custom UI (toast/banner) when the event is captured.
|
||||
- Calls `prompt()` on the event object when the user clicks "Install".
|
||||
- Handles the user's choice.
|
||||
2. Integrate `PWAInstallPrompt` into `App.tsx`.
|
||||
3. Verify `vite.config.ts` PWA settings (already done, looks good).
|
||||
|
||||
## Implementation Details
|
||||
- The component will use a fixed position styling (bottom right/center) to be noticeable but not blocking.
|
||||
- It will use existing design system (Tailwind).
|
||||
|
||||
## Status
|
||||
- [x] Create Component
|
||||
- [x] Integrate into App
|
||||
- [x] Update Config
|
||||
- **Completed**: 2025-12-18
|
||||
33
docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md
Normal file
33
docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Fix PWA Install Prompt Implementation Plan
|
||||
|
||||
## Objective
|
||||
Ensure the PWA install prompt appears reliably on mobile devices, addressing potential issues with event timing, iOS compatibility, and explicit Service Worker registration.
|
||||
|
||||
## Root Causes to Address
|
||||
1. **Late Event Listener**: The `beforeinstallprompt` event might fire before the React component mounts. We need to capture it globally as early as possible.
|
||||
2. **Missing Service Worker Registration**: While `vite-plugin-pwa` can auto-inject, explicit registration in `main.tsx` ensures it's active and handles updates.
|
||||
3. **iOS Compatibility**: iOS does not support `beforeinstallprompt`. We must detect iOS and show specific "Share -> Add to Home Screen" instructions.
|
||||
4. **Secure Context**: PWA features require HTTPS. While we can't force this on the user's network, we can ensure the app behaves best-effort and maybe warn if needed (skipped for now to avoid noise, focusing on logical fixes).
|
||||
|
||||
## Tasks
|
||||
1. **Update `src/client/src/main.tsx`**:
|
||||
- Import `registerSW` from `virtual:pwa-register`.
|
||||
- Add a global `window` event listener for `beforeinstallprompt` immediately upon script execution to capture the event.
|
||||
- Expose the captured event on `window` (or a global store) so the React component can consume it.
|
||||
2. **Update `src/client/src/components/PWAInstallPrompt.tsx`**:
|
||||
- Check `window.deferredInstallPrompt` (or similar) on mount.
|
||||
- Add User Agent detection for iOS (iPhone/iPad/iPod).
|
||||
- If iOS, display a custom "Add to Home Screen" instruction banner.
|
||||
- If Android/Desktop, use the captured prompt.
|
||||
3. **Docs**: Update devlog.
|
||||
|
||||
## Technical Details
|
||||
- **Global Property**: `window.deferredInstallPrompt`
|
||||
- **iOS Detection**: Regex on `navigator.userAgent` looking for `iPhone|iPad|iPod` (and not `MSStream`).
|
||||
|
||||
## Status
|
||||
- [x] Register SW explicitly in main.tsx
|
||||
- [x] Capture `beforeinstallprompt` globally
|
||||
- [x] Add iOS specific UI
|
||||
- **Completed**: 2025-12-18
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Persist PWA Prompt Dismissal
|
||||
|
||||
## Objective
|
||||
Ensure the PWA install prompt honors the user's previous interactions. If the user dismisses the prompt (clicks X) or initiates the install flow, the prompt should not appear again in subsequent sessions.
|
||||
|
||||
## Implementation Details
|
||||
1. **Storage**: Use `localStorage` key `pwa_prompt_dismissed` (value: 'true').
|
||||
2. **Logic Update** in `PWAInstallPrompt.tsx`:
|
||||
- On mount: Check if `localStorage.getItem('pwa_prompt_dismissed') === 'true'`. If so, return `null` immediately.
|
||||
- On Dismiss (X click): Set `localStorage.setItem('pwa_prompt_dismissed', 'true')` and hide UI.
|
||||
- On Install Click: Set `localStorage.setItem('pwa_prompt_dismissed', 'true')` immediately. Even if they cancel the native dialog, we respect their choice to have interacted with it once. (Or should we? The user said "after a use choice". I will assume entering the flow counts).
|
||||
|
||||
## Refinements
|
||||
- We might want to allow re-prompting after a long time (e.g., storing a timestamp), but the request is simple: "do not show... after a use choice". I will stick to simple boolean persistence for now.
|
||||
|
||||
## Status
|
||||
- [x] Add logic to check/set `pwa_prompt_dismissed`
|
||||
- [x] Update dismissal (X button) logic
|
||||
- [x] Update install logic
|
||||
- **Completed**: 2025-12-18
|
||||
Reference in New Issue
Block a user