fix: add media listeners immediately when using `bind:paused` (#13502)

Fix a bug where play/pause events may never be added to the media element. Also simplifies the logic by making it an effect instead of a render effect

---------

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/13529/head
Rich Harris 5 days ago committed by GitHub
parent 14ecedf33b
commit c6af26ffd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: add media listeners immediately when using `bind:paused`

@ -138,33 +138,22 @@ export function bind_playback_rate(media, get, set = get) {
* @param {(paused: boolean) => void} set * @param {(paused: boolean) => void} set
*/ */
export function bind_paused(media, get, set = get) { export function bind_paused(media, get, set = get) {
var mounted = hydrating;
var paused = get(); var paused = get();
var callback = () => { var update = () => {
if (paused !== media.paused) { if (paused !== media.paused) {
paused = media.paused;
set((paused = media.paused)); set((paused = media.paused));
} }
}; };
if (paused == null) {
callback();
}
// Defer listening if not mounted yet so that the first canplay event doesn't cause a potentially wrong update
if (mounted) {
// If someone switches the src while media is playing, the player will pause. // If someone switches the src while media is playing, the player will pause.
// Listen to the canplay event to get notified of this situation. // Listen to the canplay event to get notified of this situation.
listen(media, ['play', 'pause', 'canplay'], callback, false); listen(media, ['play', 'pause', 'canplay'], update, paused == null);
}
render_effect(() => {
paused = !!get();
if (paused !== media.paused) { // Needs to be an effect to ensure media element is mounted: else, if paused is `false` (i.e. should play right away)
var toggle = () => { // a "The play() request was interrupted by a new load request" error would be thrown because the resource isn't loaded yet.
mounted = true; effect(() => {
if ((paused = !!get()) !== media.paused) {
if (paused) { if (paused) {
media.pause(); media.pause();
} else { } else {
@ -172,23 +161,6 @@ export function bind_paused(media, get, set = get) {
set((paused = true)); set((paused = true));
}); });
} }
};
if (mounted) {
toggle();
} else {
// If this is the first invocation in dom mode, the media element isn't mounted yet,
// and therefore its resource isn't loaded yet. We need to wait for the canplay event
// in this case or else we'll get a "The play() request was interrupted by a new load request" error.
media.addEventListener(
'canplay',
() => {
listen(media, ['play', 'pause', 'canplay'], callback, false);
toggle();
},
{ once: true }
);
}
} }
}); });
} }

Loading…
Cancel
Save