mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-16 07:13:12 -06:00
Directory search: don't let the platform keyboard cover our own (#275)
The directory-search widget draws its own on-screen keyboard, on by default, sized and themed to the panel. On Android it was never visible: the page autofocuses a real <input>, which is the signal to raise the system IME, and that lands over the bottom of the screen — exactly where our keyboard is. So a directory panel showed Google's keyboard instead of the one the widget ships: split across a 1920x1080 screen, with mic, GIF, emoji, clipboard and a settings key that opens Google's own UI on a kiosk. On the panel that turned this up, the system keyboard WAS voice input — the only enabled IME was Google's voice IME, so touching the search box opened a microphone, on a wall-mounted tenant directory. When we draw a keyboard, the input now carries inputmode="none", so the platform leaves its keyboard down. The buttons write input.value directly, so nothing about typing changes. Browsers that don't know inputmode ignore it, which is the right fallback — a desktop preview behaves exactly as before. Gated on the flag, not applied to the markup: with show_onscreen_keyboard off there is nothing to cover, and the platform keyboard is the only way left to type. Verified by removing the line and watching the new guard fail. 1669/1669 pass.
This commit is contained in:
parent
04a2ad99d1
commit
702e107972
|
|
@ -1206,6 +1206,14 @@ function renderDirectorySearch(c) {
|
||||||
|
|
||||||
// ----- on-screen keyboard (drives the same filter path as typing) -----
|
// ----- on-screen keyboard (drives the same filter path as typing) -----
|
||||||
if (cfg.show_onscreen_keyboard) {
|
if (cfg.show_onscreen_keyboard) {
|
||||||
|
/* Tell the platform not to raise ITS keyboard for this field. We autofocus a real
|
||||||
|
<input>, which on Android is the signal to throw the system IME over the bottom of
|
||||||
|
the screen - directly on top of the keyboard we draw below, so a directory panel
|
||||||
|
showed Google's keyboard (mic, GIF and emoji keys included) and never showed its
|
||||||
|
own. The buttons write input.value directly, so suppressing the platform keyboard
|
||||||
|
costs nothing here. Ignored by browsers that don't know inputmode, which is the
|
||||||
|
right fallback: a desktop preview keeps behaving exactly as before. */
|
||||||
|
input.setAttribute('inputmode', 'none');
|
||||||
var kb = document.getElementById('keyboard');
|
var kb = document.getElementById('keyboard');
|
||||||
function press(ch) { input.value += ch; try { input.focus(); } catch(e){} onInput(); }
|
function press(ch) { input.value += ch; try { input.focus(); } catch(e){} onInput(); }
|
||||||
['1234567890','qwertyuiop','asdfghjkl','zxcvbnm'].forEach(function(r){
|
['1234567890','qwertyuiop','asdfghjkl','zxcvbnm'].forEach(function(r){
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,24 @@ test('show_onscreen_keyboard flag is carried into the page config', async () =>
|
||||||
assert.ok(html.includes('"show_onscreen_keyboard":false'), 'keyboard flag inlined (page hides the keyboard when false)');
|
assert.ok(html.includes('"show_onscreen_keyboard":false'), 'keyboard flag inlined (page hides the keyboard when false)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('the built-in keyboard suppresses the platform one', async () => {
|
||||||
|
// The page autofocuses a real <input>, which on Android raises the system IME over the
|
||||||
|
// bottom of the screen - covering the keyboard this widget draws itself. A panel showed
|
||||||
|
// Gboard, complete with a mic key, and never showed its own keyboard.
|
||||||
|
seed('search_kb_on', 'directory-search', { source_widget_id: 'board1', show_onscreen_keyboard: true });
|
||||||
|
const { html } = await fetchRender('search_kb_on');
|
||||||
|
assert.ok(/setAttribute\(\s*'inputmode'\s*,\s*'none'\s*\)/.test(html),
|
||||||
|
'page tells the platform not to raise its own keyboard');
|
||||||
|
|
||||||
|
// Only when we are drawing one. With the built-in keyboard off there is nothing to cover,
|
||||||
|
// and the platform keyboard is the only way left to type.
|
||||||
|
seed('search_kb_off2', 'directory-search', { source_widget_id: 'board1', show_onscreen_keyboard: false });
|
||||||
|
const off = await fetchRender('search_kb_off2');
|
||||||
|
assert.ok(off.html.includes('"show_onscreen_keyboard":false'), 'flag inlined as false');
|
||||||
|
assert.ok(!/inputmode="none"/.test(off.html),
|
||||||
|
'the input is not statically marked inputmode=none - suppression is gated on the flag at runtime');
|
||||||
|
});
|
||||||
|
|
||||||
test('missing source -> friendly fallback page, not a 500', async () => {
|
test('missing source -> friendly fallback page, not a 500', async () => {
|
||||||
seed('search_missing', 'directory-search', { source_widget_id: 'does-not-exist' });
|
seed('search_missing', 'directory-search', { source_widget_id: 'does-not-exist' });
|
||||||
const { status, html } = await fetchRender('search_missing');
|
const { status, html } = await fetchRender('search_missing');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue