# Flutter Framework Upstream Bugs and Workarounds Tracking document for Flutter framework issues that require Chanora-specific workarounds. --- ## 1. Flutter AdaptiveScaffold Discontinued **Flutter issue:** [flutter/flutter#162965](https://github.com/flutter/flutter/issues/162965) **Impact:** Chanora's adaptive 3-panel layout cannot use the built-in `AdaptiveScaffold` widget because it has been discontinued by the Flutter team. A custom breakpoint-based layout system was required. **Workaround:** Chanora implements its own centralized breakpoint system with three layout classes (compact, medium, expanded) using a custom `LayoutBuilder` approach. The breakpoint constants and layout policy are documented in [docs/ui-ux/adaptive-layout-platform-guide.md](../ui-ux/adaptive-layout-platform-guide.md). **Relevant code:** - Design spec: `docs/superpowers/specs/2026-06-05-adaptive-3-panel-layout-design.md` - Breakpoint thresholds follow Material 3 canonical breakpoints (600dp compact, 840dp medium, ≥1024dp expanded). **Status:** Workaround in place. No Flutter fix expected; this is a permanent design divergence. --- ## 2. Flutter Lacks Native Audio Session Management **Flutter issue:** No unified Flutter issue; this is a fundamental platform abstraction gap. Flutter's `audioplayers` and similar packages do not expose per-platform audio session lifecycle (iOS `AVAudioSession`, Android `AudioFocus`, macOS Core Audio). **Impact:** Chanora must manage audio focus, interruption handling, and route changes natively on each platform and bridge them to Dart via `MethodChannel`. **Workaround:** Chanora implements platform-specific audio lifecycle management: | Platform | Native Implementation | Dart Bridge | |----------|-----------------------|-------------| | iOS | `AppDelegate.swift` — AVAudioSession category/route/interruption observers | `chanora/ios_audio_lifecycle` MethodChannel | | Android | `AndroidAudioFocusController.kt` — AudioFocus request/abandon with `OnAudioFocusChangeListener` | `chanora/android_audio_lifecycle` MethodChannel | | macOS | `MacOSAudioLifecycle` — Core Audio HAL default-device and stream-format change observers | `chanora/macos_audio_lifecycle` MethodChannel | **Relevant code:** - Dart dispatcher: `apps/chanora_flutter/lib/services/audio_lifecycle_service.dart` - iOS native: `apps/chanora_flutter/ios/Runner/AppDelegate.swift` - Android native: `apps/chanora_flutter/android/app/src/main/kotlin/app/chanora/chanora_flutter/AndroidAudioFocusController.kt` - macOS native: `apps/chanora_flutter/macos/` **Status:** Ongoing. Each platform's MethodChannel handler catches and swallows errors from the Rust side to prevent exception propagation back through the platform framework (a Flutter restriction on `MethodChannel` handlers). --- ## 3. macOS Default-Device Change Not Exposed to Flutter **Flutter issue:** No Flutter issue filed. Flutter's desktop audio support does not expose Core Audio HAL default-input/output device change notifications. **Impact:** When the user changes the default audio device on macOS (e.g., plugging in headphones), the Chanora audio engine does not automatically rebind to the new device. **Workaround:** The macOS `MethodChannel` (`chanora/macos_audio_lifecycle`) receives `handleDefaultDeviceChange` and `handleConfigurationChange` events from native Swift code, but the corresponding Rust-side FRB bridge function (`macosDefaultDeviceChanged`) is not yet exposed via `flutter_rust_bridge`. Events are captured and logged for observability only. **Relevant code:** - `apps/chanora_flutter/lib/services/audio_lifecycle_service.dart:150-157` — macOS handler with TODO markers - `apps/chanora_flutter/lib/services/audio_lifecycle_service.dart:151` — `// TODO: call rust.macosDefaultDeviceChanged() once exposed` **Status:** Partial workaround. Requires `flutter_rust_bridge` update to expose the Rust function. --- ## 4. iOS Audio Session Activation Ordering **Flutter issue:** No Flutter issue filed. Flutter does not provide a mechanism to coordinate audio session activation with network connection establishment. **Impact:** On iOS, the `AVAudioSession` must be activated before the voice channel join RPC, and deactivated on failure. Without careful ordering, audio may be left in an active state after a failed join, or the session may not be active when the audio engine starts. **Workaround:** Chanora implements an explicit ordering function `joinVoiceChannelWithIosAudioSession` that activates the iOS audio session, attempts the voice join, and deactivates on failure. A `VoiceJoinSuccessPredicate` allows callers to treat certain errors (e.g., "already in channel") as successful joins, keeping the audio session active. **Relevant code:** - `apps/chanora_flutter/lib/services/voice_join_ordering.dart` — Full implementation - The `activateIosAudioSession`/`deactivateIosAudioSession` callbacks are provided by the iOS native side via `AppDelegate.swift`. **Status:** Workaround in place. This is an inherent platform design requirement rather than a Flutter bug.