A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: better handling of removal of playing audio

+26 -26
+26 -26
src/component/engine/audio/element.js
··· 92 92 if (!audio.isConnected) return; 93 93 94 94 const promise = audio.play() || Promise.resolve(); 95 - item.state = { isPlaying: true }; 95 + item.state({ isPlaying: true }); 96 96 97 97 promise.catch((e) => { 98 98 if (!audio.isConnected) { ··· 101 101 const err = 102 102 "Couldn't play audio automatically. Please resume playback manually."; 103 103 console.error(err, e); 104 - item.state = { isPlaying: false }; 104 + item.state({ isPlaying: false }); 105 105 }); 106 106 }); 107 107 } ··· 202 202 203 203 if (node) { 204 204 const item = /** @type {AudioEngineItem} */ (node); 205 - fn(item.audio, item); 205 + if (item) fn(item.audio, item); 206 206 } 207 207 } 208 208 } ··· 260 260 get engine() { 261 261 const el = this.closest("de-audio"); 262 262 if (el) return /** @type {AudioEngine} */ (el); 263 - else throw new Error("Cannot find parent de-audio element"); 263 + else return null; 264 264 } 265 265 266 266 // STATE 267 267 268 - get state() { 269 - return { ...this.#state }; 270 - } 271 - 272 268 /** 273 - * @param {Partial<AudioState>} s 269 + * @param {Partial<AudioState> | undefined} [s] 274 270 */ 275 - set state(s) { 276 - this.#state = { ...this.#state, ...s }; 271 + state(s) { 272 + if (s) this.#state = { ...this.#state, ...s }; 273 + else return { ...this.#state }; 277 274 } 278 275 279 276 // EVENTS ··· 286 283 const item = engineItem(audio); 287 284 288 285 if ( 289 - item.hasAttribute("initial-progress") && 286 + item?.hasAttribute("initial-progress") && 290 287 audio.duration && 291 288 !isNaN(audio.duration) 292 289 ) { ··· 307 304 const audio = /** @type {HTMLAudioElement} */ (event.target); 308 305 309 306 if (!isNaN(audio.duration)) { 310 - engineItem(audio).state = { duration: audio.duration }; 307 + engineItem(audio)?.state({ duration: audio.duration }); 311 308 } 312 309 } 313 310 ··· 318 315 const audio = /** @type {HTMLAudioElement} */ (event.target); 319 316 audio.currentTime = 0; 320 317 321 - engineItem(audio).state = { hasEnded: true }; 318 + engineItem(audio)?.state({ hasEnded: true }); 322 319 } 323 320 324 321 /** ··· 328 325 const audio = /** @type {HTMLAudioElement} */ (event.target); 329 326 const code = audio.error?.code || 0; 330 327 331 - engineItem(audio).state = { loadingState: { error: { code } } }; 328 + engineItem(audio)?.state({ loadingState: { error: { code } } }); 332 329 } 333 330 334 331 /** ··· 337 334 pauseEvent(event) { 338 335 const audio = /** @type {HTMLAudioElement} */ (event.target); 339 336 340 - const item = engineItem(audio).state; 341 - const ended = item ? item.hasEnded || item.progress === 1 : false; 337 + const item = engineItem(audio); 338 + const itemState = item?.state(); 339 + const ended = itemState 340 + ? itemState.hasEnded || itemState.progress === 1 341 + : false; 342 342 343 - engineItem(audio).state = { isPlaying: false }; 344 - engineItem(audio).engine.isPlaying(ended); 343 + item?.state({ isPlaying: false }); 344 + item?.engine?.isPlaying(ended); 345 345 } 346 346 347 347 /** ··· 350 350 playEvent(event) { 351 351 const audio = /** @type {HTMLAudioElement} */ (event.target); 352 352 353 - engineItem(audio).state = { isPlaying: true }; 354 - engineItem(audio).engine.isPlaying(true); 353 + engineItem(audio)?.state({ isPlaying: true }); 354 + engineItem(audio)?.engine?.isPlaying(true); 355 355 356 356 // In case audio was preloaded: 357 357 if (audio.readyState === 4) finishedLoading(event); ··· 370 370 timeupdateEvent(event) { 371 371 const audio = /** @type {HTMLAudioElement} */ (event.target); 372 372 373 - engineItem(audio).state = { 373 + engineItem(audio)?.state({ 374 374 progress: isNaN(audio.duration) || audio.duration === 0 375 375 ? 0 376 376 : audio.currentTime / audio.duration, 377 - }; 377 + }); 378 378 } 379 379 380 380 /** ··· 397 397 function engineItem(audio) { 398 398 const c = audio.closest("de-audio-item"); 399 399 if (c) return /** @type {AudioEngineItem} */ (c); 400 - else throw new Error("Cannot find parent de-audio-item element"); 400 + else return null; 401 401 } 402 402 403 403 /** ··· 405 405 */ 406 406 function finishedLoading(event) { 407 407 const audio = /** @type {HTMLAudioElement} */ (event.target); 408 - engineItem(audio).state = { loadingState: "loaded" }; 408 + engineItem(audio)?.state({ loadingState: "loaded" }); 409 409 } 410 410 411 411 /** ··· 414 414 function initiateLoading(event) { 415 415 const audio = /** @type {HTMLAudioElement} */ (event.target); 416 416 if (audio.readyState < 4) { 417 - engineItem(audio).state = { loadingState: "loading" }; 417 + engineItem(audio)?.state({ loadingState: "loading" }); 418 418 } 419 419 } 420 420