diff --git a/src/renderer-settings.ts b/src/renderer-settings.ts index 4f9677b..ac11970 100644 --- a/src/renderer-settings.ts +++ b/src/renderer-settings.ts @@ -194,9 +194,14 @@ function changeLanguage(lang: string): void { const activeTabId = document.querySelector('.tab-content.active')?.id || 'vodsTab'; const activeTab = activeTabId.replace('Tab', ''); if (activeTab === 'vods' && currentStreamer) { - byId('pageTitle').textContent = currentStreamer; + const setTitle = (window as unknown as { setPageTitle?: (text: string) => void }).setPageTitle; + if (typeof setTitle === 'function') setTitle(currentStreamer); + else byId('pageTitle').textContent = currentStreamer; } else { - byId('pageTitle').textContent = (UI_TEXT.tabs as Record)[activeTab] || UI_TEXT.appName; + const setTitle = (window as unknown as { setPageTitle?: (text: string) => void }).setPageTitle; + const text = (UI_TEXT.tabs as Record)[activeTab] || UI_TEXT.appName; + if (typeof setTitle === 'function') setTitle(text); + else byId('pageTitle').textContent = text; } void refreshRuntimeMetrics(); diff --git a/src/renderer-streamers.ts b/src/renderer-streamers.ts index 7d41cf7..9833a41 100644 --- a/src/renderer-streamers.ts +++ b/src/renderer-streamers.ts @@ -751,7 +751,9 @@ async function selectStreamer(name: string, forceRefresh = false): Promise const savedY = vodScrollPositions[name]; pendingScrollRestore = (typeof savedY === 'number' && savedY > 0) ? { streamer: name, y: savedY } : null; renderStreamers(); - byId('pageTitle').textContent = name; + const setTitle = (window as unknown as { setPageTitle?: (text: string) => void }).setPageTitle; + if (typeof setTitle === 'function') setTitle(name); + else byId('pageTitle').textContent = name; // Kick off the profile header load in parallel with VOD fetching. // It's a separate request stream and not strictly needed for the VOD diff --git a/src/renderer.ts b/src/renderer.ts index 1121e69..72203d1 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -20,6 +20,7 @@ async function init(): Promise { byId('versionText').textContent = `v${version}`; byId('versionInfo').textContent = `Version: v${version}`; + appVersion = version; document.title = `${UI_TEXT.appName} v${version}`; byId('clientId').value = config.client_id ?? ''; @@ -636,6 +637,24 @@ async function updateStatsBar(): Promise { let toastHideTimer: number | null = null; let queueSyncTimer: number | null = null; +let appVersion = ''; + +// Single source of truth for what the user is looking at — keeps the +// visible H1, the document title (which drives the OS task bar / Alt+Tab +// label), and the app version pill in sync. Previously document.title was +// stamped once at boot, so the OS task bar always read "Twitch VOD +// Manager v4.6.76" no matter what tab or streamer was active. +(window as unknown as { setPageTitle: (text: string) => void }).setPageTitle = setPageTitle; + +function setPageTitle(text: string): void { + const titleEl = document.getElementById('pageTitle'); + if (titleEl) titleEl.textContent = text; + const appName = UI_TEXT.appName; + const versionSuffix = appVersion ? ` v${appVersion}` : ''; + document.title = text && text !== appName + ? `${text} - ${appName}${versionSuffix}` + : `${appName}${versionSuffix}`; +} let queueSyncInFlight = false; let lastQueueActivityAt = Date.now(); @@ -850,9 +869,10 @@ function showTab(tab: string): void { // Only show the streamer name on the VODs tab — otherwise the title would // mismatch the tab content (e.g. "streamer X" while on Settings) - byId('pageTitle').textContent = (tab === 'vods' && currentStreamer) + const pageTitleText = (tab === 'vods' && currentStreamer) ? currentStreamer : (titles[tab] || UI_TEXT.appName); + setPageTitle(pageTitleText); persistActiveTab(tab);