feat: integrate chat voice and diagnostics client

This commit is contained in:
Edison Jwa
2026-05-23 06:51:55 +09:00
parent 7e28791ec2
commit 7d5d8c2c90
93 changed files with 10273 additions and 3347 deletions
@@ -0,0 +1,185 @@
// SPDX-License-Identifier: Apache-2.0
// Chanora design tokens for connection, voice, and latency states.
// Maps abstract server/voice/network state to Material 3 colour, icon,
// and label affordances.
import 'package:flutter/material.dart';
/// Tokenised visual mapping for a connection state.
class ConnectionTokens {
final Color color;
final Color? background;
final IconData icon;
final String label;
const ConnectionTokens({
required this.color,
required this.icon,
required this.label,
this.background,
});
static ConnectionTokens disconnected(ColorScheme cs) => ConnectionTokens(
color: cs.onSurfaceVariant,
background: cs.surfaceContainerHighest,
icon: Icons.cloud_off,
label: 'Disconnected',
);
static ConnectionTokens connecting(ColorScheme cs) => ConnectionTokens(
color: cs.primary,
background: cs.primaryContainer,
icon: Icons.sync,
label: 'Connecting',
);
static ConnectionTokens synchronizing(ColorScheme cs) => ConnectionTokens(
color: cs.secondary,
background: cs.secondaryContainer,
icon: Icons.hourglass_top,
label: 'Synchronizing',
);
static ConnectionTokens connected(ColorScheme cs) => ConnectionTokens(
color: cs.tertiary,
background: cs.tertiaryContainer,
icon: Icons.cloud_done,
label: 'Connected',
);
static ConnectionTokens reconnecting(ColorScheme cs) => ConnectionTokens(
color: cs.error,
background: cs.errorContainer,
icon: Icons.restart_alt,
label: 'Reconnecting',
);
static ConnectionTokens lost(ColorScheme cs) => ConnectionTokens(
color: cs.error,
background: cs.errorContainer,
icon: Icons.warning_amber,
label: 'Connection Lost',
);
}
/// Tokenised visual mapping for a voice transmit/mute state.
class VoiceTokens {
final Color color;
final Color? background;
final IconData icon;
const VoiceTokens({
required this.color,
required this.icon,
this.background,
});
static VoiceTokens idle(ColorScheme cs) => VoiceTokens(
color: cs.onSurfaceVariant,
icon: Icons.mic_none,
);
static VoiceTokens pttHeld(ColorScheme cs) => VoiceTokens(
color: cs.primary,
background: cs.primaryContainer,
icon: Icons.mic,
);
static VoiceTokens voiceActivity(ColorScheme cs) => VoiceTokens(
color: cs.tertiary,
background: cs.tertiaryContainer,
icon: Icons.mic,
);
static VoiceTokens continuousTx(ColorScheme cs) => VoiceTokens(
color: cs.primary,
background: cs.primaryContainer,
icon: Icons.settings_voice,
);
static VoiceTokens muted(ColorScheme cs) => VoiceTokens(
color: cs.error,
background: cs.errorContainer,
icon: Icons.mic_off,
);
static VoiceTokens outputMuted(ColorScheme cs) => VoiceTokens(
color: cs.error,
icon: Icons.headset_off,
);
static VoiceTokens deafened(ColorScheme cs) => VoiceTokens(
color: cs.error,
background: cs.errorContainer,
icon: Icons.hearing_disabled,
);
}
/// Tokenised visual mapping for network latency/quality.
class LatencyTokens {
final Color color;
final String label;
const LatencyTokens({required this.color, required this.label});
static LatencyTokens good(ColorScheme cs) => LatencyTokens(
color: cs.tertiary,
label: 'Good',
);
static LatencyTokens warning(ColorScheme cs) => LatencyTokens(
color: cs.error,
label: 'Warning',
);
static LatencyTokens unknown(ColorScheme cs) => LatencyTokens(
color: cs.outlineVariant,
label: '',
);
}
/// Tokens for channel membership status.
class ChannelTokens {
final IconData? icon;
final String? label;
const ChannelTokens({this.icon, this.label});
static ChannelTokens inChannel(ColorScheme cs) => ChannelTokens(
icon: Icons.headset_mic,
label: 'Connected',
);
static ChannelTokens joining(ColorScheme cs) => ChannelTokens(
icon: Icons.login,
label: 'Joining...',
);
static ChannelTokens notInChannel(ColorScheme cs) => ChannelTokens(
icon: null,
label: null,
);
}
/// Tokens for PTT capability display.
class PttTokens {
final String label;
final Color? color;
const PttTokens({required this.label, this.color});
static PttTokens focused(ColorScheme cs) => PttTokens(
label: 'Keyboard PTT',
color: cs.tertiary,
);
static PttTokens platformHook(ColorScheme cs) => PttTokens(
label: 'Global PTT',
color: cs.primary,
);
static PttTokens none(ColorScheme cs) => PttTokens(
label: 'No PTT input',
color: cs.error,
);
}
@@ -0,0 +1,196 @@
// SPDX-License-Identifier: Apache-2.0
// SRS-115: Unsupported/degraded platform behaviours documentation.
// Describes what is available, degraded, or unavailable per platform.
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
/// Describes capability tier for a feature on a platform.
enum CapabilityTier { supported, degraded, unavailable }
/// A single platform capability description.
class PlatformCapability {
final String feature;
final String description;
final CapabilityTier tier;
const PlatformCapability({
required this.feature,
required this.description,
required this.tier,
});
}
/// Returns the current platform's capability matrix.
List<PlatformCapability> currentPlatformCapabilities() {
if (kIsWeb) {
return [
PlatformCapability(
feature: 'Audio',
description: 'Web audio is not supported in the beta.',
tier: CapabilityTier.unavailable,
),
];
}
if (Platform.isAndroid) {
return _androidCapabilities();
}
if (Platform.isIOS) {
return _iosCapabilities();
}
if (Platform.isMacOS) {
return _macosCapabilities();
}
if (Platform.isWindows) {
return _windowsCapabilities();
}
if (Platform.isLinux) {
return _linuxCapabilities();
}
return [];
}
List<PlatformCapability> _androidCapabilities() => [
const PlatformCapability(
feature: 'Voice capture',
description: 'Oboe AAudio backend; Bluetooth SCO supported.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Voice processing',
description: 'WebRTC AEC3/NS/AGC2, VAD via Silero ONNX.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Foreground service',
description: 'Persistent notification during active connection.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Global PTT hotkey',
description: 'Not available on Android.',
tier: CapabilityTier.unavailable,
),
const PlatformCapability(
feature: 'Audio device selection',
description: 'System-managed; wired/BT/SCO automatic routing.',
tier: CapabilityTier.degraded,
),
const PlatformCapability(
feature: 'Push-to-talk button',
description: 'Media button / volume-key binding supported.',
tier: CapabilityTier.supported,
),
];
List<PlatformCapability> _iosCapabilities() => [
const PlatformCapability(
feature: 'Voice capture',
description: 'VoiceProcessingIO AudioUnit (default); Sonora raw mode optional.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Voice processing',
description: 'Platform AEC/NS/AGC via VPIO; optional Rust AEC3/NS/AGC2 via Sonora.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Audio route switching',
description: 'Handles speaker/earpiece/Bluetooth route changes and interruptions.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Global PTT hotkey',
description: 'Not available on iOS.',
tier: CapabilityTier.unavailable,
),
const PlatformCapability(
feature: 'Background audio',
description: 'Supported via AVAudioSession background mode.',
tier: CapabilityTier.supported,
),
];
List<PlatformCapability> _macosCapabilities() => [
const PlatformCapability(
feature: 'Voice capture',
description: 'cpal device enumeration; VoiceProcessingIO optional.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Voice processing',
description: 'WebRTC AEC3/NS/AGC2; VPIO available on macOS.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Global PTT hotkey',
description: 'Supported via platform-global key-binding API.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Secure storage',
description: 'macOS Keychain.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Audio device selection',
description: 'System audio output route picker.',
tier: CapabilityTier.supported,
),
];
List<PlatformCapability> _windowsCapabilities() => [
const PlatformCapability(
feature: 'Voice capture',
description: 'WASAPI via cpal.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Voice processing',
description: 'WebRTC AEC3/NS/AGC2.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Global PTT hotkey',
description: 'Supported via platform-global hotkey binding.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Secure storage',
description: 'Windows Credential Manager / DPAPI.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Installer',
description: 'MSIX packaging not yet available in beta.',
tier: CapabilityTier.unavailable,
),
];
List<PlatformCapability> _linuxCapabilities() => [
const PlatformCapability(
feature: 'Voice capture',
description: 'PulseAudio/ALSA via cpal.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Voice processing',
description: 'WebRTC AEC3/NS/AGC2; no platform VPIO.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Global PTT hotkey',
description: 'Supported via X11/Wayland global key-binding. ',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Secure storage',
description: 'Secret Service / libsecret.',
tier: CapabilityTier.supported,
),
const PlatformCapability(
feature: 'Desktop environment',
description: 'DE-specific behaviour: screen locker may suspend audio.',
tier: CapabilityTier.degraded,
),
];