From e53ef36715566eb1c246defc02786ee5e4e149b6 Mon Sep 17 00:00:00 2001 From: Nicolas Varrot Date: Thu, 12 Feb 2026 09:17:15 +0000 Subject: [PATCH] feat: show active session name in browser tab title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates document.title dynamically to show the current session label (e.g. 'main — PinchChat'). Integrates with the existing notification system so unread badges still work correctly (e.g. '(3) main — PinchChat'). Resets to plain 'PinchChat' when no session is selected. --- src/App.tsx | 9 ++++++++- src/hooks/useNotifications.ts | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 0137b4d..41aa6e4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback, useRef, lazy, Suspense } from 'react'; import { useGateway } from './hooks/useGateway'; -import { useNotifications } from './hooks/useNotifications'; +import { useNotifications, setBaseTitle } from './hooks/useNotifications'; import { Header } from './components/Header'; import { Sidebar } from './components/Sidebar'; import { LoginScreen } from './components/LoginScreen'; @@ -33,6 +33,13 @@ export default function App() { } }, [messages, notify]); + // Update document title with active session label + useEffect(() => { + const session = sessions.find(s => s.key === activeSession); + setBaseTitle(session?.label || session?.key); + return () => setBaseTitle(undefined); + }, [activeSession, sessions]); + // Close sidebar on Escape key, open shortcuts on ? const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.key === 'Escape' && sidebarOpen) { diff --git a/src/hooks/useNotifications.ts b/src/hooks/useNotifications.ts index 9d48889..2ce9e77 100644 --- a/src/hooks/useNotifications.ts +++ b/src/hooks/useNotifications.ts @@ -1,7 +1,17 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import { playNotificationSound } from '../lib/notificationSound'; -const ORIGINAL_TITLE = document.title; +const APP_NAME = 'PinchChat'; +let baseTitle = APP_NAME; + +/** Update the base title (e.g. with active session name). Called by App. */ +export function setBaseTitle(sessionLabel?: string) { + baseTitle = sessionLabel ? `${sessionLabel} — ${APP_NAME}` : APP_NAME; + // Refresh document.title if tab is visible (no unread badge) + if (!document.hidden) { + document.title = baseTitle; + } +} const SOUND_KEY = 'pinchchat-notification-sound'; const hasNotificationAPI = typeof Notification !== 'undefined'; @@ -25,7 +35,7 @@ export function useNotifications() { if (!document.hidden) { // Reset unread when tab becomes visible setUnreadCount(0); - document.title = ORIGINAL_TITLE; + document.title = baseTitle; } }; document.addEventListener('visibilitychange', handleVisibility); @@ -35,7 +45,7 @@ export function useNotifications() { // Update tab title when unread count changes useEffect(() => { if (unreadCount > 0) { - document.title = `(${unreadCount}) ${ORIGINAL_TITLE}`; + document.title = `(${unreadCount}) ${baseTitle}`; } }, [unreadCount]);