# PWA Developer Quick Reference ## Using PWA Features in Components ### 1. Access PWA State ```typescript import { usePWA } from '../context/PWAContext'; function MyComponent() { const { isOnline, // boolean - network status canInstall, // boolean - can show install prompt isInstalled, // boolean - app is installed isUpdateAvailable, // boolean - update available cacheSize, // { usage: number, quota: number } | null showInstallPrompt, // () => Promise updateApp, // () => Promise clearCache, // () => Promise cacheAudio, // (url: string) => Promise requestNotifications, // () => Promise } = usePWA(); // Use PWA state return (
{!isOnline && } {canInstall && }
); } ``` ### 2. Show Install Prompt ```typescript import { usePWA } from '../context/PWAContext'; function InstallButton() { const { canInstall, showInstallPrompt } = usePWA(); const handleInstall = async () => { const installed = await showInstallPrompt(); if (installed) { console.log('App installed!'); } }; if (!canInstall) return null; return ; } ``` ### 3. Handle Offline State ```typescript import { usePWA } from '../context/PWAContext'; function MyComponent() { const { isOnline } = usePWA(); return (
{!isOnline && ( You're offline. Some features may be limited. )} {/* Component content */}
); } ``` ### 4. Cache Audio for Offline ```typescript import { usePWA } from '../context/PWAContext'; function AudioItem({ audio }) { const { cacheAudio } = usePWA(); const [cached, setCached] = useState(false); const handleCache = async () => { const success = await cacheAudio(audio.file_url); if (success) { setCached(true); showNotification('Audio cached for offline playback'); } }; return (
{audio.title}
); } ``` ### 5. Request Notifications ```typescript import { usePWA } from '../context/PWAContext'; function NotificationSettings() { const { requestNotifications } = usePWA(); const handleEnable = async () => { const permission = await requestNotifications(); if (permission === 'granted') { console.log('Notifications enabled'); } }; return ; } ``` ### 6. Show App Update ```typescript import { usePWA } from '../context/PWAContext'; function UpdateBanner() { const { isUpdateAvailable, updateApp } = usePWA(); if (!isUpdateAvailable) return null; return ( Update Now } > New version available! ); } ``` ## Media Session API Usage ### Set Media Metadata ```typescript import { setMediaMetadata } from '../utils/mediaSession'; setMediaMetadata({ title: 'Song Title', artist: 'Artist Name', album: 'Album Name', artwork: [ { src: '/cover-96.jpg', sizes: '96x96', type: 'image/jpeg' }, { src: '/cover-512.jpg', sizes: '512x512', type: 'image/jpeg' }, ], }); ``` ### Set Action Handlers ```typescript import { setMediaActionHandlers } from '../utils/mediaSession'; setMediaActionHandlers({ play: () => audioElement.play(), pause: () => audioElement.pause(), previoustrack: () => playPrevious(), nexttrack: () => playNext(), seekbackward: () => seek(-10), seekforward: () => seek(10), seekto: (details) => audioElement.currentTime = details.seekTime, }); ``` ### Update Playback State ```typescript import { setPlaybackState, setPositionState } from '../utils/mediaSession'; // When playing/paused setPlaybackState('playing'); // or 'paused' or 'none' // Update position (for seek bar) setPositionState({ duration: audio.duration, playbackRate: 1.0, position: audioElement.currentTime, }); ``` ## Offline Storage Usage ### Save/Get Data ```typescript import { offlineStorage } from '../utils/offlineStorage'; // Save audio queue await offlineStorage.saveAudioQueue(queue); // Get audio queue const queue = await offlineStorage.getAudioQueue(); // Add favorite await offlineStorage.addFavorite({ id: audio.id, title: audio.title, // ... other data }); // Get favorites const favorites = await offlineStorage.getFavorites(); // Save setting await offlineStorage.saveSetting('theme', 'dark'); // Get setting const theme = await offlineStorage.getSetting('theme'); ``` ### Pending Uploads ```typescript import { offlineStorage } from '../utils/offlineStorage'; // Add pending upload (when offline) await offlineStorage.addPendingUpload({ file: fileData, metadata: { title: 'Song' }, }); // Get pending uploads (to sync when online) const pending = await offlineStorage.getPendingUploads(); // Remove after sync await offlineStorage.removePendingUpload(uploadId); ``` ## Service Worker Communication ### Cache Specific URL ```typescript import { cacheAudio } from '../utils/pwa'; const url = 'https://example.com/audio/song.mp3'; const success = await cacheAudio(url); if (success) { console.log('Audio cached!'); } ``` ### Clear All Caches ```typescript import { clearCache } from '../utils/pwa'; const success = await clearCache(); if (success) { console.log('Cache cleared!'); } ``` ## PWA Utilities ### Check Installation Status ```typescript import { isInstalled, canInstall } from '../utils/pwa'; if (isInstalled()) { console.log('App is installed'); } if (canInstall()) { console.log('Can show install prompt'); } ``` ### Check Online Status ```typescript import { isOnline } from '../utils/pwa'; if (isOnline()) { // Fetch from network } else { // Use cached data } ``` ### Get Cache Size ```typescript import { getCacheSize } from '../utils/pwa'; const size = await getCacheSize(); if (size) { console.log(`Using ${size.usage} of ${size.quota} bytes`); const percent = (size.usage / size.quota) * 100; console.log(`${percent.toFixed(1)}% of storage used`); } ``` ## Best Practices ### 1. Always Handle Offline State ```typescript function DataComponent() { const { isOnline } = usePWA(); const [data, setData] = useState(null); useEffect(() => { if (isOnline) { // Fetch from API fetchData().then(setData); } else { // Load from offline storage offlineStorage.get('dataStore', 'key').then(setData); } }, [isOnline]); return
{/* Render data */}
; } ``` ### 2. Show Loading States ```typescript function MyComponent() { const [loading, setLoading] = useState(true); useEffect(() => { loadData().finally(() => setLoading(false)); }, []); if (loading) { return ; } return
{/* Content */}
; } ``` ### 3. Provide Offline Feedback ```typescript function UploadButton({ file }) { const { isOnline } = usePWA(); const handleUpload = async () => { if (!isOnline) { // Queue for later await offlineStorage.addPendingUpload(file); alert('Upload queued. Will sync when online.'); return; } // Upload immediately await uploadFile(file); }; return ( ); } ``` ### 4. Cache Important Assets ```typescript function AudioPlayer({ audio }) { const { cacheAudio } = usePWA(); const [isCached, setIsCached] = useState(false); useEffect(() => { // Pre-cache important audio if (audio.is_favorite) { cacheAudio(audio.file_url).then(setIsCached); } }, [audio]); return (
); } ``` ### 5. Clean Up Resources ```typescript function MediaPlayer({ audio }) { useEffect(() => { // Set up media session setMediaMetadata(audio); setMediaActionHandlers({ /* ... */ }); // Clean up on unmount return () => { clearMediaSession(); }; }, [audio]); return