Two user-reported issues addressed:
1. 'on supported devices such as iphone or android user should be
able to select audio device such as speaker or airpods or phone'
2. 'the bottom folder is duplicated with the app bar settings'
Issue 1 \u2014 audio output route picker:
Added the audio_router 1.1.1 plugin (MIT, supports iOS + Android)
which renders the platform-native picker:
* iOS: Apple AVRoutePickerView system sheet \u2014 the same UI as
Control Center's audio chooser. Lists Speaker / iPhone receiver /
AirPods / connected Bluetooth devices / AirPlay / CarPlay.
System manages the device list; we don't have to track route
changes manually.
* Android (post-rc.8 when we wire the platform): Material Design 3
dialog backed by AudioManager.setCommunicationDevice() with
SCO Bluetooth + USB headsets filtered for VoIP.
The picker prerequisite documented by the plugin (audio session
must be playAndRecord/voiceChat before the picker fires) is already
satisfied by our AppDelegate.swift configuration from commit 0466000.
The new _AudioOutputTile widget in voice_compact.dart subscribes to
AudioRouter.currentDeviceStream so the row label + icon auto-update
when the user plugs in headphones, connects AirPods, etc. \u2014 no
manual KVO observation needed.
Tile is mobile-only (Platform.isIOS || Platform.isAndroid). Desktop
hosts continue to use the system mixer; the tile is hidden.
Plugin caveat: the published enum AudioSourceType has no .usb
variant (despite README mentioning USB support). We map only the
seven real enum cases: builtinSpeaker / builtinReceiver / bluetooth /
wiredHeadset / carAudio / airplay / unknown.
Issue 2 \u2014 collapse voice controls into the single modal sheet:
The AppBar gear icon (Icons.tune) that opened VoiceSettingsDialog
was removed. It duplicated the configuration entry point that the
status chip \u2192 modal-sheet path already provides, and the user found
that duplication confusing on a phone-narrow screen where AppBar
real estate is precious.
The voice modal sheet (showVoiceDetailsSheet) is now the **single**
voice-controls surface on mobile, with layout (top to bottom):
1. Audio output route picker tile (iOS / Android only) \u2014 new.
2. Mode + bind / release-tail recap (display only).
3. 'Adjust mode & release tail' OutlinedButton that closes the
sheet and opens the same VoiceSettingsDialog the gear icon
used to open. One config form, not two.
4. Mic level meter.
5. TX / RX frame counts + mic state.
6. PTT capability badge (desktop only).
Sheet title renamed from 'Voice settings' (which collided with the
gear-icon tooltip) to 'Voice'. New l10n keys: voiceSheetTitle,
voiceAdjustSettings, audioOutputLabel, audioRoute{Speaker,Receiver,
Bluetooth,WiredHeadset,CarAudio,Airplay,Unknown}. en + zh translated.
Build: flutter build ios --release --no-codesign clean, 50.5 s,
Runner.app 30.2 MB (+200 KB from audio_router). flutter analyze
clean (6 pre-existing Radio.groupValue deprecation infos in
voice_settings.dart, unchanged).
113 lines
5.7 KiB
Plaintext
113 lines
5.7 KiB
Plaintext
{
|
||
"@@locale": "zh",
|
||
"@@x-source-of-truth": "DEC-015 (register v0.9.5). Simplified Chinese for the Beta key set.",
|
||
|
||
"appTitle": "Chanora",
|
||
"homeNotProductionReadyBanner": "Beta 版本——已接通语音收发;尚未达到生产环境质量。",
|
||
|
||
"fieldServerHost": "服务器地址",
|
||
"fieldNickname": "昵称",
|
||
"fieldServerPassword": "服务器密码",
|
||
"fieldServerPasswordHelp": "如果服务器无需密码,留空即可。",
|
||
"fieldPassword": "密码",
|
||
"fieldDisplayName": "显示名称",
|
||
|
||
"connectAction": "连接",
|
||
"disconnectAction": "断开连接",
|
||
"refreshAction": "刷新",
|
||
"diagnosticsAction": "诊断信息",
|
||
"aboutAction": "关于",
|
||
"aboutVersion": "版本 {version}",
|
||
"aboutNonAffiliation": "Chanora 是独立项目,与 TeamSpeak 之间不存在任何附属、认可、赞助或官方关联关系。",
|
||
"aboutLicenseHeading": "许可协议",
|
||
"aboutLicenseBody": "Chanora 采用 Apache License 2.0 或 MIT License 双协议授权,使用者可任选其一。完整协议文本以 LICENSE-APACHE 与 LICENSE-MIT 形式随仓库一同分发。",
|
||
"aboutThirdPartyHeading": "第三方组件",
|
||
"aboutThirdPartyBody": "Chanora 基于 tsclientlib、flutter_rust_bridge、cpal、rusqlite、Flutter 框架等开源组件构建。完整归属信息请参阅仓库根目录的 NOTICE 文件。",
|
||
"copyAction": "复制",
|
||
"closeAction": "关闭",
|
||
"startAudioAction": "启动语音",
|
||
"pttHoldToTalk": "按住说话",
|
||
"pttTransmitting": "正在发送…",
|
||
"pttHoldToTalkSemanticsHint": "按住进行语音发送,松开停止。",
|
||
"pttCapabilityBadge": "对讲能力:{level}({backend})",
|
||
"pttCapabilityBoundKey": "按键:{key}",
|
||
"pttCapabilityExplainTitle": "对讲能力说明",
|
||
"pttCapabilityExplainFocusedHeading": "聚焦对讲",
|
||
"pttCapabilityExplainFocusedBody": "Chanora 当前使用聚焦对讲:按键只在 Chanora 窗口处于聚焦时生效。这是所有平台在无法启用全局采集时的通用回退方案。",
|
||
"pttCapabilityExplainGoGlobalWindows": "在 Windows 上,绑定按键后会自动启用全局对讲,无需额外权限。",
|
||
"pttCapabilityExplainGoGlobalMacos": "在 macOS 上,启用全局对讲需要「输入监视」权限。请打开「系统设置 → 隐私与安全 → 输入监视」,授权 Chanora 后重新绑定按键。",
|
||
"pttCapabilityExplainGoGlobalLinux": "在 Linux 上,启用全局对讲需要带 GlobalShortcuts 门户的 GNOME-Wayland 桌面。请重新绑定按键,并在桌面弹出快捷键对话框时接受。",
|
||
"pttCapabilityExplainGoGlobalGeneric": "当前环境暂不支持全局对讲。聚焦对讲在 Chanora 窗口获得焦点时仍可正常使用。",
|
||
"pttConfigureAction": "配置",
|
||
"pttConfigureTitle": "配置对讲按键",
|
||
"pttConfigurePrompt": "按下您希望用于对讲的按键或鼠标侧键。",
|
||
"pttConfigureWaiting": "(等待输入…)",
|
||
"pttConfigureCaptured": "已捕获",
|
||
"pttConfigurePrivacyNote": "Chanora 不会记录具体的按键值。本对话框只会向应用提交输入类别(键盘 / 鼠标侧键)以及一个跨平台标签。",
|
||
"pttConfigureSaveAction": "保存",
|
||
"pttConfigurePortalRedirect": "您的桌面环境将打开自带的快捷键对话框,请在其中选择用于对讲的按键。",
|
||
"inputMuteAction": "静音麦克风",
|
||
"inputUnmuteAction": "取消麦克风静音",
|
||
"outputMuteAction": "静音扬声器",
|
||
"outputUnmuteAction": "取消扬声器静音",
|
||
"joinChannelAction": "加入频道",
|
||
"channelPasswordTitle": "频道密码",
|
||
"bookmarksHeading": "书签",
|
||
"bookmarksEmpty": "尚无书签。先在上方填写服务器,然后点击“保存书签”。",
|
||
"bookmarkAddAction": "保存书签",
|
||
"bookmarkAddTitle": "保存书签",
|
||
"bookmarkDeleteAction": "删除书签",
|
||
|
||
"statusIdle": "未连接",
|
||
"statusConnecting": "正在连接…",
|
||
"statusConnected": "已连接到 {server}",
|
||
"statusError": "错误:{message}",
|
||
|
||
"statusReconnecting": "正在重新连接……第 {attempt} 次尝试,{delay} 秒后",
|
||
"statusConnectionLost": "连接已断开:{reason}",
|
||
|
||
"audioStatsLine": "发送 {sent} 帧 • 接收 {received} 帧 • 麦克风 {ptt}",
|
||
|
||
"channelsHeading": "频道",
|
||
"clientsHeading": "在线用户",
|
||
"countChannelsAndClients": "{channels} 个频道 • {clients} 在线",
|
||
|
||
"voiceModePtt": "按键说话",
|
||
"voiceModeContinuous": "持续发送",
|
||
"voiceModeVoiceActivity": "语音激活",
|
||
"voiceModeComingSoon": "即将推出",
|
||
"voiceModeLabel": "发送模式",
|
||
"voiceReleaseTailLabel": "释放延迟",
|
||
"voiceReleaseTailHint": "毫秒",
|
||
"voiceLeaveAction": "离开语音",
|
||
"voiceHardMuteLabel": "麦克风静音",
|
||
"voiceOutputMuteLabel": "扬声器静音",
|
||
"voiceSettingsTitle": "语音设置",
|
||
"voiceBindKeyAction": "绑定 PTT 按键",
|
||
"voicePttHoldHint": "按住按钮",
|
||
"voiceMicOn": "开启",
|
||
"voiceMicOff": "关闭",
|
||
"voiceSheetTitle": "语音",
|
||
"voiceAdjustSettings": "调整模式与释放尾延时",
|
||
"audioOutputLabel": "音频输出",
|
||
"audioRouteSpeaker": "扬声器",
|
||
"audioRouteReceiver": "听筒",
|
||
"audioRouteBluetooth": "蓝牙",
|
||
"audioRouteWiredHeadset": "有线耳机",
|
||
"audioRouteCarAudio": "车载音频",
|
||
"audioRouteAirplay": "AirPlay",
|
||
"audioRouteUnknown": "未知",
|
||
"channelJoinFailedPermission": "权限不足,无法加入此频道。",
|
||
"channelJoinFailedPassword": "频道密码错误。",
|
||
"channelJoinFailedFull": "频道已满。",
|
||
"channelJoinFailedFamilyFull": "频道家族人数已达上限。",
|
||
"channelJoinFailedPrivate": "此频道为私有频道。",
|
||
"channelJoinFailedTimeout": "无法加入频道:服务器响应超时。",
|
||
"channelJoinFailedGeneric": "无法加入频道:{message}",
|
||
"@channelJoinFailedGeneric": {
|
||
"placeholders": {
|
||
"message": { "type": "String" }
|
||
}
|
||
}
|
||
}
|