Move toolbar thread selection handling

This commit is contained in:
murashit 2026-05-29 06:48:29 +09:00
parent 8829962385
commit 47eb02aeb3
3 changed files with 38 additions and 6 deletions

View file

@ -1,4 +1,4 @@
import { chatTurnBusy, type ChatState, type ChatStateStore } from "./chat-state";
import { chatTurnBusy, type ChatAction, type ChatState, type ChatStateStore } from "./chat-state";
export interface ThreadSelectionControllerHost {
stateStore: ChatStateStore;
@ -22,7 +22,18 @@ export class ThreadSelectionController {
await this.host.resumeThread(threadId);
}
async selectThreadFromToolbar(threadId: string): Promise<void> {
if (chatTurnBusy(this.state) && threadId !== this.state.activeThreadId) return;
this.dispatch({ type: "ui/panel-set", panel: null });
await this.selectThread(threadId);
}
private get state(): ChatState {
return this.host.stateStore.getState();
}
private dispatch(action: ChatAction): void {
this.host.stateStore.dispatch(action);
}
}

View file

@ -989,11 +989,7 @@ export class CodexChatView extends ItemView {
},
connect: () => void this.reconnectActions.reconnectFromToolbar(),
refreshStatus: () => void this.refreshStatusPanel(),
resumeThread: (threadId) => {
if (this.turnBusy && threadId !== this.state.activeThreadId) return;
this.dispatch({ type: "ui/panel-set", panel: null });
void this.selectThread(threadId);
},
resumeThread: (threadId) => void this.threadSelection.selectThreadFromToolbar(threadId),
startArchiveThread: (threadId) => {
this.toolbarPanels.startArchive(threadId);
},

View file

@ -64,4 +64,29 @@ describe("ThreadSelectionController", () => {
expect(host.focusThreadInOpenView).not.toHaveBeenCalled();
expect(host.resumeThread).not.toHaveBeenCalled();
});
it("closes the toolbar panel before selecting from the toolbar", async () => {
const { controller, host, stateStore } = createController();
stateStore.dispatch({ type: "ui/panel-set", panel: "history" });
await controller.selectThreadFromToolbar("thread");
expect(stateStore.getState().openDetails.size).toBe(0);
expect(host.closeForThreadSelection).toHaveBeenCalledOnce();
expect(host.resumeThread).toHaveBeenCalledWith("thread");
});
it("ignores toolbar selection while another thread is busy", async () => {
const { controller, host, stateStore } = createController();
resumeThreadState(stateStore, "active");
stateStore.dispatch({ type: "ui/panel-set", panel: "history" });
stateStore.dispatch({ type: "turn/started", threadId: "active", turnId: "turn" });
await controller.selectThreadFromToolbar("other");
expect(stateStore.getState().openDetails.has("history")).toBe(true);
expect(host.addSystemMessage).not.toHaveBeenCalled();
expect(host.closeForThreadSelection).not.toHaveBeenCalled();
expect(host.resumeThread).not.toHaveBeenCalled();
});
});