screentinker/android/app/src/main/java/com/remotedisplay/player
screentinker a15086540f
Some checks are pending
CI / Unit tests (node --test) (push) Waiting to run
CI / OpenAPI spec lint (push) Waiting to run
CI / Android unit tests (Kotlin schedule evaluator vectors) (push) Waiting to run
CI / Boot smoke + version check (push) Waiting to run
feat(widgets): directory-search widget (interactive search of a directory board, live-sync) (#188)
* feat(widgets): add directory-search widget

An interactive, walk-up search view of an existing directory-board. It
references a source board by id (no data copy), so a venue can run the
scrolling board on a main screen and a search view on a tablet, letting
people find an entry instantly.

Server (routes/widgets.js):
- register 'directory-search' + renderDirectorySearch(): resolves the source
  board, inlines its categories as one \u003c-guarded JSON blob, renders all
  text via textContent (XSS-safe), live case-insensitive filter over
  identifier/name/subtitle (debounced), grouped results, available styling,
  optional touch on-screen QWERTY keyboard that drives the same filter path.
- missing / non-directory-board source -> friendly full-page fallback, not a 500.
- live-sync while open is out of scope; left a // TODO for a poll hook.

Frontend editor (views/widgets.js): type + magnifier icon, source-board
dropdown (from loaded widgets, filtered to directory-board), title, logo
(reuses the board's picker), placeholder text, theme, on-screen-keyboard toggle;
getConfigFromForm case. i18n: widget.dirsearch.* + type keys in en/es/it/de/pt/fr.
docs: openapi widget_type enum. Tests: server/test/directory-search.test.js.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(widgets): live-sync for directory-search (poll source board, no reload)

Reflect directory-board edits on an open directory-search page without a reload.

- New public GET /api/widgets/:id/data.json returns { categories } for a
  directory-board (404 for missing/wrong-type so the page keeps last-good data
  on a transient miss). CORS-open (ACAO:*) + no-store so a null-origin sandboxed
  widget iframe can read it; exposes only data already public via /render.
  Exempted from CSP + auth in server.js alongside /render.
- directory-search page inlines its source_widget_id and polls the board's
  data.json every 30s via a relative URL (works behind a proxy/base path and
  from a null-origin iframe). Only rebuilds + rerenders when the data actually
  changed, so a mid-search view isn't disturbed; skips while document.hidden;
  keeps last-good data on any fetch error. Flatten logic factored into
  buildFlat() and reused by the poll.

Tests: data.json feed (categories, CORS header, 404s) + poll wiring in
directory-search.test.js (13/13). Verified live in a browser (page.clock
fast-forward): editing the board updates the search page with no reload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(android): let player WebViews take touch focus for interactive widgets

directory-search is served through the existing generic widget path
(loadUrl <server>/api/widgets/:id/render), so it already renders on Android
with JS + DOM storage + mixed-content enabled, same-origin (so its live-sync
fetch of the source board's data.json works), and no touch blocking.

Add isFocusable/isFocusableInTouchMode to the shared WebView config so the
search field reliably takes a tap/cursor inside the kiosk lock-task WebView.
Harmless for passive widgets (board/YouTube have no focusable inputs); the
widget's own on-screen keyboard still drives the filter when the system IME
is suppressed. Verified with :app:compileDebugKotlin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 08:00:22 -05:00
..
admin feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00
data feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00
player feat(device-owner): tier foundation + QR provisioning + content-expiry & device enhancements (#168) 2026-07-12 19:41:07 -05:00
remote feat(device-owner): tier foundation + QR provisioning + content-expiry & device enhancements (#168) 2026-07-12 19:41:07 -05:00
service feat(diagnostics): device incident log — offline cause, network-vs-reboot, display-sleep (#175) 2026-07-13 11:26:04 -05:00
system feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00
telemetry feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00
util feat(widgets): directory-search widget (interactive search of a directory board, live-sync) (#188) 2026-07-15 08:00:22 -05:00
MainActivity.kt feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00
OwnerAccessibilityActivity.kt feat(device-owner): tier foundation + QR provisioning + content-expiry & device enhancements (#168) 2026-07-12 19:41:07 -05:00
ProvisioningActivity.kt feat(device-owner): tier foundation + QR provisioning + content-expiry & device enhancements (#168) 2026-07-12 19:41:07 -05:00
RemoteDisplayApp.kt feat: app-ending signal (exit-signal contract v1) — server + APK + .wgt + /player 2026-07-08 15:32:40 -05:00
ScreenCapturePermissionActivity.kt fix(android): Android 14+ MediaProjection / foreground-service compliance (#5) 2026-06-08 17:19:56 -05:00
SetupActivity.kt feat(system-control): Tier 0/1 controls with no device-owner dependency (#160) (#169) 2026-07-12 20:48:47 -05:00