BACK's isFullscreen()/navigate-away logic ran entirely on the Android
side, with no idea whether the website's Menu popup was open - so
pressing Back while the popup was showing jumped straight to the room
list (or reloaded) instead of closing it, since Android can't observe
JS-side modal state.
BACK now just relays a real Escape keypress into the page whenever
we're on a page this app controls (room list or in-room), and lets
the website's own keydown handler - which already knows about the
popup, cinema mode, and (now) fullscreen state - decide what Escape
should do. Removed the now-dead isFullscreen()/fullscreenView-reading
code path (fullscreenView itself stays: WebChromeClient still needs
onShowCustomView/onHideCustomView for HTML5 fullscreen to render).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K
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
- Menu key: WebView refuses to forward Android "system" keycodes
(KEYCODE_MENU among them) to page JS, confirmed via diagnostic
logging (downConsumed=false even though the key reaches
dispatchKeyEvent). Relay it as KEYCODE_X instead - room.js on the
website side treats 'x' as an alias for the ContextMenu trigger.
- DPAD center/up/down/media keys are now only remapped inside a room
(shouldIntercept() gates on isRoomList()) - the room-list page uses
plain ArrowUp/ArrowDown/Enter and never moved focus when those keys
arrived pre-remapped as Space/P/N.
- Removed a leftover cleartextTrafficPermitted="true" left over from
local LAN debugging against a docker instance.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K
dispatchKeyEvent() intercepts DPAD/media keys and re-dispatches real
KeyEvents into the WebView per the design spec's mapping table:
- DPAD center / Play-Pause -> Space
- DPAD Left/Right tap -> Arrow (5s seek); held -> Shift+Arrow (30s
seek), throttled to ~1 event/200ms since Android's own key-repeat
rate would otherwise flood the room's sync socket
- DPAD Up/Down + media Prev/Next -> P/N (title change, not
ArrowUp/Down - those are explicit no-ops in the website's TV mode
since volume is TV/AVR-controlled)
- Back: room list -> no-op; in a room + fullscreen -> Escape
(browser exits fullscreen natively); in a room + not fullscreen ->
navigate to /tv (native WebView navigation, not a website reaction)
- Menu (KEYCODE_MENU) deliberately NOT intercepted - passed through
unchanged, matching the already-confirmed-working raw-browser test
Fullscreen state comes from WebChromeClient.onShowCustomView/
onHideCustomView (needed for HTML5 video fullscreen support anyway).
Current-page tracking comes from WebViewClient.onPageFinished.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K
Gradle wrapper pinned to 8.7, AGP 8.5.2, compileSdk 34/minSdk 21/
targetSdk 34 - the tested combination from the original app.
MainActivity is a placeholder that just loads BuildConfig.WEBSITE_URL
(the new /tv room-list route); the real key-mapping logic is a
separate follow-up commit.
Note for future builds on this machine: Android Studio's bundled JBR
is JDK 25, which Gradle 8.7 cannot run on at all (crashes at startup
with a bare version-string error). Built and verified with a
separately-installed Temurin JDK 21 instead
(C:\Users\GGB\jdks\jdk-21.0.12.1+1) - set JAVA_HOME to that for any
Gradle command in this repo, not the Android Studio JBR.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K