fix(notifications): a notice value is no plain string, so a translated name cannot freeze in one language

A name goes in as raw(), a translated word as its own msg(): tsc now lists every value, and the
ones that froze are said when shown — Watch later and an untitled channel in the pin and channel
notices, a Plex season's name in its removal toast (a new seasonTitleText, which seasonTitle says).
This commit is contained in:
2026-10-30 00:03:48 +01:00
parent cb8b99e0e7
commit 4a0d4b0964
37 changed files with 174 additions and 109 deletions
@@ -55,10 +55,10 @@ import { useReturnFocus } from "../../components/ui/useReturnFocus";
import { SURFACE } from "../../components/ui/surfaces";
import { PageHeading } from "../../components/ui/Headings";
import { MEDIA_BADGE } from "../../components/ui/mediaCardStyles";
import { seasonTitle } from "../../lib/plexDetail";
import { seasonTitle, seasonTitleText } from "../../lib/plexDetail";
import { cardImage } from "../../lib/plexImage";
import RemoteImage from "../../components/ui/RemoteImage";
import { msg } from "../../lib/notifications";
import { msg, raw, type NotifText } from "../../lib/notifications";
// A playlist's items, grouped for readability: movies stay standalone, while a run of episodes from the
// same show collapses into a season/show group so a whole series doesn't sprawl into an endless flat
@@ -563,7 +563,6 @@ export default function PlexPlaylistView({
// Keyed: a row builds its target afresh each render, and its "…" must close the menu it opened.
const rowMenu = useContextMenu<MenuTarget>({ keyOf: targetKey });
const copy = useCopyItems();
const seasonLabel = useSeasonLabel();
const titleActions = usePlexCardActions(
{
onOpen: (c) => onPlay(c.id, order),
@@ -581,14 +580,17 @@ export default function PlexPlaylistView({
rowMenu.open,
);
// What a row's removal takes out, and the name its toast says.
const removal = (target: MenuTarget): { keys: string[]; title: string } =>
const removal = (target: MenuTarget): { keys: string[]; title: NotifText } =>
target.kind === "item"
? { keys: [target.item.id], title: target.item.title }
? { keys: [target.item.id], title: raw(target.item.title) }
: target.kind === "show"
? { keys: target.block.items.map((i) => i.id), title: target.block.title }
? { keys: target.block.items.map((i) => i.id), title: raw(target.block.title) }
: {
keys: target.season.items.map((i) => i.id),
title: `${target.block.title} · ${seasonLabel(target.season)}`,
title: msg("plex.playlist.seasonOfShow", {
show: raw(target.block.title),
season: seasonTitleText({ season_number: target.season.number }),
}),
};
const remove = (target: MenuTarget) => {
const { keys, title } = removal(target);