Stage 397: PR #2706 — fix: tablet hardware keyboard Enter sends (treat iPad with attached keyboard like desktop)

Co-authored-by: dobby-d-elf <dobby-d-elf@users.noreply.github.com>
This commit is contained in:
Hermes Agent
2026-05-21 17:13:52 +00:00
parent 958762bcfe
commit 345762cf70
2 changed files with 27 additions and 3 deletions
+9 -3
View File
@@ -1022,6 +1022,11 @@ let _imeComposing=false;
})();
function _isImeEnter(e){return e.isComposing||e.keyCode===229||_imeComposing;}
window._isImeEnter=_isImeEnter;
function _isVirtualKeyboardLikelyOpen(){
const vv=window.visualViewport;
if(!vv||!window.innerHeight)return true;
return window.innerHeight-vv.height>120;
}
$('msg').addEventListener('keydown',e=>{
// Autocomplete navigation when dropdown is open
const dd=$('cmdDropdown');
@@ -1039,13 +1044,14 @@ $('msg').addEventListener('keydown',e=>{
}
}
// Send key: respect user preference.
// On touch-primary devices (software keyboard), default to Enter = newline
// since there's no physical Shift key. Users send via the Send button.
// On touch-primary devices with the software keyboard open, default to
// Enter = newline since there's no physical Shift key. Hardware keyboards on
// tablets keep desktop behavior when the viewport is not keyboard-shrunk.
// The 'ctrl+enter' setting also uses this behavior (Enter = newline).
// Users can override in Settings by explicitly choosing 'enter' mode.
if(e.key==='Enter'){
if(_isImeEnter(e)){return;}
const _mobileDefault=matchMedia('(pointer:coarse)').matches&&window._sendKey==='enter';
const _mobileDefault=matchMedia('(pointer:coarse)').matches&&window._sendKey==='enter'&&_isVirtualKeyboardLikelyOpen();
if(window._sendKey==='ctrl+enter'||_mobileDefault){
if(e.ctrlKey||e.metaKey){e.preventDefault();send();}
} else {
+18
View File
@@ -1188,6 +1188,24 @@ def test_mobile_enter_newline_uses_match_media():
"boot.js must use matchMedia('(pointer:coarse)') for mobile detection"
def test_mobile_enter_newline_checks_virtual_keyboard_viewport():
"""Touch devices should only force newline while the software keyboard is likely open."""
boot_js = (REPO / "static" / "boot.js").read_text(encoding="utf-8")
assert "function _isVirtualKeyboardLikelyOpen()" in boot_js, \
"boot.js must isolate the software-keyboard viewport heuristic"
assert "window.visualViewport" in boot_js and "window.innerHeight-vv.height>120" in boot_js, \
"software-keyboard detection must compare visualViewport height against window.innerHeight"
assert "&&_isVirtualKeyboardLikelyOpen()" in boot_js, \
"mobile Enter newline override must not apply when a hardware keyboard leaves the viewport unshrunk"
def test_mobile_enter_newline_preserves_legacy_fallback_without_visual_viewport():
"""Browsers without visualViewport should keep the previous touch Enter=newline behavior."""
boot_js = (REPO / "static" / "boot.js").read_text(encoding="utf-8")
assert "if(!vv||!window.innerHeight)return true;" in boot_js, \
"missing visualViewport support must preserve the legacy touch-primary newline fallback"
def test_mobile_enter_newline_only_overrides_enter_default():
"""Mobile newline override must only apply when _sendKey is the default 'enter'."""
boot_js = (REPO / "static" / "boot.js").read_text(encoding="utf-8")