perf(watch): a shared link loads the player, not the app
A /watch link is opened by whoever it was sent to — signed out, often on a phone on mobile data — and it booted through main.tsx: every app provider, the app's i18n (every locale of every area), the flag sprites, ~392 KB gzip before the player could start. It now has its own HTML entry, watch.html → watchMain.tsx, which imports WatchPage and what it renders; the server hands every /watch/ path that page (the OG block injected as before), and vite dev does the same. Measured on the build: /watch JS 290 → 87 KB gzip, CSS 104 → 19 KB; the app's own bytes unchanged. Two leaks had to go for that: lib/format imported the app's i18n for one "just now" string (the relative-time formatters now take `t`, like the file's other t-formatters), and the boundary's crash copy came from the same i18n (CrashBoundary takes its copy; ErrorBoundary is the app's wrapper, the watch entry gives it the page's own strings). The page's popover tree went too: it renders no popover. Held by: a contract test walking the entry's runtime imports, naming the path to anything only the app may load (red on a planted i18n import in lib/format), and holding watch.html's head equal to index.html's; a DB-lane test that every /watch/ path gets the player's page with the link's OG tags and app paths get the app (red on the old routing). Screenshots at 375 px, EN and HU, video / audio / password / gone / wrong password / unlocked: identical to the old entry's, bar the video's buffered bar.
This commit is contained in:
@@ -9,10 +9,11 @@ import { send } from "../lib/http";
|
||||
import { Input } from "./ui/Input";
|
||||
import { SURFACE } from "./ui/surfaces";
|
||||
import { LinkButton } from "./ui/LinkButton";
|
||||
import { T, lang } from "./watchStrings";
|
||||
|
||||
// Standalone, login-free video page for a shared /watch/<token> link. Rendered OUTSIDE the app
|
||||
// tree (no auth, no providers) — like the /privacy and /terms pages. Uses plain fetch and a tiny
|
||||
// self-contained i18n dict (the public viewer has no app language preference).
|
||||
// Standalone, login-free video page for a shared /watch/<token> link. Its own entry (watchMain.tsx,
|
||||
// watch.html): no auth, no providers, none of the app's bundle. Uses plain fetch and a tiny
|
||||
// self-contained i18n dict (`watchStrings`: the public viewer has no app language preference).
|
||||
|
||||
// Advertise the playing video to the OS via the Media Session API: lock-screen / control-center
|
||||
// metadata + play/pause handlers. This is also what lets a browser's own "background playback"
|
||||
@@ -75,72 +76,6 @@ function displayUrl(url: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
const STR = {
|
||||
en: {
|
||||
loading: "Loading…",
|
||||
gone: "This link is no longer available.",
|
||||
goneHint: "It may have expired or been revoked by the owner.",
|
||||
passwordTitle: "This video is password-protected",
|
||||
passwordPlaceholder: "Enter password",
|
||||
watch: "Watch",
|
||||
wrong: "Wrong password.",
|
||||
download: "Download",
|
||||
file: "File",
|
||||
links: "Links",
|
||||
brand: "Shared via Siftlode",
|
||||
repeat: "Repeat",
|
||||
failed: "Couldn't load this link.",
|
||||
failedHint: "Check your connection and try again.",
|
||||
retry: "Try again",
|
||||
tooMany: "Too many attempts. Try again in a few minutes.",
|
||||
unlockFailed: "Couldn't check the password. Try again.",
|
||||
},
|
||||
hu: {
|
||||
loading: "Betöltés…",
|
||||
gone: "Ez a link már nem elérhető.",
|
||||
goneHint: "Lehet, hogy lejárt, vagy a tulajdonos visszavonta.",
|
||||
passwordTitle: "Ez a videó jelszóval védett",
|
||||
passwordPlaceholder: "Add meg a jelszót",
|
||||
watch: "Megnézem",
|
||||
wrong: "Hibás jelszó.",
|
||||
download: "Letöltés",
|
||||
file: "Fájl",
|
||||
links: "Linkek",
|
||||
brand: "Megosztva a Siftlode-dal",
|
||||
repeat: "Ismétlés",
|
||||
failed: "Nem sikerült betölteni a linket.",
|
||||
failedHint: "Ellenőrizd a kapcsolatot, és próbáld újra.",
|
||||
retry: "Újrapróbálás",
|
||||
tooMany: "Túl sok próbálkozás. Próbáld újra pár perc múlva.",
|
||||
unlockFailed: "Nem sikerült ellenőrizni a jelszót. Próbáld újra.",
|
||||
},
|
||||
de: {
|
||||
loading: "Wird geladen…",
|
||||
gone: "Dieser Link ist nicht mehr verfügbar.",
|
||||
goneHint: "Er ist möglicherweise abgelaufen oder wurde widerrufen.",
|
||||
passwordTitle: "Dieses Video ist passwortgeschützt",
|
||||
passwordPlaceholder: "Passwort eingeben",
|
||||
watch: "Ansehen",
|
||||
wrong: "Falsches Passwort.",
|
||||
download: "Herunterladen",
|
||||
file: "Datei",
|
||||
links: "Links",
|
||||
brand: "Geteilt über Siftlode",
|
||||
repeat: "Wiederholen",
|
||||
failed: "Der Link konnte nicht geladen werden.",
|
||||
failedHint: "Prüfe deine Verbindung und versuche es erneut.",
|
||||
retry: "Erneut versuchen",
|
||||
tooMany: "Zu viele Versuche. Versuche es in ein paar Minuten erneut.",
|
||||
unlockFailed: "Das Passwort konnte nicht geprüft werden. Versuche es erneut.",
|
||||
},
|
||||
} as const;
|
||||
|
||||
const lang =
|
||||
((navigator.language || "en").slice(0, 2) as keyof typeof STR) in STR
|
||||
? ((navigator.language || "en").slice(0, 2) as keyof typeof STR)
|
||||
: "en";
|
||||
const T = STR[lang];
|
||||
|
||||
export default function WatchPage() {
|
||||
const token = window.location.pathname.split("/watch/")[1]?.split(/[/?#]/)[0] ?? "";
|
||||
// Seeded from the URL rather than corrected by the effect below: with no token there is nothing
|
||||
|
||||
Reference in New Issue
Block a user