feat: map Rust DeviceChannel to Dart

This commit is contained in:
Tien Do Nam
2026-08-02 00:49:29 +02:00
parent be9a53b64c
commit 94082b3048
16 changed files with 264 additions and 371 deletions
@@ -51,10 +51,11 @@ extension on Device {
deviceModel: deviceModel,
deviceType: deviceType,
download: download,
discoveryMethods: {
...discoveryMethods,
...other.discoveryMethods,
},
channels: [
...channels,
for (final channel in other.channels)
if (!channels.contains(channel)) channel,
],
);
}
}
+1 -1
View File
@@ -147,7 +147,7 @@ class ReceiveHistoryPage extends StatelessWidget {
deviceModel: 'deviceModel',
deviceType: DeviceType.web,
download: true,
discoveryMethods: const {},
channels: const [],
),
showSenderInfo: false,
files: [],
+1 -1
View File
@@ -45,6 +45,6 @@ final deviceFullInfoProvider = ViewProvider((ref) {
deviceModel: rawInfo.deviceModel,
deviceType: rawInfo.deviceType,
download: serverState?.webSendState != null,
discoveryMethods: const {},
channels: const [],
);
});
@@ -60,9 +60,7 @@ class ReceiveController {
// Feed the device into the discovery store; it comes back (and is
// registered) via the [StartDiscoveryListener] stream.
server.ref
.redux(parentIsolateProvider)
.dispatch(IsolateDiscoveryAddDeviceAction(device: event.info.toDevice(event.ip, HttpDiscovery(ip: event.ip))));
server.ref.redux(parentIsolateProvider).dispatch(IsolateDiscoveryAddDeviceAction(device: event.info.toDevice(event.ip, withChannel: true)));
server.ref.notifier(discoveryLoggerProvider).addLog('[DISCOVER/TCP] Received "/register" HTTP request: ${event.info.alias} (${event.ip})');
}
@@ -98,7 +96,7 @@ class ReceiveController {
session: ReceiveSessionState(
sessionId: sessionId,
status: SessionStatus.waiting,
sender: event.info.toDevice(event.ip, null).copyWith(fingerprint: senderFingerprint),
sender: event.info.toDevice(event.ip, withChannel: false).copyWith(fingerprint: senderFingerprint),
senderAlias: server.ref.read(favoritesProvider).firstWhereOrNull((e) => e.fingerprint == senderFingerprint)?.alias ?? event.info.alias,
files: {
for (final file in files.values)
@@ -218,11 +218,11 @@ extension ClientInfoExt on ClientInfo {
deviceModel: deviceModel,
deviceType: deviceType?.toDeviceType() ?? DeviceType.desktop,
download: false,
discoveryMethods: {
SignalingDiscovery(
channels: [
SignalingChannel(
signalingServer: signalingServer,
),
},
],
);
}
}
@@ -83,7 +83,7 @@ class _AddressInputDialogState extends State<AddressInputDialog> with Refena {
payload: payload,
);
foundDevice = response.body.toDevice(ip, port, https, HttpDiscovery(ip: ip));
foundDevice = response.body.toDevice(ip, port, https);
deviceCompleter.complete();
} catch (e) {
error = e.toString();
+1 -2
View File
@@ -8,7 +8,6 @@ import 'package:localsend_app/provider/http_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/widget/dialogs/error_dialog.dart';
import 'package:localsend_app/widget/dialogs/favorite_edit_dialog.dart';
import 'package:localsend_isolates/model/device.dart';
import 'package:localsend_isolates/rust/api/model.dart';
import 'package:localsend_isolates/util/rust.dart';
import 'package:refena_flutter/refena_flutter.dart';
@@ -46,7 +45,7 @@ class _FavoritesDialogState extends State<FavoritesDialog> with Refena {
payload: payload,
);
final device = response.body.toDevice(favorite.ip, favorite.port, https, HttpDiscovery(ip: favorite.ip));
final device = response.body.toDevice(favorite.ip, favorite.port, https);
if (mounted) {
context.pop(device);
+18 -33
View File
@@ -2,59 +2,44 @@ import 'package:localsend_isolates/model/device.dart';
import 'package:test/test.dart';
void main() {
test('Should not have duplicate DiscoveryMethod', () {
final set = <DiscoveryMethod>{};
test('Should not have duplicate DeviceChannel', () {
final set = <DeviceChannel>{};
set.add(MulticastDiscovery());
set.add(HttpChannel(host: 'a', port: 1, https: true));
expect(set, hasLength(1));
set.add(MulticastDiscovery());
set.add(HttpChannel(host: 'a', port: 1, https: true));
expect(set, hasLength(1));
set.add(HttpDiscovery(ip: 'a'));
set.add(HttpChannel(host: 'a', port: 2, https: true));
expect(set, hasLength(2));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
expect(set, contains(HttpChannel(host: 'a', port: 1, https: true)));
expect(set, contains(HttpChannel(host: 'a', port: 2, https: true)));
set.add(HttpDiscovery(ip: 'a'));
expect(set, hasLength(2));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
set.add(HttpDiscovery(ip: 'b'));
set.add(HttpChannel(host: 'b', port: 1, https: true));
expect(set, hasLength(3));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
expect(set, contains(HttpDiscovery(ip: 'b')));
expect(set, contains(HttpChannel(host: 'a', port: 1, https: true)));
expect(set, contains(HttpChannel(host: 'a', port: 2, https: true)));
expect(set, contains(HttpChannel(host: 'b', port: 1, https: true)));
set.add(SignalingDiscovery(signalingServer: 'sa'));
set.add(SignalingChannel(signalingServer: 'sa'));
expect(set, hasLength(4));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
expect(set, contains(HttpDiscovery(ip: 'b')));
expect(set, contains(SignalingDiscovery(signalingServer: 'sa')));
expect(set, contains(SignalingChannel(signalingServer: 'sa')));
set.add(SignalingDiscovery(signalingServer: 'sa'));
set.add(SignalingChannel(signalingServer: 'sa'));
expect(set, hasLength(4));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
expect(set, contains(HttpDiscovery(ip: 'b')));
expect(set, contains(SignalingDiscovery(signalingServer: 'sa')));
expect(set, contains(SignalingChannel(signalingServer: 'sa')));
set.add(SignalingDiscovery(signalingServer: 'sb'));
set.add(SignalingChannel(signalingServer: 'sb'));
expect(set, hasLength(5));
expect(set, contains(MulticastDiscovery()));
expect(set, contains(HttpDiscovery(ip: 'a')));
expect(set, contains(HttpDiscovery(ip: 'b')));
expect(set, contains(SignalingDiscovery(signalingServer: 'sa')));
expect(set, contains(SignalingDiscovery(signalingServer: 'sb')));
expect(set, contains(SignalingChannel(signalingServer: 'sa')));
expect(set, contains(SignalingChannel(signalingServer: 'sb')));
});
}
@@ -62,6 +62,6 @@ Device _createDevice(String ip) {
deviceModel: 'A',
deviceType: DeviceType.mobile,
download: false,
discoveryMethods: {},
channels: [],
);
}
@@ -56,6 +56,6 @@ Device _target({
deviceModel: 'deviceModel',
deviceType: DeviceType.desktop,
download: false,
discoveryMethods: {},
channels: [],
);
}
@@ -11,28 +11,34 @@ enum DeviceType {
server,
}
/// A channel a device is reachable on.
@MappableClass()
sealed class DiscoveryMethod with DiscoveryMethodMappable {
const DiscoveryMethod();
sealed class DeviceChannel with DeviceChannelMappable {
const DeviceChannel();
}
/// The device's HTTP server, reachable at one address.
@MappableClass()
class MulticastDiscovery extends DiscoveryMethod with MulticastDiscoveryMappable {
const MulticastDiscovery();
class HttpChannel extends DeviceChannel with HttpChannelMappable {
/// The host to dial: an IP address, or the scoped form `fe80::1%3` for
/// link-local IPv6 (the Rust HTTP client accepts both back as a host).
final String host;
/// The port of the device's HTTP server at this address.
final int port;
/// Whether the HTTP server uses TLS.
final bool https;
const HttpChannel({required this.host, required this.port, required this.https});
}
/// The device is reachable over WebRTC through a signaling server.
@MappableClass()
class HttpDiscovery extends DiscoveryMethod with HttpDiscoveryMappable {
final String ip;
const HttpDiscovery({required this.ip});
}
@MappableClass()
class SignalingDiscovery extends DiscoveryMethod with SignalingDiscoveryMappable {
class SignalingChannel extends DeviceChannel with SignalingChannelMappable {
final String signalingServer;
const SignalingDiscovery({required this.signalingServer});
const SignalingChannel({required this.signalingServer});
}
enum TransmissionMethod {
@@ -64,29 +70,18 @@ class Device with DeviceMappable {
final String? deviceModel;
final DeviceType deviceType;
final bool download;
final Set<DiscoveryMethod> discoveryMethods;
/// Every channel the device was confirmed on, best first.
final List<DeviceChannel> channels;
Set<TransmissionMethod> get transmissionMethods {
bool http = false;
bool webrtc = false;
for (final method in discoveryMethods) {
if (method is SignalingDiscovery) {
webrtc = true;
} else {
http = true;
}
}
final methods = <TransmissionMethod>{};
if (http) {
methods.add(TransmissionMethod.http);
}
if (webrtc) {
methods.add(TransmissionMethod.webrtc);
}
return methods;
return {
for (final channel in channels)
switch (channel) {
HttpChannel() => TransmissionMethod.http,
SignalingChannel() => TransmissionMethod.webrtc,
},
};
}
const Device({
@@ -100,7 +95,7 @@ class Device with DeviceMappable {
required this.deviceModel,
required this.deviceType,
required this.download,
required this.discoveryMethods,
required this.channels,
});
static const empty = Device(
@@ -114,6 +109,6 @@ class Device with DeviceMappable {
deviceModel: null,
deviceType: DeviceType.desktop,
download: false,
discoveryMethods: {},
channels: [],
);
}
@@ -66,404 +66,292 @@ extension DeviceTypeMapperExtension on DeviceType {
}
}
class DiscoveryMethodMapper extends ClassMapperBase<DiscoveryMethod> {
DiscoveryMethodMapper._();
class DeviceChannelMapper extends ClassMapperBase<DeviceChannel> {
DeviceChannelMapper._();
static DiscoveryMethodMapper? _instance;
static DiscoveryMethodMapper ensureInitialized() {
static DeviceChannelMapper? _instance;
static DeviceChannelMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = DiscoveryMethodMapper._());
MulticastDiscoveryMapper.ensureInitialized();
HttpDiscoveryMapper.ensureInitialized();
SignalingDiscoveryMapper.ensureInitialized();
MapperContainer.globals.use(_instance = DeviceChannelMapper._());
HttpChannelMapper.ensureInitialized();
SignalingChannelMapper.ensureInitialized();
}
return _instance!;
}
@override
final String id = 'DiscoveryMethod';
final String id = 'DeviceChannel';
@override
final MappableFields<DiscoveryMethod> fields = const {};
final MappableFields<DeviceChannel> fields = const {};
static DiscoveryMethod _instantiate(DecodingData data) {
throw MapperException.missingConstructor('DiscoveryMethod');
static DeviceChannel _instantiate(DecodingData data) {
throw MapperException.missingConstructor('DeviceChannel');
}
@override
final Function instantiate = _instantiate;
static DiscoveryMethod fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<DiscoveryMethod>(map);
static DeviceChannel fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<DeviceChannel>(map);
}
static DiscoveryMethod deserialize(String json) {
return ensureInitialized().decodeJson<DiscoveryMethod>(json);
static DeviceChannel deserialize(String json) {
return ensureInitialized().decodeJson<DeviceChannel>(json);
}
}
mixin DiscoveryMethodMappable {
mixin DeviceChannelMappable {
String serialize();
Map<String, dynamic> toJson();
DiscoveryMethodCopyWith<DiscoveryMethod, DiscoveryMethod, DiscoveryMethod>
DeviceChannelCopyWith<DeviceChannel, DeviceChannel, DeviceChannel>
get copyWith;
}
abstract class DiscoveryMethodCopyWith<$R, $In extends DiscoveryMethod, $Out>
abstract class DeviceChannelCopyWith<$R, $In extends DeviceChannel, $Out>
implements ClassCopyWith<$R, $In, $Out> {
$R call();
DiscoveryMethodCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
);
DeviceChannelCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
}
class MulticastDiscoveryMapper extends ClassMapperBase<MulticastDiscovery> {
MulticastDiscoveryMapper._();
class HttpChannelMapper extends ClassMapperBase<HttpChannel> {
HttpChannelMapper._();
static MulticastDiscoveryMapper? _instance;
static MulticastDiscoveryMapper ensureInitialized() {
static HttpChannelMapper? _instance;
static HttpChannelMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = MulticastDiscoveryMapper._());
DiscoveryMethodMapper.ensureInitialized();
MapperContainer.globals.use(_instance = HttpChannelMapper._());
DeviceChannelMapper.ensureInitialized();
}
return _instance!;
}
@override
final String id = 'MulticastDiscovery';
final String id = 'HttpChannel';
static String _$host(HttpChannel v) => v.host;
static const Field<HttpChannel, String> _f$host = Field('host', _$host);
static int _$port(HttpChannel v) => v.port;
static const Field<HttpChannel, int> _f$port = Field('port', _$port);
static bool _$https(HttpChannel v) => v.https;
static const Field<HttpChannel, bool> _f$https = Field('https', _$https);
@override
final MappableFields<MulticastDiscovery> fields = const {};
final MappableFields<HttpChannel> fields = const {
#host: _f$host,
#port: _f$port,
#https: _f$https,
};
static MulticastDiscovery _instantiate(DecodingData data) {
return MulticastDiscovery();
static HttpChannel _instantiate(DecodingData data) {
return HttpChannel(
host: data.dec(_f$host),
port: data.dec(_f$port),
https: data.dec(_f$https),
);
}
@override
final Function instantiate = _instantiate;
static MulticastDiscovery fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<MulticastDiscovery>(map);
static HttpChannel fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<HttpChannel>(map);
}
static MulticastDiscovery deserialize(String json) {
return ensureInitialized().decodeJson<MulticastDiscovery>(json);
static HttpChannel deserialize(String json) {
return ensureInitialized().decodeJson<HttpChannel>(json);
}
}
mixin MulticastDiscoveryMappable {
mixin HttpChannelMappable {
String serialize() {
return MulticastDiscoveryMapper.ensureInitialized()
.encodeJson<MulticastDiscovery>(this as MulticastDiscovery);
return HttpChannelMapper.ensureInitialized().encodeJson<HttpChannel>(
this as HttpChannel,
);
}
Map<String, dynamic> toJson() {
return MulticastDiscoveryMapper.ensureInitialized()
.encodeMap<MulticastDiscovery>(this as MulticastDiscovery);
return HttpChannelMapper.ensureInitialized().encodeMap<HttpChannel>(
this as HttpChannel,
);
}
MulticastDiscoveryCopyWith<
MulticastDiscovery,
MulticastDiscovery,
MulticastDiscovery
>
get copyWith =>
_MulticastDiscoveryCopyWithImpl<MulticastDiscovery, MulticastDiscovery>(
this as MulticastDiscovery,
HttpChannelCopyWith<HttpChannel, HttpChannel, HttpChannel> get copyWith =>
_HttpChannelCopyWithImpl<HttpChannel, HttpChannel>(
this as HttpChannel,
$identity,
$identity,
);
@override
String toString() {
return MulticastDiscoveryMapper.ensureInitialized().stringifyValue(
this as MulticastDiscovery,
return HttpChannelMapper.ensureInitialized().stringifyValue(
this as HttpChannel,
);
}
@override
bool operator ==(Object other) {
return MulticastDiscoveryMapper.ensureInitialized().equalsValue(
this as MulticastDiscovery,
return HttpChannelMapper.ensureInitialized().equalsValue(
this as HttpChannel,
other,
);
}
@override
int get hashCode {
return MulticastDiscoveryMapper.ensureInitialized().hashValue(
this as MulticastDiscovery,
);
return HttpChannelMapper.ensureInitialized().hashValue(this as HttpChannel);
}
}
extension MulticastDiscoveryValueCopy<$R, $Out>
on ObjectCopyWith<$R, MulticastDiscovery, $Out> {
MulticastDiscoveryCopyWith<$R, MulticastDiscovery, $Out>
get $asMulticastDiscovery => $base.as(
(v, t, t2) => _MulticastDiscoveryCopyWithImpl<$R, $Out>(v, t, t2),
extension HttpChannelValueCopy<$R, $Out>
on ObjectCopyWith<$R, HttpChannel, $Out> {
HttpChannelCopyWith<$R, HttpChannel, $Out> get $asHttpChannel =>
$base.as((v, t, t2) => _HttpChannelCopyWithImpl<$R, $Out>(v, t, t2));
}
abstract class HttpChannelCopyWith<$R, $In extends HttpChannel, $Out>
implements DeviceChannelCopyWith<$R, $In, $Out> {
@override
$R call({String? host, int? port, bool? https});
HttpChannelCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
}
class _HttpChannelCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, HttpChannel, $Out>
implements HttpChannelCopyWith<$R, HttpChannel, $Out> {
_HttpChannelCopyWithImpl(super.value, super.then, super.then2);
@override
late final ClassMapperBase<HttpChannel> $mapper =
HttpChannelMapper.ensureInitialized();
@override
$R call({String? host, int? port, bool? https}) => $apply(
FieldCopyWithData({
if (host != null) #host: host,
if (port != null) #port: port,
if (https != null) #https: https,
}),
);
}
abstract class MulticastDiscoveryCopyWith<
$R,
$In extends MulticastDiscovery,
$Out
>
implements DiscoveryMethodCopyWith<$R, $In, $Out> {
@override
$R call();
MulticastDiscoveryCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
HttpChannel $make(CopyWithData data) => HttpChannel(
host: data.get(#host, or: $value.host),
port: data.get(#port, or: $value.port),
https: data.get(#https, or: $value.https),
);
}
class _MulticastDiscoveryCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, MulticastDiscovery, $Out>
implements MulticastDiscoveryCopyWith<$R, MulticastDiscovery, $Out> {
_MulticastDiscoveryCopyWithImpl(super.value, super.then, super.then2);
@override
late final ClassMapperBase<MulticastDiscovery> $mapper =
MulticastDiscoveryMapper.ensureInitialized();
@override
$R call() => $apply(FieldCopyWithData({}));
@override
MulticastDiscovery $make(CopyWithData data) => MulticastDiscovery();
@override
MulticastDiscoveryCopyWith<$R2, MulticastDiscovery, $Out2> $chain<$R2, $Out2>(
HttpChannelCopyWith<$R2, HttpChannel, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
) => _MulticastDiscoveryCopyWithImpl<$R2, $Out2>($value, $cast, t);
) => _HttpChannelCopyWithImpl<$R2, $Out2>($value, $cast, t);
}
class HttpDiscoveryMapper extends ClassMapperBase<HttpDiscovery> {
HttpDiscoveryMapper._();
class SignalingChannelMapper extends ClassMapperBase<SignalingChannel> {
SignalingChannelMapper._();
static HttpDiscoveryMapper? _instance;
static HttpDiscoveryMapper ensureInitialized() {
static SignalingChannelMapper? _instance;
static SignalingChannelMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = HttpDiscoveryMapper._());
DiscoveryMethodMapper.ensureInitialized();
MapperContainer.globals.use(_instance = SignalingChannelMapper._());
DeviceChannelMapper.ensureInitialized();
}
return _instance!;
}
@override
final String id = 'HttpDiscovery';
final String id = 'SignalingChannel';
static String _$ip(HttpDiscovery v) => v.ip;
static const Field<HttpDiscovery, String> _f$ip = Field('ip', _$ip);
@override
final MappableFields<HttpDiscovery> fields = const {#ip: _f$ip};
static HttpDiscovery _instantiate(DecodingData data) {
return HttpDiscovery(ip: data.dec(_f$ip));
}
@override
final Function instantiate = _instantiate;
static HttpDiscovery fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<HttpDiscovery>(map);
}
static HttpDiscovery deserialize(String json) {
return ensureInitialized().decodeJson<HttpDiscovery>(json);
}
}
mixin HttpDiscoveryMappable {
String serialize() {
return HttpDiscoveryMapper.ensureInitialized().encodeJson<HttpDiscovery>(
this as HttpDiscovery,
);
}
Map<String, dynamic> toJson() {
return HttpDiscoveryMapper.ensureInitialized().encodeMap<HttpDiscovery>(
this as HttpDiscovery,
);
}
HttpDiscoveryCopyWith<HttpDiscovery, HttpDiscovery, HttpDiscovery>
get copyWith => _HttpDiscoveryCopyWithImpl<HttpDiscovery, HttpDiscovery>(
this as HttpDiscovery,
$identity,
$identity,
);
@override
String toString() {
return HttpDiscoveryMapper.ensureInitialized().stringifyValue(
this as HttpDiscovery,
);
}
@override
bool operator ==(Object other) {
return HttpDiscoveryMapper.ensureInitialized().equalsValue(
this as HttpDiscovery,
other,
);
}
@override
int get hashCode {
return HttpDiscoveryMapper.ensureInitialized().hashValue(
this as HttpDiscovery,
);
}
}
extension HttpDiscoveryValueCopy<$R, $Out>
on ObjectCopyWith<$R, HttpDiscovery, $Out> {
HttpDiscoveryCopyWith<$R, HttpDiscovery, $Out> get $asHttpDiscovery =>
$base.as((v, t, t2) => _HttpDiscoveryCopyWithImpl<$R, $Out>(v, t, t2));
}
abstract class HttpDiscoveryCopyWith<$R, $In extends HttpDiscovery, $Out>
implements DiscoveryMethodCopyWith<$R, $In, $Out> {
@override
$R call({String? ip});
HttpDiscoveryCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
}
class _HttpDiscoveryCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, HttpDiscovery, $Out>
implements HttpDiscoveryCopyWith<$R, HttpDiscovery, $Out> {
_HttpDiscoveryCopyWithImpl(super.value, super.then, super.then2);
@override
late final ClassMapperBase<HttpDiscovery> $mapper =
HttpDiscoveryMapper.ensureInitialized();
@override
$R call({String? ip}) => $apply(FieldCopyWithData({if (ip != null) #ip: ip}));
@override
HttpDiscovery $make(CopyWithData data) =>
HttpDiscovery(ip: data.get(#ip, or: $value.ip));
@override
HttpDiscoveryCopyWith<$R2, HttpDiscovery, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
) => _HttpDiscoveryCopyWithImpl<$R2, $Out2>($value, $cast, t);
}
class SignalingDiscoveryMapper extends ClassMapperBase<SignalingDiscovery> {
SignalingDiscoveryMapper._();
static SignalingDiscoveryMapper? _instance;
static SignalingDiscoveryMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = SignalingDiscoveryMapper._());
DiscoveryMethodMapper.ensureInitialized();
}
return _instance!;
}
@override
final String id = 'SignalingDiscovery';
static String _$signalingServer(SignalingDiscovery v) => v.signalingServer;
static const Field<SignalingDiscovery, String> _f$signalingServer = Field(
static String _$signalingServer(SignalingChannel v) => v.signalingServer;
static const Field<SignalingChannel, String> _f$signalingServer = Field(
'signalingServer',
_$signalingServer,
);
@override
final MappableFields<SignalingDiscovery> fields = const {
final MappableFields<SignalingChannel> fields = const {
#signalingServer: _f$signalingServer,
};
static SignalingDiscovery _instantiate(DecodingData data) {
return SignalingDiscovery(signalingServer: data.dec(_f$signalingServer));
static SignalingChannel _instantiate(DecodingData data) {
return SignalingChannel(signalingServer: data.dec(_f$signalingServer));
}
@override
final Function instantiate = _instantiate;
static SignalingDiscovery fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<SignalingDiscovery>(map);
static SignalingChannel fromJson(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<SignalingChannel>(map);
}
static SignalingDiscovery deserialize(String json) {
return ensureInitialized().decodeJson<SignalingDiscovery>(json);
static SignalingChannel deserialize(String json) {
return ensureInitialized().decodeJson<SignalingChannel>(json);
}
}
mixin SignalingDiscoveryMappable {
mixin SignalingChannelMappable {
String serialize() {
return SignalingDiscoveryMapper.ensureInitialized()
.encodeJson<SignalingDiscovery>(this as SignalingDiscovery);
return SignalingChannelMapper.ensureInitialized()
.encodeJson<SignalingChannel>(this as SignalingChannel);
}
Map<String, dynamic> toJson() {
return SignalingDiscoveryMapper.ensureInitialized()
.encodeMap<SignalingDiscovery>(this as SignalingDiscovery);
return SignalingChannelMapper.ensureInitialized()
.encodeMap<SignalingChannel>(this as SignalingChannel);
}
SignalingDiscoveryCopyWith<
SignalingDiscovery,
SignalingDiscovery,
SignalingDiscovery
>
SignalingChannelCopyWith<SignalingChannel, SignalingChannel, SignalingChannel>
get copyWith =>
_SignalingDiscoveryCopyWithImpl<SignalingDiscovery, SignalingDiscovery>(
this as SignalingDiscovery,
_SignalingChannelCopyWithImpl<SignalingChannel, SignalingChannel>(
this as SignalingChannel,
$identity,
$identity,
);
@override
String toString() {
return SignalingDiscoveryMapper.ensureInitialized().stringifyValue(
this as SignalingDiscovery,
return SignalingChannelMapper.ensureInitialized().stringifyValue(
this as SignalingChannel,
);
}
@override
bool operator ==(Object other) {
return SignalingDiscoveryMapper.ensureInitialized().equalsValue(
this as SignalingDiscovery,
return SignalingChannelMapper.ensureInitialized().equalsValue(
this as SignalingChannel,
other,
);
}
@override
int get hashCode {
return SignalingDiscoveryMapper.ensureInitialized().hashValue(
this as SignalingDiscovery,
return SignalingChannelMapper.ensureInitialized().hashValue(
this as SignalingChannel,
);
}
}
extension SignalingDiscoveryValueCopy<$R, $Out>
on ObjectCopyWith<$R, SignalingDiscovery, $Out> {
SignalingDiscoveryCopyWith<$R, SignalingDiscovery, $Out>
get $asSignalingDiscovery => $base.as(
(v, t, t2) => _SignalingDiscoveryCopyWithImpl<$R, $Out>(v, t, t2),
);
extension SignalingChannelValueCopy<$R, $Out>
on ObjectCopyWith<$R, SignalingChannel, $Out> {
SignalingChannelCopyWith<$R, SignalingChannel, $Out>
get $asSignalingChannel =>
$base.as((v, t, t2) => _SignalingChannelCopyWithImpl<$R, $Out>(v, t, t2));
}
abstract class SignalingDiscoveryCopyWith<
$R,
$In extends SignalingDiscovery,
$Out
>
implements DiscoveryMethodCopyWith<$R, $In, $Out> {
abstract class SignalingChannelCopyWith<$R, $In extends SignalingChannel, $Out>
implements DeviceChannelCopyWith<$R, $In, $Out> {
@override
$R call({String? signalingServer});
SignalingDiscoveryCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
SignalingChannelCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
);
}
class _SignalingDiscoveryCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, SignalingDiscovery, $Out>
implements SignalingDiscoveryCopyWith<$R, SignalingDiscovery, $Out> {
_SignalingDiscoveryCopyWithImpl(super.value, super.then, super.then2);
class _SignalingChannelCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, SignalingChannel, $Out>
implements SignalingChannelCopyWith<$R, SignalingChannel, $Out> {
_SignalingChannelCopyWithImpl(super.value, super.then, super.then2);
@override
late final ClassMapperBase<SignalingDiscovery> $mapper =
SignalingDiscoveryMapper.ensureInitialized();
late final ClassMapperBase<SignalingChannel> $mapper =
SignalingChannelMapper.ensureInitialized();
@override
$R call({String? signalingServer}) => $apply(
FieldCopyWithData({
@@ -471,14 +359,14 @@ class _SignalingDiscoveryCopyWithImpl<$R, $Out>
}),
);
@override
SignalingDiscovery $make(CopyWithData data) => SignalingDiscovery(
SignalingChannel $make(CopyWithData data) => SignalingChannel(
signalingServer: data.get(#signalingServer, or: $value.signalingServer),
);
@override
SignalingDiscoveryCopyWith<$R2, SignalingDiscovery, $Out2> $chain<$R2, $Out2>(
SignalingChannelCopyWith<$R2, SignalingChannel, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t,
) => _SignalingDiscoveryCopyWithImpl<$R2, $Out2>($value, $cast, t);
) => _SignalingChannelCopyWithImpl<$R2, $Out2>($value, $cast, t);
}
class DeviceMapper extends ClassMapperBase<Device> {
@@ -489,7 +377,7 @@ class DeviceMapper extends ClassMapperBase<Device> {
if (_instance == null) {
MapperContainer.globals.use(_instance = DeviceMapper._());
DeviceTypeMapper.ensureInitialized();
DiscoveryMethodMapper.ensureInitialized();
DeviceChannelMapper.ensureInitialized();
}
return _instance!;
}
@@ -529,11 +417,10 @@ class DeviceMapper extends ClassMapperBase<Device> {
);
static bool _$download(Device v) => v.download;
static const Field<Device, bool> _f$download = Field('download', _$download);
static Set<DiscoveryMethod> _$discoveryMethods(Device v) =>
v.discoveryMethods;
static const Field<Device, Set<DiscoveryMethod>> _f$discoveryMethods = Field(
'discoveryMethods',
_$discoveryMethods,
static List<DeviceChannel> _$channels(Device v) => v.channels;
static const Field<Device, List<DeviceChannel>> _f$channels = Field(
'channels',
_$channels,
);
@override
@@ -548,7 +435,7 @@ class DeviceMapper extends ClassMapperBase<Device> {
#deviceModel: _f$deviceModel,
#deviceType: _f$deviceType,
#download: _f$download,
#discoveryMethods: _f$discoveryMethods,
#channels: _f$channels,
};
static Device _instantiate(DecodingData data) {
@@ -563,7 +450,7 @@ class DeviceMapper extends ClassMapperBase<Device> {
deviceModel: data.dec(_f$deviceModel),
deviceType: data.dec(_f$deviceType),
download: data.dec(_f$download),
discoveryMethods: data.dec(_f$discoveryMethods),
channels: data.dec(_f$channels),
);
}
@@ -613,6 +500,12 @@ extension DeviceValueCopy<$R, $Out> on ObjectCopyWith<$R, Device, $Out> {
abstract class DeviceCopyWith<$R, $In extends Device, $Out>
implements ClassCopyWith<$R, $In, $Out> {
ListCopyWith<
$R,
DeviceChannel,
DeviceChannelCopyWith<$R, DeviceChannel, DeviceChannel>
>
get channels;
$R call({
String? signalingId,
String? ip,
@@ -624,7 +517,7 @@ abstract class DeviceCopyWith<$R, $In extends Device, $Out>
String? deviceModel,
DeviceType? deviceType,
bool? download,
Set<DiscoveryMethod>? discoveryMethods,
List<DeviceChannel>? channels,
});
DeviceCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
}
@@ -636,6 +529,17 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
@override
late final ClassMapperBase<Device> $mapper = DeviceMapper.ensureInitialized();
@override
ListCopyWith<
$R,
DeviceChannel,
DeviceChannelCopyWith<$R, DeviceChannel, DeviceChannel>
>
get channels => ListCopyWith(
$value.channels,
(v, t) => v.copyWith.$chain(t),
(v) => call(channels: v),
);
@override
$R call({
Object? signalingId = $none,
Object? ip = $none,
@@ -647,7 +551,7 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
Object? deviceModel = $none,
DeviceType? deviceType,
bool? download,
Set<DiscoveryMethod>? discoveryMethods,
List<DeviceChannel>? channels,
}) => $apply(
FieldCopyWithData({
if (signalingId != $none) #signalingId: signalingId,
@@ -660,7 +564,7 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
if (deviceModel != $none) #deviceModel: deviceModel,
if (deviceType != null) #deviceType: deviceType,
if (download != null) #download: download,
if (discoveryMethods != null) #discoveryMethods: discoveryMethods,
if (channels != null) #channels: channels,
}),
);
@override
@@ -675,7 +579,7 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
deviceModel: data.get(#deviceModel, or: $value.deviceModel),
deviceType: data.get(#deviceType, or: $value.deviceType),
download: data.get(#download, or: $value.download),
discoveryMethods: data.get(#discoveryMethods, or: $value.discoveryMethods),
channels: data.get(#channels, or: $value.channels),
);
@override
@@ -28,7 +28,7 @@ class InfoDto with InfoDtoMappable {
extension InfoToDeviceExt on InfoDto {
/// Convert [InfoDto] to [Device].
/// Since this HTTP request was successful, the [port] and [https] are known.
Device toDevice(String ip, int port, bool https, DiscoveryMethod method) {
Device toDevice(String ip, int port, bool https) {
return Device(
signalingId: null,
ip: ip,
@@ -40,7 +40,7 @@ extension InfoToDeviceExt on InfoDto {
deviceModel: deviceModel,
deviceType: deviceType ?? DeviceType.desktop,
download: download ?? false,
discoveryMethods: {method},
channels: [HttpChannel(host: ip, port: port, https: https)],
);
}
}
@@ -34,19 +34,21 @@ class InfoRegisterDto with InfoRegisterDtoMappable {
}
extension InfoRegisterDtoExt on InfoRegisterDto {
Device toDevice(String ip, int ownPort, bool ownHttps, DiscoveryMethod? method) {
Device toDevice(String ip, int ownPort, bool ownHttps, {required bool withChannel}) {
final resolvedPort = port ?? ownPort;
final resolvedHttps = protocol != null ? protocol == ProtocolType.https : ownHttps;
return Device(
signalingId: null,
ip: ip,
version: version ?? fallbackProtocolVersion,
port: port ?? ownPort,
https: protocol != null ? protocol == ProtocolType.https : ownHttps,
port: resolvedPort,
https: resolvedHttps,
fingerprint: fingerprint ?? '',
alias: alias,
deviceModel: deviceModel,
deviceType: deviceType ?? DeviceType.desktop,
download: download ?? false,
discoveryMethods: method == null ? const {} : {method},
channels: withChannel ? [HttpChannel(host: ip, port: resolvedPort, https: resolvedHttps)] : const [],
);
}
}
@@ -31,19 +31,21 @@ class RegisterDto with RegisterDtoMappable {
}
extension RegisterDtoExt on RegisterDto {
Device toDevice(String ip, int ownPort, bool ownHttps, DiscoveryMethod method) {
Device toDevice(String ip, int ownPort, bool ownHttps) {
final resolvedPort = port ?? ownPort;
final resolvedHttps = protocol != null ? protocol == ProtocolType.https : ownHttps;
return Device(
signalingId: null,
ip: ip,
version: version ?? fallbackProtocolVersion,
port: port ?? ownPort,
https: protocol != null ? protocol == ProtocolType.https : ownHttps,
port: resolvedPort,
https: resolvedHttps,
fingerprint: fingerprint,
alias: alias,
deviceModel: deviceModel,
deviceType: deviceType ?? DeviceType.desktop,
download: download ?? false,
discoveryMethods: {method},
channels: [HttpChannel(host: ip, port: resolvedPort, https: resolvedHttps)],
);
}
}
+13 -6
View File
@@ -131,7 +131,7 @@ extension RustFileDtoExt on rust_model.FileDto {
extension RsStoredDeviceExt on rust_discovery.RsStoredDevice {
/// Maps the merged stored state to a [Device]: the best channel becomes the
/// dialed address, every channel is kept as a [HttpDiscovery] method.
/// dialed address, every channel is kept as a [HttpChannel], best first.
Device toDevice() {
final best = channels.first;
return Device(
@@ -145,7 +145,14 @@ extension RsStoredDeviceExt on rust_discovery.RsStoredDevice {
deviceModel: deviceModel,
deviceType: deviceType?.toDart() ?? DeviceType.desktop,
download: download,
discoveryMethods: {for (final channel in channels) HttpDiscovery(ip: channel.host)},
channels: [
for (final channel in channels)
HttpChannel(
host: channel.host,
port: channel.port,
https: channel.protocol == rust_model.ProtocolType.https,
),
],
);
}
}
@@ -167,7 +174,7 @@ extension DeviceToRsDiscoveredDeviceExt on Device {
}
extension RegisterDtoV2Ext on rust_server.RegisterDtoV2 {
Device toDevice(String ip, DiscoveryMethod? method) {
Device toDevice(String ip, {required bool withChannel}) {
return Device(
signalingId: null,
ip: ip,
@@ -179,13 +186,13 @@ extension RegisterDtoV2Ext on rust_server.RegisterDtoV2 {
deviceModel: deviceModel,
deviceType: deviceType?.toDart() ?? DeviceType.desktop,
download: download,
discoveryMethods: method == null ? const {} : {method},
channels: withChannel ? [HttpChannel(host: ip, port: port, https: protocol == rust_model.ProtocolType.https)] : const [],
);
}
}
extension RegisterResponseDtoExt on rust_model.RegisterResponseDto {
Device toDevice(String ip, int port, bool https, DiscoveryMethod method) {
Device toDevice(String ip, int port, bool https) {
return Device(
signalingId: null,
ip: ip,
@@ -197,7 +204,7 @@ extension RegisterResponseDtoExt on rust_model.RegisterResponseDto {
deviceModel: deviceModel,
deviceType: deviceType?.toDart() ?? DeviceType.desktop,
download: hasWebInterface,
discoveryMethods: {method},
channels: [HttpChannel(host: ip, port: port, https: https)],
);
}
}