MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / SessionPlayer

Function SessionPlayer

e2e/viewer/src/SessionPlayer.tsx:61–434  ·  view source on GitHub ↗
({
  castUrl,
  videoUrl,
  timeline,
  traces,
  playwrightTraceUrl,
  motelViewer,
}: {
  castUrl: string;
  videoUrl: string;
  timeline: SessionTimeline;
  traces: SessionTraceRef[];
  playwrightTraceUrl: string | null;
  motelViewer: string;
})

Source from the content-addressed store, hash-verified

59};
60
61export const SessionPlayer = ({
62 castUrl,
63 videoUrl,
64 timeline,
65 traces,
66 playwrightTraceUrl,
67 motelViewer,
68}: {
69 castUrl: string;
70 videoUrl: string;
71 timeline: SessionTimeline;
72 traces: SessionTraceRef[];
73 playwrightTraceUrl: string | null;
74 motelViewer: string;
75}) => {
76 const sessionStart = timeline.focus[0]?.at ?? 0;
77 const terminalAnchor = timeline.anchors.terminal ?? sessionStart;
78 const browserAnchor = timeline.anchors.browser ?? sessionStart;
79
80 const castMount = useRef<HTMLDivElement>(null);
81 const videoRef = useRef<HTMLVideoElement>(null);
82 const castPlayer = useRef<CastPlayer | null>(null);
83 // Session-time playhead the tick reads/writes without re-subscribing.
84 const tRef = useRef(0);
85
86 const [castDuration, setCastDuration] = useState<number | null>(null);
87 const [videoDuration, setVideoDuration] = useState<number | null>(null);
88 const [t, setT] = useState(0);
89 const [playing, setPlaying] = useState(false);
90
91 // Acts: each focus entry runs until the next one; the last runs until its
92 // recording's end (anchored back into session time).
93 const acts = useMemo<Act[]>(() => {
94 const toSession = (wall: number) => (wall - sessionStart) / 1000;
95 return timeline.focus.map((entry, index) => {
96 const next = timeline.focus[index + 1];
97 let to = Infinity;
98 if (next) {
99 to = toSession(next.at);
100 } else if (entry.window === "terminal" && castDuration !== null) {
101 to = toSession(terminalAnchor + castDuration * 1000);
102 } else if (entry.window === "browser" && videoDuration !== null) {
103 to = toSession(browserAnchor + videoDuration * 1000);
104 }
105 return { window: entry.window, from: toSession(entry.at), to };
106 });
107 }, [timeline, sessionStart, terminalAnchor, browserAnchor, castDuration, videoDuration]);
108
109 const duration = acts.at(-1)?.to ?? 0;
110 const ready = castDuration !== null && videoDuration !== null && Number.isFinite(duration);
111
112 const actAt = (time: number): number => {
113 for (let i = acts.length - 1; i >= 0; i -= 1) {
114 const act = acts[i];
115 if (act && time >= act.from - 0.001) return i;
116 }
117 return 0;
118 };

Callers

nothing calls this directly

Calls 9

toSessionFunction · 0.85
actAtFunction · 0.85
fetchCastDurationFunction · 0.85
seekToFunction · 0.85
disposeMethod · 0.80
getCurrentTimeMethod · 0.80
applyFunction · 0.70
fmtFunction · 0.70
replaceMethod · 0.65

Tested by

no test coverage detected