mirror of
https://github.com/localsend/localsend.git
synced 2026-04-19 22:47:09 -04:00
feat: update favorite device name if unchanged (#1009)
This commit is contained in:
@@ -13,12 +13,18 @@ class FavoriteDevice with FavoriteDeviceMappable {
|
||||
final int port;
|
||||
final String alias;
|
||||
|
||||
/// If true, the alias was set by the user.
|
||||
/// If false, the alias is derived from the original device alias and
|
||||
/// should be updated when the original device alias changes.
|
||||
final bool customAlias;
|
||||
|
||||
const FavoriteDevice({
|
||||
required this.id,
|
||||
required this.fingerprint,
|
||||
required this.ip,
|
||||
required this.port,
|
||||
required this.alias,
|
||||
this.customAlias = false,
|
||||
});
|
||||
|
||||
factory FavoriteDevice.fromValues({
|
||||
@@ -33,6 +39,7 @@ class FavoriteDevice with FavoriteDeviceMappable {
|
||||
ip: ip,
|
||||
port: port,
|
||||
alias: alias,
|
||||
customAlias: false,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ class FavoriteDeviceMapper extends ClassMapperBase<FavoriteDevice> {
|
||||
static const Field<FavoriteDevice, int> _f$port = Field('port', _$port);
|
||||
static String _$alias(FavoriteDevice v) => v.alias;
|
||||
static const Field<FavoriteDevice, String> _f$alias = Field('alias', _$alias);
|
||||
static bool _$customAlias(FavoriteDevice v) => v.customAlias;
|
||||
static const Field<FavoriteDevice, bool> _f$customAlias =
|
||||
Field('customAlias', _$customAlias, opt: true, def: false);
|
||||
|
||||
@override
|
||||
final Map<Symbol, Field<FavoriteDevice, dynamic>> fields = const {
|
||||
@@ -39,6 +42,7 @@ class FavoriteDeviceMapper extends ClassMapperBase<FavoriteDevice> {
|
||||
#ip: _f$ip,
|
||||
#port: _f$port,
|
||||
#alias: _f$alias,
|
||||
#customAlias: _f$customAlias,
|
||||
};
|
||||
|
||||
static FavoriteDevice _instantiate(DecodingData data) {
|
||||
@@ -47,7 +51,8 @@ class FavoriteDeviceMapper extends ClassMapperBase<FavoriteDevice> {
|
||||
fingerprint: data.dec(_f$fingerprint),
|
||||
ip: data.dec(_f$ip),
|
||||
port: data.dec(_f$port),
|
||||
alias: data.dec(_f$alias));
|
||||
alias: data.dec(_f$alias),
|
||||
customAlias: data.dec(_f$customAlias));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -106,7 +111,12 @@ extension FavoriteDeviceValueCopy<$R, $Out>
|
||||
abstract class FavoriteDeviceCopyWith<$R, $In extends FavoriteDevice, $Out>
|
||||
implements ClassCopyWith<$R, $In, $Out> {
|
||||
$R call(
|
||||
{String? id, String? fingerprint, String? ip, int? port, String? alias});
|
||||
{String? id,
|
||||
String? fingerprint,
|
||||
String? ip,
|
||||
int? port,
|
||||
String? alias,
|
||||
bool? customAlias});
|
||||
FavoriteDeviceCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
|
||||
Then<$Out2, $R2> t);
|
||||
}
|
||||
@@ -125,13 +135,15 @@ class _FavoriteDeviceCopyWithImpl<$R, $Out>
|
||||
String? fingerprint,
|
||||
String? ip,
|
||||
int? port,
|
||||
String? alias}) =>
|
||||
String? alias,
|
||||
bool? customAlias}) =>
|
||||
$apply(FieldCopyWithData({
|
||||
if (id != null) #id: id,
|
||||
if (fingerprint != null) #fingerprint: fingerprint,
|
||||
if (ip != null) #ip: ip,
|
||||
if (port != null) #port: port,
|
||||
if (alias != null) #alias: alias
|
||||
if (alias != null) #alias: alias,
|
||||
if (customAlias != null) #customAlias: customAlias
|
||||
}));
|
||||
@override
|
||||
FavoriteDevice $make(CopyWithData data) => FavoriteDevice(
|
||||
@@ -139,7 +151,8 @@ class _FavoriteDeviceCopyWithImpl<$R, $Out>
|
||||
fingerprint: data.get(#fingerprint, or: $value.fingerprint),
|
||||
ip: data.get(#ip, or: $value.ip),
|
||||
port: data.get(#port, or: $value.port),
|
||||
alias: data.get(#alias, or: $value.alias));
|
||||
alias: data.get(#alias, or: $value.alias),
|
||||
customAlias: data.get(#customAlias, or: $value.customAlias));
|
||||
|
||||
@override
|
||||
FavoriteDeviceCopyWith<$R2, FavoriteDevice, $Out2> $chain<$R2, $Out2>(
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:localsend_app/model/device.dart';
|
||||
import 'package:localsend_app/model/persistence/favorite_device.dart';
|
||||
import 'package:localsend_app/model/state/nearby_devices_state.dart';
|
||||
import 'package:localsend_app/provider/favorites_provider.dart';
|
||||
import 'package:localsend_app/provider/logging/discovery_logs_provider.dart';
|
||||
import 'package:localsend_app/provider/network/multicast_provider.dart';
|
||||
import 'package:localsend_app/provider/network/targeted_discovery_provider.dart';
|
||||
@@ -22,6 +24,7 @@ final nearbyDevicesProvider = ReduxProvider<NearbyDevicesService, NearbyDevicesS
|
||||
discoveryLogs: ref.notifier(discoveryLoggerProvider),
|
||||
targetedDiscoveryService: ref.accessor(targetedDiscoveryProvider),
|
||||
multicastService: ref.accessor(multicastProvider),
|
||||
favoriteService: ref.notifier(favoritesProvider),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -31,14 +34,17 @@ class NearbyDevicesService extends ReduxNotifier<NearbyDevicesState> {
|
||||
final DiscoveryLogger _discoveryLogs;
|
||||
final StateAccessor<TargetedDiscoveryService> _targetedDiscoveryService;
|
||||
final StateAccessor<MulticastService> _multicastService;
|
||||
final FavoritesService _favoriteService;
|
||||
|
||||
NearbyDevicesService({
|
||||
required DiscoveryLogger discoveryLogs,
|
||||
required StateAccessor<TargetedDiscoveryService> targetedDiscoveryService,
|
||||
required StateAccessor<MulticastService> multicastService,
|
||||
required FavoritesService favoriteService,
|
||||
}) : _discoveryLogs = discoveryLogs,
|
||||
_targetedDiscoveryService = targetedDiscoveryService,
|
||||
_multicastService = multicastService;
|
||||
_multicastService = multicastService,
|
||||
_favoriteService = favoriteService;
|
||||
|
||||
@override
|
||||
NearbyDevicesState init() => const NearbyDevicesState(
|
||||
@@ -98,7 +104,7 @@ class StartMulticastListener extends AsyncReduxAction<NearbyDevicesService, Near
|
||||
@override
|
||||
Future<NearbyDevicesState> reduce() async {
|
||||
await for (final device in notifier._multicastService.state.startListener()) {
|
||||
dispatch(RegisterDeviceAction(device));
|
||||
await dispatchAsync(RegisterDeviceAction(device));
|
||||
notifier._discoveryLogs.addLog('[DISCOVER/UDP] ${device.alias} (${device.ip}, model: ${device.deviceModel})');
|
||||
}
|
||||
return state;
|
||||
@@ -117,7 +123,7 @@ class ClearFoundDevicesAction extends ReduxAction<NearbyDevicesService, NearbyDe
|
||||
|
||||
/// Registers a device in the state.
|
||||
/// It will override any existing device with the same IP.
|
||||
class RegisterDeviceAction extends ReduxAction<NearbyDevicesService, NearbyDevicesState> {
|
||||
class RegisterDeviceAction extends AsyncReduxAction<NearbyDevicesService, NearbyDevicesState> {
|
||||
final Device device;
|
||||
|
||||
RegisterDeviceAction(this.device);
|
||||
@@ -126,7 +132,12 @@ class RegisterDeviceAction extends ReduxAction<NearbyDevicesService, NearbyDevic
|
||||
bool get trackOrigin => false;
|
||||
|
||||
@override
|
||||
NearbyDevicesState reduce() {
|
||||
Future<NearbyDevicesState> reduce() async {
|
||||
final favoriteDevice = notifier._favoriteService.state.firstWhereOrNull((e) => e.fingerprint == device.fingerprint);
|
||||
if (favoriteDevice != null && !favoriteDevice.customAlias) {
|
||||
// Update existing favorite with new alias
|
||||
await external(notifier._favoriteService).dispatchAsync(UpdateFavoriteAction(favoriteDevice.copyWith(alias: device.alias)));
|
||||
}
|
||||
return state.copyWith(
|
||||
devices: {...state.devices}..update(device.ip, (_) => device, ifAbsent: () => device),
|
||||
);
|
||||
@@ -166,7 +177,7 @@ class StartLegacyScan extends AsyncReduxAction<NearbyDevicesService, NearbyDevic
|
||||
dispatch(_SetRunningIpsAction({...state.runningIps, localIp}));
|
||||
|
||||
await for (final device in notifier._getStream(localIp, port, https)) {
|
||||
dispatch(RegisterDeviceAction(device));
|
||||
await dispatchAsync(RegisterDeviceAction(device));
|
||||
}
|
||||
|
||||
return state.copyWith(
|
||||
@@ -191,7 +202,7 @@ class StartFavoriteScan extends AsyncReduxAction<NearbyDevicesService, NearbyDev
|
||||
}
|
||||
dispatch(_SetRunningFavoriteScanAction(true));
|
||||
await for (final device in notifier._getFavoriteStream(devices: devices, https: https)) {
|
||||
dispatch(RegisterDeviceAction(device));
|
||||
await dispatchAsync(RegisterDeviceAction(device));
|
||||
}
|
||||
return state.copyWith(
|
||||
runningFavoriteScan: false,
|
||||
|
||||
@@ -159,7 +159,7 @@ class ReceiveController {
|
||||
}
|
||||
|
||||
// Save device information
|
||||
server.ref.redux(nearbyDevicesProvider).dispatch(RegisterDeviceAction(requestDto.toDevice(request.ip, port, https)));
|
||||
await server.ref.redux(nearbyDevicesProvider).dispatchAsync(RegisterDeviceAction(requestDto.toDevice(request.ip, port, https)));
|
||||
server.ref.notifier(discoveryLoggerProvider).addLog('[DISCOVER/TCP] Received "/register" HTTP request: ${requestDto.alias} (${request.ip})');
|
||||
|
||||
final deviceInfo = server.ref.read(deviceInfoProvider);
|
||||
|
||||
@@ -127,16 +127,21 @@ class _FavoriteEditDialogState extends State<FavoriteEditDialog> with Refena {
|
||||
}
|
||||
|
||||
if (widget.favorite != null) {
|
||||
if (_aliasController.text.trim().isEmpty) {
|
||||
// Update existing favorite
|
||||
final existingFavorite = widget.favorite!;
|
||||
final trimmedNewAlias = _aliasController.text.trim();
|
||||
if (trimmedNewAlias.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
await ref.redux(favoritesProvider).dispatchAsync(UpdateFavoriteAction(widget.favorite!.copyWith(
|
||||
await ref.redux(favoritesProvider).dispatchAsync(UpdateFavoriteAction(existingFavorite.copyWith(
|
||||
ip: _ipController.text,
|
||||
port: int.parse(_portController.text),
|
||||
alias: _aliasController.text,
|
||||
alias: trimmedNewAlias,
|
||||
customAlias: existingFavorite.customAlias || trimmedNewAlias != existingFavorite.alias,
|
||||
)));
|
||||
} else {
|
||||
// Add new favorite
|
||||
final ip = _ipController.text;
|
||||
final port = int.parse(_portController.text);
|
||||
final https = ref.read(settingsProvider).https;
|
||||
|
||||
Reference in New Issue
Block a user