wear: tile Galaxy Watch per aprire i cancelli (relay dal telefono) #4

Merged
marcello merged 4 commits from feat/wear-tile into main 2026-09-29 13:02:00 +00:00
Owner

Cosa fa

Nuovo APK Wear OS (:wear) con una sola tile, Cancelli: un bottone per ogni cancello show_on_car (max 3), stato Aperto/Chiuso, tasto Aggiorna.

L'orologio non ha token: ogni tap è una LoadAction, la tile manda una richiesta Data Layer al telefono e il nuovo WearRelayService in :app esegue la chiamata con il JWT dell'app. Serve il telefono in portata e loggato.

Scelte non ovvie

  • payload e path in un modulo JVM condiviso (:wear-protocol), così i due APK non divergono
  • ogni clickable id ha un nonce e viene eseguito una volta sola (TileStore.consumeClick): un cancello non si riapre se una tile request successiva ripete l'ultimo id cliccato
  • :wear ha lo stesso applicationId e la stessa firma di :app (anche .debug): il Data Layer consegna solo tra APK gemelli
  • android_wear_capabilities con tools:keep: senza, lo shrinker della release lo toglieva (verificato con aapt2 sull'APK release)
  • versionCode watch da 1001: Play vuole codici unici su tutti gli APK del listing
  • nessuna modifica al backend: riusa ?car=true

C'è anche un commit separato con le impostazioni Gradle scritte da Android Studio (daemon JVM su JBR 21, foojay resolver, sync parallelo).

Verifiche

  • :app e :wear compilano in debug e release (R8)
  • lint :wear senza errori; lint :app con i soli 3 errori preesistenti
  • applicationId identico tra telefono e orologio in entrambi i variant

Non ancora provato su un orologio vero. Procedura e scenari di test in android/WEAR.md.

🤖 Generated with Claude Code

## Cosa fa Nuovo APK Wear OS (`:wear`) con una sola tile, **Cancelli**: un bottone per ogni cancello `show_on_car` (max 3), stato Aperto/Chiuso, tasto *Aggiorna*. L'orologio **non ha token**: ogni tap è una `LoadAction`, la tile manda una richiesta Data Layer al telefono e il nuovo `WearRelayService` in `:app` esegue la chiamata con il JWT dell'app. Serve il telefono in portata e loggato. ## Scelte non ovvie - payload e path in un modulo JVM condiviso (`:wear-protocol`), così i due APK non divergono - ogni clickable id ha un nonce e viene eseguito **una volta sola** (`TileStore.consumeClick`): un cancello non si riapre se una tile request successiva ripete l'ultimo id cliccato - `:wear` ha lo stesso `applicationId` e la stessa firma di `:app` (anche `.debug`): il Data Layer consegna solo tra APK gemelli - `android_wear_capabilities` con `tools:keep`: senza, lo shrinker della release lo toglieva (verificato con aapt2 sull'APK release) - `versionCode` watch da 1001: Play vuole codici unici su tutti gli APK del listing - nessuna modifica al backend: riusa `?car=true` C'è anche un commit separato con le impostazioni Gradle scritte da Android Studio (daemon JVM su JBR 21, foojay resolver, sync parallelo). ## Verifiche - `:app` e `:wear` compilano in debug e release (R8) - lint `:wear` senza errori; lint `:app` con i soli 3 errori preesistenti - `applicationId` identico tra telefono e orologio in entrambi i variant **Non ancora provato su un orologio vero.** Procedura e scenari di test in `android/WEAR.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Settings written by Android Studio on project sync: pin the Gradle daemon
JVM (gradle-daemon-jvm.properties), let Gradle download it through the
foojay resolver, and enable parallel tooling-API sync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New :wear APK with a single Wear OS tile listing the show_on_car gates
(max 3). The watch holds no token: each tap is a LoadAction, the tile
sends a Data Layer request to the phone, and the new WearRelayService in
:app runs the call with the app's JWT. The payloads live in the shared
:wear-protocol JVM module so the two APKs cannot drift.

Every clickable id carries a nonce and is acted upon once
(TileStore.consumeClick): a gate must never reopen because a later tile
request replayed the last clicked id. The phone's capability array is
tools:keep'd so the release resource shrinker cannot drop it. Install and
test steps in android/WEAR.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Galaxy Watch4 still on Wear OS 3 (minSdk 30) ships a tile renderer
older than schema 1.300, which ignores weight(): every gate button would
expand to the whole column and the first would cover the others. Detect
it from deviceConfiguration.rendererSchemaVersion and show at most two
48dp buttons there, without the state line unless a single gate is shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With a dead refresh token (expired, or a new jwt_secret on the bridge)
the /auth/refresh call went through the same refreshInterceptor, got a
401 and tried to refresh again. Each level blocked an OkHttp thread in
runBlocking on the next one; after five requests to the same host the
dispatcher queued the sixth forever and the app hung on the splash
("Pronto.") instead of falling back to the login screen.

Return a 401 from /auth/refresh untouched: the caller clears the tokens
and the splash routes to login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
marcello deleted branch feat/wear-tile 2026-09-29 13:02:00 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Soltea-org/skynet-ha!4
No description provided.