Files
hyperframes/packages/studio/src/hooks/useThumbnailLease.ts
T
Miguel ÁngelandCodex 96861cbafc perf(studio-server): coordinate cancelable thumbnail generation (#2720)
* perf(studio): schedule adaptive timeline thumbnails

* perf(studio): bound thumbnail decoding resources

* perf(studio): virtualize timeline thumbnail media

* perf(studio): prioritize timeline thumbnail work

* perf(studio-server): coordinate cancelable thumbnail generation

---------

Co-authored-by: Codex <codex@local>
2026-08-05 20:41:35 -07:00

45 lines
1.5 KiB
TypeScript

import { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from "react";
import {
createThumbnailRequestIdentity,
thumbnailScheduler,
type ThumbnailRequest,
type ThumbnailScheduler,
type ThumbnailSnapshot,
} from "../player/lib/thumbnailScheduler";
const IDLE: ThumbnailSnapshot = Object.freeze({ status: "idle" });
export function useThumbnailLease(
request: ThumbnailRequest | null,
scheduler: ThumbnailScheduler = thumbnailScheduler,
): ThumbnailSnapshot {
const requestRef = useRef(request);
requestRef.current = request;
const leaseRef = useRef<ReturnType<ThumbnailScheduler["acquire"]> | null>(null);
const identity = request ? createThumbnailRequestIdentity(request) : null;
const priority = request?.priority;
const subscribe = useCallback(
(listener: () => void) => {
const current = requestRef.current;
if (!current || identity === null) return () => {};
const lease = scheduler.acquire(current, listener);
leaseRef.current = lease;
return () => {
if (leaseRef.current === lease) leaseRef.current = null;
lease.release();
};
},
[identity, scheduler],
);
const getSnapshot = useCallback(() => {
const current = requestRef.current;
return current && identity !== null ? scheduler.getSnapshot(current) : IDLE;
}, [identity, scheduler]);
useLayoutEffect(() => {
if (priority) leaseRef.current?.updatePriority(priority);
}, [priority]);
return useSyncExternalStore(subscribe, getSnapshot, () => IDLE);
}