phimpal-tv
v0.2.3
Published
D-pad (TV remote) navigation for phimpal.com on Samsung Tizen TVs, as a TizenBrew site-modification module.
Readme
phimpal-tv
D-pad navigation for phimpal.com on a Samsung TV, shipped as a TizenBrew site-modification module. The Samsung browser's pointer is replaced by block-to-block navigation with the remote: focus rings, a card popup, a control-bar mode and a preview-based seek that never stutters the stream.
| File | Role |
|---|---|
| phimpal-tv.user.js | The source. Desktop test build (Tampermonkey), keyboard stands in for the remote |
| mod.js | Generated TV build injected by TizenBrew — do not edit by hand |
| build.js | Derives mod.js from the userscript (npm run build) |
| package.json | TizenBrew manifest |
| SPECS.md | Site analysis, key map, mode state machine, algorithms |
Remote keys
| Button | Everywhere | On the player | |---|---|---| | ↑ ↓ ← → | move the focus ring between blocks | ←/→ open the seek cursor, ↓ the control bar | | OK | open the focused item | fullscreen, then play/pause; commits a seek | | Return | back / close a menu / exit fullscreen | | | Play/Pause | direct Xem on a focused card | play/pause | | Ch ▲ / ▼ | previous / next row | ±5 min in the seek cursor |
Volume, Home and the app shortcuts stay with the TV. Colour keys are not used —
on the Frame's remote they only exist behind the 123 keypad.
Two behaviours worth knowing:
- Seeking never jumps immediately. ←/→ move a preview cursor along the red timeline with the site's own thumbnail; the step accelerates (10 s → 30 s → 1 min → 5 min). OK commits, Return cancels — nothing is re-buffered until you confirm.
- Cards open their popup on focus, exactly like the mouse hover: OK opens the title page, ↓ then OK plays straight away.
Install on the TV
Install TizenBrew on the Frame — follow the official guide (developer mode + TizenBrew Installer). Nothing here works without it.
Publish this module to npm — TizenBrew installs modules as npm packages:
cd phimpal-tizen npm run build # regenerates mod.js from the userscript npm login npm publish --access publicThe package name is
phimpal-tv(changenameinpackage.jsonif it is taken, e.g.@yourname/phimpal-tv).Add it in TizenBrew → module manager → add an NPM module → type the package name → launch it. TizenBrew opens
https://phimpal.com/, injectsmod.jsand registers the media/channel keys listed inpackage.json.First run: log in. The site is account-gated. Focus the email field, press OK, and the TV's on-screen keyboard appears; Return leaves the field. The session cookie persists in the webview, so this is a one-time chore.
Updating
Bump version in package.json, npm run build, npm publish, then update the module
in TizenBrew.
Desktop testing (before touching the TV)
Install phimpal-tv.user.js in Violentmonkey/Tampermonkey and open phimpal.com. The
keyboard emulates the remote:
| Keyboard | Remote | |---|---| | Arrows / Enter | D-pad / OK | | Esc or Backspace | Return | | Space | Play/Pause | | PageUp / PageDown | Ch ▲ / ▼ |
A badge in the top-right shows the current mode and the last key code. In the TV build
the badge is off; enable it on the TV by running localStorage['tv-debug'] = '1' once
(TizenBrew's dev console) and reloading.
What the TV build changes
build.js only flips a few switches, so both builds share one engine:
- keyboard emulation off — only real remote codes are accepted;
- the debug badge is off unless
tv-debugis set; - the pointer is hidden;
- the keys from
package.jsonare also registered defensively if the Tizen API is reachable.
Three TV-specific behaviours live in the engine itself:
- Return on the home page is not swallowed, so TizenBrew can close the module. Anywhere else it means back / close.
- Fullscreen has a fallback: if the webview refuses
requestFullscreen, the player is stretched over the viewport with CSS instead (header and footer hidden). - Hover menus are forced visible. The avatar menu is mounted on
mouseenterbut the site fades it in only while the element really matches:hover, which never happens with a remote — so the module reveals it itself.
If it freezes on the TV
Every key is intercepted before it is handled, so an exception inside the module used to swallow all input — that looked like a frozen cursor with a dead Return key. Since 0.2.1:
- Return ×3 within 1.5 s always resets the module (mode, menus, seek cursor) — the universal escape hatch.
- any exception is caught, the state is reset automatically, and a red box bottom-left
shows the error for 10 s. Photograph it: that text is the bug report. The last one is also
kept in
localStorage['tv-lasterror']. - page scans are memoised (a TV CPU was re-computing the same styles hundreds of times per
key), held keys are coalesced, and carousels are recognised structurally so paging also
works on Tizen ≤ 6.5, whose Chromium ignores
overflow-x: clip. - (0.2.2) a black box: the last 40 steps (key, mode, focus, scope, paging…) are written to
localStorage['tv-trace']as they happen. If a session ends in the middle of a key, the next launch shows the last 12 steps in the same red box for 25 s — so after a freeze, relaunch the module and photograph that box. - (0.2.2) a navigation scope (dialog/menu) now has to be on screen and contain something
focusable; an element merely carrying
role="dialog"cannot trap the keys any more, and a scope that refuses to close is ignored afterwards. - (0.2.3) low-gfx rendering on the TV: all CSS transitions,
backdrop-filter, and the filters/shadows on the card popup and the player are removed. A freeze with no error and no trace points at the renderer, not at the script — TV compositors are known to stall onbackdrop-blurand on a 500 ms transform over a row of 4K posters. Restore the site's effects withlocalStorage['tv-gfx'] = 'full'. - (0.2.3) the running version is announced bottom-right for 2 s at startup
(
PhimPal TV 0.2.3 · low-gfx). If you don't see the version you just published, TizenBrew is still serving a cached module: remove and re-add it in the module manager.
Known limits
- The per-track timing button (clock icon) in the subtitle panel is not reachable with the D-pad: it sits inside a track row and would trap horizontal moves.
- The hero row auto-rotates; if it moves under the focus, the focus jumps to the first visible card of that row.
- Selectors follow the site. Svelte's hashed classes are never used, but a redesign of the
cards, the carousels or the player would need a pass over
SPECS.md. - Tizen's WebKit is older than desktop Chrome; the engine sticks to ES5-compatible syntax
in spirit but does use
const/arrow functions/template literals, which Tizen 5.5+ (2020 Frame and newer) supports. For a 2017–2019 set, transpile before publishing.
