feat: show active session name in browser tab title

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.
This commit is contained in:
Nicolas Varrot
2026-02-12 09:17:15 +00:00
parent b5eafdeed8
commit e53ef36715
2 changed files with 21 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback, useRef, lazy, Suspense } from 'react'; import { useState, useEffect, useCallback, useRef, lazy, Suspense } from 'react';
import { useGateway } from './hooks/useGateway'; import { useGateway } from './hooks/useGateway';
import { useNotifications } from './hooks/useNotifications'; import { useNotifications, setBaseTitle } from './hooks/useNotifications';
import { Header } from './components/Header'; import { Header } from './components/Header';
import { Sidebar } from './components/Sidebar'; import { Sidebar } from './components/Sidebar';
import { LoginScreen } from './components/LoginScreen'; import { LoginScreen } from './components/LoginScreen';
@@ -33,6 +33,13 @@ export default function App() {
} }
}, [messages, notify]); }, [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 ? // Close sidebar on Escape key, open shortcuts on ?
const handleKeyDown = useCallback((e: KeyboardEvent) => { const handleKeyDown = useCallback((e: KeyboardEvent) => {
if (e.key === 'Escape' && sidebarOpen) { if (e.key === 'Escape' && sidebarOpen) {

View File

@@ -1,7 +1,17 @@
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { playNotificationSound } from '../lib/notificationSound'; 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 SOUND_KEY = 'pinchchat-notification-sound';
const hasNotificationAPI = typeof Notification !== 'undefined'; const hasNotificationAPI = typeof Notification !== 'undefined';
@@ -25,7 +35,7 @@ export function useNotifications() {
if (!document.hidden) { if (!document.hidden) {
// Reset unread when tab becomes visible // Reset unread when tab becomes visible
setUnreadCount(0); setUnreadCount(0);
document.title = ORIGINAL_TITLE; document.title = baseTitle;
} }
}; };
document.addEventListener('visibilitychange', handleVisibility); document.addEventListener('visibilitychange', handleVisibility);
@@ -35,7 +45,7 @@ export function useNotifications() {
// Update tab title when unread count changes // Update tab title when unread count changes
useEffect(() => { useEffect(() => {
if (unreadCount > 0) { if (unreadCount > 0) {
document.title = `(${unreadCount}) ${ORIGINAL_TITLE}`; document.title = `(${unreadCount}) ${baseTitle}`;
} }
}, [unreadCount]); }, [unreadCount]);