The large-logical-iframe + CSS-scale-down trick to force a 1080p start did not work behind the user's work VPN (YouTube caps quality by network there regardless of viewport size), and the two-phase native switch could downgrade a latched 1080p to 480p on some streams. Not worth the complexity for an unreliable win — revert to the original "opens at whatever resolution YouTube picks" behaviour; the user sets 1080p manually via fullscreen + the gear as before. Kept: the windowed maximise (fullscreen) button added to the player meta row.
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
// Minimal typings for the YouTube IFrame Player API surface this app actually uses. The API is
|
|
// loaded at runtime from youtube.com/iframe_api and ships no official npm types; rather than pull in
|
|
// @types/youtube we declare just the methods/events PlayerModal calls, so tsc flags any new call
|
|
// that isn't covered here. See [[reference-yt-iframe-api-remote-control-map]] for what's driveable.
|
|
|
|
interface YTVideoData {
|
|
title: string;
|
|
author: string;
|
|
video_id?: string;
|
|
}
|
|
|
|
export interface YTPlayer {
|
|
getPlayerState(): number;
|
|
getCurrentTime(): number;
|
|
getDuration(): number;
|
|
getVideoData(): YTVideoData;
|
|
getIframe(): HTMLIFrameElement;
|
|
getVolume(): number;
|
|
isMuted(): boolean;
|
|
setVolume(volume: number): void;
|
|
mute(): void;
|
|
unMute(): void;
|
|
playVideo(): void;
|
|
pauseVideo(): void;
|
|
loadVideoById(opts: { videoId: string; startSeconds?: number }): void;
|
|
seekTo(seconds: number, allowSeekAhead: boolean): void;
|
|
destroy(): void;
|
|
}
|
|
|
|
// The IFrame API fires events carrying a numeric `data` — a player-state code (onStateChange) or an
|
|
// error code (onError).
|
|
export interface YTPlayerEvent {
|
|
data: number;
|
|
target: YTPlayer;
|
|
}
|
|
|
|
interface YTPlayerOptions {
|
|
width?: string | number;
|
|
height?: string | number;
|
|
videoId?: string;
|
|
playerVars?: Record<string, string | number | undefined>;
|
|
events?: {
|
|
onReady?: (e: YTPlayerEvent) => void;
|
|
onStateChange?: (e: YTPlayerEvent) => void;
|
|
onError?: (e: YTPlayerEvent) => void;
|
|
};
|
|
}
|
|
|
|
export interface YTNamespace {
|
|
Player: new (el: HTMLElement, opts: YTPlayerOptions) => YTPlayer;
|
|
}
|
|
|
|
// The globals the IFrame API script installs on `window` once loaded.
|
|
declare global {
|
|
interface Window {
|
|
YT?: YTNamespace;
|
|
onYouTubeIframeAPIReady?: () => void;
|
|
}
|
|
}
|