Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/all/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"devDependencies": {
"puppeteer": "^24.0.0",
"typescript": "^4.7.3",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^2.1.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/packer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
],
"devDependencies": {
"typescript": "^4.7.3",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^2.1.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/record/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"devDependencies": {
"puppeteer": "^24.0.0",
"typescript": "^4.7.3",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^2.1.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/replay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"devDependencies": {
"puppeteer": "^24.0.0",
"typescript": "^4.7.3",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^2.1.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/rrdom-nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"eslint": "^8.15.0",
"puppeteer": "^24.0.0",
"typescript": "^4.7.3",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^2.1.9"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/rrdom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"eslint": "^8.15.0",
"puppeteer": "^24.0.0",
"typescript": "^4.9.0",
"vite": "^6.4.1",
"vite": "^6.4.2",
"vite-plugin-dts": "^4.5.4"
},
"dependencies": {
Expand Down
11 changes: 4 additions & 7 deletions packages/rrweb-player/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
"version": "2.41.0",
"devDependencies": {
"@sentry-internal/rrweb-types": "2.41.0",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/package": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint-plugin-svelte": "^2.37.0",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.14",
"svelte-check": "^3.4.3",
"svelte-preprocess": "^5.0.3",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"svelte2tsx": "^0.7.6",
"tslib": "^2.0.0",
"vite": "^5.2.8"
"vite": "^6.4.2"
},
"dependencies": {
"@sentry-internal/rrweb": "2.41.0",
Expand Down
121 changes: 69 additions & 52 deletions packages/rrweb-player/src/Controller.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,49 @@
import {
onMount,
onDestroy,
createEventDispatcher,
afterUpdate,
} from 'svelte';
import { formatTime, getInactivePeriods } from './utils';
import Switch from './components/Switch.svelte';

const dispatch = createEventDispatcher();

export let replayer: Replayer;
export let showController: boolean;
export let autoPlay: boolean;
export let skipInactive: boolean;
export let speedOption: number[];
export let speed = speedOption.length ? speedOption[0] : 1;
export let tags: Record<string, string> = {};
export let inactiveColor: string;

let currentTime = 0;
$: {
dispatch('ui-update-current-time', { payload: currentTime });
}
let {
replayer,
showController,
autoPlay,
skipInactive = $bindable(),
speedOption,
speed = $bindable(speedOption.length ? speedOption[0] : 1),
tags = {},
inactiveColor,
onfullscreen,
onuiupdatecurrenttime,
onuiupdateprogress,
onuiupdateplayerstate,
}: {
replayer: Replayer;
showController: boolean;
autoPlay: boolean;
skipInactive: boolean;
speedOption: number[];
speed?: number;
tags?: Record<string, string>;
inactiveColor: string;
onfullscreen?: () => void;
onuiupdatecurrenttime?: (payload: { payload: number }) => void;
onuiupdateprogress?: (payload: { payload: number }) => void;
onuiupdateplayerstate?: (payload: { payload: string }) => void;
} = $props();

let currentTime = $state(0);
$effect(() => {
onuiupdatecurrenttime?.({ payload: currentTime });
});
let timer: number | null = null;
let playerState: 'playing' | 'paused' | 'live';
$: {
dispatch('ui-update-player-state', { payload: playerState });
}
let speedState: 'normal' | 'skipping';
let progress: HTMLElement;
let playerState = $state<'playing' | 'paused' | 'live'>('paused');
$effect(() => {
onuiupdateplayerstate?.({ payload: playerState });
});
Comment thread
chargome marked this conversation as resolved.
let speedState = $state<'normal' | 'skipping'>('normal');
let progress = $state<HTMLElement>() as HTMLElement;
let finished: boolean;

let pauseAt: number | false = false;
Expand All @@ -46,14 +61,13 @@
end: number;
} | null = null;

let meta: playerMetaData;
$: meta = replayer.getMetaData();
let percentage: string;
$: {
const percent = Math.min(1, currentTime / meta.totalTime);
percentage = `${100 * percent}%`;
dispatch('ui-update-progress', { payload: percent });
}
let meta = $state<playerMetaData>(replayer.getMetaData());
let progressPercent = $derived(Math.min(1, currentTime / meta.totalTime));
let percentage = $derived(`${100 * progressPercent}%`);
$effect(() => {
onuiupdateprogress?.({ payload: progressPercent });
});
Comment thread
cursor[bot] marked this conversation as resolved.

type CustomEvent = {
name: string;
background: string;
Expand All @@ -74,8 +88,7 @@
return eventPosition.toFixed(2);
}

let customEvents: CustomEvent[];
$: customEvents = (() => {
let customEvents: CustomEvent[] = $derived.by(() => {
const { context } = replayer.service.state;
const totalEvents = context.events.length;
const start = context.events[0].timestamp;
Expand All @@ -99,15 +112,14 @@
});

return customEvents;
})();
});

let inactivePeriods: {
name: string;
background: string;
position: string;
width: string;
}[];
$: inactivePeriods = (() => {
}[] = $derived.by(() => {
try {
const { context } = replayer.service.state;
const totalEvents = context.events.length;
Expand Down Expand Up @@ -136,7 +148,7 @@
// For safety concern, if there is any error, the main function won't be affected.
return [];
}
})();
});

const loopTimer = () => {
stopTimer();
Expand Down Expand Up @@ -253,7 +265,7 @@
goto(timeOffset);
};

const handleProgressKeydown = (event: KeyboardEvent) => {
const handleProgressKeydown = (event: KeyboardEvent) => {
if (speedState === 'skipping') {
return;
}
Expand Down Expand Up @@ -287,14 +299,14 @@
};

onMount(() => {
playerState = replayer.service.state.value;
speedState = replayer.speedService.state.value;
playerState = replayer.service.state.value as typeof playerState;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: why do we need the type casts here (and below)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast narrows string down to the expected union type.

speedState = replayer.speedService.state.value as typeof speedState;
replayer.on(
'state-change',
(states) => {
const { player, speed } = states as { player?: PlayerMachineState; speed?: SpeedMachineState };
if (player?.value && playerState !== player.value) {
playerState = player.value;
playerState = player.value as typeof playerState;
switch (playerState) {
case 'playing':
loopTimer();
Expand All @@ -307,7 +319,7 @@
}
}
if (speed?.value && speedState !== speed.value) {
speedState = speed.value;
speedState = speed.value as typeof speedState;
}
},
);
Expand All @@ -324,7 +336,7 @@
}
});

afterUpdate(() => {
$effect(() => {
if (skipInactive !== replayer.config.skipInactive) {
replayer.setConfig({ skipInactive });
}
Expand Down Expand Up @@ -437,35 +449,40 @@
class="rr-progress"
class:disabled={speedState === 'skipping'}
bind:this={progress}
on:click={handleProgressClick}
on:keydown={handleProgressKeydown}
onclick={handleProgressClick}
onkeydown={handleProgressKeydown}
role="slider"
tabindex="0"
aria-valuenow={currentTime}
aria-valuemin={0}
aria-valuemax={meta.totalTime}
>
<div
class="rr-progress__step"
style="width: {percentage}"
/>
></div>
{#each inactivePeriods as period}
<div
title={period.name}
style="width: {period.width};height: 4px;position: absolute;background: {period.background};left:
{period.position};"
/>
></div>
{/each}
{#each customEvents as event}
<div
title={event.name}
style="width: 10px;height: 5px;position: absolute;top:
2px;transform: translate(-50%, -50%);background: {event.background};left:
{event.position};"
/>
></div>
{/each}

<div class="rr-progress__handler" style="left: {percentage}" />
<div class="rr-progress__handler" style="left: {percentage}"></div>
</div>
<span class="rr-timeline__time">{formatTime(meta.totalTime)}</span>
</div>
<div class="rr-controller__btns">
<button on:click={toggle}>
<button onclick={toggle}>
{#if playerState === 'playing'}
<svg
class="icon"
Expand Down Expand Up @@ -513,7 +530,7 @@
{#each speedOption as s}
<button
class:active={s === speed && speedState !== 'skipping'}
on:click={() => setSpeed(s)}
onclick={() => setSpeed(s)}
disabled={speedState === 'skipping'}
>
{s}x
Expand All @@ -525,7 +542,7 @@
disabled={speedState === 'skipping'}
label="skip inactive"
/>
<button on:click={() => dispatch('fullscreen')}>
<button aria-label="fullscreen" onclick={() => onfullscreen?.()}>
<svg
class="icon"
viewBox="0 0 1024 1024"
Expand Down
Loading
Loading