@@ -29,8 +29,66 @@ export function NavUser({
2929 unread_notifications_count : number
3030 }
3131} ) {
32+ // Play iOS-inspired notification sound using Web Audio API
33+ const playNotificationSound = ( ) => {
34+ const ctx = new window . AudioContext ( )
35+ const masterGain = ctx . createGain ( )
36+ masterGain . gain . setValueAtTime ( 0.2 , ctx . currentTime )
37+ masterGain . connect ( ctx . destination )
38+
39+ // iOS "Tri-tone" inspired melody with bell-like harmonics
40+ const fundamentalNotes = [
41+ { freq : 659.25 , time : 0.0 , duration : 0.35 } , // E5
42+ { freq : 783.99 , time : 0.1 , duration : 0.35 } , // G5
43+ { freq : 1046.5 , time : 0.2 , duration : 0.4 } , // C6
44+ ]
45+
46+ fundamentalNotes . forEach ( ( { freq, time, duration } ) => {
47+ // Main tone
48+ const osc1 = ctx . createOscillator ( )
49+ const gain1 = ctx . createGain ( )
50+ osc1 . type = 'sine'
51+ osc1 . frequency . setValueAtTime ( freq , ctx . currentTime + time )
52+ gain1 . gain . setValueAtTime ( 0.4 , ctx . currentTime + time )
53+ gain1 . gain . exponentialRampToValueAtTime (
54+ 0.01 ,
55+ ctx . currentTime + time + duration
56+ )
57+ osc1 . connect ( gain1 )
58+ gain1 . connect ( masterGain )
59+ osc1 . start ( ctx . currentTime + time )
60+ osc1 . stop ( ctx . currentTime + time + duration )
61+
62+ // Harmonic (octave higher for bell-like quality)
63+ const osc2 = ctx . createOscillator ( )
64+ const gain2 = ctx . createGain ( )
65+ osc2 . type = 'triangle'
66+ osc2 . frequency . setValueAtTime ( freq * 2 , ctx . currentTime + time )
67+ gain2 . gain . setValueAtTime ( 0.15 , ctx . currentTime + time )
68+ gain2 . gain . exponentialRampToValueAtTime (
69+ 0.001 ,
70+ ctx . currentTime + time + duration * 0.7
71+ )
72+ osc2 . connect ( gain2 )
73+ gain2 . connect ( masterGain )
74+ osc2 . start ( ctx . currentTime + time )
75+ osc2 . stop ( ctx . currentTime + time + duration * 0.7 )
76+
77+ // Cleanup oscillators
78+ osc1 . onended = ( ) => osc1 . disconnect ( )
79+ osc2 . onended = ( ) => osc2 . disconnect ( )
80+ } )
81+
82+ // Close audio context after sound completes
83+ setTimeout ( ( ) => {
84+ masterGain . disconnect ( )
85+ ctx . close ( )
86+ } , 800 )
87+ }
88+
3289 useEffect ( ( ) => {
3390 function onMessage ( data : Notification ) {
91+ playNotificationSound ( )
3492 toast . info ( data . title , {
3593 description : data . message ,
3694 } )
0 commit comments