@@ -12,9 +12,10 @@ class NotificationSoundService {
1212 private groupChatSound : Audio . Sound | null = null ;
1313 private defaultSound : Audio . Sound | null = null ;
1414 private isInitialized = false ;
15+ private initializationPromise : Promise < void > | null = null ;
1516
1617 private constructor ( ) {
17- this . initializeAudio ( ) ;
18+ // Initialization will happen lazily on first use
1819 }
1920
2021 static getInstance ( ) : NotificationSoundService {
@@ -29,10 +30,22 @@ class NotificationSoundService {
2930 }
3031
3132 private async initializeAudio ( ) : Promise < void > {
33+ // If already initialized, return immediately
3234 if ( this . isInitialized ) {
3335 return ;
3436 }
3537
38+ // If initialization is in progress, wait for it to complete
39+ if ( this . initializationPromise ) {
40+ return this . initializationPromise ;
41+ }
42+
43+ // Start initialization and store the promise
44+ this . initializationPromise = this . performInitialization ( ) ;
45+ await this . initializationPromise ;
46+ }
47+
48+ private async performInitialization ( ) : Promise < void > {
3649 try {
3750 // Configure audio mode
3851 await Audio . setAudioModeAsync ( {
@@ -60,6 +73,8 @@ class NotificationSoundService {
6073 message : 'Failed to initialize notification sound service' ,
6174 context : { error } ,
6275 } ) ;
76+ // Reset initialization promise on failure so it can be retried
77+ this . initializationPromise = null ;
6378 }
6479 }
6580
@@ -83,40 +98,46 @@ class NotificationSoundService {
8398 }
8499 }
85100
86- private async loadAudioFiles ( ) : Promise < void > {
101+ /**
102+ * Helper method to load a sound asset from a require path
103+ * @param assetRequire - The required asset module
104+ * @param soundName - Name of the sound for logging purposes
105+ * @returns The created Audio.Sound or null on failure
106+ */
107+ private async loadSound ( assetRequire : number , soundName : string ) : Promise < Audio . Sound | null > {
87108 try {
88- // Load call sound
89- const callSoundAsset = Asset . fromModule ( require ( '@assets/audio/newcall.wav' ) ) ;
90- await callSoundAsset . downloadAsync ( ) ;
109+ const asset = Asset . fromModule ( assetRequire ) ;
110+ await asset . downloadAsync ( ) ;
91111
92- const { sound : callSound } = await Audio . Sound . createAsync ( { uri : callSoundAsset . localUri || callSoundAsset . uri } as AVPlaybackSource , {
112+ const { sound } = await Audio . Sound . createAsync ( { uri : asset . localUri || asset . uri } as AVPlaybackSource , {
93113 shouldPlay : false ,
94114 isLooping : false ,
95115 volume : 1.0 ,
96116 } ) ;
97- this . callSound = callSound ;
98-
99- // Load message sound
100- const messageSoundAsset = Asset . fromModule ( require ( '@assets/audio/newmessage.wav' ) ) ;
101- await messageSoundAsset . downloadAsync ( ) ;
102117
103- const { sound : messageSound } = await Audio . Sound . createAsync ( { uri : messageSoundAsset . localUri || messageSoundAsset . uri } as AVPlaybackSource , {
104- shouldPlay : false ,
105- isLooping : false ,
106- volume : 1.0 ,
118+ return sound ;
119+ } catch ( error ) {
120+ logger . error ( {
121+ message : `Failed to load sound: ${ soundName } ` ,
122+ context : { error } ,
107123 } ) ;
108- this . messageSound = messageSound ;
124+ return null ;
125+ }
126+ }
127+
128+ private async loadAudioFiles ( ) : Promise < void > {
129+ try {
130+ // Load call sound
131+ this . callSound = await this . loadSound ( require ( '@assets/audio/newcall.wav' ) , 'call' ) ;
132+
133+ // Load message sound
134+ this . messageSound = await this . loadSound ( require ( '@assets/audio/newmessage.wav' ) , 'message' ) ;
109135
110136 // Load chat sound
111137 const chatSoundAsset = Asset . fromModule ( require ( '@assets/audio/newchat.wav' ) ) ;
112138 await chatSoundAsset . downloadAsync ( ) ;
113139
114- const { sound : chatSound } = await Audio . Sound . createAsync ( { uri : chatSoundAsset . localUri || chatSoundAsset . uri } as AVPlaybackSource , {
115- shouldPlay : false ,
116- isLooping : false ,
117- volume : 1.0 ,
118- } ) ;
119- this . chatSound = chatSound ;
140+ this . chatSound = await this . loadSound ( require ( '@assets/audio/newchat.wav' ) , 'chat' ) ;
120141
121142 // Group chat uses the same sound as regular chat
122143 const { sound : groupChatSound } = await Audio . Sound . createAsync ( { uri : chatSoundAsset . localUri || chatSoundAsset . uri } as AVPlaybackSource , {
@@ -127,15 +148,7 @@ class NotificationSoundService {
127148 this . groupChatSound = groupChatSound ;
128149
129150 // Load default notification sound
130- const defaultSoundAsset = Asset . fromModule ( require ( '@assets/audio/notification.wav' ) ) ;
131- await defaultSoundAsset . downloadAsync ( ) ;
132-
133- const { sound : defaultSound } = await Audio . Sound . createAsync ( { uri : defaultSoundAsset . localUri || defaultSoundAsset . uri } as AVPlaybackSource , {
134- shouldPlay : false ,
135- isLooping : false ,
136- volume : 1.0 ,
137- } ) ;
138- this . defaultSound = defaultSound ;
151+ this . defaultSound = await this . loadSound ( require ( '@assets/audio/notification.wav' ) , 'default' ) ;
139152
140153 logger . debug ( {
141154 message : 'Notification audio files loaded successfully' ,
@@ -235,6 +248,7 @@ class NotificationSoundService {
235248 }
236249
237250 this . isInitialized = false ;
251+ this . initializationPromise = null ;
238252
239253 logger . info ( {
240254 message : 'Notification sound service cleaned up' ,
0 commit comments