feat(core): A.6 — supervisor reconnect with watchdog and event stream
Adds an end-to-end auto-reconnect path so a brief network outage no longer leaves the client wedged in a half-dead state. The flow has three layers, each motivated by a real failure mode observed on the Moto G live test: * `chanora_protocol::DisconnectReason` (`UserRequested` / `StreamEnded` / `Error(String)`) is reported on a `oneshot` when the per-connection task exits, so the supervisor can tell user intent apart from a real loss. * `chanora_core` spawns a supervisor task per `ChanoraSession`. It listens for the loss notifier AND runs a watchdog that issues `snapshot()` probes every 5s with a 4s timeout — three consecutive misses synthesise a `DisconnectReason::Error(...)` and trigger the reconnect path. The watchdog catches the "ghost connected" case where tsclientlib silently resets internal state but the event stream never errors. Backoff schedule: 1s, 2s, 5s, 15s, 30s, 60s (capped). On success the supervisor swaps the dead `ProtocolClient` for the new one in place and, if audio was running, restarts the audio engine bound to the new `voice_in`/`voice_out` channels. * `SessionEvent` (Connected / Lost / Reconnecting / Disconnected / AudioStarted / AudioStopped) is broadcast on a 64-slot channel. `chanora_bridge` re-exports it as `BridgeEvent` and exposes `events_stream(StreamSink)`; the Flutter side subscribes from `initState` and renders a reconnect banner with attempt count and delay. New `SnapshotProbe` exposes a clone-friendly snapshot path so the watchdog can probe without holding `&self` across awaits. Localization adds `statusReconnecting` and `statusConnectionLost` keys to `app_en.arb` and `app_zh.arb`. Verified on Moto G Stylus 5G (Android 14) against cn.teamspeak.app: killed Wi-Fi + cellular for ~70 s; watchdog declared loss at three misses, supervisor walked the backoff schedule, and the UI reconnected automatically once the radios came back. Snapshot tree re-rendered without user action.
This commit is contained in:
@@ -27,6 +27,18 @@
|
||||
"placeholders": { "message": { "type": "String" } }
|
||||
},
|
||||
|
||||
"statusReconnecting": "Reconnecting… attempt {attempt}, in {delay}s",
|
||||
"@statusReconnecting": {
|
||||
"placeholders": {
|
||||
"attempt": { "type": "int" },
|
||||
"delay": { "type": "int" }
|
||||
}
|
||||
},
|
||||
"statusConnectionLost": "Connection lost: {reason}",
|
||||
"@statusConnectionLost": {
|
||||
"placeholders": { "reason": { "type": "String" } }
|
||||
},
|
||||
|
||||
"audioStatsLine": "TX {sent} frames • RX {received} frames • PTT {ptt}",
|
||||
"@audioStatsLine": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
"statusConnected": "已连接到 {server}",
|
||||
"statusError": "错误:{message}",
|
||||
|
||||
"statusReconnecting": "正在重新连接……第 {attempt} 次尝试,{delay} 秒后",
|
||||
"statusConnectionLost": "连接已断开:{reason}",
|
||||
|
||||
"audioStatsLine": "发送 {sent} 帧 • 接收 {received} 帧 • PTT {ptt}",
|
||||
|
||||
"channelsHeading": "频道",
|
||||
|
||||
@@ -181,6 +181,18 @@ abstract class AppL10n {
|
||||
/// **'Error: {message}'**
|
||||
String statusError(String message);
|
||||
|
||||
/// No description provided for @statusReconnecting.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reconnecting… attempt {attempt}, in {delay}s'**
|
||||
String statusReconnecting(int attempt, int delay);
|
||||
|
||||
/// No description provided for @statusConnectionLost.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Connection lost: {reason}'**
|
||||
String statusConnectionLost(String reason);
|
||||
|
||||
/// No description provided for @audioStatsLine.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -55,6 +55,16 @@ class AppL10nEn extends AppL10n {
|
||||
return 'Error: $message';
|
||||
}
|
||||
|
||||
@override
|
||||
String statusReconnecting(int attempt, int delay) {
|
||||
return 'Reconnecting… attempt $attempt, in ${delay}s';
|
||||
}
|
||||
|
||||
@override
|
||||
String statusConnectionLost(String reason) {
|
||||
return 'Connection lost: $reason';
|
||||
}
|
||||
|
||||
@override
|
||||
String audioStatsLine(int sent, int received, String ptt) {
|
||||
return 'TX $sent frames • RX $received frames • PTT $ptt';
|
||||
|
||||
@@ -54,6 +54,16 @@ class AppL10nZh extends AppL10n {
|
||||
return '错误:$message';
|
||||
}
|
||||
|
||||
@override
|
||||
String statusReconnecting(int attempt, int delay) {
|
||||
return '正在重新连接……第 $attempt 次尝试,$delay 秒后';
|
||||
}
|
||||
|
||||
@override
|
||||
String statusConnectionLost(String reason) {
|
||||
return '连接已断开:$reason';
|
||||
}
|
||||
|
||||
@override
|
||||
String audioStatsLine(int sent, int received, String ptt) {
|
||||
return '发送 $sent 帧 • 接收 $received 帧 • PTT $ptt';
|
||||
|
||||
@@ -60,9 +60,57 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
bool _audioStarted = false;
|
||||
rust.BridgeAudioStats? _audioStats;
|
||||
Timer? _statsTimer;
|
||||
StreamSubscription<rust.BridgeEvent>? _eventsSub;
|
||||
|
||||
// A.6 reconnect banner state.
|
||||
String? _lostReason;
|
||||
int? _reconnectAttempt;
|
||||
int? _reconnectDelay;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_eventsSub = rust.eventsStream().listen(_onEvent);
|
||||
}
|
||||
|
||||
void _onEvent(rust.BridgeEvent evt) {
|
||||
if (!mounted) return;
|
||||
switch (evt) {
|
||||
case rust.BridgeEvent_Connected():
|
||||
setState(() {
|
||||
_phase = _Phase.connected;
|
||||
_lostReason = null;
|
||||
_reconnectAttempt = null;
|
||||
_reconnectDelay = null;
|
||||
});
|
||||
case rust.BridgeEvent_Lost(:final reason):
|
||||
setState(() {
|
||||
_lostReason = reason;
|
||||
_reconnectAttempt = null;
|
||||
_reconnectDelay = null;
|
||||
});
|
||||
case rust.BridgeEvent_Reconnecting(:final attempt, :final delaySecs):
|
||||
setState(() {
|
||||
_reconnectAttempt = attempt;
|
||||
_reconnectDelay = delaySecs;
|
||||
});
|
||||
case rust.BridgeEvent_Disconnected():
|
||||
setState(() {
|
||||
_phase = _Phase.idle;
|
||||
_lostReason = null;
|
||||
_reconnectAttempt = null;
|
||||
_reconnectDelay = null;
|
||||
});
|
||||
case rust.BridgeEvent_AudioStarted():
|
||||
setState(() => _audioStarted = true);
|
||||
case rust.BridgeEvent_AudioStopped():
|
||||
setState(() => _audioStarted = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_eventsSub?.cancel();
|
||||
_statsTimer?.cancel();
|
||||
_hostCtl.dispose();
|
||||
_nickCtl.dispose();
|
||||
@@ -201,6 +249,42 @@ class _BetaHomeState extends State<_BetaHome> {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(statusText(), style: theme.textTheme.titleMedium),
|
||||
if (_lostReason != null || _reconnectAttempt != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.errorContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_reconnectAttempt != null
|
||||
? l10n.statusReconnecting(
|
||||
_reconnectAttempt!,
|
||||
_reconnectDelay ?? 0,
|
||||
)
|
||||
: l10n.statusConnectionLost(_lostReason ?? ''),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
if (_phase == _Phase.idle) ...[
|
||||
_ConnectForm(
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
import 'frb_generated.dart';
|
||||
import 'lib.dart';
|
||||
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`: `runtime`, `session`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`, `from`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`
|
||||
|
||||
/// Connect to a TeamSpeak-compatible server and return the initial
|
||||
/// state snapshot. Honours the DEC-006 single-connection invariant
|
||||
@@ -35,6 +37,13 @@ Future<void> startAudio() => RustLib.instance.api.crateApiStartAudio();
|
||||
Future<void> setPtt({required bool active}) =>
|
||||
RustLib.instance.api.crateApiSetPtt(active: active);
|
||||
|
||||
/// Subscribe to lifecycle events. Each call yields a fresh
|
||||
/// subscription; multiple subscribers are supported. On slow
|
||||
/// consumers, events are dropped rather than blocking the supervisor
|
||||
/// (consistent with `tokio::sync::broadcast::Receiver` semantics).
|
||||
Stream<BridgeEvent> eventsStream() =>
|
||||
RustLib.instance.api.crateApiEventsStream();
|
||||
|
||||
/// Read audio statistics. Errors if no connection or audio not started.
|
||||
Future<BridgeAudioStats> audioStats() =>
|
||||
RustLib.instance.api.crateApiAudioStats();
|
||||
@@ -138,6 +147,44 @@ class BridgeClient {
|
||||
name == other.name;
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class BridgeEvent with _$BridgeEvent {
|
||||
const BridgeEvent._();
|
||||
|
||||
/// Initial connect succeeded, or a reconnect attempt succeeded.
|
||||
const factory BridgeEvent.connected({
|
||||
/// Server name reported by the server snapshot.
|
||||
required String serverName,
|
||||
}) = BridgeEvent_Connected;
|
||||
|
||||
/// Connection lost; supervisor will retry.
|
||||
const factory BridgeEvent.lost({
|
||||
/// Reason classification from the protocol layer.
|
||||
required String reason,
|
||||
}) = BridgeEvent_Lost;
|
||||
|
||||
/// Supervisor is sleeping before its next reconnect attempt.
|
||||
const factory BridgeEvent.reconnecting({
|
||||
/// 1-based attempt counter for the current outage.
|
||||
required int attempt,
|
||||
|
||||
/// Seconds the supervisor will sleep before this attempt.
|
||||
required int delaySecs,
|
||||
}) = BridgeEvent_Reconnecting;
|
||||
|
||||
/// Session ended (user-requested disconnect or unrecoverable).
|
||||
const factory BridgeEvent.disconnected({
|
||||
/// Reason classification.
|
||||
required String reason,
|
||||
}) = BridgeEvent_Disconnected;
|
||||
|
||||
/// Audio engine started.
|
||||
const factory BridgeEvent.audioStarted() = BridgeEvent_AudioStarted;
|
||||
|
||||
/// Audio engine stopped.
|
||||
const factory BridgeEvent.audioStopped() = BridgeEvent_AudioStopped;
|
||||
}
|
||||
|
||||
/// Server snapshot as seen by Dart.
|
||||
class BridgeSnapshot {
|
||||
/// Server name.
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'api.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$BridgeEvent {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class $BridgeEventCopyWith<$Res> {
|
||||
$BridgeEventCopyWith(BridgeEvent _, $Res Function(BridgeEvent) __);
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [BridgeEvent].
|
||||
extension BridgeEventPatterns on BridgeEvent {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( BridgeEvent_Connected value)? connected,TResult Function( BridgeEvent_Lost value)? lost,TResult Function( BridgeEvent_Reconnecting value)? reconnecting,TResult Function( BridgeEvent_Disconnected value)? disconnected,TResult Function( BridgeEvent_AudioStarted value)? audioStarted,TResult Function( BridgeEvent_AudioStopped value)? audioStopped,required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that);case BridgeEvent_Lost() when lost != null:
|
||||
return lost(_that);case BridgeEvent_Reconnecting() when reconnecting != null:
|
||||
return reconnecting(_that);case BridgeEvent_Disconnected() when disconnected != null:
|
||||
return disconnected(_that);case BridgeEvent_AudioStarted() when audioStarted != null:
|
||||
return audioStarted(_that);case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( BridgeEvent_Connected value) connected,required TResult Function( BridgeEvent_Lost value) lost,required TResult Function( BridgeEvent_Reconnecting value) reconnecting,required TResult Function( BridgeEvent_Disconnected value) disconnected,required TResult Function( BridgeEvent_AudioStarted value) audioStarted,required TResult Function( BridgeEvent_AudioStopped value) audioStopped,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected():
|
||||
return connected(_that);case BridgeEvent_Lost():
|
||||
return lost(_that);case BridgeEvent_Reconnecting():
|
||||
return reconnecting(_that);case BridgeEvent_Disconnected():
|
||||
return disconnected(_that);case BridgeEvent_AudioStarted():
|
||||
return audioStarted(_that);case BridgeEvent_AudioStopped():
|
||||
return audioStopped(_that);}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( BridgeEvent_Connected value)? connected,TResult? Function( BridgeEvent_Lost value)? lost,TResult? Function( BridgeEvent_Reconnecting value)? reconnecting,TResult? Function( BridgeEvent_Disconnected value)? disconnected,TResult? Function( BridgeEvent_AudioStarted value)? audioStarted,TResult? Function( BridgeEvent_AudioStopped value)? audioStopped,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that);case BridgeEvent_Lost() when lost != null:
|
||||
return lost(_that);case BridgeEvent_Reconnecting() when reconnecting != null:
|
||||
return reconnecting(_that);case BridgeEvent_Disconnected() when disconnected != null:
|
||||
return disconnected(_that);case BridgeEvent_AudioStarted() when audioStarted != null:
|
||||
return audioStarted(_that);case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@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,required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that.serverName);case BridgeEvent_Lost() when lost != null:
|
||||
return lost(_that.reason);case BridgeEvent_Reconnecting() when reconnecting != null:
|
||||
return reconnecting(_that.attempt,_that.delaySecs);case BridgeEvent_Disconnected() when disconnected != null:
|
||||
return disconnected(_that.reason);case BridgeEvent_AudioStarted() when audioStarted != null:
|
||||
return audioStarted();case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped();case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@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,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected():
|
||||
return connected(_that.serverName);case BridgeEvent_Lost():
|
||||
return lost(_that.reason);case BridgeEvent_Reconnecting():
|
||||
return reconnecting(_that.attempt,_that.delaySecs);case BridgeEvent_Disconnected():
|
||||
return disconnected(_that.reason);case BridgeEvent_AudioStarted():
|
||||
return audioStarted();case BridgeEvent_AudioStopped():
|
||||
return audioStopped();}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@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,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeEvent_Connected() when connected != null:
|
||||
return connected(_that.serverName);case BridgeEvent_Lost() when lost != null:
|
||||
return lost(_that.reason);case BridgeEvent_Reconnecting() when reconnecting != null:
|
||||
return reconnecting(_that.attempt,_that.delaySecs);case BridgeEvent_Disconnected() when disconnected != null:
|
||||
return disconnected(_that.reason);case BridgeEvent_AudioStarted() when audioStarted != null:
|
||||
return audioStarted();case BridgeEvent_AudioStopped() when audioStopped != null:
|
||||
return audioStopped();case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_Connected extends BridgeEvent {
|
||||
const BridgeEvent_Connected({required this.serverName}): super._();
|
||||
|
||||
|
||||
/// Server name reported by the server snapshot.
|
||||
final String serverName;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BridgeEvent_ConnectedCopyWith<BridgeEvent_Connected> get copyWith => _$BridgeEvent_ConnectedCopyWithImpl<BridgeEvent_Connected>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_Connected&&(identical(other.serverName, serverName) || other.serverName == serverName));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,serverName);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.connected(serverName: $serverName)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BridgeEvent_ConnectedCopyWith<$Res> implements $BridgeEventCopyWith<$Res> {
|
||||
factory $BridgeEvent_ConnectedCopyWith(BridgeEvent_Connected value, $Res Function(BridgeEvent_Connected) _then) = _$BridgeEvent_ConnectedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String serverName
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BridgeEvent_ConnectedCopyWithImpl<$Res>
|
||||
implements $BridgeEvent_ConnectedCopyWith<$Res> {
|
||||
_$BridgeEvent_ConnectedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BridgeEvent_Connected _self;
|
||||
final $Res Function(BridgeEvent_Connected) _then;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? serverName = null,}) {
|
||||
return _then(BridgeEvent_Connected(
|
||||
serverName: null == serverName ? _self.serverName : serverName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_Lost extends BridgeEvent {
|
||||
const BridgeEvent_Lost({required this.reason}): super._();
|
||||
|
||||
|
||||
/// Reason classification from the protocol layer.
|
||||
final String reason;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BridgeEvent_LostCopyWith<BridgeEvent_Lost> get copyWith => _$BridgeEvent_LostCopyWithImpl<BridgeEvent_Lost>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_Lost&&(identical(other.reason, reason) || other.reason == reason));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,reason);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.lost(reason: $reason)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BridgeEvent_LostCopyWith<$Res> implements $BridgeEventCopyWith<$Res> {
|
||||
factory $BridgeEvent_LostCopyWith(BridgeEvent_Lost value, $Res Function(BridgeEvent_Lost) _then) = _$BridgeEvent_LostCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String reason
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BridgeEvent_LostCopyWithImpl<$Res>
|
||||
implements $BridgeEvent_LostCopyWith<$Res> {
|
||||
_$BridgeEvent_LostCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BridgeEvent_Lost _self;
|
||||
final $Res Function(BridgeEvent_Lost) _then;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? reason = null,}) {
|
||||
return _then(BridgeEvent_Lost(
|
||||
reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_Reconnecting extends BridgeEvent {
|
||||
const BridgeEvent_Reconnecting({required this.attempt, required this.delaySecs}): super._();
|
||||
|
||||
|
||||
/// 1-based attempt counter for the current outage.
|
||||
final int attempt;
|
||||
/// Seconds the supervisor will sleep before this attempt.
|
||||
final int delaySecs;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BridgeEvent_ReconnectingCopyWith<BridgeEvent_Reconnecting> get copyWith => _$BridgeEvent_ReconnectingCopyWithImpl<BridgeEvent_Reconnecting>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_Reconnecting&&(identical(other.attempt, attempt) || other.attempt == attempt)&&(identical(other.delaySecs, delaySecs) || other.delaySecs == delaySecs));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,attempt,delaySecs);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.reconnecting(attempt: $attempt, delaySecs: $delaySecs)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BridgeEvent_ReconnectingCopyWith<$Res> implements $BridgeEventCopyWith<$Res> {
|
||||
factory $BridgeEvent_ReconnectingCopyWith(BridgeEvent_Reconnecting value, $Res Function(BridgeEvent_Reconnecting) _then) = _$BridgeEvent_ReconnectingCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int attempt, int delaySecs
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BridgeEvent_ReconnectingCopyWithImpl<$Res>
|
||||
implements $BridgeEvent_ReconnectingCopyWith<$Res> {
|
||||
_$BridgeEvent_ReconnectingCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BridgeEvent_Reconnecting _self;
|
||||
final $Res Function(BridgeEvent_Reconnecting) _then;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? attempt = null,Object? delaySecs = null,}) {
|
||||
return _then(BridgeEvent_Reconnecting(
|
||||
attempt: null == attempt ? _self.attempt : attempt // ignore: cast_nullable_to_non_nullable
|
||||
as int,delaySecs: null == delaySecs ? _self.delaySecs : delaySecs // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_Disconnected extends BridgeEvent {
|
||||
const BridgeEvent_Disconnected({required this.reason}): super._();
|
||||
|
||||
|
||||
/// Reason classification.
|
||||
final String reason;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BridgeEvent_DisconnectedCopyWith<BridgeEvent_Disconnected> get copyWith => _$BridgeEvent_DisconnectedCopyWithImpl<BridgeEvent_Disconnected>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_Disconnected&&(identical(other.reason, reason) || other.reason == reason));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,reason);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.disconnected(reason: $reason)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BridgeEvent_DisconnectedCopyWith<$Res> implements $BridgeEventCopyWith<$Res> {
|
||||
factory $BridgeEvent_DisconnectedCopyWith(BridgeEvent_Disconnected value, $Res Function(BridgeEvent_Disconnected) _then) = _$BridgeEvent_DisconnectedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String reason
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BridgeEvent_DisconnectedCopyWithImpl<$Res>
|
||||
implements $BridgeEvent_DisconnectedCopyWith<$Res> {
|
||||
_$BridgeEvent_DisconnectedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BridgeEvent_Disconnected _self;
|
||||
final $Res Function(BridgeEvent_Disconnected) _then;
|
||||
|
||||
/// Create a copy of BridgeEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? reason = null,}) {
|
||||
return _then(BridgeEvent_Disconnected(
|
||||
reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_AudioStarted extends BridgeEvent {
|
||||
const BridgeEvent_AudioStarted(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_AudioStarted);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.audioStarted()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeEvent_AudioStopped extends BridgeEvent {
|
||||
const BridgeEvent_AudioStopped(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeEvent_AudioStopped);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeEvent.audioStopped()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// dart format on
|
||||
@@ -67,7 +67,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
String get codegenVersion => '2.12.0';
|
||||
|
||||
@override
|
||||
int get rustContentHash => 1944264248;
|
||||
int get rustContentHash => -1896742393;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
@@ -90,6 +90,8 @@ abstract class RustLibApi extends BaseApi {
|
||||
|
||||
Future<void> crateApiDisconnect();
|
||||
|
||||
Stream<BridgeEvent> crateApiEventsStream();
|
||||
|
||||
Future<bool> crateApiIsConnected();
|
||||
|
||||
Future<void> crateApiSetPtt({required bool active});
|
||||
@@ -220,6 +222,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiDisconnectConstMeta =>
|
||||
const TaskConstMeta(debugName: "disconnect", argNames: []);
|
||||
|
||||
@override
|
||||
Stream<BridgeEvent> crateApiEventsStream() {
|
||||
final sink = RustStreamSink<BridgeEvent>();
|
||||
unawaited(
|
||||
handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
final serializer = SseSerializer(generalizedFrbRustBinding);
|
||||
sse_encode_StreamSink_bridge_event_Sse(sink, serializer);
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 5,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
codec: SseCodec(
|
||||
decodeSuccessData: sse_decode_unit,
|
||||
decodeErrorData: sse_decode_bridge_error,
|
||||
),
|
||||
constMeta: kCrateApiEventsStreamConstMeta,
|
||||
argValues: [sink],
|
||||
apiImpl: this,
|
||||
),
|
||||
),
|
||||
);
|
||||
return sink.stream;
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiEventsStreamConstMeta =>
|
||||
const TaskConstMeta(debugName: "events_stream", argNames: ["sink"]);
|
||||
|
||||
@override
|
||||
Future<bool> crateApiIsConnected() {
|
||||
return handler.executeNormal(
|
||||
@@ -229,7 +263,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 5,
|
||||
funcId: 6,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
@@ -257,7 +291,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 6,
|
||||
funcId: 7,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
@@ -284,7 +318,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 7,
|
||||
funcId: 8,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
@@ -311,7 +345,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 8,
|
||||
funcId: 9,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
@@ -329,6 +363,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiStartAudioConstMeta =>
|
||||
const TaskConstMeta(debugName: "start_audio", argNames: []);
|
||||
|
||||
@protected
|
||||
AnyhowException dco_decode_AnyhowException(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
return AnyhowException(raw as String);
|
||||
}
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> dco_decode_StreamSink_bridge_event_Sse(
|
||||
dynamic raw,
|
||||
) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@protected
|
||||
String dco_decode_String(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -388,18 +436,47 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
case 0:
|
||||
return BridgeError_InvalidCommand(dco_decode_String(raw[1]));
|
||||
case 1:
|
||||
return BridgeError_Connection(dco_decode_String(raw[1]));
|
||||
return BridgeError_DnsFailed(
|
||||
host: dco_decode_String(raw[1]),
|
||||
reason: dco_decode_String(raw[2]),
|
||||
);
|
||||
case 2:
|
||||
return BridgeError_NotConnected();
|
||||
return BridgeError_Connection(dco_decode_String(raw[1]));
|
||||
case 3:
|
||||
return BridgeError_AlreadyConnected();
|
||||
return BridgeError_NotConnected();
|
||||
case 4:
|
||||
return BridgeError_AlreadyConnected();
|
||||
case 5:
|
||||
return BridgeError_Unmapped(dco_decode_String(raw[1]));
|
||||
default:
|
||||
throw Exception("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeEvent dco_decode_bridge_event(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
switch (raw[0]) {
|
||||
case 0:
|
||||
return BridgeEvent_Connected(serverName: dco_decode_String(raw[1]));
|
||||
case 1:
|
||||
return BridgeEvent_Lost(reason: dco_decode_String(raw[1]));
|
||||
case 2:
|
||||
return BridgeEvent_Reconnecting(
|
||||
attempt: dco_decode_u_32(raw[1]),
|
||||
delaySecs: dco_decode_u_32(raw[2]),
|
||||
);
|
||||
case 3:
|
||||
return BridgeEvent_Disconnected(reason: dco_decode_String(raw[1]));
|
||||
case 4:
|
||||
return BridgeEvent_AudioStarted();
|
||||
case 5:
|
||||
return BridgeEvent_AudioStopped();
|
||||
default:
|
||||
throw Exception("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeSnapshot dco_decode_bridge_snapshot(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@@ -464,6 +541,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return;
|
||||
}
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var inner = sse_decode_String(deserializer);
|
||||
return AnyhowException(inner);
|
||||
}
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> sse_decode_StreamSink_bridge_event_Sse(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
throw UnimplementedError('Unreachable ()');
|
||||
}
|
||||
|
||||
@protected
|
||||
String sse_decode_String(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -524,13 +616,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
var var_field0 = sse_decode_String(deserializer);
|
||||
return BridgeError_InvalidCommand(var_field0);
|
||||
case 1:
|
||||
var var_host = sse_decode_String(deserializer);
|
||||
var var_reason = sse_decode_String(deserializer);
|
||||
return BridgeError_DnsFailed(host: var_host, reason: var_reason);
|
||||
case 2:
|
||||
var var_field0 = sse_decode_String(deserializer);
|
||||
return BridgeError_Connection(var_field0);
|
||||
case 2:
|
||||
return BridgeError_NotConnected();
|
||||
case 3:
|
||||
return BridgeError_AlreadyConnected();
|
||||
return BridgeError_NotConnected();
|
||||
case 4:
|
||||
return BridgeError_AlreadyConnected();
|
||||
case 5:
|
||||
var var_field0 = sse_decode_String(deserializer);
|
||||
return BridgeError_Unmapped(var_field0);
|
||||
default:
|
||||
@@ -538,6 +634,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeEvent sse_decode_bridge_event(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
var tag_ = sse_decode_i_32(deserializer);
|
||||
switch (tag_) {
|
||||
case 0:
|
||||
var var_serverName = sse_decode_String(deserializer);
|
||||
return BridgeEvent_Connected(serverName: var_serverName);
|
||||
case 1:
|
||||
var var_reason = sse_decode_String(deserializer);
|
||||
return BridgeEvent_Lost(reason: var_reason);
|
||||
case 2:
|
||||
var var_attempt = sse_decode_u_32(deserializer);
|
||||
var var_delaySecs = sse_decode_u_32(deserializer);
|
||||
return BridgeEvent_Reconnecting(
|
||||
attempt: var_attempt,
|
||||
delaySecs: var_delaySecs,
|
||||
);
|
||||
case 3:
|
||||
var var_reason = sse_decode_String(deserializer);
|
||||
return BridgeEvent_Disconnected(reason: var_reason);
|
||||
case 4:
|
||||
return BridgeEvent_AudioStarted();
|
||||
case 5:
|
||||
return BridgeEvent_AudioStopped();
|
||||
default:
|
||||
throw UnimplementedError('');
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
BridgeSnapshot sse_decode_bridge_snapshot(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -627,6 +754,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
return deserializer.buffer.getInt32();
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_AnyhowException(
|
||||
AnyhowException self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(self.message, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_StreamSink_bridge_event_Sse(
|
||||
RustStreamSink<BridgeEvent> self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(
|
||||
self.setupAndSerialize(
|
||||
codec: SseCodec(
|
||||
decodeSuccessData: sse_decode_bridge_event,
|
||||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
),
|
||||
serializer,
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_String(String self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@@ -674,19 +827,50 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
case BridgeError_InvalidCommand(field0: final field0):
|
||||
sse_encode_i_32(0, serializer);
|
||||
sse_encode_String(field0, serializer);
|
||||
case BridgeError_Connection(field0: final field0):
|
||||
case BridgeError_DnsFailed(host: final host, reason: final reason):
|
||||
sse_encode_i_32(1, serializer);
|
||||
sse_encode_String(host, serializer);
|
||||
sse_encode_String(reason, serializer);
|
||||
case BridgeError_Connection(field0: final field0):
|
||||
sse_encode_i_32(2, serializer);
|
||||
sse_encode_String(field0, serializer);
|
||||
case BridgeError_NotConnected():
|
||||
sse_encode_i_32(2, serializer);
|
||||
case BridgeError_AlreadyConnected():
|
||||
sse_encode_i_32(3, serializer);
|
||||
case BridgeError_Unmapped(field0: final field0):
|
||||
case BridgeError_AlreadyConnected():
|
||||
sse_encode_i_32(4, serializer);
|
||||
case BridgeError_Unmapped(field0: final field0):
|
||||
sse_encode_i_32(5, serializer);
|
||||
sse_encode_String(field0, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_event(BridgeEvent self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
switch (self) {
|
||||
case BridgeEvent_Connected(serverName: final serverName):
|
||||
sse_encode_i_32(0, serializer);
|
||||
sse_encode_String(serverName, serializer);
|
||||
case BridgeEvent_Lost(reason: final reason):
|
||||
sse_encode_i_32(1, serializer);
|
||||
sse_encode_String(reason, serializer);
|
||||
case BridgeEvent_Reconnecting(
|
||||
attempt: final attempt,
|
||||
delaySecs: final delaySecs,
|
||||
):
|
||||
sse_encode_i_32(2, serializer);
|
||||
sse_encode_u_32(attempt, serializer);
|
||||
sse_encode_u_32(delaySecs, serializer);
|
||||
case BridgeEvent_Disconnected(reason: final reason):
|
||||
sse_encode_i_32(3, serializer);
|
||||
sse_encode_String(reason, serializer);
|
||||
case BridgeEvent_AudioStarted():
|
||||
sse_encode_i_32(4, serializer);
|
||||
case BridgeEvent_AudioStopped():
|
||||
sse_encode_i_32(5, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_snapshot(
|
||||
BridgeSnapshot self,
|
||||
|
||||
@@ -19,6 +19,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
required super.portManager,
|
||||
});
|
||||
|
||||
@protected
|
||||
AnyhowException dco_decode_AnyhowException(dynamic raw);
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> dco_decode_StreamSink_bridge_event_Sse(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
String dco_decode_String(dynamic raw);
|
||||
|
||||
@@ -37,6 +45,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeError dco_decode_bridge_error(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeEvent dco_decode_bridge_event(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeSnapshot dco_decode_bridge_snapshot(dynamic raw);
|
||||
|
||||
@@ -64,6 +75,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void dco_decode_unit(dynamic raw);
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> sse_decode_StreamSink_bridge_event_Sse(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
String sse_decode_String(SseDeserializer deserializer);
|
||||
|
||||
@@ -82,6 +101,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeError sse_decode_bridge_error(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeEvent sse_decode_bridge_event(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeSnapshot sse_decode_bridge_snapshot(SseDeserializer deserializer);
|
||||
|
||||
@@ -116,6 +138,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
int sse_decode_i_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_AnyhowException(
|
||||
AnyhowException self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_StreamSink_bridge_event_Sse(
|
||||
RustStreamSink<BridgeEvent> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_String(String self, SseSerializer serializer);
|
||||
|
||||
@@ -137,6 +171,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_bridge_error(BridgeError self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_event(BridgeEvent self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_snapshot(
|
||||
BridgeSnapshot self,
|
||||
|
||||
@@ -21,6 +21,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
required super.portManager,
|
||||
});
|
||||
|
||||
@protected
|
||||
AnyhowException dco_decode_AnyhowException(dynamic raw);
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> dco_decode_StreamSink_bridge_event_Sse(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
String dco_decode_String(dynamic raw);
|
||||
|
||||
@@ -39,6 +47,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeError dco_decode_bridge_error(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeEvent dco_decode_bridge_event(dynamic raw);
|
||||
|
||||
@protected
|
||||
BridgeSnapshot dco_decode_bridge_snapshot(dynamic raw);
|
||||
|
||||
@@ -66,6 +77,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void dco_decode_unit(dynamic raw);
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
RustStreamSink<BridgeEvent> sse_decode_StreamSink_bridge_event_Sse(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
String sse_decode_String(SseDeserializer deserializer);
|
||||
|
||||
@@ -84,6 +103,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
BridgeError sse_decode_bridge_error(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeEvent sse_decode_bridge_event(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
BridgeSnapshot sse_decode_bridge_snapshot(SseDeserializer deserializer);
|
||||
|
||||
@@ -118,6 +140,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
int sse_decode_i_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_AnyhowException(
|
||||
AnyhowException self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_StreamSink_bridge_event_Sse(
|
||||
RustStreamSink<BridgeEvent> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_String(String self, SseSerializer serializer);
|
||||
|
||||
@@ -139,6 +173,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
void sse_encode_bridge_error(BridgeError self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_event(BridgeEvent self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bridge_snapshot(
|
||||
BridgeSnapshot self,
|
||||
|
||||
@@ -16,6 +16,16 @@ sealed class BridgeError with _$BridgeError implements FrbException {
|
||||
const factory BridgeError.invalidCommand(String field0) =
|
||||
BridgeError_InvalidCommand;
|
||||
|
||||
/// Hostname resolution failed. Distinct from `Connection` so the
|
||||
/// UI can show a meaningful "Server not found" message.
|
||||
const factory BridgeError.dnsFailed({
|
||||
/// The hostname (or `host:port`) the caller submitted.
|
||||
required String host,
|
||||
|
||||
/// Reason from the platform resolver.
|
||||
required String reason,
|
||||
}) = BridgeError_DnsFailed;
|
||||
|
||||
/// Connection layer failure (typed-mapped from CoreError).
|
||||
const factory BridgeError.connection(String field0) = BridgeError_Connection;
|
||||
|
||||
|
||||
@@ -55,11 +55,12 @@ extension BridgeErrorPatterns on BridgeError {
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( BridgeError_InvalidCommand value)? invalidCommand,TResult Function( BridgeError_Connection value)? connection,TResult Function( BridgeError_NotConnected value)? notConnected,TResult Function( BridgeError_AlreadyConnected value)? alreadyConnected,TResult Function( BridgeError_Unmapped value)? unmapped,required TResult orElse(),}){
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( BridgeError_InvalidCommand value)? invalidCommand,TResult Function( BridgeError_DnsFailed value)? dnsFailed,TResult Function( BridgeError_Connection value)? connection,TResult Function( BridgeError_NotConnected value)? notConnected,TResult Function( BridgeError_AlreadyConnected value)? alreadyConnected,TResult Function( BridgeError_Unmapped value)? unmapped,required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand() when invalidCommand != null:
|
||||
return invalidCommand(_that);case BridgeError_Connection() when connection != null:
|
||||
return invalidCommand(_that);case BridgeError_DnsFailed() when dnsFailed != null:
|
||||
return dnsFailed(_that);case BridgeError_Connection() when connection != null:
|
||||
return connection(_that);case BridgeError_NotConnected() when notConnected != null:
|
||||
return notConnected(_that);case BridgeError_AlreadyConnected() when alreadyConnected != null:
|
||||
return alreadyConnected(_that);case BridgeError_Unmapped() when unmapped != null:
|
||||
@@ -81,11 +82,12 @@ return unmapped(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( BridgeError_InvalidCommand value) invalidCommand,required TResult Function( BridgeError_Connection value) connection,required TResult Function( BridgeError_NotConnected value) notConnected,required TResult Function( BridgeError_AlreadyConnected value) alreadyConnected,required TResult Function( BridgeError_Unmapped value) unmapped,}){
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( BridgeError_InvalidCommand value) invalidCommand,required TResult Function( BridgeError_DnsFailed value) dnsFailed,required TResult Function( BridgeError_Connection value) connection,required TResult Function( BridgeError_NotConnected value) notConnected,required TResult Function( BridgeError_AlreadyConnected value) alreadyConnected,required TResult Function( BridgeError_Unmapped value) unmapped,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand():
|
||||
return invalidCommand(_that);case BridgeError_Connection():
|
||||
return invalidCommand(_that);case BridgeError_DnsFailed():
|
||||
return dnsFailed(_that);case BridgeError_Connection():
|
||||
return connection(_that);case BridgeError_NotConnected():
|
||||
return notConnected(_that);case BridgeError_AlreadyConnected():
|
||||
return alreadyConnected(_that);case BridgeError_Unmapped():
|
||||
@@ -103,11 +105,12 @@ return unmapped(_that);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( BridgeError_InvalidCommand value)? invalidCommand,TResult? Function( BridgeError_Connection value)? connection,TResult? Function( BridgeError_NotConnected value)? notConnected,TResult? Function( BridgeError_AlreadyConnected value)? alreadyConnected,TResult? Function( BridgeError_Unmapped value)? unmapped,}){
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( BridgeError_InvalidCommand value)? invalidCommand,TResult? Function( BridgeError_DnsFailed value)? dnsFailed,TResult? Function( BridgeError_Connection value)? connection,TResult? Function( BridgeError_NotConnected value)? notConnected,TResult? Function( BridgeError_AlreadyConnected value)? alreadyConnected,TResult? Function( BridgeError_Unmapped value)? unmapped,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand() when invalidCommand != null:
|
||||
return invalidCommand(_that);case BridgeError_Connection() when connection != null:
|
||||
return invalidCommand(_that);case BridgeError_DnsFailed() when dnsFailed != null:
|
||||
return dnsFailed(_that);case BridgeError_Connection() when connection != null:
|
||||
return connection(_that);case BridgeError_NotConnected() when notConnected != null:
|
||||
return notConnected(_that);case BridgeError_AlreadyConnected() when alreadyConnected != null:
|
||||
return alreadyConnected(_that);case BridgeError_Unmapped() when unmapped != null:
|
||||
@@ -128,10 +131,11 @@ return unmapped(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String field0)? invalidCommand,TResult Function( String field0)? connection,TResult Function()? notConnected,TResult Function()? alreadyConnected,TResult Function( String field0)? unmapped,required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String field0)? invalidCommand,TResult Function( String host, String reason)? dnsFailed,TResult Function( String field0)? connection,TResult Function()? notConnected,TResult Function()? alreadyConnected,TResult Function( String field0)? unmapped,required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand() when invalidCommand != null:
|
||||
return invalidCommand(_that.field0);case BridgeError_Connection() when connection != null:
|
||||
return invalidCommand(_that.field0);case BridgeError_DnsFailed() when dnsFailed != null:
|
||||
return dnsFailed(_that.host,_that.reason);case BridgeError_Connection() when connection != null:
|
||||
return connection(_that.field0);case BridgeError_NotConnected() when notConnected != null:
|
||||
return notConnected();case BridgeError_AlreadyConnected() when alreadyConnected != null:
|
||||
return alreadyConnected();case BridgeError_Unmapped() when unmapped != null:
|
||||
@@ -153,10 +157,11 @@ return unmapped(_that.field0);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String field0) invalidCommand,required TResult Function( String field0) connection,required TResult Function() notConnected,required TResult Function() alreadyConnected,required TResult Function( String field0) unmapped,}) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String field0) invalidCommand,required TResult Function( String host, String reason) dnsFailed,required TResult Function( String field0) connection,required TResult Function() notConnected,required TResult Function() alreadyConnected,required TResult Function( String field0) unmapped,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand():
|
||||
return invalidCommand(_that.field0);case BridgeError_Connection():
|
||||
return invalidCommand(_that.field0);case BridgeError_DnsFailed():
|
||||
return dnsFailed(_that.host,_that.reason);case BridgeError_Connection():
|
||||
return connection(_that.field0);case BridgeError_NotConnected():
|
||||
return notConnected();case BridgeError_AlreadyConnected():
|
||||
return alreadyConnected();case BridgeError_Unmapped():
|
||||
@@ -174,10 +179,11 @@ return unmapped(_that.field0);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String field0)? invalidCommand,TResult? Function( String field0)? connection,TResult? Function()? notConnected,TResult? Function()? alreadyConnected,TResult? Function( String field0)? unmapped,}) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String field0)? invalidCommand,TResult? Function( String host, String reason)? dnsFailed,TResult? Function( String field0)? connection,TResult? Function()? notConnected,TResult? Function()? alreadyConnected,TResult? Function( String field0)? unmapped,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case BridgeError_InvalidCommand() when invalidCommand != null:
|
||||
return invalidCommand(_that.field0);case BridgeError_Connection() when connection != null:
|
||||
return invalidCommand(_that.field0);case BridgeError_DnsFailed() when dnsFailed != null:
|
||||
return dnsFailed(_that.host,_that.reason);case BridgeError_Connection() when connection != null:
|
||||
return connection(_that.field0);case BridgeError_NotConnected() when notConnected != null:
|
||||
return notConnected();case BridgeError_AlreadyConnected() when alreadyConnected != null:
|
||||
return alreadyConnected();case BridgeError_Unmapped() when unmapped != null:
|
||||
@@ -258,6 +264,76 @@ as String,
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeError_DnsFailed extends BridgeError {
|
||||
const BridgeError_DnsFailed({required this.host, required this.reason}): super._();
|
||||
|
||||
|
||||
/// The hostname (or `host:port`) the caller submitted.
|
||||
final String host;
|
||||
/// Reason from the platform resolver.
|
||||
final String reason;
|
||||
|
||||
/// Create a copy of BridgeError
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BridgeError_DnsFailedCopyWith<BridgeError_DnsFailed> get copyWith => _$BridgeError_DnsFailedCopyWithImpl<BridgeError_DnsFailed>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BridgeError_DnsFailed&&(identical(other.host, host) || other.host == host)&&(identical(other.reason, reason) || other.reason == reason));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,host,reason);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BridgeError.dnsFailed(host: $host, reason: $reason)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BridgeError_DnsFailedCopyWith<$Res> implements $BridgeErrorCopyWith<$Res> {
|
||||
factory $BridgeError_DnsFailedCopyWith(BridgeError_DnsFailed value, $Res Function(BridgeError_DnsFailed) _then) = _$BridgeError_DnsFailedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String host, String reason
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BridgeError_DnsFailedCopyWithImpl<$Res>
|
||||
implements $BridgeError_DnsFailedCopyWith<$Res> {
|
||||
_$BridgeError_DnsFailedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BridgeError_DnsFailed _self;
|
||||
final $Res Function(BridgeError_DnsFailed) _then;
|
||||
|
||||
/// Create a copy of BridgeError
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? host = null,Object? reason = null,}) {
|
||||
return _then(BridgeError_DnsFailed(
|
||||
host: null == host ? _self.host : host // ignore: cast_nullable_to_non_nullable
|
||||
as String,reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class BridgeError_Connection extends BridgeError {
|
||||
const BridgeError_Connection(this.field0): super._();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user