From 966543da6a9cb27ab1e575fd1d6e298f41cb49b9 Mon Sep 17 00:00:00 2001 From: Tien Do Nam Date: Tue, 4 Aug 2026 15:23:44 +0200 Subject: [PATCH] feat(core): update device logs structure --- packages/core/src/discovery/mod.rs | 3 +- packages/core/src/discovery/store.rs | 65 +++-- .../lib/rust/api/discovery.dart | 41 ++- .../lib/rust/frb_generated.dart | 206 +++++++++---- .../lib/rust/frb_generated.io.dart | 27 ++ .../lib/rust/frb_generated.web.dart | 27 ++ .../rust/src/api/discovery.rs | 49 +++- .../rust/src/frb_generated.rs | 276 ++++++++++++++---- 8 files changed, 561 insertions(+), 133 deletions(-) diff --git a/packages/core/src/discovery/mod.rs b/packages/core/src/discovery/mod.rs index 68bb5470..e27cafb1 100644 --- a/packages/core/src/discovery/mod.rs +++ b/packages/core/src/discovery/mod.rs @@ -1,7 +1,8 @@ mod store; pub use store::{ - ChannelStatus, DeviceChannel, DeviceLog, DiscoveredDevice, HttpChannel, StatefulDevice, + ChannelStatus, DeviceChannel, DeviceLog, DeviceLogKind, DiscoveredDevice, HttpChannel, + StatefulDevice, }; use crate::http::client::{ClientError, LsHttpClientV2}; diff --git a/packages/core/src/discovery/store.rs b/packages/core/src/discovery/store.rs index 456cec99..81f0898f 100644 --- a/packages/core/src/discovery/store.rs +++ b/packages/core/src/discovery/store.rs @@ -66,11 +66,27 @@ pub enum ChannelStatus { NotReachable, } -/// A [`DiscoveryEvent`] that affected a device, with the time it happened. +/// A confirmation of a device, as retained on it for display. #[derive(Clone, Debug)] pub struct DeviceLog { pub timestamp: SystemTime, - pub event: DiscoveryEvent, + + /// Whether the confirmation discovered the device or re-confirmed it. + pub kind: DeviceLogKind, + + /// The channel the confirmation happened on. + pub channel: DeviceChannel, +} + +/// What a logged confirmation meant for the device, mirroring the +/// [`DiscoveryEvent`] variants. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum DeviceLogKind { + /// The device entered the store. + Discovered, + + /// An already known device was confirmed again. + Updated, } impl StatefulDevice { @@ -93,11 +109,7 @@ impl StatefulDevice { /// The position of the channel's most recent confirmation in the logs; /// `None` when its confirmations have been dropped from the log cap. fn last_confirmed(&self, channel: &DeviceChannel) -> Option { - self.logs.iter().rposition(|log| { - let (DiscoveryEvent::Discovered { device } | DiscoveryEvent::Updated { device }) = - &log.event; - device.channel == *channel - }) + self.logs.iter().rposition(|log| log.channel == *channel) } } @@ -192,10 +204,6 @@ impl DeviceStore { .find(|known| known.device.fingerprint == device.fingerprint) { Some(known) => { - let event = DiscoveryEvent::Updated { - device: device.clone(), - }; - known .channels .retain(|channel, _| !channel.same_endpoint(&device.channel)); @@ -205,30 +213,32 @@ impl DeviceStore { known.logs.push(DeviceLog { timestamp, - event: event.clone(), + kind: DeviceLogKind::Updated, + channel: device.channel.clone(), }); if known.logs.len() > MAX_LOGS { let excess = known.logs.len() - MAX_LOGS; known.logs.drain(..excess); } + let event = DiscoveryEvent::Updated { + device: device.clone(), + }; known.device = device; (event, known.clone()) } None => { - let event = DiscoveryEvent::Discovered { - device: device.clone(), - }; let known = StatefulDevice { channels: HashMap::from([(device.channel.clone(), ChannelStatus::Available)]), - device, logs: vec![DeviceLog { timestamp, - event: event.clone(), + kind: DeviceLogKind::Discovered, + channel: device.channel.clone(), }], + device: device.clone(), }; devices.push(known.clone()); - (event, known) + (DiscoveryEvent::Discovered { device }, known) } } } @@ -272,13 +282,10 @@ mod tests { channel.http().unwrap().host.as_str() } - /// The marker telling log entries apart: the host the logged snapshot - /// was confirmed on. + /// The marker telling log entries apart: the host the confirmation + /// happened on. fn log_marker(log: &DeviceLog) -> &str { - let device = match &log.event { - DiscoveryEvent::Discovered { device } | DiscoveryEvent::Updated { device } => device, - }; - device.http().unwrap().host.as_str() + log.channel.http().unwrap().host.as_str() } #[test] @@ -303,14 +310,8 @@ mod tests { let known = store.by_fingerprint("a").unwrap(); assert_eq!(known.logs.len(), 2, "every confirmation must be logged"); - assert!(matches!( - known.logs[0].event, - DiscoveryEvent::Discovered { .. } - )); - assert!(matches!( - known.logs[1].event, - DiscoveryEvent::Updated { .. } - )); + assert_eq!(known.logs[0].kind, DeviceLogKind::Discovered); + assert_eq!(known.logs[1].kind, DeviceLogKind::Updated); assert_eq!(log_marker(&known.logs[1]), "fe80::1%3"); } diff --git a/packages/localsend_isolates/lib/rust/api/discovery.dart b/packages/localsend_isolates/lib/rust/api/discovery.dart index c81e4e20..c800be60 100644 --- a/packages/localsend_isolates/lib/rust/api/discovery.dart +++ b/packages/localsend_isolates/lib/rust/api/discovery.dart @@ -7,7 +7,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:localsend_isolates/rust/api/model.dart'; import 'package:localsend_isolates/rust/frb_generated.dart'; -// These functions are ignored because they are not marked as `pub`: `rs_stored_device`, `stop` +// These functions are ignored because they are not marked as `pub`: `rs_device_log`, `rs_stored_device`, `stop` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DiscoveryInstance` /// Starts the discovery: binds the UDP multicast sockets on all usable @@ -79,6 +79,10 @@ abstract class RsDiscovery implements RustOpaqueInterface { /// multicast is unavailable. Future announce(); + /// The retained confirmations of a stored device, oldest first, capped at + /// the store's log limit. Empty when the fingerprint is unknown. + Future> deviceLogs({required String fingerprint}); + /// Discovers a device at a known address, e.g. a favorite or a peer that /// multicast does not reach, by sending it a register request. /// @@ -121,6 +125,11 @@ abstract class RsDiscovery implements RustOpaqueInterface { Future stop(); } +enum DeviceLogKind { + discovered, + updated, +} + /// An address a stored device was confirmed on and is dialed at. class RsDeviceChannel { /// The host to dial: an IP address, or the scoped form `fe80::1%3` for @@ -146,6 +155,36 @@ class RsDeviceChannel { other is RsDeviceChannel && runtimeType == other.runtimeType && host == other.host && port == other.port && protocol == other.protocol; } +/// One retained confirmation of a stored device, for the device details UI. +class RsDeviceLog { + /// When the confirmation happened, in milliseconds since the Unix epoch. + final BigInt timestampMillis; + + /// Whether the confirmation discovered the device or re-confirmed it. + final DeviceLogKind kind; + + /// The channel the confirmation happened on. + final RsDeviceChannel channel; + + const RsDeviceLog({ + required this.timestampMillis, + required this.kind, + required this.channel, + }); + + @override + int get hashCode => timestampMillis.hashCode ^ kind.hashCode ^ channel.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is RsDeviceLog && + runtimeType == other.runtimeType && + timestampMillis == other.timestampMillis && + kind == other.kind && + channel == other.channel; +} + /// A single device confirmation over HTTP, fed into the store via /// [RsDiscovery::add_device]: the device's register request was accepted by /// our server, so it is known to be reachable at [RsDiscoveredDevice::host]. diff --git a/packages/localsend_isolates/lib/rust/frb_generated.dart b/packages/localsend_isolates/lib/rust/frb_generated.dart index 1021e789..2bc25d32 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.dart @@ -75,7 +75,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -1120530143; + int get rustContentHash => -2095161624; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( stem: 'rust_lib_localsend_app', @@ -117,6 +117,8 @@ abstract class RustLibApi extends BaseApi { Future crateApiDiscoveryRsDiscoveryAnnounce({required RsDiscovery that}); + Future> crateApiDiscoveryRsDiscoveryDeviceLogs({required RsDiscovery that, required String fingerprint}); + Future crateApiDiscoveryRsDiscoveryDiscover({ required RsDiscovery that, required String host, @@ -613,6 +615,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that'], ); + @override + Future> crateApiDiscoveryRsDiscoveryDeviceLogs({required RsDiscovery that, required String fingerprint}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_String(fingerprint, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_rs_device_log, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryDeviceLogsConstMeta, + argValues: [that, fingerprint], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryDeviceLogsConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_device_logs', + argNames: ['that', 'fingerprint'], + ); + @override Future crateApiDiscoveryRsDiscoveryDiscover({ required RsDiscovery that, @@ -628,7 +656,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(host, serializer); sse_encode_u_16(port, serializer); sse_encode_protocol_type(protocol, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_rs_stored_device, @@ -656,7 +684,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); sse_encode_StreamSink_rs_stored_device_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -683,7 +711,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -716,7 +744,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(interfaceIp, serializer); sse_encode_u_16(port, serializer); sse_encode_protocol_type(protocol, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -742,7 +770,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); sse_encode_bool(answer, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -767,7 +795,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -802,7 +830,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ip, serializer); sse_encode_u_16(port, serializer); sse_encode_String(sessionId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -843,7 +871,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(publicKey, serializer); sse_encode_opt_String(pin, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_prepare_upload_result, @@ -878,7 +906,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ip, serializer); sse_encode_u_16(port, serializer); sse_encode_box_autoadd_register_dto(payload, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_result_with_public_key_register_response_dto, @@ -935,7 +963,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_u_64(contentLength, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -978,7 +1006,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1005,7 +1033,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1032,7 +1060,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1060,7 +1088,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_StreamSink_rs_server_event_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1097,7 +1125,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fileId, serializer); sse_encode_opt_String(path, serializer); sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1137,7 +1165,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(path, serializer); sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_u_64(fileSize, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1166,7 +1194,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_bool(accept, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1192,7 +1220,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_opt_list_String(acceptedFileIds, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1217,7 +1245,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1242,7 +1270,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1270,7 +1298,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver(that, serializer); sse_encode_StreamSink_list_prim_u_8_strict_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1298,7 +1326,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileSender(that, serializer); sse_encode_list_prim_u_8_loose(data, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1323,7 +1351,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1351,7 +1379,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_rtc_file_error_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1378,7 +1406,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_file_dto, @@ -1406,7 +1434,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1436,7 +1464,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_rtc_status_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1464,7 +1492,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_box_autoadd_rtc_send_file_response(status, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1490,7 +1518,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_String(pin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1516,7 +1544,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_Set_String_None(selection, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1544,7 +1572,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_StreamSink_rtc_file_error_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1571,7 +1599,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Set_String_None, @@ -1599,7 +1627,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_StreamSink_rtc_status_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1627,7 +1655,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileSender, @@ -1653,7 +1681,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_String(pin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1692,7 +1720,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { onConnection, serializer, ); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1718,7 +1746,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken, @@ -1753,7 +1781,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_ls_http_client_version(version, serializer); sse_encode_opt_String(expectedFingerprint, serializer); sse_encode_opt_box_autoadd_u_32(timeoutMs, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient, @@ -1777,7 +1805,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -1802,7 +1830,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1826,7 +1854,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_key_pair, @@ -1850,7 +1878,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_security_context, @@ -1881,7 +1909,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_opt_list_prim_u_8_strict(bytes, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1908,7 +1936,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(name, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -1933,7 +1961,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(name, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1986,7 +2014,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(certPem, serializer); sse_encode_String(privateKeyPem, serializer); sse_encode_u_64(timeoutMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery, @@ -2063,7 +2091,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(verifyChecksums, serializer); sse_encode_opt_box_autoadd_web_params(web, serializer); sse_encode_opt_String(showToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer, @@ -2089,7 +2117,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(cert, serializer); sse_encode_String(publicKey, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2689,6 +2717,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + DeviceLogKind dco_decode_device_log_kind(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return DeviceLogKind.values[raw as int]; + } + @protected DeviceType dco_decode_device_type(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2810,6 +2844,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_rs_device_channel).toList(); } + @protected + List dco_decode_list_rs_device_log(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_rs_device_log).toList(); + } + @protected LsHttpClientVersion dco_decode_ls_http_client_version(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3086,6 +3126,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + RsDeviceLog dco_decode_rs_device_log(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return RsDeviceLog( + timestampMillis: dco_decode_u_64(arr[0]), + kind: dco_decode_device_log_kind(arr[1]), + channel: dco_decode_rs_device_channel(arr[2]), + ); + } + @protected RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3954,6 +4006,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ClientInfoWithoutId(alias: var_alias, version: var_version, deviceModel: var_deviceModel, deviceType: var_deviceType, token: var_token); } + @protected + DeviceLogKind sse_decode_device_log_kind(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_i_32(deserializer); + return DeviceLogKind.values[inner]; + } + @protected DeviceType sse_decode_device_type(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4110,6 +4169,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_rs_device_log(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_rs_device_log(deserializer)); + } + return ans_; + } + @protected LsHttpClientVersion sse_decode_ls_http_client_version(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4443,6 +4514,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsDeviceChannel(host: var_host, port: var_port, protocol: var_protocol); } + @protected + RsDeviceLog sse_decode_rs_device_log(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_timestampMillis = sse_decode_u_64(deserializer); + var var_kind = sse_decode_device_log_kind(deserializer); + var var_channel = sse_decode_rs_device_channel(deserializer); + return RsDeviceLog(timestampMillis: var_timestampMillis, kind: var_kind, channel: var_channel); + } + @protected RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5427,6 +5507,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.token, serializer); } + @protected + void sse_encode_device_log_kind(DeviceLogKind self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.index, serializer); + } + @protected void sse_encode_device_type(DeviceType self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5552,6 +5638,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_rs_device_log(List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_rs_device_log(item, serializer); + } + } + @protected void sse_encode_ls_http_client_version(LsHttpClientVersion self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5831,6 +5926,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_protocol_type(self.protocol, serializer); } + @protected + void sse_encode_rs_device_log(RsDeviceLog self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_64(self.timestampMillis, serializer); + sse_encode_device_log_kind(self.kind, serializer); + sse_encode_rs_device_channel(self.channel, serializer); + } + @protected void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -6266,6 +6369,11 @@ class RsDiscoveryImpl extends RustOpaque implements RsDiscovery { that: this, ); + /// The retained confirmations of a stored device, oldest first, capped at + /// the store's log limit. Empty when the fingerprint is unknown. + Future> deviceLogs({required String fingerprint}) => + RustLib.instance.api.crateApiDiscoveryRsDiscoveryDeviceLogs(that: this, fingerprint: fingerprint); + /// Discovers a device at a known address, e.g. a favorite or a peer that /// multicast does not reach, by sending it a register request. /// diff --git a/packages/localsend_isolates/lib/rust/frb_generated.io.dart b/packages/localsend_isolates/lib/rust/frb_generated.io.dart index 6799b7a7..08b4d37b 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.io.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.io.dart @@ -300,6 +300,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ClientInfoWithoutId dco_decode_client_info_without_id(dynamic raw); + @protected + DeviceLogKind dco_decode_device_log_kind(dynamic raw); + @protected DeviceType dco_decode_device_type(dynamic raw); @@ -348,6 +351,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_rs_device_channel(dynamic raw); + @protected + List dco_decode_list_rs_device_log(dynamic raw); + @protected LsHttpClientVersion dco_decode_ls_http_client_version(dynamic raw); @@ -442,6 +448,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsDeviceChannel dco_decode_rs_device_channel(dynamic raw); + @protected + RsDeviceLog dco_decode_rs_device_log(dynamic raw); + @protected RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw); @@ -767,6 +776,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ClientInfoWithoutId sse_decode_client_info_without_id(SseDeserializer deserializer); + @protected + DeviceLogKind sse_decode_device_log_kind(SseDeserializer deserializer); + @protected DeviceType sse_decode_device_type(SseDeserializer deserializer); @@ -815,6 +827,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_rs_device_channel(SseDeserializer deserializer); + @protected + List sse_decode_list_rs_device_log(SseDeserializer deserializer); + @protected LsHttpClientVersion sse_decode_ls_http_client_version(SseDeserializer deserializer); @@ -911,6 +926,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsDeviceChannel sse_decode_rs_device_channel(SseDeserializer deserializer); + @protected + RsDeviceLog sse_decode_rs_device_log(SseDeserializer deserializer); + @protected RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer); @@ -1281,6 +1299,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_client_info_without_id(ClientInfoWithoutId self, SseSerializer serializer); + @protected + void sse_encode_device_log_kind(DeviceLogKind self, SseSerializer serializer); + @protected void sse_encode_device_type(DeviceType self, SseSerializer serializer); @@ -1329,6 +1350,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_rs_device_channel(List self, SseSerializer serializer); + @protected + void sse_encode_list_rs_device_log(List self, SseSerializer serializer); + @protected void sse_encode_ls_http_client_version(LsHttpClientVersion self, SseSerializer serializer); @@ -1426,6 +1450,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_rs_device_channel(RsDeviceChannel self, SseSerializer serializer); + @protected + void sse_encode_rs_device_log(RsDeviceLog self, SseSerializer serializer); + @protected void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); diff --git a/packages/localsend_isolates/lib/rust/frb_generated.web.dart b/packages/localsend_isolates/lib/rust/frb_generated.web.dart index d4c79868..9a7c8ee7 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.web.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.web.dart @@ -302,6 +302,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ClientInfoWithoutId dco_decode_client_info_without_id(dynamic raw); + @protected + DeviceLogKind dco_decode_device_log_kind(dynamic raw); + @protected DeviceType dco_decode_device_type(dynamic raw); @@ -350,6 +353,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_rs_device_channel(dynamic raw); + @protected + List dco_decode_list_rs_device_log(dynamic raw); + @protected LsHttpClientVersion dco_decode_ls_http_client_version(dynamic raw); @@ -444,6 +450,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsDeviceChannel dco_decode_rs_device_channel(dynamic raw); + @protected + RsDeviceLog dco_decode_rs_device_log(dynamic raw); + @protected RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw); @@ -769,6 +778,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ClientInfoWithoutId sse_decode_client_info_without_id(SseDeserializer deserializer); + @protected + DeviceLogKind sse_decode_device_log_kind(SseDeserializer deserializer); + @protected DeviceType sse_decode_device_type(SseDeserializer deserializer); @@ -817,6 +829,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_rs_device_channel(SseDeserializer deserializer); + @protected + List sse_decode_list_rs_device_log(SseDeserializer deserializer); + @protected LsHttpClientVersion sse_decode_ls_http_client_version(SseDeserializer deserializer); @@ -913,6 +928,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsDeviceChannel sse_decode_rs_device_channel(SseDeserializer deserializer); + @protected + RsDeviceLog sse_decode_rs_device_log(SseDeserializer deserializer); + @protected RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer); @@ -1283,6 +1301,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_client_info_without_id(ClientInfoWithoutId self, SseSerializer serializer); + @protected + void sse_encode_device_log_kind(DeviceLogKind self, SseSerializer serializer); + @protected void sse_encode_device_type(DeviceType self, SseSerializer serializer); @@ -1331,6 +1352,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_rs_device_channel(List self, SseSerializer serializer); + @protected + void sse_encode_list_rs_device_log(List self, SseSerializer serializer); + @protected void sse_encode_ls_http_client_version(LsHttpClientVersion self, SseSerializer serializer); @@ -1428,6 +1452,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_rs_device_channel(RsDeviceChannel self, SseSerializer serializer); + @protected + void sse_encode_rs_device_log(RsDeviceLog self, SseSerializer serializer); + @protected void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); diff --git a/packages/localsend_isolates/rust/src/api/discovery.rs b/packages/localsend_isolates/rust/src/api/discovery.rs index 005a5a9f..342758f2 100644 --- a/packages/localsend_isolates/rust/src/api/discovery.rs +++ b/packages/localsend_isolates/rust/src/api/discovery.rs @@ -1,6 +1,8 @@ use crate::frb_generated::StreamSink; +use flutter_rust_bridge::frb; +pub use localsend::discovery::DeviceLogKind; use localsend::discovery::{ - DeviceChannel, DeviceIdentity, DiscoveredDevice, DiscoveryConfig, DiscoveryEvent, + DeviceChannel, DeviceIdentity, DeviceLog, DiscoveredDevice, DiscoveryConfig, DiscoveryEvent, DiscoveryHandle, HttpChannel, StatefulDevice, }; use localsend::model::discovery::{DeviceType, ProtocolType}; @@ -83,6 +85,24 @@ pub struct RsStoredDevice { pub channels: Vec, } +/// One retained confirmation of a stored device, for the device details UI. +pub struct RsDeviceLog { + /// When the confirmation happened, in milliseconds since the Unix epoch. + pub timestamp_millis: u64, + + /// Whether the confirmation discovered the device or re-confirmed it. + pub kind: DeviceLogKind, + + /// The channel the confirmation happened on. + pub channel: RsDeviceChannel, +} + +#[frb(mirror(DeviceLogKind))] +pub enum _DeviceLogKind { + Discovered, + Updated, +} + pub struct RsDiscovery { instance: Arc, event_rx: Mutex>>, @@ -334,6 +354,16 @@ impl RsDiscovery { .await; } + /// The retained confirmations of a stored device, oldest first, capped at + /// the store's log limit. Empty when the fingerprint is unknown. + pub fn device_logs(&self, fingerprint: String) -> Vec { + self.instance + .handle + .device_by_fingerprint(&fingerprint) + .map(|stored| stored.logs.into_iter().map(rs_device_log).collect()) + .unwrap_or_default() + } + /// Stops the discovery, which also ends the [RsDiscovery::listen] stream. /// Returns after all sockets are closed, so the port can be bound again. pub async fn stop(&self) { @@ -349,6 +379,23 @@ impl RsDiscovery { } } +fn rs_device_log(log: DeviceLog) -> RsDeviceLog { + let DeviceChannel::Http(http) = log.channel; + RsDeviceLog { + timestamp_millis: log + .timestamp + .duration_since(std::time::UNIX_EPOCH) + .map(|elapsed| elapsed.as_millis() as u64) + .unwrap_or(0), + kind: log.kind, + channel: RsDeviceChannel { + host: http.host, + port: http.port, + protocol: http.protocol, + }, + } +} + /// The merged stored device flattened for the Dart side, its channels ranked /// best first. fn rs_stored_device(stored: StatefulDevice) -> RsStoredDevice { diff --git a/packages/localsend_isolates/rust/src/frb_generated.rs b/packages/localsend_isolates/rust/src/frb_generated.rs index 522e3657..33e949da 100644 --- a/packages/localsend_isolates/rust/src/frb_generated.rs +++ b/packages/localsend_isolates/rust/src/frb_generated.rs @@ -44,7 +44,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1120530143; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -2095161624; // Section: executor @@ -528,6 +528,60 @@ fn wire__crate__api__discovery__RsDiscovery_announce_impl( }, ) } +fn wire__crate__api__discovery__RsDiscovery_device_logs_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_device_logs", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_fingerprint = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = + Result::<_, ()>::Ok(crate::api::discovery::RsDiscovery::device_logs( + &*api_that_guard, + api_fingerprint, + ))?; + Ok(output_ok) + })()) + } + }, + ) +} fn wire__crate__api__discovery__RsDiscovery_discover_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -3932,6 +3986,18 @@ impl SseDecode for crate::api::webrtc::ClientInfoWithoutId { } } +impl SseDecode for crate::api::discovery::DeviceLogKind { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return match inner { + 0 => crate::api::discovery::DeviceLogKind::Discovered, + 1 => crate::api::discovery::DeviceLogKind::Updated, + _ => unreachable!("Invalid variant for DeviceLogKind: {}", inner), + }; + } +} + impl SseDecode for crate::api::model::DeviceType { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4114,6 +4180,20 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for crate::api::http::LsHttpClientVersion { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4500,6 +4580,20 @@ impl SseDecode for crate::api::discovery::RsDeviceChannel { } } +impl SseDecode for crate::api::discovery::RsDeviceLog { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_timestampMillis = ::sse_decode(deserializer); + let mut var_kind = ::sse_decode(deserializer); + let mut var_channel = ::sse_decode(deserializer); + return crate::api::discovery::RsDeviceLog { + timestamp_millis: var_timestampMillis, + kind: var_kind, + channel: var_channel, + }; + } +} + impl SseDecode for crate::api::discovery::RsDiscoveredDevice { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -5028,194 +5122,200 @@ fn pde_ffi_dispatcher_primary_impl( rust_vec_len, data_len, ), - 9 => wire__crate__api__discovery__RsDiscovery_discover_impl( + 9 => wire__crate__api__discovery__RsDiscovery_device_logs_impl( port, ptr, rust_vec_len, data_len, ), - 10 => { + 10 => wire__crate__api__discovery__RsDiscovery_discover_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 11 => { wire__crate__api__discovery__RsDiscovery_listen_impl(port, ptr, rust_vec_len, data_len) } - 11 => wire__crate__api__discovery__RsDiscovery_multicast_error_impl( + 12 => wire__crate__api__discovery__RsDiscovery_multicast_error_impl( port, ptr, rust_vec_len, data_len, ), - 12 => wire__crate__api__discovery__RsDiscovery_scan_subnet_impl( + 13 => wire__crate__api__discovery__RsDiscovery_scan_subnet_impl( port, ptr, rust_vec_len, data_len, ), - 13 => wire__crate__api__discovery__RsDiscovery_set_answer_announcements_impl( + 14 => wire__crate__api__discovery__RsDiscovery_set_answer_announcements_impl( port, ptr, rust_vec_len, data_len, ), - 14 => wire__crate__api__discovery__RsDiscovery_stop_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__http__RsHttpClient_cancel_impl(port, ptr, rust_vec_len, data_len), - 16 => wire__crate__api__http__RsHttpClient_prepare_upload_impl( + 15 => wire__crate__api__discovery__RsDiscovery_stop_impl(port, ptr, rust_vec_len, data_len), + 16 => wire__crate__api__http__RsHttpClient_cancel_impl(port, ptr, rust_vec_len, data_len), + 17 => wire__crate__api__http__RsHttpClient_prepare_upload_impl( port, ptr, rust_vec_len, data_len, ), - 17 => wire__crate__api__http__RsHttpClient_register_impl(port, ptr, rust_vec_len, data_len), - 18 => wire__crate__api__http__RsHttpClient_upload_impl(port, ptr, rust_vec_len, data_len), - 19 => wire__crate__api__server__RsHttpServer_cancel_session_impl( + 18 => wire__crate__api__http__RsHttpClient_register_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__http__RsHttpClient_upload_impl(port, ptr, rust_vec_len, data_len), + 20 => wire__crate__api__server__RsHttpServer_cancel_session_impl( port, ptr, rust_vec_len, data_len, ), - 20 => wire__crate__api__server__RsHttpServer_fail_file_download_impl( + 21 => wire__crate__api__server__RsHttpServer_fail_file_download_impl( port, ptr, rust_vec_len, data_len, ), - 21 => wire__crate__api__server__RsHttpServer_fail_file_upload_impl( + 22 => wire__crate__api__server__RsHttpServer_fail_file_upload_impl( port, ptr, rust_vec_len, data_len, ), - 22 => wire__crate__api__server__RsHttpServer_listen_impl(port, ptr, rust_vec_len, data_len), - 23 => wire__crate__api__server__RsHttpServer_respond_file_download_impl( + 23 => wire__crate__api__server__RsHttpServer_listen_impl(port, ptr, rust_vec_len, data_len), + 24 => wire__crate__api__server__RsHttpServer_respond_file_download_impl( port, ptr, rust_vec_len, data_len, ), - 24 => wire__crate__api__server__RsHttpServer_respond_file_upload_impl( + 25 => wire__crate__api__server__RsHttpServer_respond_file_upload_impl( port, ptr, rust_vec_len, data_len, ), - 25 => wire__crate__api__server__RsHttpServer_respond_prepare_download_impl( + 26 => wire__crate__api__server__RsHttpServer_respond_prepare_download_impl( port, ptr, rust_vec_len, data_len, ), - 26 => wire__crate__api__server__RsHttpServer_respond_prepare_upload_impl( + 27 => wire__crate__api__server__RsHttpServer_respond_prepare_upload_impl( port, ptr, rust_vec_len, data_len, ), - 27 => wire__crate__api__server__RsHttpServer_stop_impl(port, ptr, rust_vec_len, data_len), - 28 => wire__crate__api__webrtc__RtcFileReceiver_get_file_id_impl( + 28 => wire__crate__api__server__RsHttpServer_stop_impl(port, ptr, rust_vec_len, data_len), + 29 => wire__crate__api__webrtc__RtcFileReceiver_get_file_id_impl( port, ptr, rust_vec_len, data_len, ), - 29 => wire__crate__api__webrtc__RtcFileReceiver_receive_impl( + 30 => wire__crate__api__webrtc__RtcFileReceiver_receive_impl( port, ptr, rust_vec_len, data_len, ), - 30 => wire__crate__api__webrtc__RtcFileSender_send_impl(port, ptr, rust_vec_len, data_len), - 31 => wire__crate__api__webrtc__RtcReceiveController_decline_impl( + 31 => wire__crate__api__webrtc__RtcFileSender_send_impl(port, ptr, rust_vec_len, data_len), + 32 => wire__crate__api__webrtc__RtcReceiveController_decline_impl( port, ptr, rust_vec_len, data_len, ), - 32 => wire__crate__api__webrtc__RtcReceiveController_listen_error_impl( + 33 => wire__crate__api__webrtc__RtcReceiveController_listen_error_impl( port, ptr, rust_vec_len, data_len, ), - 33 => wire__crate__api__webrtc__RtcReceiveController_listen_files_impl( + 34 => wire__crate__api__webrtc__RtcReceiveController_listen_files_impl( port, ptr, rust_vec_len, data_len, ), - 34 => wire__crate__api__webrtc__RtcReceiveController_listen_receiving_impl( + 35 => wire__crate__api__webrtc__RtcReceiveController_listen_receiving_impl( port, ptr, rust_vec_len, data_len, ), - 35 => wire__crate__api__webrtc__RtcReceiveController_listen_status_impl( + 36 => wire__crate__api__webrtc__RtcReceiveController_listen_status_impl( port, ptr, rust_vec_len, data_len, ), - 36 => wire__crate__api__webrtc__RtcReceiveController_send_file_status_impl( + 37 => wire__crate__api__webrtc__RtcReceiveController_send_file_status_impl( port, ptr, rust_vec_len, data_len, ), - 37 => wire__crate__api__webrtc__RtcReceiveController_send_pin_impl( + 38 => wire__crate__api__webrtc__RtcReceiveController_send_pin_impl( port, ptr, rust_vec_len, data_len, ), - 38 => wire__crate__api__webrtc__RtcReceiveController_send_selection_impl( + 39 => wire__crate__api__webrtc__RtcReceiveController_send_selection_impl( port, ptr, rust_vec_len, data_len, ), - 39 => wire__crate__api__webrtc__RtcSendController_listen_error_impl( + 40 => wire__crate__api__webrtc__RtcSendController_listen_error_impl( port, ptr, rust_vec_len, data_len, ), - 40 => wire__crate__api__webrtc__RtcSendController_listen_selected_files_impl( + 41 => wire__crate__api__webrtc__RtcSendController_listen_selected_files_impl( port, ptr, rust_vec_len, data_len, ), - 41 => wire__crate__api__webrtc__RtcSendController_listen_status_impl( + 42 => wire__crate__api__webrtc__RtcSendController_listen_status_impl( port, ptr, rust_vec_len, data_len, ), - 42 => wire__crate__api__webrtc__RtcSendController_send_file_impl( + 43 => wire__crate__api__webrtc__RtcSendController_send_file_impl( port, ptr, rust_vec_len, data_len, ), - 43 => wire__crate__api__webrtc__RtcSendController_send_pin_impl( + 44 => wire__crate__api__webrtc__RtcSendController_send_pin_impl( port, ptr, rust_vec_len, data_len, ), - 44 => wire__crate__api__webrtc__connect_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__stream__create_stream_impl(port, ptr, rust_vec_len, data_len), - 48 => { + 45 => wire__crate__api__webrtc__connect_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__stream__create_stream_impl(port, ptr, rust_vec_len, data_len), + 49 => { wire__crate__api__logging__enable_debug_logging_impl(port, ptr, rust_vec_len, data_len) } - 49 => wire__crate__api__crypto__generate_key_pair_impl(port, ptr, rust_vec_len, data_len), - 50 => wire__crate__api__crypto__generate_security_context_impl( + 50 => wire__crate__api__crypto__generate_key_pair_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__crypto__generate_security_context_impl( port, ptr, rust_vec_len, data_len, ), - 51 => wire__crate__api__crypto__hash_file_impl(port, ptr, rust_vec_len, data_len), - 54 => wire__crate__api__discovery__start_discovery_impl(port, ptr, rust_vec_len, data_len), - 55 => wire__crate__api__server__start_server_impl(port, ptr, rust_vec_len, data_len), - 56 => wire__crate__api__crypto__verify_cert_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__crypto__hash_file_impl(port, ptr, rust_vec_len, data_len), + 55 => wire__crate__api__discovery__start_discovery_impl(port, ptr, rust_vec_len, data_len), + 56 => wire__crate__api__server__start_server_impl(port, ptr, rust_vec_len, data_len), + 57 => wire__crate__api__crypto__verify_cert_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -5230,10 +5330,10 @@ fn pde_ffi_dispatcher_sync_impl( match func_id { 2 => wire__crate__api__stream__Dart2RustStreamSink_close_impl(ptr, rust_vec_len, data_len), 6 => wire__crate__api__cancel__RsCancellationToken_cancel_impl(ptr, rust_vec_len, data_len), - 45 => wire__crate__api__cancel__create_cancellation_token_impl(ptr, rust_vec_len, data_len), - 46 => wire__crate__api__http__create_client_impl(ptr, rust_vec_len, data_len), - 52 => wire__crate__api__filename__is_valid_file_name_impl(ptr, rust_vec_len, data_len), - 53 => wire__crate__api__filename__sanitize_file_name_impl(ptr, rust_vec_len, data_len), + 46 => wire__crate__api__cancel__create_cancellation_token_impl(ptr, rust_vec_len, data_len), + 47 => wire__crate__api__http__create_client_impl(ptr, rust_vec_len, data_len), + 53 => wire__crate__api__filename__is_valid_file_name_impl(ptr, rust_vec_len, data_len), + 54 => wire__crate__api__filename__sanitize_file_name_impl(ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -5474,6 +5574,27 @@ impl flutter_rust_bridge::IntoIntoDart { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self.0 { + crate::api::discovery::DeviceLogKind::Discovered => 0.into_dart(), + crate::api::discovery::DeviceLogKind::Updated => 1.into_dart(), + _ => unreachable!(), + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} +impl flutter_rust_bridge::IntoIntoDart> + for crate::api::discovery::DeviceLogKind +{ + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { match self.0 { @@ -5855,6 +5976,28 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::discovery::RsDeviceLog { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.timestamp_millis.into_into_dart().into_dart(), + self.kind.into_into_dart().into_dart(), + self.channel.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::discovery::RsDeviceLog +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::discovery::RsDeviceLog +{ + fn into_into_dart(self) -> crate::api::discovery::RsDeviceLog { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::discovery::RsDiscoveredDevice { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -6762,6 +6905,22 @@ impl SseEncode for crate::api::webrtc::ClientInfoWithoutId { } } +impl SseEncode for crate::api::discovery::DeviceLogKind { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode( + match self { + crate::api::discovery::DeviceLogKind::Discovered => 0, + crate::api::discovery::DeviceLogKind::Updated => 1, + _ => { + unimplemented!(""); + } + }, + serializer, + ); + } +} + impl SseEncode for crate::api::model::DeviceType { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6912,6 +7071,16 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + impl SseEncode for crate::api::http::LsHttpClientVersion { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -7222,6 +7391,15 @@ impl SseEncode for crate::api::discovery::RsDeviceChannel { } } +impl SseEncode for crate::api::discovery::RsDeviceLog { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.timestamp_millis, serializer); + ::sse_encode(self.kind, serializer); + ::sse_encode(self.channel, serializer); + } +} + impl SseEncode for crate::api::discovery::RsDiscoveredDevice { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {