@@ -10,18 +10,22 @@ import GlobalSearch from "./GlobalSearch"
1010import { useGlobalShortcuts } from "@hooks/useGlobalShortcuts"
1111import { cn } from "@utils/cn"
1212import toast from "react-hot-toast"
13+ import { subscribeUser } from "@app/actions"
1314
1415// Helper function to convert VAPID key
1516function urlBase64ToUint8Array ( base64String ) {
16- const padding = "=" . repeat ( ( 4 - ( base64String . length % 4 ) ) % 4 ) ;
17- const base64 = ( base64String + padding ) . replace ( / - / g, "+" ) . replace ( / _ / g, "/" ) ;
18- const rawData = window . atob ( base64 ) ;
19- const outputArray = new Uint8Array ( rawData . length ) ;
17+ const padding = "=" . repeat ( ( 4 - ( base64String . length % 4 ) ) % 4 )
18+ const base64 = ( base64String + padding )
19+ . replace ( / - / g, "+" )
20+ . replace ( / _ / g, "/" )
21+ const rawData = atob ( base64 )
22+ const outputArray = new Uint8Array ( rawData . length )
2023 for ( let i = 0 ; i < rawData . length ; ++ i ) {
21- outputArray [ i ] = rawData . charCodeAt ( i ) ;
24+ outputArray [ i ] = rawData . charCodeAt ( i )
2225 }
23- return outputArray ;
26+ return outputArray
2427}
28+
2529export default function LayoutWrapper ( { children } ) {
2630 const [ isNotificationsOpen , setNotificationsOpen ] = useState ( false )
2731 const [ isSearchOpen , setSearchOpen ] = useState ( false )
@@ -189,11 +193,9 @@ export default function LayoutWrapper({ children }) {
189193 // PWA Update Handler
190194
191195 useEffect ( ( ) => {
192- // This effect runs only on the client side, after the component mounts.
193- if (
194- "serviceWorker" in navigator &&
195- process . env . NODE_ENV !== "development"
196- ) {
196+ // This effect runs only on the client side to register the service worker.
197+ // It's enabled for all environments to allow testing in development.
198+ if ( "serviceWorker" in navigator ) {
197199 // The 'load' event ensures that SW registration doesn't delay page rendering.
198200 window . addEventListener ( "load" , function ( ) {
199201 navigator . serviceWorker . register ( "/sw.js" ) . then (
@@ -265,73 +267,51 @@ export default function LayoutWrapper({ children }) {
265267 }
266268 } , [ ] )
267269
268- useEffect ( ( ) => {
269- // This effect runs only on the client side, after the component mounts.
270- if (
271- "serviceWorker" in navigator &&
272- process . env . NODE_ENV === "production"
273- ) {
274- // The 'load' event ensures that SW registration doesn't delay page rendering.
275- window . addEventListener ( "load" , function ( ) {
276- navigator . serviceWorker . register ( "/sw.js" ) . then (
277- function ( registration ) {
278- console . log (
279- "ServiceWorker registration successful with scope: " ,
280- registration . scope
281- )
282- } ,
283- function ( err ) {
284- console . log ( "ServiceWorker registration failed: " , err )
285- }
286- )
287- } )
288- }
289- } , [ ] )
290-
291270 const subscribeToPushNotifications = useCallback ( async ( ) => {
292- if ( ! ( "serviceWorker" in navigator ) || ! ( "PushManager" in window ) ) return ;
271+ if ( ! ( "serviceWorker" in navigator ) || ! ( "PushManager" in window ) ) {
272+ console . log ( "Push notifications not supported by this browser." )
273+ return
274+ }
293275 if ( ! process . env . NEXT_PUBLIC_VAPID_PUBLIC_KEY ) {
294- console . warn ( "VAPID public key not configured. Skipping push subscription." ) ;
295- return ;
276+ console . warn (
277+ "VAPID public key not configured. Skipping push subscription."
278+ )
279+ return
296280 }
297- console . log ( "VAPID Public Key is configured. Proceeding with push subscription." ) ;
298281
299282 try {
300- const registration = await navigator . serviceWorker . ready ;
301- console . log ( "Service Worker is ready:" , registration ) ;
302-
303- let subscription = await registration . pushManager . getSubscription ( ) ;
304- console . log ( "Existing subscription:" , subscription ) ;
283+ const registration = await navigator . serviceWorker . ready
284+ let subscription = await registration . pushManager . getSubscription ( )
305285
306286 if ( subscription === null ) {
307- console . log ( "No existing subscription found. Requesting permission..." ) ;
308- const permission = await window . Notification . requestPermission ( ) ;
309- console . log ( "Notification permission status:" , permission ) ;
287+ const permission = await window . Notification . requestPermission ( )
288+ if ( permission !== "granted" ) {
289+ console . log ( "Notification permission not granted." )
290+ return
291+ }
310292
311- if ( permission !== "granted" ) return ;
293+ console . log ( "Permission granted. Subscribing..." )
294+ const applicationServerKey = urlBase64ToUint8Array (
295+ process . env . NEXT_PUBLIC_VAPID_PUBLIC_KEY
296+ )
312297
313- console . log ( "Permission granted. Subscribing to push manager..." ) ;
314298 subscription = await registration . pushManager . subscribe ( {
315299 userVisibleOnly : true ,
316- applicationServerKey : urlBase64ToUint8Array ( process . env . NEXT_PUBLIC_VAPID_PUBLIC_KEY ) ,
317- } ) ;
318- console . log ( "New subscription created:" , subscription ) ;
319-
320- const response = await fetch ( "/api/notifications/subscribe" , {
321- method : "POST" ,
322- headers : { "Content-Type" : "application/json" } ,
323- body : JSON . stringify ( subscription ) ,
324- } ) ;
325-
326- if ( ! response . ok ) {
327- throw new Error ( "Failed to send subscription to server." ) ;
328- }
329- console . log ( "Subscription successfully sent to server." ) ;
300+ applicationServerKey
301+ } )
302+
303+ console . log ( "New subscription created:" , subscription )
304+ const serializedSub = JSON . parse ( JSON . stringify ( subscription ) )
305+ await subscribeUser ( serializedSub )
306+ toast . success ( "Subscribed to push notifications!" )
307+ } else {
308+ console . log ( "User is already subscribed." )
330309 }
331310 } catch ( error ) {
332- console . error ( "Error during push notification subscription:" , error ) ;
311+ console . error ( "Error during push notification subscription:" , error )
312+ toast . error ( "Failed to subscribe to push notifications." )
333313 }
334- } , [ ] ) ;
314+ } , [ ] )
335315
336316 useEffect ( ( ) => {
337317 if ( showNav && userDetails ?. sub ) subscribeToPushNotifications ( )
@@ -406,4 +386,3 @@ export default function LayoutWrapper({ children }) {
406386 </ >
407387 )
408388}
409-
0 commit comments