mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 18:39:33 +01:00
Merge pull request #673: fix(mobile): keep the keyboard up when an accessory key is pressed
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
30a60f7bb5
4 files changed
+127
-3
No files matched your search
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @fileoverview Accessory keys that keep the keyboard up must not take focus on
|
||||
* press. A tap used to blur the terminal's textarea and the click handler then
|
||||
* refocused it, so every arrow/Tab/Esc tap started a keyboard dismissal. The bar
|
||||
* now cancels the mousedown default for exactly those keys (and the first,
|
||||
* arming tap of clear/compact); every other key keeps the old behavior.
|
||||
*
|
||||
* Loaded with `vm` against a minimal fake DOM, like the other accessory-bar tests.
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
import vm from 'node:vm';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
type Listener = (e: unknown) => void;
|
||||
type Bar = {
|
||||
init(): void;
|
||||
_confirmAction: string | null;
|
||||
syncReadMyMind(): void;
|
||||
syncCodexKeys(): void;
|
||||
_syncComposerDraftIndicator(): void;
|
||||
};
|
||||
|
||||
function loadBar() {
|
||||
const listeners: Record<string, Listener> = {};
|
||||
const element = {
|
||||
className: '',
|
||||
innerHTML: '',
|
||||
addEventListener: (type: string, fn: Listener) => {
|
||||
listeners[type] = fn;
|
||||
},
|
||||
};
|
||||
const context = vm.createContext({
|
||||
console,
|
||||
document: { createElement: () => element, querySelector: () => null },
|
||||
MobileDetection: { isTouchDevice: () => true },
|
||||
localStorage: { getItem: () => null, setItem: () => {} },
|
||||
});
|
||||
vm.runInContext(
|
||||
`${readFileSync(resolve('src/web/public/keyboard-accessory.js'), 'utf8')}\nglobalThis.__bar = KeyboardAccessoryBar;`,
|
||||
context
|
||||
);
|
||||
const bar = (context as unknown as { __bar: Bar }).__bar;
|
||||
bar.syncReadMyMind = () => {};
|
||||
bar.syncCodexKeys = () => {};
|
||||
bar._syncComposerDraftIndicator = () => {};
|
||||
bar.init();
|
||||
// `null` is a press on the bar itself (padding, a gap): closest() finds no key.
|
||||
const press = (action: string | null) => {
|
||||
const preventDefault = vi.fn();
|
||||
listeners.mousedown({
|
||||
target: { closest: () => (action === null ? null : { dataset: { action } }) },
|
||||
preventDefault,
|
||||
});
|
||||
return preventDefault.mock.calls.length > 0;
|
||||
};
|
||||
return { bar, press };
|
||||
}
|
||||
|
||||
describe('accessory keys keep the terminal focused on press', () => {
|
||||
it('cancels the press default for keys that leave the keyboard up', () => {
|
||||
const { press } = loadBar();
|
||||
for (const action of [
|
||||
'scroll-up',
|
||||
'scroll-down',
|
||||
'arrow-left',
|
||||
'arrow-right',
|
||||
'tab',
|
||||
'shift-tab',
|
||||
'shift-left',
|
||||
'shift-right',
|
||||
'ctrl',
|
||||
'ctrl-o',
|
||||
'opt-enter',
|
||||
'esc',
|
||||
'effort-max',
|
||||
'clear-input',
|
||||
]) {
|
||||
expect(press(action), action).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('leaves keys that move focus or dismiss the keyboard alone', () => {
|
||||
const { press } = loadBar();
|
||||
for (const action of ['compose', 'readmymind', 'pick-path', 'paste', 'dismiss', 'init']) {
|
||||
expect(press(action), action).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('cancels only the arming tap of clear/compact, not the confirming one', () => {
|
||||
const { bar, press } = loadBar();
|
||||
bar._confirmAction = null;
|
||||
expect(press('clear')).toBe(true);
|
||||
bar._confirmAction = 'clear';
|
||||
expect(press('clear')).toBe(false);
|
||||
expect(press('compact')).toBe(true);
|
||||
bar._confirmAction = 'compact';
|
||||
expect(press('compact')).toBe(false);
|
||||
});
|
||||
|
||||
it('ignores a press outside a key', () => {
|
||||
const { press } = loadBar();
|
||||
expect(press(null)).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user