feat: subtitle size, face and placement, set from the player
One fixed size cannot suit everyone — the default was too big, then too small. The subtitle menu in the transport bar now carries an Appearance section: Size (S/M/L/XL), Font (Sans/Serif/Mono) and Place (Bottom/Raised/Top). Choices apply at once and are remembered across videos and launches, like every other preference. Size and face are written into a style element rather than the stylesheet: ::cue takes no custom properties, so the values have to be literal. Placement is not a CSS property at all — WebVTT carries position on the cue — so it is rewritten into the cues themselves and the track re-cut. Every source is text now, including the sidecars beside older downloads, so all three can be placed the same way. The default lands at 85%, between WebKit's own size and the 58% that replaced it. Re-cutting a track exposed a bug in the guard that applies the subtitle preference: it keyed on how many text tracks there were, and re-cutting one leaves that unchanged, so the fresh track would have stayed disabled and the subtitles would have vanished on any change of Place. It keys on the tracks themselves.
This commit is contained in:
@@ -113,6 +113,39 @@ export const STREAM_QUALITIES: Array<{ value: Quality; label: string }> = [
|
||||
{ value: "480", label: "480p" },
|
||||
];
|
||||
|
||||
/** How subtitles look, set from the player's subtitle menu. */
|
||||
export interface SubStyle {
|
||||
/** Percentage of the player's default cue size. */
|
||||
size: number;
|
||||
font: "sans" | "serif" | "mono";
|
||||
place: "bottom" | "raised" | "top";
|
||||
}
|
||||
|
||||
export const DEFAULT_SUB_STYLE: SubStyle = { size: 85, font: "sans", place: "bottom" };
|
||||
|
||||
export const SUB_SIZES: Array<{ value: number; label: string }> = [
|
||||
{ value: 65, label: "S" },
|
||||
{ value: 85, label: "M" },
|
||||
{ value: 110, label: "L" },
|
||||
{ value: 145, label: "XL" },
|
||||
];
|
||||
|
||||
export const SUB_FONTS: Array<{ value: SubStyle["font"]; label: string; stack: string }> = [
|
||||
{ value: "sans", label: "Sans", stack: "system-ui, -apple-system, Helvetica, sans-serif" },
|
||||
{ value: "serif", label: "Serif", stack: "Georgia, 'Times New Roman', serif" },
|
||||
{ value: "mono", label: "Mono", stack: "ui-monospace, SFMono-Regular, Menlo, monospace" },
|
||||
];
|
||||
|
||||
/**
|
||||
* Where the cues sit, as a WebVTT `line` percentage down the picture.
|
||||
* Null leaves the player's own placement, which is the bottom.
|
||||
*/
|
||||
export const SUB_PLACES: Array<{ value: SubStyle["place"]; label: string; line: number | null }> = [
|
||||
{ value: "bottom", label: "Bottom", line: null },
|
||||
{ value: "raised", label: "Raised", line: 78 },
|
||||
{ value: "top", label: "Top", line: 8 },
|
||||
];
|
||||
|
||||
/**
|
||||
* How many videos one "Download all" may queue. All subscriptions can be
|
||||
* hundreds of videos, which is not something to set going by accident.
|
||||
|
||||
Reference in New Issue
Block a user