mirror of
https://github.com/localsend/localsend.git
synced 2026-04-29 03:00:23 -04:00
feat: show found webrtc devices
This commit is contained in:
@@ -21,6 +21,7 @@ import 'package:localsend_app/provider/app_arguments_provider.dart';
|
||||
import 'package:localsend_app/provider/device_info_provider.dart';
|
||||
import 'package:localsend_app/provider/network/nearby_devices_provider.dart';
|
||||
import 'package:localsend_app/provider/network/server/server_provider.dart';
|
||||
import 'package:localsend_app/provider/network/webrtc/signaling_provider.dart';
|
||||
import 'package:localsend_app/provider/persistence_provider.dart';
|
||||
|
||||
// [FOSS_REMOVE_START]
|
||||
@@ -32,8 +33,6 @@ import 'package:localsend_app/provider/settings_provider.dart';
|
||||
import 'package:localsend_app/provider/tv_provider.dart';
|
||||
import 'package:localsend_app/provider/window_dimensions_provider.dart';
|
||||
import 'package:localsend_app/rust/api/logging.dart' as rust_logging;
|
||||
import 'package:localsend_app/rust/api/model.dart' as model;
|
||||
import 'package:localsend_app/rust/api/webrtc.dart' as webrtc;
|
||||
import 'package:localsend_app/rust/frb_generated.dart';
|
||||
import 'package:localsend_app/util/i18n.dart';
|
||||
import 'package:localsend_app/util/native/autostart_helper.dart';
|
||||
@@ -65,55 +64,13 @@ Future<RefenaContainer> preInit(List<String> args) async {
|
||||
|
||||
await RustLib.init();
|
||||
|
||||
await rust_logging.enableDebugLogging();
|
||||
|
||||
webrtc.LsSignalingConnection? connection;
|
||||
final stream = webrtc.connect(
|
||||
uri: 'wss://public.localsend.org/v1/ws',
|
||||
info: webrtc.ClientInfoWithoutId(
|
||||
alias: 'alias',
|
||||
version: 'version',
|
||||
deviceModel: 'deviceModel',
|
||||
deviceType: webrtc.PeerDeviceType.mobile,
|
||||
fingerprint: 'fingerprint',
|
||||
),
|
||||
onConnection: (c) {
|
||||
connection = c;
|
||||
print('Got connection');
|
||||
},
|
||||
);
|
||||
|
||||
const stunServers = ['stun:stun.l.google.com:19302'];
|
||||
|
||||
stream.listen((message) async {
|
||||
print('Got message: $message');
|
||||
webrtc.WsServerMessage;
|
||||
await message.when(
|
||||
hello: (_, __) {},
|
||||
joined: (j) async {
|
||||
await connection?.sendOffer(
|
||||
stunServers: stunServers,
|
||||
target: j.id,
|
||||
files: [
|
||||
model.FileDto(
|
||||
id: '1',
|
||||
fileName: 'test.mp4',
|
||||
size: BigInt.from(1),
|
||||
fileType: 'fileType',
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
left: (l) {},
|
||||
offer: (o) async {
|
||||
await connection?.acceptOffer(stunServers: stunServers, offer: o);
|
||||
},
|
||||
answer: (a) {},
|
||||
error: (e) {},
|
||||
);
|
||||
}, onDone: () {
|
||||
print('Done!!!');
|
||||
});
|
||||
if (kDebugMode) {
|
||||
try {
|
||||
await rust_logging.enableDebugLogging();
|
||||
} catch (e) {
|
||||
_logger.warning('Enabling debug logging failed', e);
|
||||
}
|
||||
}
|
||||
|
||||
await Rhttp.init();
|
||||
|
||||
@@ -259,6 +216,8 @@ Future<void> postInit(BuildContext context, Ref ref, bool appStart) async {
|
||||
_logger.warning('Starting multicast listener failed', e);
|
||||
}
|
||||
|
||||
ref.redux(signalingProvider).dispatch(SetupSignalingConnection());
|
||||
|
||||
if (appStart) {
|
||||
if (defaultTargetPlatform == TargetPlatform.macOS) {
|
||||
// handle dropped files
|
||||
|
||||
@@ -20,4 +20,41 @@ class NearbyDevicesState with NearbyDevicesStateMappable {
|
||||
required this.devices,
|
||||
required this.signalingDevices,
|
||||
});
|
||||
|
||||
Map<String, Device> get allDevices {
|
||||
final Map<String, Device> allDevices = {};
|
||||
allDevices.addAll(devices);
|
||||
for (final devices in signalingDevices.values) {
|
||||
for (final device in devices) {
|
||||
final currentDevice = allDevices[device.fingerprint];
|
||||
if (currentDevice != null && currentDevice.alias == device.alias) {
|
||||
allDevices[device.fingerprint] = currentDevice.merge(device);
|
||||
} else {
|
||||
allDevices[device.fingerprint] = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
return allDevices;
|
||||
}
|
||||
}
|
||||
|
||||
extension on Device {
|
||||
Device merge(Device other) {
|
||||
return Device(
|
||||
signalingId: signalingId ?? other.signalingId,
|
||||
ip: ip ?? other.ip,
|
||||
version: version,
|
||||
port: port,
|
||||
https: https,
|
||||
fingerprint: fingerprint,
|
||||
alias: alias,
|
||||
deviceModel: deviceModel,
|
||||
deviceType: deviceType,
|
||||
download: download,
|
||||
discoveryMethods: {
|
||||
...discoveryMethods,
|
||||
...other.discoveryMethods,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ class ReceivePageController extends ReduxNotifier<ReceivePageVm> {
|
||||
return ReceivePageVm(
|
||||
status: SessionStatus.waiting,
|
||||
sender: const Device(
|
||||
signalingId: null,
|
||||
ip: '0.0.0.0',
|
||||
version: '1.0.0',
|
||||
port: 8080,
|
||||
@@ -155,6 +156,7 @@ class InitReceivePageFromHistoryMessageAction extends ReduxAction<ReceivePageCon
|
||||
ReceivePageVm reduce() {
|
||||
return state.copyWith(
|
||||
sender: Device(
|
||||
signalingId: null,
|
||||
ip: '0.0.0.0',
|
||||
version: '1.0.0',
|
||||
port: 8080,
|
||||
|
||||
@@ -219,7 +219,7 @@ class SendTab extends StatelessWidget {
|
||||
device: device,
|
||||
isFavorite: favoriteEntry != null,
|
||||
nameOverride: favoriteEntry?.alias,
|
||||
onFavoriteTap: () async => await vm.onToggleFavorite(context, device),
|
||||
onFavoriteTap: device.ip == null ? null : () async => await vm.onToggleFavorite(context, device),
|
||||
onTap: () async => await vm.onTapDevice(context, device),
|
||||
),
|
||||
),
|
||||
@@ -534,7 +534,7 @@ class _MultiSendDeviceListTile extends StatelessWidget {
|
||||
progress: progress,
|
||||
isFavorite: isFavorite,
|
||||
nameOverride: nameOverride,
|
||||
onFavoriteTap: () async => await vm.onToggleFavorite(context, device),
|
||||
onFavoriteTap: device.ip == null ? null : () async => await vm.onToggleFavorite(context, device),
|
||||
onTap: () async => await vm.onTapDeviceMultiSend(context, device),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ final sendTabVmProvider = ViewProvider((ref) {
|
||||
final sendMode = ref.watch(settingsProvider.select((s) => s.sendMode));
|
||||
final selectedFiles = ref.watch(selectedSendingFilesProvider);
|
||||
final localIps = ref.watch(localIpProvider).localIps;
|
||||
final nearbyDevices = ref.watch(nearbyDevicesProvider).devices.values;
|
||||
final nearbyDevices = ref.watch(nearbyDevicesProvider).allDevices.values;
|
||||
final favoriteDevices = ref.watch(favoritesProvider);
|
||||
|
||||
return SendTabVm(
|
||||
|
||||
@@ -32,6 +32,7 @@ final deviceFullInfoProvider = ViewProvider((ref) {
|
||||
final rawInfo = ref.watch(deviceInfoProvider);
|
||||
final securityContext = ref.read(securityProvider);
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: networkInfo.localIps.firstOrNull ?? '-',
|
||||
version: protocolVersion,
|
||||
port: serverState?.port ?? -1,
|
||||
|
||||
@@ -79,7 +79,7 @@ class RegisterDeviceAction extends AsyncReduxAction<NearbyDevicesService, Nearby
|
||||
|
||||
@override
|
||||
Future<NearbyDevicesState> reduce() async {
|
||||
assert(device.ip?.isNotEmpty ?? false);
|
||||
assert(device.ip?.isNotEmpty ?? false, 'IP must not be empty');
|
||||
|
||||
final favoriteDevice = notifier._favoriteService.state.firstWhereOrNull((e) => e.fingerprint == device.fingerprint);
|
||||
if (favoriteDevice != null && !favoriteDevice.customAlias) {
|
||||
@@ -94,6 +94,41 @@ class RegisterDeviceAction extends AsyncReduxAction<NearbyDevicesService, Nearby
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a new device found via signaling.
|
||||
class RegisterSignalingDeviceAction extends ReduxAction<NearbyDevicesService, NearbyDevicesState> {
|
||||
final Device device;
|
||||
|
||||
RegisterSignalingDeviceAction(this.device);
|
||||
|
||||
@override
|
||||
NearbyDevicesState reduce() {
|
||||
final Set<Device> existingDevices = state.signalingDevices[device.fingerprint] ?? {};
|
||||
existingDevices.add(device);
|
||||
|
||||
return state.copyWith(
|
||||
signalingDevices: {
|
||||
...state.signalingDevices,
|
||||
device.fingerprint: existingDevices,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UnregisterSignalingDeviceAction extends ReduxAction<NearbyDevicesService, NearbyDevicesState> {
|
||||
final String signalingId;
|
||||
|
||||
UnregisterSignalingDeviceAction(this.signalingId);
|
||||
|
||||
@override
|
||||
NearbyDevicesState reduce() {
|
||||
return state.copyWith(
|
||||
signalingDevices: {
|
||||
for (final entry in state.signalingDevices.entries) entry.key: entry.value.where((e) => e.signalingId != signalingId).toSet(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// It does not really "scan".
|
||||
/// It just sends an announcement which will cause a response on every other LocalSend member of the network.
|
||||
class StartMulticastScan extends ReduxAction<NearbyDevicesService, NearbyDevicesState> {
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:common/constants.dart';
|
||||
import 'package:common/model/device.dart';
|
||||
import 'package:common/model/device_info_result.dart';
|
||||
import 'package:dart_mappable/dart_mappable.dart';
|
||||
import 'package:localsend_app/provider/device_info_provider.dart';
|
||||
import 'package:localsend_app/provider/network/nearby_devices_provider.dart';
|
||||
import 'package:localsend_app/provider/persistence_provider.dart';
|
||||
import 'package:localsend_app/provider/security_provider.dart';
|
||||
import 'package:localsend_app/provider/settings_provider.dart';
|
||||
import 'package:localsend_app/rust/api/webrtc.dart';
|
||||
import 'package:refena_flutter/refena_flutter.dart';
|
||||
|
||||
part 'signaling_provider.mapper.dart';
|
||||
|
||||
final signalingProvider = ReduxProvider<SignalingService, SignalingState>((ref) {
|
||||
return SignalingService(
|
||||
persistence: ref.read(persistenceProvider),
|
||||
);
|
||||
});
|
||||
|
||||
@MappableClass()
|
||||
class SignalingState with SignalingStateMappable {
|
||||
final List<String> signalingServers;
|
||||
@@ -24,26 +27,50 @@ class SignalingState with SignalingStateMappable {
|
||||
});
|
||||
}
|
||||
|
||||
final signalingProvider = ReduxProvider<SignalingService, SignalingState>((ref) {
|
||||
return SignalingService(
|
||||
persistence: ref.read(persistenceProvider),
|
||||
nearbyDevices: ref.notifier(nearbyDevicesProvider),
|
||||
settings: ref.notifier(settingsProvider),
|
||||
deviceInfo: ref.accessor(deviceInfoProvider),
|
||||
security: ref.notifier(securityProvider),
|
||||
);
|
||||
});
|
||||
|
||||
class SignalingService extends ReduxNotifier<SignalingState> {
|
||||
final PersistenceService _persistence;
|
||||
final NearbyDevicesService _nearbyDevices;
|
||||
final SettingsService _settings;
|
||||
final StateAccessor<DeviceInfoResult> _deviceInfo;
|
||||
final SecurityService _security;
|
||||
|
||||
SignalingService({required PersistenceService persistence}) : _persistence = persistence;
|
||||
SignalingService({
|
||||
required PersistenceService persistence,
|
||||
required NearbyDevicesService nearbyDevices,
|
||||
required SettingsService settings,
|
||||
required StateAccessor<DeviceInfoResult> deviceInfo,
|
||||
required SecurityService security,
|
||||
}) : _persistence = persistence,
|
||||
_nearbyDevices = nearbyDevices,
|
||||
_settings = settings,
|
||||
_deviceInfo = deviceInfo,
|
||||
_security = security;
|
||||
|
||||
@override
|
||||
SignalingState init() {
|
||||
return SignalingState(
|
||||
signalingServers: _persistence.getSignalingServers(),
|
||||
stunServers: _persistence.getStunServers(),
|
||||
signalingServers: _persistence.getSignalingServers() ?? ['wss://public.localsend.org/v1/ws'],
|
||||
stunServers: _persistence.getStunServers() ?? ['stun:stun.localsend.org:5349'],
|
||||
connections: {},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SetupSignalingConnection extends AsyncReduxAction<SignalingService, SignalingState> {
|
||||
class SetupSignalingConnection extends ReduxAction<SignalingService, SignalingState> {
|
||||
@override
|
||||
Future<SignalingState> reduce() async {
|
||||
SignalingState reduce() {
|
||||
for (final signalingServer in state.signalingServers) {
|
||||
// ignore: unawaited_futures
|
||||
// ignore: discarded_futures
|
||||
dispatchAsync(_SetupSignalingConnection(signalingServer: signalingServer));
|
||||
}
|
||||
return state;
|
||||
@@ -62,19 +89,133 @@ class _SetupSignalingConnection extends AsyncReduxAction<SignalingService, Signa
|
||||
final stream = connect(
|
||||
uri: 'wss://public.localsend.org/v1/ws',
|
||||
info: ClientInfoWithoutId(
|
||||
alias: 'alias',
|
||||
version: 'version',
|
||||
deviceModel: 'deviceModel',
|
||||
deviceType: PeerDeviceType.mobile,
|
||||
fingerprint: 'fingerprint',
|
||||
alias: notifier._settings.state.alias,
|
||||
version: protocolVersion,
|
||||
deviceModel: notifier._deviceInfo.state.deviceModel,
|
||||
deviceType: notifier._deviceInfo.state.deviceType.toPeerDeviceType(),
|
||||
fingerprint: notifier._security.state.certificateHash,
|
||||
),
|
||||
onConnection: (c) {
|
||||
connection = c;
|
||||
|
||||
dispatch(_SetConnectionAction(
|
||||
signalingServer: signalingServer,
|
||||
connection: c,
|
||||
));
|
||||
},
|
||||
);
|
||||
|
||||
await for (final message in stream) {}
|
||||
try {
|
||||
await for (final message in stream) {
|
||||
switch (message) {
|
||||
case WsServerMessage_Hello():
|
||||
for (final d in message.peers) {
|
||||
external(notifier._nearbyDevices).dispatch(RegisterSignalingDeviceAction(
|
||||
d.toDevice(signalingServer),
|
||||
));
|
||||
}
|
||||
break;
|
||||
case WsServerMessage_Joined():
|
||||
external(notifier._nearbyDevices).dispatch(RegisterSignalingDeviceAction(
|
||||
message.peer.toDevice(signalingServer),
|
||||
));
|
||||
break;
|
||||
case WsServerMessage_Left():
|
||||
external(notifier._nearbyDevices).dispatch(UnregisterSignalingDeviceAction(
|
||||
message.peerId.uuid,
|
||||
));
|
||||
break;
|
||||
case WsServerMessage_Offer():
|
||||
case WsServerMessage_Answer():
|
||||
case WsServerMessage_Error():
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
dispatch(_RemoveConnectionAction(signalingServer: signalingServer));
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
class _SetConnectionAction extends ReduxAction<SignalingService, SignalingState> {
|
||||
final String signalingServer;
|
||||
final LsSignalingConnection connection;
|
||||
|
||||
_SetConnectionAction({
|
||||
required this.signalingServer,
|
||||
required this.connection,
|
||||
});
|
||||
|
||||
@override
|
||||
SignalingState reduce() {
|
||||
return state.copyWith(
|
||||
connections: {
|
||||
...state.connections,
|
||||
signalingServer: connection,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RemoveConnectionAction extends ReduxAction<SignalingService, SignalingState> {
|
||||
final String signalingServer;
|
||||
|
||||
_RemoveConnectionAction({required this.signalingServer});
|
||||
|
||||
@override
|
||||
SignalingState reduce() {
|
||||
return state.copyWith(
|
||||
connections: {
|
||||
for (final entry in state.connections.entries)
|
||||
if (entry.key != signalingServer) entry.key: entry.value,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension on ClientInfo {
|
||||
Device toDevice(String signalingServer) {
|
||||
return Device(
|
||||
signalingId: id.uuid,
|
||||
ip: null,
|
||||
version: version,
|
||||
port: -1,
|
||||
https: false,
|
||||
fingerprint: fingerprint,
|
||||
alias: alias,
|
||||
deviceModel: deviceModel,
|
||||
deviceType: deviceType?.toDeviceType() ?? DeviceType.desktop,
|
||||
download: false,
|
||||
discoveryMethods: {
|
||||
SignalingDiscovery(
|
||||
signalingServer: signalingServer,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension on PeerDeviceType {
|
||||
DeviceType toDeviceType() {
|
||||
return switch (this) {
|
||||
PeerDeviceType.mobile => DeviceType.mobile,
|
||||
PeerDeviceType.desktop => DeviceType.desktop,
|
||||
PeerDeviceType.web => DeviceType.web,
|
||||
PeerDeviceType.headless => DeviceType.headless,
|
||||
PeerDeviceType.server => DeviceType.server,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension on DeviceType {
|
||||
PeerDeviceType toPeerDeviceType() {
|
||||
return switch (this) {
|
||||
DeviceType.mobile => PeerDeviceType.mobile,
|
||||
DeviceType.desktop => PeerDeviceType.desktop,
|
||||
DeviceType.web => PeerDeviceType.web,
|
||||
DeviceType.headless => PeerDeviceType.headless,
|
||||
DeviceType.server => PeerDeviceType.server,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,10 +212,10 @@ class PersistenceService {
|
||||
await _prefs.setString(_securityContext, jsonEncode(context));
|
||||
}
|
||||
|
||||
List<String> getSignalingServers() {
|
||||
List<String>? getSignalingServers() {
|
||||
final serversRaw = _prefs.getString(_signalingServers);
|
||||
if (serversRaw == null) {
|
||||
return [];
|
||||
return null;
|
||||
}
|
||||
|
||||
return (jsonDecode(serversRaw) as List).cast<String>();
|
||||
@@ -225,10 +225,10 @@ class PersistenceService {
|
||||
await _prefs.setString(_signalingServers, jsonEncode(servers));
|
||||
}
|
||||
|
||||
List<String> getStunServers() {
|
||||
List<String>? getStunServers() {
|
||||
final serversRaw = _prefs.getString(_stunServers);
|
||||
if (serversRaw == null) {
|
||||
return [];
|
||||
return null;
|
||||
}
|
||||
|
||||
return (jsonDecode(serversRaw) as List).cast<String>();
|
||||
|
||||
@@ -565,7 +565,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
},
|
||||
codec: SseCodec(
|
||||
decodeSuccessData: sse_decode_unit,
|
||||
decodeErrorData: null,
|
||||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiLoggingEnableDebugLoggingConstMeta,
|
||||
argValues: [],
|
||||
|
||||
@@ -59,7 +59,7 @@ class DeviceListTile extends StatelessWidget {
|
||||
foregroundColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
label: '#${device.ip!.visualId}',
|
||||
)
|
||||
else
|
||||
else
|
||||
DeviceBadge(
|
||||
backgroundColor: badgeColor,
|
||||
foregroundColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
use anyhow::Result;
|
||||
use tracing::Level;
|
||||
|
||||
pub fn enable_debug_logging() {
|
||||
pub fn enable_debug_logging() -> Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::DEBUG)
|
||||
.init();
|
||||
.try_init()
|
||||
.map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1007,12 +1007,12 @@ fn wire__crate__api__logging__enable_debug_logging_impl(
|
||||
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||
deserializer.end();
|
||||
move |context| {
|
||||
transform_result_sse::<_, ()>((move || {
|
||||
let output_ok = Result::<_, ()>::Ok({
|
||||
crate::api::logging::enable_debug_logging();
|
||||
})?;
|
||||
Ok(output_ok)
|
||||
})())
|
||||
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::logging::enable_debug_logging()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -94,16 +94,6 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
|
||||
returnValueForMissingStub: _i4.Future<void>.value(),
|
||||
) as _i4.Future<void>);
|
||||
|
||||
@override
|
||||
List<String> getSignalingServers() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getSignalingServers,
|
||||
[],
|
||||
),
|
||||
returnValue: <String>[],
|
||||
returnValueForMissingStub: <String>[],
|
||||
) as List<String>);
|
||||
|
||||
@override
|
||||
_i4.Future<void> setSignalingServers(List<String>? servers) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -114,16 +104,6 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
|
||||
returnValueForMissingStub: _i4.Future<void>.value(),
|
||||
) as _i4.Future<void>);
|
||||
|
||||
@override
|
||||
List<String> getStunServers() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getStunServers,
|
||||
[],
|
||||
),
|
||||
returnValue: <String>[],
|
||||
returnValueForMissingStub: <String>[],
|
||||
) as List<String>);
|
||||
|
||||
@override
|
||||
_i4.Future<void> setStunServers(List<String>? servers) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
||||
@@ -52,6 +52,7 @@ void main() {
|
||||
|
||||
Device _createDevice(String ip) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: ip,
|
||||
version: '1',
|
||||
port: 123,
|
||||
|
||||
@@ -46,6 +46,7 @@ Device _target({
|
||||
required bool https,
|
||||
}) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: '0.0.0.0',
|
||||
version: version,
|
||||
port: 8080,
|
||||
|
||||
@@ -24,6 +24,7 @@ class MulticastDiscovery extends DiscoveryMethod with MulticastDiscoveryMappable
|
||||
@MappableClass()
|
||||
class HttpDiscovery extends DiscoveryMethod with HttpDiscoveryMappable {
|
||||
final String ip;
|
||||
|
||||
const HttpDiscovery({required this.ip});
|
||||
}
|
||||
|
||||
@@ -47,7 +48,13 @@ enum TransmissionMethod {
|
||||
/// It gets not serialized.
|
||||
@MappableClass()
|
||||
class Device with DeviceMappable {
|
||||
/// A unique ID provided by the signaling server.
|
||||
final String? signalingId;
|
||||
|
||||
/// The IP address of the device.
|
||||
/// Is null when found via signaling.
|
||||
final String? ip;
|
||||
|
||||
final String version;
|
||||
final int port;
|
||||
final bool https;
|
||||
@@ -82,6 +89,7 @@ class Device with DeviceMappable {
|
||||
}
|
||||
|
||||
const Device({
|
||||
required this.signalingId,
|
||||
required this.ip,
|
||||
required this.version,
|
||||
required this.port,
|
||||
|
||||
@@ -399,6 +399,8 @@ class DeviceMapper extends ClassMapperBase<Device> {
|
||||
@override
|
||||
final String id = 'Device';
|
||||
|
||||
static String? _$signalingId(Device v) => v.signalingId;
|
||||
static const Field<Device, String> _f$signalingId = Field('signalingId', _$signalingId);
|
||||
static String? _$ip(Device v) => v.ip;
|
||||
static const Field<Device, String> _f$ip = Field('ip', _$ip);
|
||||
static String _$version(Device v) => v.version;
|
||||
@@ -422,6 +424,7 @@ class DeviceMapper extends ClassMapperBase<Device> {
|
||||
|
||||
@override
|
||||
final MappableFields<Device> fields = const {
|
||||
#signalingId: _f$signalingId,
|
||||
#ip: _f$ip,
|
||||
#version: _f$version,
|
||||
#port: _f$port,
|
||||
@@ -436,6 +439,7 @@ class DeviceMapper extends ClassMapperBase<Device> {
|
||||
|
||||
static Device _instantiate(DecodingData data) {
|
||||
return Device(
|
||||
signalingId: data.dec(_f$signalingId),
|
||||
ip: data.dec(_f$ip),
|
||||
version: data.dec(_f$version),
|
||||
port: data.dec(_f$port),
|
||||
@@ -492,7 +496,8 @@ extension DeviceValueCopy<$R, $Out> on ObjectCopyWith<$R, Device, $Out> {
|
||||
|
||||
abstract class DeviceCopyWith<$R, $In extends Device, $Out> implements ClassCopyWith<$R, $In, $Out> {
|
||||
$R call(
|
||||
{String? ip,
|
||||
{String? signalingId,
|
||||
String? ip,
|
||||
String? version,
|
||||
int? port,
|
||||
bool? https,
|
||||
@@ -512,7 +517,8 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
|
||||
late final ClassMapperBase<Device> $mapper = DeviceMapper.ensureInitialized();
|
||||
@override
|
||||
$R call(
|
||||
{Object? ip = $none,
|
||||
{Object? signalingId = $none,
|
||||
Object? ip = $none,
|
||||
String? version,
|
||||
int? port,
|
||||
bool? https,
|
||||
@@ -523,6 +529,7 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
|
||||
bool? download,
|
||||
Set<DiscoveryMethod>? discoveryMethods}) =>
|
||||
$apply(FieldCopyWithData({
|
||||
if (signalingId != $none) #signalingId: signalingId,
|
||||
if (ip != $none) #ip: ip,
|
||||
if (version != null) #version: version,
|
||||
if (port != null) #port: port,
|
||||
@@ -536,6 +543,7 @@ class _DeviceCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, Device, $Out>
|
||||
}));
|
||||
@override
|
||||
Device $make(CopyWithData data) => Device(
|
||||
signalingId: data.get(#signalingId, or: $value.signalingId),
|
||||
ip: data.get(#ip, or: $value.ip),
|
||||
version: data.get(#version, or: $value.version),
|
||||
port: data.get(#port, or: $value.port),
|
||||
|
||||
@@ -30,6 +30,7 @@ extension InfoToDeviceExt on InfoDto {
|
||||
/// Since this HTTP request was successful, the [port] and [https] are known.
|
||||
Device toDevice(String ip, int port, bool https, DiscoveryMethod method) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: ip,
|
||||
version: version ?? fallbackProtocolVersion,
|
||||
port: port,
|
||||
|
||||
@@ -36,6 +36,7 @@ class InfoRegisterDto with InfoRegisterDtoMappable {
|
||||
extension InfoRegisterDtoExt on InfoRegisterDto {
|
||||
Device toDevice(String ip, int ownPort, bool ownHttps, DiscoveryMethod? method) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: ip,
|
||||
version: version ?? fallbackProtocolVersion,
|
||||
port: port ?? ownPort,
|
||||
|
||||
@@ -39,6 +39,7 @@ class MulticastDto with MulticastDtoMappable {
|
||||
extension MulticastDtoToDeviceExt on MulticastDto {
|
||||
Device toDevice(String ip, int ownPort, bool ownHttps) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: ip,
|
||||
version: version ?? fallbackProtocolVersion,
|
||||
port: port ?? ownPort,
|
||||
|
||||
@@ -33,6 +33,7 @@ class RegisterDto with RegisterDtoMappable {
|
||||
extension RegisterDtoExt on RegisterDto {
|
||||
Device toDevice(String ip, int ownPort, bool ownHttps, DiscoveryMethod method) {
|
||||
return Device(
|
||||
signalingId: null,
|
||||
ip: ip,
|
||||
version: version ?? fallbackProtocolVersion,
|
||||
port: port ?? ownPort,
|
||||
|
||||
Reference in New Issue
Block a user