From 9cf3b851707b718173dbe5b66c31643d3fc4f511 Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 13 Aug 2026 18:41:11 -0500 Subject: [PATCH] fix(mobile): cast discovery fix test --- mobile/ios/Podfile.lock | 2 +- mobile/lib/providers/cast.provider.dart | 7 ++++--- mobile/lib/repositories/cast.repository.dart | 18 +++++++++--------- mobile/lib/services/cast.service.dart | 7 +++++-- .../lib/widgets/asset_viewer/cast_dialog.dart | 15 +++++---------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index db2e58f1c9..3a309180c3 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -60,4 +60,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 3c43a700a4bffb4120bf696cad263aefd4bb3c8c -COCOAPODS: 1.16.2 +COCOAPODS: 1.17.0 diff --git a/mobile/lib/providers/cast.provider.dart b/mobile/lib/providers/cast.provider.dart index eaa700b46b..5582bb59ce 100644 --- a/mobile/lib/providers/cast.provider.dart +++ b/mobile/lib/providers/cast.provider.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/models/cast/cast_manager_state.dart'; @@ -57,9 +58,9 @@ class CastNotifier extends StateNotifier { await _castService.connect(device); } - Future> getDevices() { - return _castService.getDevices(); - } + Listenable get discoveryChanges => _castService.discoveryChanges; + + List get currentDevices => _castService.currentDevices; void toggle() { switch (state.castState) { diff --git a/mobile/lib/repositories/cast.repository.dart b/mobile/lib/repositories/cast.repository.dart index f36ec4d6ad..baed44e92e 100644 --- a/mobile/lib/repositories/cast.repository.dart +++ b/mobile/lib/repositories/cast.repository.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:fcast_sender_sdk/fcast_sender_sdk.dart'; +import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; final castRepositoryProvider = Provider((_) => CastRepository()); @@ -12,11 +13,15 @@ class CastRepository { void Function(DeviceEvent)? onDeviceEvent; final Map<(String, ProtocolType), (DeviceInfo, int?)> _discoveredDevices = {}; + final ValueNotifier _discoveryRevision = ValueNotifier(0); int _currentDeviceGeneration = 0; - late final Future _initialized; + + Listenable get discoveryChanges => _discoveryRevision; + + List<(DeviceInfo, int?)> get destinations => _discoveredDevices.values.toList(growable: false); void init() { - _initialized = _initialize(); + unawaited(_initialize()); } Future connect(DeviceInfo deviceInfo) async { @@ -69,12 +74,6 @@ class CastRepository { void stop() => _activeDevice?.stopPlayback(); void seekTo(Duration position) => _activeDevice?.seek(timeSeconds: position.inSeconds.toDouble()); - Future> listDestinations() async { - await _initialized; - - return _discoveredDevices.values.toList(growable: false); - } - Future _initialize() async { await FCastSenderSdkLib.init(); _castContext = CastContext(); @@ -88,9 +87,10 @@ class CastRepository { case DiscoveryEventDeviceRemoved(): _discoveredDevices.removeWhere((key, _) => key.$1 == event.name); } + + _discoveryRevision.value++; }); await discoverer.init(); - await Future.delayed(const Duration(seconds: 3)); } } diff --git a/mobile/lib/services/cast.service.dart b/mobile/lib/services/cast.service.dart index 4dfc25291c..ee921c0047 100644 --- a/mobile/lib/services/cast.service.dart +++ b/mobile/lib/services/cast.service.dart @@ -1,4 +1,5 @@ import 'package:fcast_sender_sdk/fcast_sender_sdk.dart'; +import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -161,8 +162,10 @@ class CastService { bool hasDisplayCapability(int capabilities) => (capabilities & 0x01) != 0; - Future> getDevices() async { - final dests = await _castRepository.listDestinations(); + Listenable get discoveryChanges => _castRepository.discoveryChanges; + + List get currentDevices { + final dests = _castRepository.destinations; final fCastDevices = dests.where((dest) => dest.$1.protocol == ProtocolType.fCast).map((dest) => dest.$1); final fCastNames = fCastDevices.map((device) => device.name).toSet(); diff --git a/mobile/lib/widgets/asset_viewer/cast_dialog.dart b/mobile/lib/widgets/asset_viewer/cast_dialog.dart index 98b67d4d0d..deeef8a7cc 100644 --- a/mobile/lib/widgets/asset_viewer/cast_dialog.dart +++ b/mobile/lib/widgets/asset_viewer/cast_dialog.dart @@ -27,20 +27,15 @@ class CastDialog extends ConsumerWidget { content: SizedBox( width: 250, height: 250, - child: FutureBuilder>( - future: ref.watch(castProvider.notifier).getDevices(), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Text('error_saving_image'.tr(args: [snapshot.error.toString()])); - } else if (!snapshot.hasData) { - return const SizedBox(height: 48, child: Center(child: CircularProgressIndicator())); - } + child: ListenableBuilder( + listenable: ref.watch(castProvider.notifier).discoveryChanges, + builder: (context, _) { + final devices = ref.read(castProvider.notifier).currentDevices; - if (snapshot.data!.isEmpty) { + if (devices.isEmpty) { return const Text('no_cast_devices_found').tr(); } - final devices = snapshot.data!; final connected = devices.where((d) => isCurrentDevice(d.$1)).toList(); final others = devices.where((d) => !isCurrentDevice(d.$1)).toList();