feat(voice): harden Android audio and channel joins
This commit is contained in:
@@ -252,6 +252,9 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
bool _hardMute = false;
|
||||
int _releaseTailMs = 200;
|
||||
BigInt? _currentVoiceChannelId;
|
||||
BigInt? _pendingVoiceChannelId;
|
||||
bool _canJoinVoiceChannel = true;
|
||||
bool _canLeaveVoiceChannel = false;
|
||||
|
||||
String? _lostReason;
|
||||
int? _reconnectAttempt;
|
||||
@@ -312,7 +315,8 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
|
||||
bool _handleFocusedPttKey(KeyEvent event) {
|
||||
final label = _pttDisplayLabelForKey(event.logicalKey);
|
||||
final isBoundKey = _pttBoundKeyLabel.isNotEmpty && label == _pttBoundKeyLabel;
|
||||
final isBoundKey =
|
||||
_pttBoundKeyLabel.isNotEmpty && label == _pttBoundKeyLabel;
|
||||
if (event is KeyUpEvent && _focusedPttHeldKeys.contains(event.logicalKey)) {
|
||||
if (_focusedPttHeldKeys.remove(event.logicalKey)) {
|
||||
unawaited(_setPtt(false));
|
||||
@@ -423,6 +427,10 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
:final transmitMode,
|
||||
:final mute,
|
||||
:final releaseTailMs,
|
||||
:final currentChannelId,
|
||||
:final pendingTargetChannelId,
|
||||
:final canJoin,
|
||||
:final canLeave,
|
||||
):
|
||||
setState(() {
|
||||
_inChannel = inChannel;
|
||||
@@ -430,6 +438,10 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
_hardMute = mute;
|
||||
_releaseTailMs = releaseTailMs;
|
||||
_audioStarted = inChannel;
|
||||
_currentVoiceChannelId = currentChannelId;
|
||||
_pendingVoiceChannelId = pendingTargetChannelId;
|
||||
_canJoinVoiceChannel = canJoin;
|
||||
_canLeaveVoiceChannel = canLeave;
|
||||
});
|
||||
if (inChannel) {
|
||||
_ensureStatsTimer();
|
||||
@@ -438,7 +450,6 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
_statsTimer?.cancel();
|
||||
_statsTimer = null;
|
||||
_releaseFocusedPttIfHeld();
|
||||
setState(() => _currentVoiceChannelId = null);
|
||||
}
|
||||
if (transmitMode != rust.BridgeTransmitMode.ptt) {
|
||||
_releaseFocusedPttIfHeld();
|
||||
@@ -485,10 +496,7 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
// remains the canonical Dart-side state holder (driven by
|
||||
// the MethodChannel); a future revision may expose a
|
||||
// setter so both paths converge on a single ValueNotifier.
|
||||
case rust.BridgeEvent_PermissionState(
|
||||
:final permission,
|
||||
:final state,
|
||||
):
|
||||
case rust.BridgeEvent_PermissionState(:final permission, :final state):
|
||||
debugPrint(
|
||||
'bridge permission_state: permission=$permission state=$state',
|
||||
);
|
||||
@@ -568,27 +576,27 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
|
||||
void _showPermissionDeniedDialog(String rawError) {
|
||||
final l10n = AppL10n.of(context);
|
||||
final isNetwork =
|
||||
rawError.contains('9987') || rawError.contains('connect');
|
||||
final isNetwork = rawError.contains('9987') || rawError.contains('connect');
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title:
|
||||
Text(isNetwork ? l10n.networkPermissionTitle : l10n.permissionDenied),
|
||||
title: Text(
|
||||
isNetwork ? l10n.networkPermissionTitle : l10n.permissionDenied,
|
||||
),
|
||||
content: Text(
|
||||
isNetwork ? l10n.networkPermissionBody : l10n.microphonePermissionBody),
|
||||
isNetwork
|
||||
? l10n.networkPermissionBody
|
||||
: l10n.microphonePermissionBody,
|
||||
),
|
||||
actions: [
|
||||
if (Platform.isMacOS)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(ctx);
|
||||
try {
|
||||
Process.run(
|
||||
'open',
|
||||
[
|
||||
'x-apple.systempreferences:com.apple.preference.security?Privacy_LocalNetwork',
|
||||
],
|
||||
);
|
||||
Process.run('open', [
|
||||
'x-apple.systempreferences:com.apple.preference.security?Privacy_LocalNetwork',
|
||||
]);
|
||||
} catch (_) {}
|
||||
},
|
||||
child: Text(l10n.networkPermissionOpenSettings),
|
||||
@@ -649,6 +657,8 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
}
|
||||
|
||||
Future<void> _onJoinChannel(rust.BridgeChannel ch) async {
|
||||
if (!_canJoinVoiceChannel) return;
|
||||
if (_pendingVoiceChannelId != null) return;
|
||||
if (ch.id == _currentVoiceChannelId) return;
|
||||
final l10n = AppL10n.of(context);
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
@@ -689,7 +699,7 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
}
|
||||
await rust.voiceJoin(channelId: ch.id, password: password ?? '');
|
||||
if (!mounted) return;
|
||||
setState(() => _currentVoiceChannelId = ch.id);
|
||||
unawaited(_onRefresh());
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
// Surface as a SnackBar so the user sees it even while
|
||||
@@ -753,10 +763,9 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
|
||||
// ignore: unused_element
|
||||
Future<void> _onLeaveVoice() async {
|
||||
if (!_canLeaveVoiceChannel) return;
|
||||
try {
|
||||
await rust.voiceLeave();
|
||||
if (!mounted) return;
|
||||
setState(() => _currentVoiceChannelId = null);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() => _error = e.toString());
|
||||
@@ -916,6 +925,9 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
_outputMuted = false;
|
||||
_inChannel = false;
|
||||
_currentVoiceChannelId = null;
|
||||
_pendingVoiceChannelId = null;
|
||||
_canJoinVoiceChannel = true;
|
||||
_canLeaveVoiceChannel = false;
|
||||
});
|
||||
_releaseFocusedPttIfHeld();
|
||||
}
|
||||
@@ -932,17 +944,6 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
|
||||
void _applySnapshot(rust.BridgeSnapshot snap) {
|
||||
_snapshot = snap;
|
||||
if (!_inChannel) {
|
||||
_currentVoiceChannelId = null;
|
||||
return;
|
||||
}
|
||||
for (final client in snap.clients) {
|
||||
if (client.id == snap.ownClientId) {
|
||||
_currentVoiceChannelId = client.channel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_currentVoiceChannelId = null;
|
||||
}
|
||||
|
||||
Future<void> _onShowDiagnostics(BuildContext context) async {
|
||||
@@ -1335,6 +1336,10 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
final snapshotView = _SnapshotView(
|
||||
snapshot: _snapshot!,
|
||||
currentVoiceChannelId: _currentVoiceChannelId,
|
||||
pendingVoiceChannelId: _pendingVoiceChannelId,
|
||||
hasJoinPending: _pendingVoiceChannelId != null,
|
||||
canJoinVoiceChannel: _canJoinVoiceChannel,
|
||||
canLeaveVoiceChannel: _canLeaveVoiceChannel,
|
||||
onJoinChannel: _onJoinChannel,
|
||||
onLeaveVoice: _onLeaveVoice,
|
||||
);
|
||||
@@ -1346,8 +1351,7 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
SizedBox(
|
||||
width: voiceBarWidthWide,
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.stretch,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
banner,
|
||||
const SizedBox(height: 12),
|
||||
@@ -1376,8 +1380,7 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
onTap: () => _onOpenVoiceDetailsSheet(),
|
||||
),
|
||||
if (_inChannel &&
|
||||
_transmitMode ==
|
||||
rust.BridgeTransmitMode.ptt) ...[
|
||||
_transmitMode == rust.BridgeTransmitMode.ptt) ...[
|
||||
const SizedBox(height: 8),
|
||||
VoicePttButton(
|
||||
active: _audioStats?.pttActive ?? false,
|
||||
@@ -1410,7 +1413,12 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: Padding(padding: const EdgeInsets.all(16), child: bodyContent)),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: bodyContent,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1418,14 +1426,8 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: headerTitle,
|
||||
actions: headerActions,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: bodyContent,
|
||||
),
|
||||
appBar: AppBar(title: headerTitle, actions: headerActions),
|
||||
body: Padding(padding: const EdgeInsets.all(16), child: bodyContent),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1991,12 +1993,20 @@ class _SnapshotView extends StatelessWidget {
|
||||
const _SnapshotView({
|
||||
required this.snapshot,
|
||||
required this.currentVoiceChannelId,
|
||||
required this.pendingVoiceChannelId,
|
||||
required this.hasJoinPending,
|
||||
required this.canJoinVoiceChannel,
|
||||
required this.canLeaveVoiceChannel,
|
||||
required this.onJoinChannel,
|
||||
required this.onLeaveVoice,
|
||||
});
|
||||
|
||||
final rust.BridgeSnapshot snapshot;
|
||||
final BigInt? currentVoiceChannelId;
|
||||
final BigInt? pendingVoiceChannelId;
|
||||
final bool hasJoinPending;
|
||||
final bool canJoinVoiceChannel;
|
||||
final bool canLeaveVoiceChannel;
|
||||
final ValueChanged<rust.BridgeChannel> onJoinChannel;
|
||||
final VoidCallback onLeaveVoice;
|
||||
|
||||
@@ -2077,17 +2087,27 @@ class _SnapshotView extends StatelessWidget {
|
||||
subtitle: Text('id=${ch.id} parent=${ch.parent}'),
|
||||
trailing: IconButton(
|
||||
icon: Icon(
|
||||
ch.id == currentVoiceChannelId ? Icons.logout : Icons.login,
|
||||
ch.id == currentVoiceChannelId
|
||||
? Icons.logout
|
||||
: ch.id == pendingVoiceChannelId
|
||||
? Icons.hourglass_top
|
||||
: Icons.login,
|
||||
),
|
||||
tooltip: ch.id == currentVoiceChannelId
|
||||
? l10n.leaveChannelAction
|
||||
: ch.id == pendingVoiceChannelId
|
||||
? l10n.statusConnecting
|
||||
: l10n.joinChannelAction,
|
||||
onPressed: ch.id == currentVoiceChannelId
|
||||
? onLeaveVoice
|
||||
onPressed: hasJoinPending
|
||||
? null
|
||||
: ch.id == pendingVoiceChannelId
|
||||
? null
|
||||
: ch.id == currentVoiceChannelId
|
||||
? (canLeaveVoiceChannel ? onLeaveVoice : null)
|
||||
: () => onJoinChannel(ch),
|
||||
),
|
||||
selected: ch.id == currentVoiceChannelId,
|
||||
onTap: ch.id == currentVoiceChannelId
|
||||
onTap: hasJoinPending || !canJoinVoiceChannel || ch.id == currentVoiceChannelId
|
||||
? null
|
||||
: () => onJoinChannel(ch),
|
||||
),
|
||||
|
||||
@@ -9,8 +9,8 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||
part 'api.freezed.dart';
|
||||
|
||||
// These functions are ignored because they are not marked as `pub`: `log_file_path`, `log_sink`, `open_log_file`, `permission_events`, `publish_permission_state`, `runtime`, `session`, `transmit_mode_from_u8`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`
|
||||
// These functions are ignored because they are not marked as `pub`: `log_file_path`, `log_sink`, `map_join_error_code`, `map_join_sync_state`, `open_log_file`, `permission_events`, `publish_permission_state`, `runtime`, `session`, `transmit_mode_from_u8`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`
|
||||
// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `from_kotlin_str`, `to_permission_gate`
|
||||
|
||||
/// Return the platform-conventional log-file path as a string, or
|
||||
@@ -454,6 +454,24 @@ sealed class BridgeEvent with _$BridgeEvent {
|
||||
|
||||
/// Current release-tail in milliseconds (0..=500).
|
||||
required int releaseTailMs,
|
||||
|
||||
/// Last confirmed authoritative channel id.
|
||||
BigInt? currentChannelId,
|
||||
|
||||
/// Non-authoritative pending join target channel id.
|
||||
BigInt? pendingTargetChannelId,
|
||||
|
||||
/// Whether a new join intent is currently allowed.
|
||||
required bool canJoin,
|
||||
|
||||
/// Whether leave intent is currently allowed.
|
||||
required bool canLeave,
|
||||
|
||||
/// Join projection sync state.
|
||||
required BridgeVoiceJoinSyncState joinSyncState,
|
||||
|
||||
/// Last stable join error code, if any.
|
||||
BridgeVoiceJoinErrorCode? joinErrorCode,
|
||||
}) = BridgeEvent_VoiceState;
|
||||
|
||||
/// iOS audio interruption state (SDD-101).
|
||||
@@ -587,6 +605,28 @@ enum BridgeTransmitMode {
|
||||
voiceActivity,
|
||||
}
|
||||
|
||||
/// Bridge mirror of stable join error/status codes.
|
||||
enum BridgeVoiceJoinErrorCode {
|
||||
duplicateSameTargetCoalesced,
|
||||
joinAlreadyPendingDifferentTarget,
|
||||
joinDenied,
|
||||
joinProtocolFailure,
|
||||
joinNetworkFailure,
|
||||
joinTimeout,
|
||||
joinSupersededByLeave,
|
||||
joinStaleOutcomeIgnored,
|
||||
joinReconciledDifferentChannel,
|
||||
joinCommandRejectedBeforeSend,
|
||||
joinCannotStartWhileSynchronizing,
|
||||
}
|
||||
|
||||
/// Bridge mirror of core join projection sync state.
|
||||
enum BridgeVoiceJoinSyncState {
|
||||
ready,
|
||||
synchronizingInitialSnapshot,
|
||||
synchronizingReconnect,
|
||||
}
|
||||
|
||||
/// Schema-controlled mirror of the Kotlin
|
||||
/// `AndroidPermissionRequester.PermissionState` sealed class
|
||||
/// (SDD-106 §5). Crosses the bridge as an enum so the Dart side can
|
||||
|
||||
@@ -146,7 +146,7 @@ return permissionState(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String serverName)? connected,TResult Function( String reason)? lost,TResult Function( int attempt, int delaySecs)? reconnecting,TResult Function( String reason)? disconnected,TResult Function()? audioStarted,TResult Function()? audioStopped,TResult Function( int channels, int clients)? snapshotChanged,TResult Function( String level, String backendId, String boundInputClass)? pttCapability,TResult Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs)? voiceState,TResult Function( bool began, bool shouldResume)? interruptionState,TResult Function( String permission, PermissionStateKind state)? permissionState,required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String serverName)? connected,TResult Function( String reason)? lost,TResult Function( int attempt, int delaySecs)? reconnecting,TResult Function( String reason)? disconnected,TResult Function()? audioStarted,TResult Function()? audioStopped,TResult Function( int channels, int clients)? snapshotChanged,TResult Function( String level, String backendId, String boundInputClass)? pttCapability,TResult Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs, BigInt? currentChannelId, BigInt? pendingTargetChannelId, bool canJoin, bool canLeave, BridgeVoiceJoinSyncState joinSyncState, BridgeVoiceJoinErrorCode? joinErrorCode)? voiceState,TResult Function( bool began, bool shouldResume)? interruptionState,TResult Function( String permission, PermissionStateKind state)? permissionState,required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that.serverName);case BridgeEvent_Lost() when lost != null:
|
||||
@@ -157,7 +157,7 @@ return audioStarted();case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped();case BridgeEvent_SnapshotChanged() when snapshotChanged != null:
|
||||
return snapshotChanged(_that.channels,_that.clients);case BridgeEvent_PttCapability() when pttCapability != null:
|
||||
return pttCapability(_that.level,_that.backendId,_that.boundInputClass);case BridgeEvent_VoiceState() when voiceState != null:
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs);case BridgeEvent_InterruptionState() when interruptionState != null:
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs,_that.currentChannelId,_that.pendingTargetChannelId,_that.canJoin,_that.canLeave,_that.joinSyncState,_that.joinErrorCode);case BridgeEvent_InterruptionState() when interruptionState != null:
|
||||
return interruptionState(_that.began,_that.shouldResume);case BridgeEvent_PermissionState() when permissionState != null:
|
||||
return permissionState(_that.permission,_that.state);case _:
|
||||
return orElse();
|
||||
@@ -177,7 +177,7 @@ return permissionState(_that.permission,_that.state);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String serverName) connected,required TResult Function( String reason) lost,required TResult Function( int attempt, int delaySecs) reconnecting,required TResult Function( String reason) disconnected,required TResult Function() audioStarted,required TResult Function() audioStopped,required TResult Function( int channels, int clients) snapshotChanged,required TResult Function( String level, String backendId, String boundInputClass) pttCapability,required TResult Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs) voiceState,required TResult Function( bool began, bool shouldResume) interruptionState,required TResult Function( String permission, PermissionStateKind state) permissionState,}) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String serverName) connected,required TResult Function( String reason) lost,required TResult Function( int attempt, int delaySecs) reconnecting,required TResult Function( String reason) disconnected,required TResult Function() audioStarted,required TResult Function() audioStopped,required TResult Function( int channels, int clients) snapshotChanged,required TResult Function( String level, String backendId, String boundInputClass) pttCapability,required TResult Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs, BigInt? currentChannelId, BigInt? pendingTargetChannelId, bool canJoin, bool canLeave, BridgeVoiceJoinSyncState joinSyncState, BridgeVoiceJoinErrorCode? joinErrorCode) voiceState,required TResult Function( bool began, bool shouldResume) interruptionState,required TResult Function( String permission, PermissionStateKind state) permissionState,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected():
|
||||
return connected(_that.serverName);case BridgeEvent_Lost():
|
||||
@@ -188,7 +188,7 @@ return audioStarted();case BridgeEvent_AudioStopped():
|
||||
return audioStopped();case BridgeEvent_SnapshotChanged():
|
||||
return snapshotChanged(_that.channels,_that.clients);case BridgeEvent_PttCapability():
|
||||
return pttCapability(_that.level,_that.backendId,_that.boundInputClass);case BridgeEvent_VoiceState():
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs);case BridgeEvent_InterruptionState():
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs,_that.currentChannelId,_that.pendingTargetChannelId,_that.canJoin,_that.canLeave,_that.joinSyncState,_that.joinErrorCode);case BridgeEvent_InterruptionState():
|
||||
return interruptionState(_that.began,_that.shouldResume);case BridgeEvent_PermissionState():
|
||||
return permissionState(_that.permission,_that.state);}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ return permissionState(_that.permission,_that.state);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String serverName)? connected,TResult? Function( String reason)? lost,TResult? Function( int attempt, int delaySecs)? reconnecting,TResult? Function( String reason)? disconnected,TResult? Function()? audioStarted,TResult? Function()? audioStopped,TResult? Function( int channels, int clients)? snapshotChanged,TResult? Function( String level, String backendId, String boundInputClass)? pttCapability,TResult? Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs)? voiceState,TResult? Function( bool began, bool shouldResume)? interruptionState,TResult? Function( String permission, PermissionStateKind state)? permissionState,}) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String serverName)? connected,TResult? Function( String reason)? lost,TResult? Function( int attempt, int delaySecs)? reconnecting,TResult? Function( String reason)? disconnected,TResult? Function()? audioStarted,TResult? Function()? audioStopped,TResult? Function( int channels, int clients)? snapshotChanged,TResult? Function( String level, String backendId, String boundInputClass)? pttCapability,TResult? Function( bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs, BigInt? currentChannelId, BigInt? pendingTargetChannelId, bool canJoin, bool canLeave, BridgeVoiceJoinSyncState joinSyncState, BridgeVoiceJoinErrorCode? joinErrorCode)? voiceState,TResult? Function( bool began, bool shouldResume)? interruptionState,TResult? Function( String permission, PermissionStateKind state)? permissionState,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that.serverName);case BridgeEvent_Lost() when lost != null:
|
||||
@@ -215,7 +215,7 @@ return audioStarted();case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped();case BridgeEvent_SnapshotChanged() when snapshotChanged != null:
|
||||
return snapshotChanged(_that.channels,_that.clients);case BridgeEvent_PttCapability() when pttCapability != null:
|
||||
return pttCapability(_that.level,_that.backendId,_that.boundInputClass);case BridgeEvent_VoiceState() when voiceState != null:
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs);case BridgeEvent_InterruptionState() when interruptionState != null:
|
||||
return voiceState(_that.inChannel,_that.transmitMode,_that.mute,_that.releaseTailMs,_that.currentChannelId,_that.pendingTargetChannelId,_that.canJoin,_that.canLeave,_that.joinSyncState,_that.joinErrorCode);case BridgeEvent_InterruptionState() when interruptionState != null:
|
||||
return interruptionState(_that.began,_that.shouldResume);case BridgeEvent_PermissionState() when permissionState != null:
|
||||
return permissionState(_that.permission,_that.state);case _:
|
||||
return null;
|
||||
@@ -710,7 +710,7 @@ as String,
|
||||
|
||||
|
||||
class BridgeEvent_VoiceState extends BridgeEvent {
|
||||
const BridgeEvent_VoiceState({required this.inChannel, required this.transmitMode, required this.mute, required this.releaseTailMs}): super._();
|
||||
const BridgeEvent_VoiceState({required this.inChannel, required this.transmitMode, required this.mute, required this.releaseTailMs, this.currentChannelId, this.pendingTargetChannelId, required this.canJoin, required this.canLeave, required this.joinSyncState, this.joinErrorCode}): super._();
|
||||
|
||||
|
||||
/// True when the session is currently joined to a voice
|
||||
@@ -722,6 +722,18 @@ class BridgeEvent_VoiceState extends BridgeEvent {
|
||||
final bool mute;
|
||||
/// Current release-tail in milliseconds (0..=500).
|
||||
final int releaseTailMs;
|
||||
/// Last confirmed authoritative channel id.
|
||||
final BigInt? currentChannelId;
|
||||
/// Non-authoritative pending join target channel id.
|
||||
final BigInt? pendingTargetChannelId;
|
||||
/// Whether a new join intent is currently allowed.
|
||||
final bool canJoin;
|
||||
/// Whether leave intent is currently allowed.
|
||||
final bool canLeave;
|
||||
/// Join projection sync state.
|
||||
final BridgeVoiceJoinSyncState joinSyncState;
|
||||
/// Last stable join error code, if any.
|
||||
final BridgeVoiceJoinErrorCode? joinErrorCode;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -733,16 +745,16 @@ $BridgeEvent_VoiceStateCopyWith<BridgeEvent_VoiceState> get copyWith => _$Bridge
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_VoiceState&&(identical(other.inChannel, inChannel) || other.inChannel == inChannel)&&(identical(other.transmitMode, transmitMode) || other.transmitMode == transmitMode)&&(identical(other.mute, mute) || other.mute == mute)&&(identical(other.releaseTailMs, releaseTailMs) || other.releaseTailMs == releaseTailMs));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_VoiceState&&(identical(other.inChannel, inChannel) || other.inChannel == inChannel)&&(identical(other.transmitMode, transmitMode) || other.transmitMode == transmitMode)&&(identical(other.mute, mute) || other.mute == mute)&&(identical(other.releaseTailMs, releaseTailMs) || other.releaseTailMs == releaseTailMs)&&(identical(other.currentChannelId, currentChannelId) || other.currentChannelId == currentChannelId)&&(identical(other.pendingTargetChannelId, pendingTargetChannelId) || other.pendingTargetChannelId == pendingTargetChannelId)&&(identical(other.canJoin, canJoin) || other.canJoin == canJoin)&&(identical(other.canLeave, canLeave) || other.canLeave == canLeave)&&(identical(other.joinSyncState, joinSyncState) || other.joinSyncState == joinSyncState)&&(identical(other.joinErrorCode, joinErrorCode) || other.joinErrorCode == joinErrorCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,inChannel,transmitMode,mute,releaseTailMs);
|
||||
int get hashCode => Object.hash(runtimeType,inChannel,transmitMode,mute,releaseTailMs,currentChannelId,pendingTargetChannelId,canJoin,canLeave,joinSyncState,joinErrorCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.voiceState(inChannel: $inChannel, transmitMode: $transmitMode, mute: $mute, releaseTailMs: $releaseTailMs)';
|
||||
return 'BridgeEvent.voiceState(inChannel: $inChannel, transmitMode: $transmitMode, mute: $mute, releaseTailMs: $releaseTailMs, currentChannelId: $currentChannelId, pendingTargetChannelId: $pendingTargetChannelId, canJoin: $canJoin, canLeave: $canLeave, joinSyncState: $joinSyncState, joinErrorCode: $joinErrorCode)';
|
||||
}
|
||||
|
||||
|
||||
@@ -753,7 +765,7 @@ abstract mixin class $BridgeEvent_VoiceStateCopyWith<$Res> implements $BridgeEve
|
||||
factory $BridgeEvent_VoiceStateCopyWith(BridgeEvent_VoiceState value, $Res Function(BridgeEvent_VoiceState) _then) = _$BridgeEvent_VoiceStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs
|
||||
bool inChannel, BridgeTransmitMode transmitMode, bool mute, int releaseTailMs, BigInt? currentChannelId, BigInt? pendingTargetChannelId, bool canJoin, bool canLeave, BridgeVoiceJoinSyncState joinSyncState, BridgeVoiceJoinErrorCode? joinErrorCode
|
||||
});
|
||||
|
||||
|
||||
@@ -770,13 +782,19 @@ class _$BridgeEvent_VoiceStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? inChannel = null,Object? transmitMode = null,Object? mute = null,Object? releaseTailMs = null,}) {
|
||||
@pragma('vm:prefer-inline') $Res call({Object? inChannel = null,Object? transmitMode = null,Object? mute = null,Object? releaseTailMs = null,Object? currentChannelId = freezed,Object? pendingTargetChannelId = freezed,Object? canJoin = null,Object? canLeave = null,Object? joinSyncState = null,Object? joinErrorCode = freezed,}) {
|
||||
return _then(BridgeEvent_VoiceState(
|
||||
inChannel: null == inChannel ? _self.inChannel : inChannel // ignore: cast_nullable_to_non_nullable
|
||||
as bool,transmitMode: null == transmitMode ? _self.transmitMode : transmitMode // ignore: cast_nullable_to_non_nullable
|
||||
as BridgeTransmitMode,mute: null == mute ? _self.mute : mute // ignore: cast_nullable_to_non_nullable
|
||||
as bool,releaseTailMs: null == releaseTailMs ? _self.releaseTailMs : releaseTailMs // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
as int,currentChannelId: freezed == currentChannelId ? _self.currentChannelId : currentChannelId // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt?,pendingTargetChannelId: freezed == pendingTargetChannelId ? _self.pendingTargetChannelId : pendingTargetChannelId // ignore: cast_nullable_to_non_nullable
|
||||
as BigInt?,canJoin: null == canJoin ? _self.canJoin : canJoin // ignore: cast_nullable_to_non_nullable
|
||||
as bool,canLeave: null == canLeave ? _self.canLeave : canLeave // ignore: cast_nullable_to_non_nullable
|
||||
as bool,joinSyncState: null == joinSyncState ? _self.joinSyncState : joinSyncState // ignore: cast_nullable_to_non_nullable
|
||||
as BridgeVoiceJoinSyncState,joinErrorCode: freezed == joinErrorCode ? _self.joinErrorCode : joinErrorCode // ignore: cast_nullable_to_non_nullable
|
||||
as BridgeVoiceJoinErrorCode?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1111,6 +1111,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return dco_decode_bridge_bookmark(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
dynamic raw,
|
||||
) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return dco_decode_bridge_voice_join_error_code(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_box_autoadd_u_64(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return dco_decode_u_64(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeAudioStats dco_decode_bridge_audio_stats(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -1232,6 +1246,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
transmitMode: dco_decode_bridge_transmit_mode(raw[2]),
|
||||
mute: dco_decode_bool(raw[3]),
|
||||
releaseTailMs: dco_decode_u_32(raw[4]),
|
||||
currentChannelId: dco_decode_opt_box_autoadd_u_64(raw[5]),
|
||||
pendingTargetChannelId: dco_decode_opt_box_autoadd_u_64(raw[6]),
|
||||
canJoin: dco_decode_bool(raw[7]),
|
||||
canLeave: dco_decode_bool(raw[8]),
|
||||
joinSyncState: dco_decode_bridge_voice_join_sync_state(raw[9]),
|
||||
joinErrorCode:
|
||||
dco_decode_opt_box_autoadd_bridge_voice_join_error_code(raw[10]),
|
||||
);
|
||||
case 9:
|
||||
return BridgeEvent_InterruptionState(
|
||||
@@ -1283,6 +1304,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return BridgeTransmitMode.values[raw as int];
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_bridge_voice_join_error_code(
|
||||
dynamic raw,
|
||||
) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return BridgeVoiceJoinErrorCode.values[raw as int];
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState dco_decode_bridge_voice_join_sync_state(
|
||||
dynamic raw,
|
||||
) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return BridgeVoiceJoinSyncState.values[raw as int];
|
||||
}
|
||||
|
||||
@protected
|
||||
double dco_decode_f_32(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -1325,6 +1362,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return raw as Uint8List;
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
dco_decode_opt_box_autoadd_bridge_voice_join_error_code(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return raw == null
|
||||
? null
|
||||
: dco_decode_box_autoadd_bridge_voice_join_error_code(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return raw == null ? null : dco_decode_box_autoadd_u_64(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
PermissionStateKind dco_decode_permission_state_kind(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -1415,6 +1467,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return (sse_decode_bridge_bookmark(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
return (sse_decode_bridge_voice_join_error_code(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_box_autoadd_u_64(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
return (sse_decode_u_64(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeAudioStats sse_decode_bridge_audio_stats(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1554,11 +1620,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
var var_transmitMode = sse_decode_bridge_transmit_mode(deserializer);
|
||||
var var_mute = sse_decode_bool(deserializer);
|
||||
var var_releaseTailMs = sse_decode_u_32(deserializer);
|
||||
var var_currentChannelId = sse_decode_opt_box_autoadd_u_64(
|
||||
deserializer,
|
||||
);
|
||||
var var_pendingTargetChannelId = sse_decode_opt_box_autoadd_u_64(
|
||||
deserializer,
|
||||
);
|
||||
var var_canJoin = sse_decode_bool(deserializer);
|
||||
var var_canLeave = sse_decode_bool(deserializer);
|
||||
var var_joinSyncState = sse_decode_bridge_voice_join_sync_state(
|
||||
deserializer,
|
||||
);
|
||||
var var_joinErrorCode =
|
||||
sse_decode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
deserializer,
|
||||
);
|
||||
return BridgeEvent_VoiceState(
|
||||
inChannel: var_inChannel,
|
||||
transmitMode: var_transmitMode,
|
||||
mute: var_mute,
|
||||
releaseTailMs: var_releaseTailMs,
|
||||
currentChannelId: var_currentChannelId,
|
||||
pendingTargetChannelId: var_pendingTargetChannelId,
|
||||
canJoin: var_canJoin,
|
||||
canLeave: var_canLeave,
|
||||
joinSyncState: var_joinSyncState,
|
||||
joinErrorCode: var_joinErrorCode,
|
||||
);
|
||||
case 9:
|
||||
var var_began = sse_decode_bool(deserializer);
|
||||
@@ -1627,6 +1714,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return BridgeTransmitMode.values[inner];
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var inner = sse_decode_i_32(deserializer);
|
||||
return BridgeVoiceJoinErrorCode.values[inner];
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState sse_decode_bridge_voice_join_sync_state(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var inner = sse_decode_i_32(deserializer);
|
||||
return BridgeVoiceJoinSyncState.values[inner];
|
||||
}
|
||||
|
||||
@protected
|
||||
double sse_decode_f_32(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -1694,6 +1799,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return deserializer.buffer.getUint8List(len_);
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
sse_decode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
if (sse_decode_bool(deserializer)) {
|
||||
return (sse_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
deserializer,
|
||||
));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
if (sse_decode_bool(deserializer)) {
|
||||
return (sse_decode_box_autoadd_u_64(deserializer));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
PermissionStateKind sse_decode_permission_state_kind(
|
||||
SseDeserializer deserializer,
|
||||
@@ -1794,6 +1926,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_bridge_bookmark(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_bridge_voice_join_error_code(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_64(BigInt self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_u_64(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_audio_stats(
|
||||
BridgeAudioStats self,
|
||||
@@ -1909,12 +2056,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
transmitMode: final transmitMode,
|
||||
mute: final mute,
|
||||
releaseTailMs: final releaseTailMs,
|
||||
currentChannelId: final currentChannelId,
|
||||
pendingTargetChannelId: final pendingTargetChannelId,
|
||||
canJoin: final canJoin,
|
||||
canLeave: final canLeave,
|
||||
joinSyncState: final joinSyncState,
|
||||
joinErrorCode: final joinErrorCode,
|
||||
):
|
||||
sse_encode_i_32(8, serializer);
|
||||
sse_encode_bool(inChannel, serializer);
|
||||
sse_encode_bridge_transmit_mode(transmitMode, serializer);
|
||||
sse_encode_bool(mute, serializer);
|
||||
sse_encode_u_32(releaseTailMs, serializer);
|
||||
sse_encode_opt_box_autoadd_u_64(currentChannelId, serializer);
|
||||
sse_encode_opt_box_autoadd_u_64(pendingTargetChannelId, serializer);
|
||||
sse_encode_bool(canJoin, serializer);
|
||||
sse_encode_bool(canLeave, serializer);
|
||||
sse_encode_bridge_voice_join_sync_state(joinSyncState, serializer);
|
||||
sse_encode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
joinErrorCode,
|
||||
serializer,
|
||||
);
|
||||
case BridgeEvent_InterruptionState(
|
||||
began: final began,
|
||||
shouldResume: final shouldResume,
|
||||
@@ -1974,6 +2136,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_i_32(self.index, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_i_32(self.index, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_sync_state(
|
||||
BridgeVoiceJoinSyncState self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_i_32(self.index, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_f_32(double self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -2038,6 +2218,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
serializer.buffer.putUint8List(self);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode? self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
sse_encode_bool(self != null, serializer);
|
||||
if (self != null) {
|
||||
sse_encode_box_autoadd_bridge_voice_join_error_code(self, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
sse_encode_bool(self != null, serializer);
|
||||
if (self != null) {
|
||||
sse_encode_box_autoadd_u_64(self, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_permission_state_kind(
|
||||
PermissionStateKind self,
|
||||
|
||||
@@ -36,6 +36,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeBookmark dco_decode_box_autoadd_bridge_bookmark(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeAudioStats dco_decode_bridge_audio_stats(dynamic raw);
|
||||
|
||||
@@ -66,6 +74,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeTransmitMode dco_decode_bridge_transmit_mode(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_bridge_voice_join_error_code(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState dco_decode_bridge_voice_join_sync_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
double dco_decode_f_32(dynamic raw);
|
||||
|
||||
@@ -87,6 +101,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
dco_decode_opt_box_autoadd_bridge_voice_join_error_code(dynamic raw);
|
||||
|
||||
@protected
|
||||
BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
PermissionStateKind dco_decode_permission_state_kind(dynamic raw);
|
||||
|
||||
@@ -127,6 +148,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeAudioStats sse_decode_bridge_audio_stats(SseDeserializer deserializer);
|
||||
|
||||
@@ -163,6 +192,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState sse_decode_bridge_voice_join_sync_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
double sse_decode_f_32(SseDeserializer deserializer);
|
||||
|
||||
@@ -190,6 +229,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
sse_decode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
PermissionStateKind sse_decode_permission_state_kind(
|
||||
SseDeserializer deserializer,
|
||||
@@ -241,6 +289,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_64(BigInt self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_audio_stats(
|
||||
BridgeAudioStats self,
|
||||
@@ -289,6 +346,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_sync_state(
|
||||
BridgeVoiceJoinSyncState self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_f_32(double self, SseSerializer serializer);
|
||||
|
||||
@@ -322,6 +391,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode? self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_permission_state_kind(
|
||||
PermissionStateKind self,
|
||||
|
||||
@@ -38,6 +38,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeBookmark dco_decode_box_autoadd_bridge_bookmark(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt dco_decode_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeAudioStats dco_decode_bridge_audio_stats(dynamic raw);
|
||||
|
||||
@@ -68,6 +76,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeTransmitMode dco_decode_bridge_transmit_mode(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode dco_decode_bridge_voice_join_error_code(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState dco_decode_bridge_voice_join_sync_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
double dco_decode_f_32(dynamic raw);
|
||||
|
||||
@@ -89,6 +103,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
dco_decode_opt_box_autoadd_bridge_voice_join_error_code(dynamic raw);
|
||||
|
||||
@protected
|
||||
BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
PermissionStateKind dco_decode_permission_state_kind(dynamic raw);
|
||||
|
||||
@@ -129,6 +150,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt sse_decode_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeAudioStats sse_decode_bridge_audio_stats(SseDeserializer deserializer);
|
||||
|
||||
@@ -165,6 +194,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode sse_decode_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinSyncState sse_decode_bridge_voice_join_sync_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
double sse_decode_f_32(SseDeserializer deserializer);
|
||||
|
||||
@@ -192,6 +231,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeVoiceJoinErrorCode?
|
||||
sse_decode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
PermissionStateKind sse_decode_permission_state_kind(
|
||||
SseDeserializer deserializer,
|
||||
@@ -243,6 +291,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_u_64(BigInt self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_audio_stats(
|
||||
BridgeAudioStats self,
|
||||
@@ -291,6 +348,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_voice_join_sync_state(
|
||||
BridgeVoiceJoinSyncState self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_f_32(double self, SseSerializer serializer);
|
||||
|
||||
@@ -324,6 +393,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_bridge_voice_join_error_code(
|
||||
BridgeVoiceJoinErrorCode? self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_permission_state_kind(
|
||||
PermissionStateKind self,
|
||||
|
||||
@@ -353,9 +353,9 @@ class _VoiceSheetBodyState extends State<_VoiceSheetBody> {
|
||||
final levelActive = stats?.pttActive ?? false;
|
||||
final isPtt = _mode == rust.BridgeTransmitMode.ptt;
|
||||
|
||||
// Route picker only meaningful on iOS + Android where the OS
|
||||
// owns audio routing. Desktop hosts skip the tile entirely.
|
||||
final showRoutePicker = !kIsWeb && (Platform.isIOS || Platform.isAndroid);
|
||||
// Route picker is iOS-only; the picker uses AVAudioSession-backed
|
||||
// widgets that must not be constructed on Android.
|
||||
final showRoutePicker = !kIsWeb && Platform.isIOS;
|
||||
|
||||
return SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
|
||||
Reference in New Issue
Block a user