Fix DPAD/Menu key remaps leaking into login and other non-room pages

isRoomList() only matched the exact "/tv" room-list path, so the
"!isRoomList()" checks gating DPAD center/up/down/left/right and Menu
treated every OTHER page - including /login - as if it were inside a
room. Result: DPAD OK typed a literal space into focused text fields,
DPAD up/down typed 'p'/'n', and Menu typed 'x'.

Replaced with isInRoom() (path starts with "/tv/"), so these remaps
only apply on an actual room page. Also stopped BACK from reloading to
the room list from unrelated pages like /login, which discarded
whatever the user had typed and, since /tv requires auth, just bounced
straight back to /login anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K
This commit is contained in:
GGB
2026-09-17 20:28:47 +02:00
co-authored by Claude Sonnet 5
parent 3412357526
commit ba422bf089
@@ -30,15 +30,18 @@ import android.webkit.WebViewClient
* deshalb als Alias fuer die 'ContextMenu'-Taste, ausschliesslich fuer * deshalb als Alias fuer die 'ContextMenu'-Taste, ausschliesslich fuer
* diesen App-Anwendungsfall. * diesen App-Anwendungsfall.
* *
* DPAD Center/Up/Down (und die entsprechenden Medientasten) werden NUR * DPAD Center/Up/Down/Left/Right, Menu und die entsprechenden Medientasten
* innerhalb eines Raums remapped (Space/P/N - siehe Design-Spec). Auf der * werden NUR innerhalb eines Raums (Pfad "/tv/<id>") remapped - siehe
* Raumliste (/tv) haben sie dort keine Bedeutung: die Raumliste hat ihr * isInRoom(). Auf jeder anderen Seite (Raumliste "/tv", Login, Signup, ...)
* eigenes Tastaturschema (ArrowUp/ArrowDown/Enter, siehe tv-rooms.js auf * muessen sie unveraendert durchgereicht werden, sonst zerschiesst die
* der Website) und muss die echten, unveraenderten Tasten bekommen, sonst * Remapping-Logik dort Texteingaben. Zwei konkrete Bugs kamen genau daher,
* bewegt sich der Fokus zwischen den Raum-Kacheln nie (genau der Fehler, * dass frueher statt isInRoom() die Umkehrung von isRoomList() geprueft
* der beim ersten Hardware-Test auftrat: die Raumliste laed, aber keine * wurde (also "ueberall ausser der Raumliste"), was auch Login/Signup
* Taste tut etwas, weil DPAD_DOWN/CENTER als 'n'/Space statt als * einschloss: auf der Raumliste bewegte sich der Fokus zwischen den
* ArrowDown/Enter ankamen). * Raum-Kacheln nicht (DPAD_DOWN/CENTER kamen als 'n'/Space statt als
* ArrowDown/Enter an), und auf der Login-Seite tippte DPAD OK ein
* Leerzeichen in das fokussierte Textfeld statt das Formular zu bestaetigen
* (DPAD_CENTER kam als Space-Taste an statt als echtes Enter).
*/ */
class MainActivity : Activity() { class MainActivity : Activity() {
@@ -90,6 +93,7 @@ class MainActivity : Activity() {
private fun isFullscreen() = fullscreenView != null private fun isFullscreen() = fullscreenView != null
private fun isRoomList() = currentPath == "/tv" private fun isRoomList() = currentPath == "/tv"
private fun isInRoom() = currentPath.startsWith("/tv/")
private fun sendKey(keyCode: Int, shift: Boolean = false) { private fun sendKey(keyCode: Int, shift: Boolean = false) {
val metaState = if (shift) KeyEvent.META_SHIFT_ON else 0 val metaState = if (shift) KeyEvent.META_SHIFT_ON else 0
@@ -115,11 +119,12 @@ class MainActivity : Activity() {
* Tastendrucks abgefangen wird (sonst haengt Chromiums interner * Tastendrucks abgefangen wird (sonst haengt Chromiums interner
* Tastenstatus fest, weil ein Keydown ohne passendes Keyup ankaeme). */ * Tastenstatus fest, weil ein Keydown ohne passendes Keyup ankaeme). */
private fun shouldIntercept(keyCode: Int): Boolean = when (keyCode) { private fun shouldIntercept(keyCode: Int): Boolean = when (keyCode) {
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK -> true
KeyEvent.KEYCODE_MENU -> true KeyEvent.KEYCODE_MENU -> isRoomList() || isInRoom()
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_MEDIA_NEXT -> !isRoomList() KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_MEDIA_NEXT -> isInRoom()
else -> false else -> false
} }
@@ -136,8 +141,13 @@ class MainActivity : Activity() {
KeyEvent.KEYCODE_MENU -> sendKey(KeyEvent.KEYCODE_X) KeyEvent.KEYCODE_MENU -> sendKey(KeyEvent.KEYCODE_X)
KeyEvent.KEYCODE_BACK -> when { KeyEvent.KEYCODE_BACK -> when {
isRoomList() -> { /* verschluckt, keine weitere Aktion */ } isRoomList() -> { /* verschluckt, keine weitere Aktion */ }
isFullscreen() -> sendKey(KeyEvent.KEYCODE_ESCAPE) isInRoom() && isFullscreen() -> sendKey(KeyEvent.KEYCODE_ESCAPE)
else -> webView.loadUrl(BuildConfig.WEBSITE_URL) isInRoom() -> webView.loadUrl(BuildConfig.WEBSITE_URL)
/* Login/Signup/sonstige Seiten: nichts tun, statt zur Raumliste
zu reloaden - sonst gehen unfertig ausgefuellte Formulare
verloren, und da /tv Login voraussetzt, landete man dort
sofort wieder auf der Login-Seite. */
else -> { /* verschluckt, keine weitere Aktion */ }
} }
} }
return true return true