Files
chanora/crates/chanora_storage
EdisonJwa 8cd919cffc fix(audio,storage,ui): allow PTT binding before audio is running
Save-binding before joining a voice channel used to return
BridgeError.invalidCommand(audio not started) because the
PttController only exists after start_audio runs and
set_ptt_binding required a live controller. Users naturally want
to bind their PTT key once on first launch, not every time they
join a channel — fix:

* chanora_storage::IdentityFileStore::set_ptt_binding /
  get_ptt_binding persist the privacy-safe binding triple
  (input_class, platform_key, key_label) into audio_meta.json
  next to transmit_mode and release_tail_ms.
* ChanoraSession holds pending_binding: Arc<Mutex<Option<PttBinding>>>.
  set_ptt_binding now (1) persists to storage best-effort, (2)
  stashes into pending_binding, (3) forwards live to the
  controller only if one exists. No more AudioNotStarted.
* init_storage loads the persisted binding into pending_binding
  so it survives app restarts.
* start_audio applies pending_binding immediately after constructing
  the PttController so the first key-press after join already works.
* supervisor_loop carries pending_binding and re-applies it after
  any reconnect-driven audio engine restart, so reconnects don't
  silently drop the hotkey.
* New bridge call get_ptt_binding() -> (input_class, key_label) plus
  a matching Flutter _hydratePttBinding() in initState lets the
  Voice Bar show the user's saved hotkey label on launch (e.g.
  'PTT: Space') before any voice channel is joined.

cargo test --workspace --lib: 72 passed / 0 failed / 1 ignored.
flutter analyze: clean (6 pre-existing Radio.groupValue infos).
FRB bindings regenerated.
2026-05-15 23:45:20 +08:00
..