let renaming a chat take the tab name back
`label ?? override ?? route` made a typed tab name permanent. That is right for navigation — you named the window to find it again — and wrong the moment you rename the conversation itself: the tab kept the old name, and kept it across reloads, because the stale one is in sessionStorage. The rename looked like it had failed. Both are deliberate acts, so the newer wins. The hard part is telling a rename from ordinary navigation: from the outside, "same conversation, new title" and "different conversation, different title" are the same event — a changed override. Clearing the tab name on any change would have wiped it every time you clicked a chat. So the override now carries the id of the thing it names. Same id with a new title is a rename and drops the tab name; a new id is navigation and leaves it alone. The alternative was to have the panel clear the label directly, which needs a QueryClient dragged across the workspace boundary the bridge exists to avoid — the shell owns the tab name, so the shell decides when to drop it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import type { PageTitleOverride } from 'officerdev';
|
||||
import { usePageTitleOverride } from 'officerdev';
|
||||
import { useSessionState, writeSessionValue } from 'hooks/useSessionState';
|
||||
|
||||
@@ -163,9 +164,28 @@ export function usePageTitle() {
|
||||
|
||||
useEffect(() => onTabLabelDropped(() => setLabel(null)), [setLabel]);
|
||||
|
||||
/**
|
||||
* A rename outranks a tab name you typed earlier; opening a different chat does not.
|
||||
*
|
||||
* The precedence below makes a typed name permanent, which is right for navigation — you named this
|
||||
* window to find it again — and wrong the moment you rename the conversation itself. That was a
|
||||
* deliberate act on the same thing the tab is showing, and it appeared to do nothing: the tab kept the
|
||||
* old name, and kept it across reloads, because the stale one is in sessionStorage.
|
||||
*
|
||||
* The two are told apart by the id, which is why the override carries one. Same id and a new title is
|
||||
* a rename, and the newer act wins. A new id is navigation, and the tab name survives it.
|
||||
*/
|
||||
const seenRef = useRef<PageTitleOverride | null>(null);
|
||||
useEffect(() => {
|
||||
const seen = seenRef.current;
|
||||
seenRef.current = override;
|
||||
if (!override || !seen) return;
|
||||
if (seen.id === override.id && seen.title !== override.title) setLabel(null);
|
||||
}, [override, setLabel]);
|
||||
|
||||
const rename = useCallback((next: string) => setLabel(next.trim() || null), [setLabel]);
|
||||
|
||||
return [label ?? override ?? titleForPath(pathname), rename] as const;
|
||||
return [label ?? override?.title ?? titleForPath(pathname), rename] as const;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user