feat(05-04): usePushSubscription hook + PushPermissionPrompt + App mount
- Create apps/pwa/src/hooks/usePushSubscription.ts: subscribe (in tap handler, VAPID key cached), unsubscribe, permission; health-check on mount (D-10); urlBase64ToUint8Array helper; prefetchVapidKey export - Create apps/pwa/src/components/PushPermissionPrompt.tsx: WalkthroughSheet-style bottom sheet, Bell icon, 'Stay in the loop' heading, 48px Enable CTA (var(--color-member-0)), 44px Not-now ghost, no backdrop-dismiss, pushPermissionDismissed key, Loader2 spinner while awaiting - Mount PushPermissionPrompt in App.tsx (for installed-PWA path) and InstallPrompt.tsx (for post-Android-install justInstalled path) - Build green; tsc clean
This commit is contained in:
@@ -22,6 +22,7 @@ import { CalendarShell } from './components/CalendarShell.js'
|
||||
import { ListsIndex } from './routes/ListsIndex.js'
|
||||
import { ListDetail } from './routes/ListDetail.js'
|
||||
import { BottomTabBar } from './components/BottomTabBar.js'
|
||||
import { PushPermissionPrompt } from './components/PushPermissionPrompt.js'
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -33,6 +34,9 @@ export default function App() {
|
||||
<Route path="/lists/:listId" element={<ListDetail />} />
|
||||
</Routes>
|
||||
<BottomTabBar />
|
||||
{/* Post-install permission prompt (D-08): renders only when isInstalled() is true
|
||||
and Notification.permission === 'default' and not dismissed */}
|
||||
<PushPermissionPrompt />
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user