An in-browser wisp.place site explorer
at main 95 lines 2.5 kB view raw
1/** 2 * Service Worker Debug Component 3 * 4 * Displays service worker status for debugging purposes. 5 * Only shows in development mode. 6 */ 7 8import { useState, useEffect } from 'react'; 9 10export function ServiceWorkerDebug() { 11 const [status, setStatus] = useState<{ 12 ready: boolean; 13 controlled: boolean; 14 scope: string | null; 15 hasManifest: boolean; 16 siteInfo: any; 17 }>({ 18 ready: false, 19 controlled: false, 20 scope: null, 21 hasManifest: false, 22 siteInfo: null, 23 }); 24 25 useEffect(() => { 26 const checkStatus = async () => { 27 if (!('serviceWorker' in navigator)) { 28 setStatus(prev => ({ ...prev, ready: false })); 29 return; 30 } 31 32 const ready = 'serviceWorker' in navigator; 33 const controlled = !!navigator.serviceWorker.controller; 34 const registration = await navigator.serviceWorker.getRegistration(); 35 const scope = registration?.scope || null; 36 37 setStatus(prev => ({ ...prev, ready, controlled, scope })); 38 39 // Check with service worker for manifest status 40 if (navigator.serviceWorker.controller) { 41 const channel = new MessageChannel(); 42 channel.port1.onmessage = (event) => { 43 setStatus(prev => ({ 44 ...prev, 45 hasManifest: event.data.hasManifest || false, 46 siteInfo: event.data.siteInfo, 47 })); 48 }; 49 50 navigator.serviceWorker.controller.postMessage( 51 { type: 'GET_STATUS' }, 52 [channel.port2] 53 ); 54 } 55 }; 56 57 checkStatus(); 58 const interval = setInterval(checkStatus, 2000); 59 return () => clearInterval(interval); 60 }, []); 61 62 // Only show in development 63 if (import.meta.env.PROD) { 64 return null; 65 } 66 67 return ( 68 <div style={{ 69 position: 'fixed', 70 bottom: 0, 71 right: 0, 72 backgroundColor: 'rgba(0, 0, 0, 0.8)', 73 color: 'white', 74 padding: '8px', 75 fontSize: '10px', 76 fontFamily: 'monospace', 77 zIndex: 999999, 78 maxWidth: '300px', 79 maxHeight: '200px', 80 overflow: 'auto', 81 }}> 82 <div><strong>Service Worker Debug</strong></div> 83 <div>Ready: {status.ready ? '✓' : '✗'}</div> 84 <div>Controlled: {status.controlled ? '✓' : '✗'}</div> 85 <div>Scope: {status.scope || 'none'}</div> 86 <div>Has Manifest: {status.hasManifest ? '✓' : '✗'}</div> 87 {status.siteInfo && ( 88 <div> 89 <div>DID: {status.siteInfo.did?.substring(0, 20)}...</div> 90 <div>Site: {status.siteInfo.siteName}</div> 91 </div> 92 )} 93 </div> 94 ); 95}