fix(player): related marks survive, Restart restarts, and refused pages offer nothing to click

- Every state and Watch-later write goes through features/video/videoWrites,
  which marks the never-refetched lists (related lists, live searches) once
  the server has it; a contract test holds it. The Notification Center's
  undo, the feed's reset and the Watch-later toggles skipped it before.
- Confirmed marks are also kept apart (qk.videoMarks) and laid over the
  related rows: a Show more page landing later rebuilt them from the pages
  it read when it started, and dropped a mark made meanwhile.
- Restart on a related video starts at 0 (the session's stored position
  won before), and on the one already playing it seeks.
- The watched toggle remembers each video's mark: Back showed the opened
  video's launch-time state after a related one was marked.
- The help sheet leaves out the player's keys while a layer above it has
  them waiting.
- After a refusal a retry cannot answer, neither Show more (related) nor
  Load more (live search) is offered; a failed live-search page keeps the
  results already read and says why under them.
- The related cap message counts requests, as the cap does.
This commit is contained in:
2026-10-25 02:50:34 +02:00
parent ed51f5be7e
commit 4b5b66343d
26 changed files with 667 additions and 93 deletions
+7 -1
View File
@@ -339,6 +339,7 @@ function playerTimes(p: YTPlayer | null): { cur: number; dur: number } | null {
export function useYtProgress({
activeId,
resumeAt,
exactStart,
mountRef,
playerRef,
currentIdRef,
@@ -355,6 +356,8 @@ export function useYtProgress({
}: {
activeId: string;
resumeAt: number;
// `resumeAt` is where the user asked to start, so it beats a position this session stored.
exactStart: boolean;
mountRef: RefObject<HTMLDivElement | null>;
playerRef: RefObject<YTPlayer | null>;
currentIdRef: RefObject<string>;
@@ -378,6 +381,7 @@ export function useYtProgress({
// the end of the effect).
const itemSnapshot = useEffectEvent(() => ({
resumeAt,
exactStart,
setWatched,
setPlayerError,
setLiveData,
@@ -392,6 +396,7 @@ export function useYtProgress({
const id = activeId;
const {
resumeAt,
exactStart,
setWatched,
setPlayerError,
setLiveData,
@@ -401,7 +406,8 @@ export function useYtProgress({
qc,
} = itemSnapshot();
// A position this session already stored for the item beats the queue's snapshot of it.
const startAt = sessionPosRef.current.get(id) ?? resumeAt;
// …unless the user asked for a start of their own (Restart on a related row).
const startAt = exactStart ? resumeAt : (sessionPosRef.current.get(id) ?? resumeAt);
autoMarkedRef.current = false;
setPlayerError(null);