Commit Graph
2 Commits
Author SHA1 Message Date
bonaminandClaude Opus 5.5 a486e3ff63 feat(waiter): native pairing, venue switcher, QR scanner, Android back handling
- First run in the native app shows only the pairing screen (VenuesPage):
  scan the manager's pairing QR or type the server address; the server must
  answer /api/system/identity as xenia-pos with a supported api_version, and
  a QR's ?pair=<site_id> must match - a code from another venue is refused
- /venues (native only): list of paired venues, switch (reloads into that
  venue's own token/IndexedDB), remove (data kept - may hold unsynced
  orders). Reachable from the login screen, the user menu and the offline page
- QrScannerModal: WebView camera via qr-scanner (no Google Play Services
  dependency, carries over to iOS); requests the camera once up front so the
  Android prompt appears a single time and "denied" gets its own message
- Hardware back: @capacitor/app listener - no-op on root screens (/, /tables,
  /login), otherwise history back. Path-based because Chrome's history
  intervention makes the WebView report canGoBack=false for the sentinel
  entry AndroidBackGuard pushes
- Before pairing no IndexedDB is opened, so nothing is created under the
  un-namespaced name
- InstallAppBanner now shows in plain-HTTP browser mode only when the venue
  server actually serves the APK (HEAD /downloads/xenia-waiter.apk)

Verified on an Android 15 emulator (API 35) with real taps via adb and state
via WebView DevTools: wrong address -> error; other venue's QR -> refused;
pairing -> venue-namespaced storage, live WebSocket; back on /tables keeps the
app open; restart keeps venue + session; second venue pairs logged-out and
switching back keeps venue 1's session; camera deny -> one prompt + message;
allow -> live preview. Signed release APK installed and paired. Web modes
(same-origin, plain-HTTP LAN IP, VITE_SERVER_URL) re-verified in Edge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:31:23 +03:00
bonaminandClaude Opus 5.5 18012c2c95 feat(waiter): configurable server/venue layer for native app and plain-HTTP browser mode
New waiter_pwa/src/config/server.js is the single place that knows where the
backend is. Served by the venue's server (https domain or http://<LAN IP>)
nothing changes: same-origin URLs and the original storage keys, so existing
installs keep their token and unsynced offline queue. With an active venue
(native app, or dev builds with VITE_SERVER_URL) URLs become absolute and all
venue data is namespaced by siteId: token/savedUsername keys, the Dexie DB
(pos_snapshot__<siteId>, which also covers the WS cursor), favorites and
table-view prefs. Switching venue reloads the app.

- api client baseURL, WebSocket and SSE URLs routed through the layer
- product images / waiter avatars rendered via assetUrl()
- service-worker update prompt skipped in native builds
- InstallAppBanner: shown only in plain-HTTP browser mode and only when
  VITE_APP_DOWNLOAD_URL is set at build time (dismiss for 7 days)
- VITE_SERVER_URL override is DEV-only (a URL-controlled server in prod would
  let a crafted link capture PINs)
- pack README: rule CS-8 on never assuming same-origin

Verified with Playwright/Edge against a local backend: prod build same-origin,
prod build via LAN IP over plain HTTP (insecure context, no SW, banner shown),
and dev build pointed at the backend by URL - all three log in, reach /tables
and receive the WebSocket 'ready' frame; storage keys and IndexedDB names are
as expected. Lint: no new problems (103 before/after). Build passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:38:42 +03:00