diff --git a/bun.lock b/bun.lock index 7f488a0a..ade5b68f 100644 --- a/bun.lock +++ b/bun.lock @@ -52,10 +52,10 @@ "vite-plugin-pwa": "^1.2.0", }, "optionalDependencies": { - "@gbasin/agentboard-darwin-arm64": "0.4.0", - "@gbasin/agentboard-darwin-x64": "0.4.0", - "@gbasin/agentboard-linux-arm64": "0.4.0", - "@gbasin/agentboard-linux-x64": "0.4.0", + "@gbasin/agentboard-darwin-arm64": "0.4.1", + "@gbasin/agentboard-darwin-x64": "0.4.1", + "@gbasin/agentboard-linux-arm64": "0.4.1", + "@gbasin/agentboard-linux-x64": "0.4.1", }, }, }, diff --git a/package.json b/package.json index d6d0b44d..0d6304a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gbasin/agentboard", - "version": "0.4.0", + "version": "0.4.1", "type": "module", "description": "Web GUI for tmux optimized for AI agent TUIs", "author": "gbasin", @@ -20,10 +20,10 @@ "bun": ">=1.3.14" }, "optionalDependencies": { - "@gbasin/agentboard-darwin-arm64": "0.4.0", - "@gbasin/agentboard-darwin-x64": "0.4.0", - "@gbasin/agentboard-linux-x64": "0.4.0", - "@gbasin/agentboard-linux-arm64": "0.4.0" + "@gbasin/agentboard-darwin-arm64": "0.4.1", + "@gbasin/agentboard-darwin-x64": "0.4.1", + "@gbasin/agentboard-linux-x64": "0.4.1", + "@gbasin/agentboard-linux-arm64": "0.4.1" }, "scripts": { "dev": "concurrently -k \"bun run dev:server\" \"bun run dev:client\"", diff --git a/src/client/__tests__/useTerminal.test.tsx b/src/client/__tests__/useTerminal.test.tsx index eea51653..0f820d48 100644 --- a/src/client/__tests__/useTerminal.test.tsx +++ b/src/client/__tests__/useTerminal.test.tsx @@ -169,9 +169,14 @@ interface ListenerEntry { capture: boolean } +type MockTextarea = HTMLTextAreaElement & { focusCalls: number } + function createContainerMock() { const textareaListeners = new Map() + const textareaState = { focusCalls: 0 } const textarea = { + get focusCalls() { return textareaState.focusCalls }, + set focusCalls(value: number) { textareaState.focusCalls = value }, addEventListener: (event: string, handler: EventListener) => { textareaListeners.set(event, handler) }, @@ -182,8 +187,10 @@ function createContainerMock() { }, setAttribute: () => {}, removeAttribute: () => {}, - focus: () => {}, - } as unknown as HTMLTextAreaElement + focus: () => { + textareaState.focusCalls += 1 + }, + } as unknown as MockTextarea // Store multiple listeners per event to support both bubble and capture phase const listenerEntries = new Map() @@ -1782,7 +1789,7 @@ describe('useTerminal', () => { const sendCalls: Array> = [] const listeners: Array<(message: ServerMessage) => void> = [] - const { container, dispatchEvent } = createContainerMock() + const { container, dispatchEvent, textarea } = createContainerMock() let preventDefaultCalls = 0 let stopPropagationCalls = 0 @@ -1838,6 +1845,7 @@ describe('useTerminal', () => { sessionId: 'session-1', data: '\x1b[<0;3;3M\x1b[<0;3;3m', }]) + expect((textarea as HTMLTextAreaElement & { focusCalls: number }).focusCalls).toBe(1) expect(preventDefaultCalls).toBe(1) expect(stopPropagationCalls).toBe(1) @@ -1977,7 +1985,7 @@ describe('useTerminal', () => { const sendCalls: Array> = [] const listeners: Array<(message: ServerMessage) => void> = [] - const { container, dispatchEvent } = createContainerMock() + const { container, dispatchEvent, textarea } = createContainerMock() let renderer!: TestRenderer.ReactTestRenderer await act(async () => { @@ -2027,6 +2035,7 @@ describe('useTerminal', () => { }) expect(sendCalls.some((call) => call.type === 'terminal-input')).toBe(false) + expect((textarea as HTMLTextAreaElement & { focusCalls: number }).focusCalls).toBe(1) act(() => { renderer.unmount() diff --git a/src/client/components/Terminal.tsx b/src/client/components/Terminal.tsx index 232d7c6a..17d3cb53 100644 --- a/src/client/components/Terminal.tsx +++ b/src/client/components/Terminal.tsx @@ -909,6 +909,7 @@ export default function Terminal({ if (appMouseRef.current) { const touch = e.changedTouches[0] if (touch && sendTapClickToApp(touch)) { + focusTerminalInput() e.preventDefault() e.stopPropagation() return