diff --git a/packages/rrweb-player/src/Controller.svelte b/packages/rrweb-player/src/Controller.svelte index f183e7d66e..61c3d56ac1 100644 --- a/packages/rrweb-player/src/Controller.svelte +++ b/packages/rrweb-player/src/Controller.svelte @@ -39,6 +39,13 @@ let step: HTMLElement; let finished: boolean; + let pauseAt: number | false = false; + let onPauseHook: () => unknown | undefined = undefined; + let loop: { + start: number; + end: number; + } | null = null; + let meta: playerMetaData; $: meta = replayer.getMetaData(); let percentage: string; @@ -94,6 +101,18 @@ function update() { currentTime = replayer.getCurrentTime(); + if (pauseAt && currentTime >= pauseAt) { + if (loop) { + playRange(loop.start, loop.end, true, undefined); + } else { + replayer.pause(); + if (onPauseHook) { + onPauseHook(); + onPauseHook = null; + } + } + } + if (currentTime < meta.totalTime) { timer = requestAnimationFrame(update); } @@ -139,10 +158,12 @@ return; } replayer.pause(); + pauseAt = false; }; export const goto = (timeOffset: number, play?: boolean) => { currentTime = timeOffset; + pauseAt = false; const resumePlaying = typeof play === 'boolean' ? play : playerState === 'playing'; if (resumePlaying) { @@ -152,6 +173,27 @@ } }; + export const playRange = ( + timeOffset: number, + endTimeOffset: number, + startLooping: boolean = false, + afterHook: undefined | (() => void) = undefined, + ) => { + if (startLooping) { + loop = { + start: timeOffset, + end: endTimeOffset, + }; + } else { + loop = null; + } + currentTime = timeOffset; + pauseAt = endTimeOffset; + onPauseHook = afterHook; + replayer.play(timeOffset); + }; + + const handleProgressClick = (event: MouseEvent) => { if (speedState === 'skipping') { return; @@ -218,6 +260,10 @@ ); replayer.on('finish', () => { finished = true; + if (onPauseHook) { + onPauseHook(); + onPauseHook = null; + } }); if (autoPlay) { diff --git a/packages/rrweb-player/src/Player.svelte b/packages/rrweb-player/src/Player.svelte index bb2f4b6c87..86c8f702eb 100644 --- a/packages/rrweb-player/src/Player.svelte +++ b/packages/rrweb-player/src/Player.svelte @@ -114,6 +114,14 @@ export const goto = (timeOffset: number, play?: boolean) => { controller.goto(timeOffset, play); }; + export const playRange = ( + timeOffset: number, + endTimeOffset: number, + startLooping: boolean = false, + afterHook: undefined | (() => void) = undefined, + ) => { + controller.playRange(timeOffset, endTimeOffset, startLooping, afterHook); + }; onMount(() => { // runtime type check