diff --git a/src/hooks/useNotifications.ts b/src/hooks/useNotifications.ts index 67c3e94..58b3e9d 100644 --- a/src/hooks/useNotifications.ts +++ b/src/hooks/useNotifications.ts @@ -58,6 +58,36 @@ export function useNotifications(reminderSettings: ReminderSettings) { [isSupported, permission] ); + // Play a "bubble pop" sound using Web Audio API + const playNotificationSound = useCallback(() => { + try { + const AudioContext = window.AudioContext || (window as any).webkitAudioContext; + if (!AudioContext) return; + + const ctx = new AudioContext(); + const oscillator = ctx.createOscillator(); + const gainNode = ctx.createGain(); + + oscillator.connect(gainNode); + gainNode.connect(ctx.destination); + + // Bubble 'pop' effect: sine wave with rapid frequency drop + oscillator.type = 'sine'; + oscillator.frequency.setValueAtTime(800, ctx.currentTime); + oscillator.frequency.exponentialRampToValueAtTime(100, ctx.currentTime + 0.1); + + // Envelope: quick attack, quick decay + gainNode.gain.setValueAtTime(0, ctx.currentTime); + gainNode.gain.linearRampToValueAtTime(0.3, ctx.currentTime + 0.01); + gainNode.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.1); + + oscillator.start(); + oscillator.stop(ctx.currentTime + 0.15); + } catch (e) { + console.error('Error playing notification sound:', e); + } + }, []); + // Check and send daily reminder const checkAndSendReminder = useCallback(() => { if (!reminderSettings.enabled || permission !== 'granted') return; @@ -74,6 +104,7 @@ export function useNotifications(reminderSettings: ReminderSettings) { // If current time is past the reminder time, send it if (now >= reminderTime) { + playNotificationSound(); sendNotification('QuitTraq Reminder', { body: "Time to log your daily usage! Every day counts on your journey.", tag: 'daily-reminder', // Tag ensures we don't stack multiple notifications @@ -81,7 +112,7 @@ export function useNotifications(reminderSettings: ReminderSettings) { }); localStorage.setItem(LAST_NOTIFICATION_KEY, today); } - }, [reminderSettings, permission, sendNotification]); + }, [reminderSettings, permission, sendNotification, playNotificationSound]); // Set up interval to check for reminder time useEffect(() => {