# Changelog All notable changes to Chanora will be documented in this file. This project follows a Conventional Commits style workflow. ## [v0.3.0] — Cross-platform voice client baseline The v0.3.0 milestone transitions Chanora from an internal-beta voice prototype to a cross-platform baseline client with event-driven UI, visible per-client audio state, non-self client info parity, and documented host Rust workspace plus Flutter validation gates. Android target compile/install/smoke evidence remains blocked locally pending the required NDK compiler and an authorized ADB target. ### Added - **Event-driven UI** replaces timer-based snapshot polling. Protocol deltas (client join/leave/move/update, channel add/remove/update) flow through a typed `ProtocolDelta` enum and update the Flutter UI in real time. Channel switching is instant. - **Per-client audio state visibility.** Client rows surface muted/deafened state in avatar badges. Per-user volume UI, persistence, and mixer wiring remain tracked as follow-up work. - **Non-self client info parity with Qint.** The Info tab now populates connection metadata (name, description, created, last connected, connections, transfer, ping deviation) for other clients via an explicit `ClientProfileRefreshPlan` that fetches `connectioninfo` and recent text messages with a bounded timeout. - **Ping deviation in client profiles.** `ping_deviation_milliseconds` propagated from protocol DTO through bridge API to Dart, with a conditional l10n row in the client info sheet (en + zh). - **Apple CoreML Silero VAD scaffolding/assets** for iOS / macOS when the private `silero-coreml` SwiftPM package is available. Product `VoiceActivity` remains reserved/disabled per DEC-030 until a later baseline enables and verifies it. - **TeamSpeak address resolver** (`chanora_resolver`) for DNS SRV lookups and `ts3server://` URI handling. - **Per-ABI Android APK splitting.** `flutter build apk --split-per-abi` produces separate arm64-v8a / armeabi-v7a / x86_64 APKs instead of a single fat APK. - **Cross-platform CI** (GitHub Actions): cargo check + test, cargo deny, cargo about license inventory, flutter analyze, flutter test, flutter iOS unsigned release build. All gates must pass before merge. - **Diagnostic recording.** Bridge events, audio interruptions, and Rust-level log entries are captured into an in-memory ring buffer accessible from the diagnostics page. - **Shared app snackbar styling** for consistent error/info feedback. ### Changed - **iOS / macOS audio lifecycle hardened.** Voice unit restart-in-place, serialized lifecycle events, WebRTC VAD on iOS, unblocked connect-time audio startup. - **Linux native audio path promoted** with ONNX Runtime VAD assets bundled for future `VoiceActivity` work. Desktop voice I/O works on PipeWire / PulseAudio; product `VoiceActivity` remains disabled. - **Android audio routing** uses `MODE_IN_COMMUNICATION`, proper startup permission flow, and system back-button integration. - **`SnapshotChanged` event removed.** Replaced by the typed delta stream. The dead variant was removed end-to-end (protocol, bridge, Flutter). - **Prefetch crate renamed** from the PoC-era name to `chanora_prefetch`. All docs, specs, and code updated. - **Flutter app version/build bumped to `0.3.0+100`.** Rust workspace packages remain versioned separately at `0.2.0-beta.1`. - **Flutter bridge regenerated** for `flutter_rust_bridge` 2.12.0. ### Fixed - **`clamp` panic on Info tab open.** `adapter.rs` cast `i64::MIN` to `u128` before clamping, producing `min > max`. Replaced with `.min(i64::MAX as u128) as i64`. - **Non-self client profiles empty.** Added `request_client_db_info()` with graceful fallback for missing fields. - **Server query clients visible in UI.** Delta joins now filter `is_server_query` clients from the channel tree. - **Speaking indicators lost after reconnect.** Event forwarders are reattached after the connection task restarts. - **Channel double-tap join.** 1-second cooldown prevents rapid re-join attempts. - **`getconnectioninfo` errors silently discarded.** Now logged at warning level instead. - **iOS keyboard lag.** Multiple focus/tap handling fixes for iOS 26 `TextField` stale-focus regression. - **Storage test isolation.** Temp directories no longer collide across parallel test runs. - **CI submodule fetch.** iOS build job uses best-effort `git submodule update` with `|| true` fallback for the private `silero-coreml` package. - **Stale license inventory.** Regenerated `docs/security/license- inventory.md` to match current `Cargo.lock`. ### Notes - The `silero-coreml` submodule references a private repository (`chanoraapp/silero-coreml`). CI builds skip the iOS unsigned build when the submodule is unavailable. - Default base branch is `main` (previously `product/scaffold-v0`). - DSP chain (AEC / AGC / NS / HPF) is not yet production-tuned. `AudioEffects` struct exists but filters are placeholder-grade. - Desktop push-to-talk is capability-based; global PTT requires OS-specific permissions and is not yet wired end-to-end in the UI. ## [v0.2.0-beta.1] — Internal Beta first build - **Voice in/out wired end-to-end through the Flutter UI.** Per DEC-001 this reaches the Internal Beta milestone. - `crates/chanora_audio/` promoted from scaffold to working engine: cpal capture (mic gain, linear resampling to 48 kHz, mono down-mix) and playback (48 kHz stereo). Opus VoIP encoding (20 ms frames). Push-to-talk gate. Live counters. - `crates/chanora_protocol/` extended with voice channels. - `core/chanora_core::ChanoraSession` audio API. - `crates/chanora_bridge/` audio surface for Dart. - Beta UI rewrite with connect, PTT, and audio stats. ### Notes - DSP chain not yet implemented (AEC / AGC / NS / HPF deferred). - Capture resampler is linear interpolation (production resampler deferred). - Identity is ephemeral per connect; persistence deferred. - No live event stream — UI polls on timer. - `chanora_diagnostics` still scaffold. - Audio engine is desktop-only in this build. ## [v0.1.0-alpha.1] — Internal Alpha - First Alpha build wires connect → snapshot → disconnect end-to-end from the Flutter UI to a live TeamSpeak-compatible server via the typed Flutter/Rust bridge. - `crates/chanora_protocol/` promoted from scaffold to working adapter. - `crates/chanora_bridge/` wired against `flutter_rust_bridge` 2.12.0. - Alpha UI: server address form, connect button, snapshot view. ## Versioning note The project implementation has not reached a public release version yet.