Merge pull request #408 from shenlvkang-collab/feat/codex-shift-arrow-keys

feat(mobile): add Shift arrows for Codex queued input and prompt navigation
This commit is contained in:
Codeman maintainer
2026-09-14 23:30:14 +02:00
5 changed files with 59 additions and 5 deletions
+28
View File
@@ -597,6 +597,34 @@ describe('composer nav keys from the bar', () => {
const sentKeys = (fetchMock: { mock: { calls: unknown[][] } }) =>
fetchMock.mock.calls.map((call) => JSON.parse((call[1] as { body: string }).body).input);
it.each(['simple', 'extended'])('exposes Shift arrows in the %s agent layout', (mode) => {
const { bar, barElement } = loadBar('codex');
bar.setMode(mode);
expect(barElement.actions).toContain('shift-left');
expect(barElement.actions).toContain('shift-right');
});
it.each([
['shift-left', '\x1b[1;2D'],
['shift-right', '\x1b[1;2C'],
])('%s flushes the draft before navigation and hands editing to the PTY', (action, sequence) => {
const { bar, app, overlay, fetchMock } = barWithDraft('unfinished follow-up');
const events: string[] = [];
app.sendInput = vi.fn(() => events.push('draft'));
fetchMock.mockImplementation(() => {
events.push('key');
return Promise.resolve({ ok: true, catch: () => {} });
});
bar.handleAction(action);
expect(app.sendInput).toHaveBeenCalledWith('unfinished follow-up');
expect(events).toEqual(['draft', 'key']);
expect(sentKeys(fetchMock)).toEqual([sequence]);
expect(overlay.pendingText).toBe('');
expect([...(app._echoPassthroughSessions as Set<string>)]).toEqual(['session-1']);
});
it('flushes the unsent draft before sending the arrow', () => {
// On a phone the typed text lives in the overlay and has NEVER reached the
// PTY, so an arrow sent on its own arrives at a composer the CLI still
+12 -1
View File
@@ -471,7 +471,18 @@ describe('Virtual Keyboard', () => {
});
// Tab replaced /clear in the simple bar; /clear and /compact live in the
// extended bar only.
expect(actions).toEqual(['scroll-up', 'scroll-down', 'init', 'tab', 'paste', 'esc', 'dismiss']);
expect(actions).toEqual([
'scroll-up',
'scroll-down',
'init',
'tab',
'shift-left',
'shift-right',
'paste',
'readmymind',
'esc',
'dismiss',
]);
});
it('double-tap confirm on /clear button', async () => {