Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 1d10549159ed4661eb6c94eef4608d5e1e873a39
parent 43346eceffd001ad032710de04478ef7da57f629
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri,  2 Oct 2026 00:09:45 -0400

editor: the video page's subtitle-deferral line reads a GET route, not a server action

Next runs a page's server actions one at a time, so an action fired on mount
sat in front of the operator's first click; video-page.spec's "Mark
untranscribable" timed out behind it once. The line now fetches
GET /api/channels/<slug>/videos/<id>/subtitle-deferral.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Aeditor/app/api/channels/[slug]/videos/[id]/subtitle-deferral/route.ts | 26++++++++++++++++++++++++++
Meditor/app/channels/[slug]/videos/[id]/components/SubtitleDeferralLine.tsx | 11++++++++---
Meditor/app/channels/[slug]/videos/[id]/videoActions.ts | 15---------------
3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/editor/app/api/channels/[slug]/videos/[id]/subtitle-deferral/route.ts b/editor/app/api/channels/[slug]/videos/[id]/subtitle-deferral/route.ts @@ -0,0 +1,26 @@ +import { NextResponse } from "next/server"; +import { getPaths } from "yt-dlp-transcript-common/lib/paths"; +import { readSubtitleDeferrals } from "yt-dlp-transcript-common/jobs/downloadBackoff"; + +export const dynamic = "force-dynamic"; + +// GET → { count, lastAt, until } | null — the video's SUBTITLE deferral +// (release 17, slice RL): how many times its subtitle fetch answered 429, when +// last, and until when Download missing subs leaves it alone. Read by the video +// page's one-line note. +// +// A ROUTE, NOT A SERVER ACTION: the note asks on mount, and Next runs a page's +// server actions one at a time — a mount-time action would sit in front of the +// operator's first click (Mark untranscribable, Download, …) while it ran. +export async function GET( + _req: Request, + ctx: { params: Promise<{ slug: string; id: string }> }, +): Promise<NextResponse> { + const { slug, id } = await ctx.params; + const all = await readSubtitleDeferrals(getPaths()).catch(() => ({})); + const d = (all as Record<string, { count: number; lastAt: number; until: number; channelSlug: string }>)[id]; + return NextResponse.json( + d && d.channelSlug === slug ? { count: d.count, lastAt: d.lastAt, until: d.until } : null, + { headers: { "cache-control": "no-store" } }, + ); +} diff --git a/editor/app/channels/[slug]/videos/[id]/components/SubtitleDeferralLine.tsx b/editor/app/channels/[slug]/videos/[id]/components/SubtitleDeferralLine.tsx @@ -1,7 +1,6 @@ "use client"; import { useEffect, useState } from "react"; -import { subtitleDeferralAction } from "../videoActions"; // THE SUBTITLE DEFERRAL, IN ONE LINE (release 17, slice RL). A video whose // YouTube subtitles answered HTTP 429 while its media came down: how many @@ -19,8 +18,14 @@ export function SubtitleDeferralLine({ const [d, setD] = useState<{ count: number; lastAt: number; until: number } | null>(null); useEffect(() => { let live = true; - subtitleDeferralAction(slug, videoId) - .then((r) => { + // A plain GET, not a server action: Next queues a page's server actions, + // and this one would run ahead of the operator's first click. + fetch( + `/api/channels/${encodeURIComponent(slug)}/videos/${encodeURIComponent(videoId)}/subtitle-deferral`, + { cache: "no-store" }, + ) + .then((r) => (r.ok ? r.json() : null)) + .then((r: { count: number; lastAt: number; until: number } | null) => { if (live) setD(r); }) .catch(() => {}); diff --git a/editor/app/channels/[slug]/videos/[id]/videoActions.ts b/editor/app/channels/[slug]/videos/[id]/videoActions.ts @@ -67,7 +67,6 @@ import { applyTagAssignmentsAction } from "../../../../tags/actions"; import { heldPlatformRefusal, platformCooldownRemainingMs, - readSubtitleDeferrals, recordDownloadBackoff, } from "yt-dlp-transcript-common/jobs/downloadBackoff"; import { getSettings } from "yt-dlp-transcript-common/lib/settings"; @@ -1148,17 +1147,3 @@ export async function fetchFullSourceAction(req: { to: 0, }; } - -// THE VIDEO'S SUBTITLE DEFERRAL (release 17, slice RL), for the line on the -// video page: how many times its subtitle fetch answered 429, when last, and -// until when the batch subtitle fetch leaves it alone. Null when it has none. -// Read-only; the video page's own download never consults it. -export async function subtitleDeferralAction( - slug: string, - videoId: string, -): Promise<{ count: number; lastAt: number; until: number } | null> { - const deferrals = await readSubtitleDeferrals(getPaths()).catch(() => ({})); - const d = (deferrals as Record<string, { count: number; lastAt: number; until: number; channelSlug: string }>)[videoId]; - if (!d || d.channelSlug !== slug) return null; - return { count: d.count, lastAt: d.lastAt, until: d.until }; -}