make the editable tab name survive refreshes
sessionStorage is the per-tab store — separate per tab, survives reload and navigation, dies with the tab. The route title is derived rather than assigned, so navigating no longer wipes a name you typed. Duplicating a tab clones sessionStorage, so a `navigate` that arrives already holding a name is treated as a clone and drops it; fails soft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,29 +11,39 @@ import { RescanButton } from '../Rescan/RescanButton';
|
||||
import { usePageTitle } from '@/state/usePageTitle';
|
||||
// import { BugReportButton } from '../BugReport/BugReportButton';
|
||||
|
||||
// Center title: click to rename this browser tab (per-tab, not persisted).
|
||||
// Center title: click to rename this browser tab. The name is kept in sessionStorage, so it survives a
|
||||
// refresh and navigation and dies with the tab — see usePageTitle.
|
||||
function EditablePageTitle() {
|
||||
const [title, setTitle] = usePageTitle();
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [title, rename] = usePageTitle();
|
||||
const [draft, setDraft] = useState<string | null>(null);
|
||||
|
||||
if (editing) {
|
||||
// The edit is a draft committed on blur/Enter rather than a live write. Writing every keystroke was
|
||||
// fine while the title was a plain string, but an empty field now means "use the route name", so
|
||||
// deleting the last character would snap the input to "Chat" underneath the cursor.
|
||||
if (draft !== null) {
|
||||
return (
|
||||
<input
|
||||
autoFocus
|
||||
value={title}
|
||||
onChange={(ev) => setTitle(ev.target.value)}
|
||||
onBlur={() => setEditing(false)}
|
||||
onKeyDown={(ev) => {
|
||||
if (ev.key === 'Enter' || ev.key === 'Escape') setEditing(false);
|
||||
value={draft}
|
||||
onChange={(ev) => setDraft(ev.target.value)}
|
||||
onBlur={() => {
|
||||
rename(draft);
|
||||
setDraft(null);
|
||||
}}
|
||||
onKeyDown={(ev) => {
|
||||
if (ev.key === 'Enter') ev.currentTarget.blur();
|
||||
if (ev.key === 'Escape') setDraft(null); // discard, keeping whatever the tab was called
|
||||
}}
|
||||
aria-label="Tab name"
|
||||
placeholder={title}
|
||||
className="pointer-events-auto max-w-[50vw] border-b border-[#1d2724]/40 bg-transparent text-center text-base font-bold text-[#1d2724] outline-none md:text-xl"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<button
|
||||
onClick={() => setEditing(true)}
|
||||
title="Click to rename this tab"
|
||||
onClick={() => setDraft(title)}
|
||||
title="Click to rename this tab — clear it to go back to the page name"
|
||||
className="pointer-events-auto max-w-[50vw] cursor-text truncate text-base font-bold text-[#1d2724] transition-opacity hover:opacity-70 md:text-xl"
|
||||
>
|
||||
{title}
|
||||
|
||||
Reference in New Issue
Block a user