authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-02 13:47:40-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-02 13:49:04-08:00
log5a0006f7efabb03888573a2029f1d0a30b614422
tree947a9272a5f496322a85edb6b0b55118bb38ef9b
parent9e2e73c070710bfcb132cfff3ca1eb7b03996dd7

Guard all commitRename cleanup paths against concurrent renames

All exit paths in commitRename now use a thread-guarded finishRename helper that only clears renamingThreadId when it still matches the original threadId. Prevents a stale onBlur from cancelling a newly started rename on a different thread. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

1 files changed, 13 insertions(+), 9 deletions(-)

apps/web/src/components/Sidebar.tsx+13-9
......@@ -514,19 +514,27 @@ export default function Sidebar() {
514514
515515 const commitRename = useCallback(
516516 async (threadId: ThreadId, newTitle: string, originalTitle: string) => {
517 const finishRename = () => {
518 setRenamingThreadId((current) => {
519 if (current !== threadId) return current;
520 renamingInputRef.current = null;
521 return null;
522 });
523 };
524
517525 const trimmed = newTitle.trim();
518526 if (trimmed.length === 0) {
519527 toastManager.add({ type: "warning", title: "Thread title cannot be empty" });
520 cancelRename();
528 finishRename();
521529 return;
522530 }
523531 if (trimmed === originalTitle) {
524 cancelRename();
532 finishRename();
525533 return;
526534 }
527535 const api = readNativeApi();
528536 if (!api) {
529 cancelRename();
537 finishRename();
530538 return;
531539 }
532540 try {
......@@ -543,13 +551,9 @@ export default function Sidebar() {
543551 description: error instanceof Error ? error.message : "An error occurred.",
544552 });
545553 }
546 setRenamingThreadId((current) => {
547 if (current !== threadId) return current;
548 renamingInputRef.current = null;
549 return null;
550 });
554 finishRename();
551555 },
552 [cancelRename],
556 [],
553557 );
554558
555559 const handleThreadContextMenu = useCallback(