diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml index b9f18d0d81..3f5a33b2b2 100644 --- a/mobile/analysis_options.yaml +++ b/mobile/analysis_options.yaml @@ -28,7 +28,6 @@ linter: rules: # Formatting avoid_print: true - unawaited_futures: true require_trailing_commas: true unrelated_type_equality_checks: true prefer_const_constructors: true @@ -50,6 +49,17 @@ linter: avoid_multiple_declarations_per_line: true unnecessary_breaks: true + # Correctness + no_adjacent_strings_in_list: true + cancel_subscriptions: true + close_sinks: true + unawaited_futures: true + discarded_futures: true + no_self_assignments: true + throw_in_finally: true + collection_methods_unrelated_type: true + cast_nullable_to_non_nullable: true + # Known issues avoid_slow_async_io: true avoid_type_to_string: true diff --git a/mobile/lib/domain/models/user_metadata.model.dart b/mobile/lib/domain/models/user_metadata.model.dart index b73f798255..0e702ba868 100644 --- a/mobile/lib/domain/models/user_metadata.model.dart +++ b/mobile/lib/domain/models/user_metadata.model.dart @@ -23,7 +23,7 @@ class Onboarding { } factory Onboarding.fromMap(Map map) { - return Onboarding(isOnboarded: map["isOnboarded"] as bool); + return Onboarding(isOnboarded: map["isOnboarded"]! as bool); } @override @@ -195,9 +195,9 @@ class License { factory License.fromMap(Map map) { return License( - activatedAt: DateTime.parse(map["activatedAt"] as String), - activationKey: map["activationKey"] as String, - licenseKey: map["licenseKey"] as String, + activatedAt: DateTime.parse(map["activatedAt"]! as String), + activationKey: map["activationKey"]! as String, + licenseKey: map["licenseKey"]! as String, ); } diff --git a/mobile/lib/domain/services/hash.service.dart b/mobile/lib/domain/services/hash.service.dart index e4c332b283..b0dbf8fbea 100644 --- a/mobile/lib/domain/services/hash.service.dart +++ b/mobile/lib/domain/services/hash.service.dart @@ -32,7 +32,7 @@ class HashService { }) : _batchSize = batchSize ?? kBatchHashFileLimit { // Stop the in-flight native hash call promptly on cancellation; the loops // below also observe [isCancelled] to bail between batches. - _cancellation?.future.then((_) => _nativeSyncApi.cancelHashing().onError(_log.warning)); + unawaited(_cancellation?.future.then((_) => _nativeSyncApi.cancelHashing().onError(_log.warning))); } bool get isCancelled => _cancellation?.isCompleted ?? false; diff --git a/mobile/lib/domain/services/local_sync.service.dart b/mobile/lib/domain/services/local_sync.service.dart index feb104f90d..b4ebc66f89 100644 --- a/mobile/lib/domain/services/local_sync.service.dart +++ b/mobile/lib/domain/services/local_sync.service.dart @@ -40,7 +40,7 @@ class LocalSyncService { required this._permissionRepository, this._cancellation, }) { - _cancellation?.future.then((_) => _nativeSyncApi.cancelSync().onError(_log.warning)); + unawaited(_cancellation?.future.then((_) => _nativeSyncApi.cancelSync().onError(_log.warning))); } bool get _isCancelled => _cancellation?.isCompleted ?? false; diff --git a/mobile/lib/domain/services/timeline.service.dart b/mobile/lib/domain/services/timeline.service.dart index 9b539ec218..b20ba306ff 100644 --- a/mobile/lib/domain/services/timeline.service.dart +++ b/mobile/lib/domain/services/timeline.service.dart @@ -106,32 +106,34 @@ class TimelineService { TimelineService._({required this._assetSource, required this._bucketSource, required this.origin}) { _bucketSubscription = _bucketSource().listen((buckets) { - _mutex.run(() async { - final totalAssets = buckets.fold(0, (acc, bucket) => acc + bucket.assetCount); + unawaited( + _mutex.run(() async { + final totalAssets = buckets.fold(0, (acc, bucket) => acc + bucket.assetCount); - if (totalAssets == 0) { - _bufferOffset = 0; - _buffer = []; - } else { - final int offset; - final int count; - // When the buffer is empty or the old bufferOffset is greater than the new total assets, - // we need to reset the buffer and load the first batch of assets. - if (_bufferOffset >= totalAssets || _buffer.isEmpty) { - offset = 0; - count = kTimelineAssetLoadBatchSize; + if (totalAssets == 0) { + _bufferOffset = 0; + _buffer = []; } else { - offset = _bufferOffset; - count = math.min(_buffer.length, totalAssets - _bufferOffset); + final int offset; + final int count; + // When the buffer is empty or the old bufferOffset is greater than the new total assets, + // we need to reset the buffer and load the first batch of assets. + if (_bufferOffset >= totalAssets || _buffer.isEmpty) { + offset = 0; + count = kTimelineAssetLoadBatchSize; + } else { + offset = _bufferOffset; + count = math.min(_buffer.length, totalAssets - _bufferOffset); + } + _buffer = await _assetSource(offset, count); + _bufferOffset = offset; } - _buffer = await _assetSource(offset, count); - _bufferOffset = offset; - } - // change the state's total assets count only after the buffer is reloaded - _totalAssets = totalAssets; - EventStream.shared.emit(const TimelineReloadEvent()); - }); + // change the state's total assets count only after the buffer is reloaded + _totalAssets = totalAssets; + EventStream.shared.emit(const TimelineReloadEvent()); + }), + ); }); } diff --git a/mobile/lib/domain/utils/event_stream.dart b/mobile/lib/domain/utils/event_stream.dart index 5967fdca50..0069c75f86 100644 --- a/mobile/lib/domain/utils/event_stream.dart +++ b/mobile/lib/domain/utils/event_stream.dart @@ -32,7 +32,7 @@ class EventStream { } /// Closes the stream controller - void dispose() { - _controller.close(); + Future dispose() { + return _controller.close(); } } diff --git a/mobile/lib/infrastructure/entities/asset_edit.entity.dart b/mobile/lib/infrastructure/entities/asset_edit.entity.dart index 87a05ab8fe..58e1a91d33 100644 --- a/mobile/lib/infrastructure/entities/asset_edit.entity.dart +++ b/mobile/lib/infrastructure/entities/asset_edit.entity.dart @@ -25,7 +25,7 @@ class AssetEditEntity extends Table with DriftDefaultsMixin { } final JsonTypeConverter2, Uint8List, Object?> editParameterConverter = TypeConverter.jsonb( - fromJson: (json) => json as Map, + fromJson: (json) => json! as Map, ); extension AssetEditEntityDataDomainEx on AssetEditEntityData { diff --git a/mobile/lib/infrastructure/entities/user_metadata.entity.dart b/mobile/lib/infrastructure/entities/user_metadata.entity.dart index ede3de3966..da2070fd71 100644 --- a/mobile/lib/infrastructure/entities/user_metadata.entity.dart +++ b/mobile/lib/infrastructure/entities/user_metadata.entity.dart @@ -17,5 +17,5 @@ class UserMetadataEntity extends Table with DriftDefaultsMixin { } final JsonTypeConverter2, Uint8List, Object?> userMetadataConverter = TypeConverter.jsonb( - fromJson: (json) => json as Map, + fromJson: (json) => json! as Map, ); diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 844226d49f..c43de69c5d 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -358,12 +358,12 @@ class SyncStreamRepository extends DriftDatabaseRepository { final map = metadata.value as Map; final companion = RemoteAssetCloudIdEntityCompanion( cloudId: Value(map['iCloudId']?.toString()), - createdAt: Value(map['createdAt'] != null ? DateTime.parse(map['createdAt'] as String) : null), + createdAt: Value(map['createdAt'] != null ? DateTime.parse(map['createdAt']! as String) : null), adjustmentTime: Value( - map['adjustmentTime'] != null ? DateTime.parse(map['adjustmentTime'] as String) : null, + map['adjustmentTime'] != null ? DateTime.parse(map['adjustmentTime']! as String) : null, ), - latitude: Value(map['latitude'] != null ? (double.tryParse(map['latitude'] as String)) : null), - longitude: Value(map['longitude'] != null ? (double.tryParse(map['longitude'] as String)) : null), + latitude: Value(map['latitude'] != null ? (double.tryParse(map['latitude']! as String)) : null), + longitude: Value(map['longitude'] != null ? (double.tryParse(map['longitude']! as String)) : null), ); batch.insert( _db.remoteAssetCloudIdEntity, diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 09bcdc752f..58e93891a2 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -128,17 +128,17 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve switch (state) { case AppLifecycleState.resumed: dPrint(() => "[APP STATE] resumed"); - ref.read(appStateProvider.notifier).handleAppResume(); + unawaited(ref.read(appStateProvider.notifier).handleAppResume()); unawaited(ref.read(viewIntentHandlerProvider).onAppResumed()); case AppLifecycleState.inactive: dPrint(() => "[APP STATE] inactive"); ref.read(appStateProvider.notifier).handleAppInactivity(); case AppLifecycleState.paused: dPrint(() => "[APP STATE] paused"); - ref.read(appStateProvider.notifier).handleAppPause(); + unawaited(ref.read(appStateProvider.notifier).handleAppPause()); case AppLifecycleState.detached: dPrint(() => "[APP STATE] detached"); - ref.read(appStateProvider.notifier).handleAppDetached(); + unawaited(ref.read(appStateProvider.notifier).handleAppDetached()); case AppLifecycleState.hidden: dPrint(() => "[APP STATE] hidden"); ref.read(appStateProvider.notifier).handleAppHidden(); @@ -216,17 +216,19 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve @override void initState() { super.initState(); - initApp().then((_) => dPrint(() => "App Init Completed")); + unawaited(initApp().then((_) => dPrint(() => "App Init Completed"))); WidgetsBinding.instance.addPostFrameCallback((_) { // needs to be delayed so that EasyLocalization is working - ref.read(backgroundWorkerFgServiceProvider).enable(); + unawaited(ref.read(backgroundWorkerFgServiceProvider).enable()); if (Platform.isAndroid) { - ref - .read(backgroundWorkerFgServiceProvider) - .saveNotificationMessage( - StaticTranslations.instance.uploading_media, - StaticTranslations.instance.backup_background_service_default_notification, - ); + unawaited( + ref + .read(backgroundWorkerFgServiceProvider) + .saveNotificationMessage( + StaticTranslations.instance.uploading_media, + StaticTranslations.instance.backup_background_service_default_notification, + ), + ); } }); @@ -243,7 +245,7 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve @override void reassemble() { if (kDebugMode) { - NetworkRepository.init(); + unawaited(NetworkRepository.init()); } super.reassemble(); } diff --git a/mobile/lib/pages/backup/drift_backup.page.dart b/mobile/lib/pages/backup/drift_backup.page.dart index 793437579a..cc618dbe60 100644 --- a/mobile/lib/pages/backup/drift_backup.page.dart +++ b/mobile/lib/pages/backup/drift_backup.page.dart @@ -43,7 +43,7 @@ class _DriftBackupPageState extends ConsumerState { void initState() { super.initState(); - WakelockPlus.enable(); + unawaited(WakelockPlus.enable()); final currentUser = ref.read(currentUserProvider); if (currentUser == null) { @@ -69,7 +69,7 @@ class _DriftBackupPageState extends ConsumerState { @override void dispose() { super.dispose(); - WakelockPlus.disable(); + unawaited(WakelockPlus.disable()); } @override @@ -111,7 +111,7 @@ class _DriftBackupPageState extends ConsumerState { title: Text("backup_controller_page_backup".t()), leading: IconButton( onPressed: () { - context.maybePop(true); + unawaited(context.maybePop(true)); }, splashRadius: 24, icon: const Icon(Icons.arrow_back_ios_rounded), @@ -119,7 +119,7 @@ class _DriftBackupPageState extends ConsumerState { actions: [ IconButton( onPressed: () { - context.pushRoute(const DriftBackupOptionsRoute()); + unawaited(context.pushRoute(const DriftBackupOptionsRoute())); }, icon: const Icon(Icons.settings_outlined), tooltip: "backup_options".t(context: context), @@ -207,8 +207,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin } } - void showPermissionsDialog() { - showDialog( + Future showPermissionsDialog() { + return showDialog( context: context, builder: (ctx) => AlertDialog( content: Text(context.t.notification_permission_dialog_content), @@ -225,7 +225,7 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin expanded: false, onPressed: () { ContextHelper(context).pop(); - openAppSettings(); + unawaited(openAppSettings()); }, ), ], @@ -233,8 +233,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin ); } - void showBatteryOptimizationInfo() { - showDialog( + Future showBatteryOptimizationInfo() { + return showDialog( context: context, barrierDismissible: false, builder: (BuildContext ctx) { @@ -246,7 +246,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin labelText: context.t.backup_controller_page_background_battery_info_link, variant: .ghost, expanded: false, - onPressed: () => launchUrl(Uri.parse('https://dontkillmyapp.com'), mode: LaunchMode.externalApplication), + onPressed: () => + unawaited(launchUrl(Uri.parse('https://dontkillmyapp.com'), mode: LaunchMode.externalApplication)), ), ImmichTextButton( labelText: context.t.backup_controller_page_background_battery_info_ok, @@ -279,11 +280,13 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), onPressed: () { - ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((p) { - if (p == PermissionStatus.permanentlyDenied) { - showPermissionsDialog(); - } - }); + unawaited( + ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((p) { + if (p == PermissionStatus.permanentlyDenied) { + unawaited(showPermissionsDialog()); + } + }), + ); }, ), if (notificationStatus != PermissionStatus.granted && batteryOptimizationStatus != PermissionStatus.granted) @@ -297,7 +300,7 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin textAlign: TextAlign.left, style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), - onPressed: showBatteryOptimizationInfo, + onPressed: () => unawaited(showBatteryOptimizationInfo()), ), ], TextButton.icon( diff --git a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart index 6589741aab..396f4224a7 100644 --- a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart @@ -214,34 +214,36 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState removeSelection() { + return ref.read(backupAlbumProvider.notifier).deselectAlbum(album); } return Padding( padding: const EdgeInsets.only(right: 8.0), child: GestureDetector( - onTap: removeSelection, + onTap: () => unawaited(removeSelection()), child: AnimatedContainer( duration: const Duration(milliseconds: 200), curve: Curves.easeInOut, @@ -387,7 +389,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget { backgroundColor: context.primaryColor, deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white, deleteIcon: const Icon(Icons.cancel_rounded, size: 15), - onDeleted: removeSelection, + onDeleted: () => unawaited(removeSelection()), ), ), ), @@ -408,12 +410,12 @@ class _ExcludedAlbumNameChips extends ConsumerWidget { children: excludedBackupAlbums.asMap().entries.map((entry) { final album = entry.value; - void removeSelection() { - ref.read(backupAlbumProvider.notifier).deselectAlbum(album); + Future removeSelection() { + return ref.read(backupAlbumProvider.notifier).deselectAlbum(album); } return GestureDetector( - onTap: removeSelection, + onTap: () => unawaited(removeSelection()), child: Padding( padding: const EdgeInsets.only(right: 8.0), child: AnimatedContainer( @@ -427,7 +429,7 @@ class _ExcludedAlbumNameChips extends ConsumerWidget { backgroundColor: Colors.red[300], deleteIconColor: context.scaffoldBackgroundColor, deleteIcon: const Icon(Icons.cancel_rounded, size: 15), - onDeleted: removeSelection, + onDeleted: () => unawaited(removeSelection()), ), ), ), @@ -457,7 +459,7 @@ class _SelectAllButton extends ConsumerWidget { ? () { for (final album in filteredAlbums) { if (album.backupSelection != BackupSelection.selected) { - ref.read(backupAlbumProvider.notifier).selectAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).selectAlbum(album)); } } } @@ -477,7 +479,7 @@ class _SelectAllButton extends ConsumerWidget { ? () { for (final album in filteredAlbums) { if (album.backupSelection == BackupSelection.selected) { - ref.read(backupAlbumProvider.notifier).deselectAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).deselectAlbum(album)); } } } diff --git a/mobile/lib/pages/common/app_log.page.dart b/mobile/lib/pages/common/app_log.page.dart index 5458d90808..b04d8dc926 100644 --- a/mobile/lib/pages/common/app_log.page.dart +++ b/mobile/lib/pages/common/app_log.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -61,7 +63,7 @@ class AppLogPage extends HookConsumerWidget { size: 20.0, ), onPressed: () { - immichLogger.clearLogs(); + unawaited(immichLogger.clearLogs()); shouldReload.value = !shouldReload.value; }, ), @@ -70,7 +72,7 @@ class AppLogPage extends HookConsumerWidget { return IconButton( icon: Icon(Icons.share_rounded, color: context.primaryColor, semanticLabel: "Share logs", size: 20.0), onPressed: () { - ImmichLogger.shareLogs(iconContext); + unawaited(ImmichLogger.shareLogs(iconContext)); }, ); }, @@ -78,7 +80,7 @@ class AppLogPage extends HookConsumerWidget { ], leading: IconButton( onPressed: () { - context.maybePop(); + unawaited(context.maybePop()); }, icon: const Icon(Icons.arrow_back_ios_new_rounded, size: 20.0), ), diff --git a/mobile/lib/pages/common/app_log_detail.page.dart b/mobile/lib/pages/common/app_log_detail.page.dart index ab7668f845..330ca51075 100644 --- a/mobile/lib/pages/common/app_log_detail.page.dart +++ b/mobile/lib/pages/common/app_log_detail.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -33,16 +35,18 @@ class AppLogDetailPage extends HookConsumerWidget { ), IconButton( onPressed: () { - Clipboard.setData(ClipboardData(text: text)).then((_) { - context.scaffoldMessenger.showSnackBar( - SnackBar( - content: Text( - "copied_to_clipboard".tr(), - style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), + unawaited( + Clipboard.setData(ClipboardData(text: text)).then((_) { + context.scaffoldMessenger.showSnackBar( + SnackBar( + content: Text( + "copied_to_clipboard".tr(), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), + ), ), - ), - ); - }); + ); + }), + ); }, icon: Icon(Icons.copy, size: 16.0, color: context.primaryColor), ), diff --git a/mobile/lib/pages/common/download_panel.dart b/mobile/lib/pages/common/download_panel.dart index f39aa07166..267d32fc3d 100644 --- a/mobile/lib/pages/common/download_panel.dart +++ b/mobile/lib/pages/common/download_panel.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:background_downloader/background_downloader.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -15,7 +17,7 @@ class DownloadPanel extends ConsumerWidget { final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList(); void onCancelDownload(String id) { - ref.watch(downloadStateProvider.notifier).cancelDownload(id); + unawaited(ref.watch(downloadStateProvider.notifier).cancelDownload(id)); } return Positioned( diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 711783bc94..4c417cc87c 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -282,11 +282,13 @@ class SplashScreenPageState extends ConsumerState { @override void initState() { super.initState(); - ref - .read(authProvider.notifier) - .setOpenApiServiceEndpoint() - .then(logConnectionInfo) - .whenComplete(() => resumeSession()); + unawaited( + ref + .read(authProvider.notifier) + .setOpenApiServiceEndpoint() + .then(logConnectionInfo) + .whenComplete(() => resumeSession()), + ); } void logConnectionInfo(String? endpoint) { @@ -327,7 +329,7 @@ class SplashScreenPageState extends ConsumerState { if (syncSuccess) { await Future.wait([ backgroundManager.hashAssets().then((_) { - _resumeBackup(backupProvider); + unawaited(_resumeBackup(backupProvider)); }), _resumeBackup(backupProvider), // TODO: Bring back when the soft freeze issue is addressed diff --git a/mobile/lib/pages/common/tab_shell.page.dart b/mobile/lib/pages/common/tab_shell.page.dart index 2fdcec4054..f834e4ac51 100644 --- a/mobile/lib/pages/common/tab_shell.page.dart +++ b/mobile/lib/pages/common/tab_shell.page.dart @@ -126,7 +126,7 @@ void _onNavigationSelected(TabsRouter router, int index, WidgetRef ref) { // Album page if (index == kAlbumTabIndex) { - ref.read(remoteAlbumProvider.notifier).refresh(); + unawaited(ref.read(remoteAlbumProvider.notifier).refresh()); } // Library page @@ -168,7 +168,7 @@ class _BottomNavigationBarState extends ConsumerState<_BottomNavigationBar> { @override void dispose() { - _eventSubscription?.cancel(); + unawaited(_eventSubscription?.cancel()); super.dispose(); } diff --git a/mobile/lib/pages/library/folder/folder.page.dart b/mobile/lib/pages/library/folder/folder.page.dart index 6934d7b6c5..69631efe4e 100644 --- a/mobile/lib/pages/library/folder/folder.page.dart +++ b/mobile/lib/pages/library/folder/folder.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -53,7 +55,7 @@ class FolderPage extends HookConsumerWidget { useEffect(() { if (folder == null) { - ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value); + unawaited(ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value)); } return null; }, []); @@ -72,7 +74,7 @@ class FolderPage extends HookConsumerWidget { void onToggleSortOrder() { final newOrder = sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc; - ref.read(folderStructureProvider.notifier).fetchFolders(newOrder); + unawaited(ref.read(folderStructureProvider.notifier).fetchFolders(newOrder)); sortOrder.value = newOrder; } @@ -118,7 +120,7 @@ class FolderContent extends HookConsumerWidget { if (folder == null) { return; } - ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder); + unawaited(ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder)); return null; }, [folder]); @@ -176,12 +178,14 @@ class FolderContent extends HookConsumerWidget { (index, asset) => LargeLeadingTile( onTap: () { AssetViewer.setAsset(ref, asset); - context.pushRoute( - AssetViewerRoute( - initialIndex: index, - timelineService: ref - .read(timelineFactoryProvider) - .fromAssets(folderAssets, TimelineOrigin.folder), + unawaited( + context.pushRoute( + AssetViewerRoute( + initialIndex: index, + timelineService: ref + .read(timelineFactoryProvider) + .fromAssets(folderAssets, TimelineOrigin.folder), + ), ), ); }, diff --git a/mobile/lib/pages/library/locked/pin_auth.page.dart b/mobile/lib/pages/library/locked/pin_auth.page.dart index 7beda1d47b..2da9a8ddab 100644 --- a/mobile/lib/pages/library/locked/pin_auth.page.dart +++ b/mobile/lib/pages/library/locked/pin_auth.page.dart @@ -38,8 +38,8 @@ class PinAuthPage extends HookConsumerWidget { } } - void enableBiometricAuth() { - showDialog( + Future enableBiometricAuth() { + return showDialog( context: context, builder: (buildContext) { return SimpleDialog( @@ -53,7 +53,7 @@ class PinAuthPage extends HookConsumerWidget { description: 'enable_biometric_auth_description'.tr(), onSuccess: (pinCode) { Navigator.pop(buildContext); - registerBiometric(pinCode); + unawaited(registerBiometric(pinCode)); }, autoFocus: true, icon: Icons.fingerprint_rounded, @@ -83,7 +83,7 @@ class PinAuthPage extends HookConsumerWidget { child: PinVerificationForm( autoFocus: true, onSuccess: (_) { - context.replaceRoute(const DriftLockedFolderRoute()); + unawaited(context.replaceRoute(const DriftLockedFolderRoute())); }, ), ), @@ -93,7 +93,7 @@ class PinAuthPage extends HookConsumerWidget { padding: const EdgeInsets.only(right: 16.0), child: TextButton.icon( icon: const Icon(Icons.fingerprint, size: 28), - onPressed: enableBiometricAuth, + onPressed: () => unawaited(enableBiometricAuth()), label: Text( 'use_biometric'.tr(), style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor, fontSize: 18), diff --git a/mobile/lib/pages/library/shared_link/shared_link.page.dart b/mobile/lib/pages/library/shared_link/shared_link.page.dart index a4f52ebd4c..18fc235dd8 100644 --- a/mobile/lib/pages/library/shared_link/shared_link.page.dart +++ b/mobile/lib/pages/library/shared_link/shared_link.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -17,7 +19,7 @@ class SharedLinkPage extends HookConsumerWidget { final sharedLinks = ref.watch(sharedLinksStateProvider); useEffect(() { - ref.read(sharedLinksStateProvider.notifier).fetchLinks(); + unawaited(ref.read(sharedLinksStateProvider.notifier).fetchLinks()); return () { if (!context.mounted) { return; diff --git a/mobile/lib/pages/login/login.page.dart b/mobile/lib/pages/login/login.page.dart index 79091d2679..e225c4c066 100644 --- a/mobile/lib/pages/login/login.page.dart +++ b/mobile/lib/pages/login/login.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -22,7 +24,7 @@ class LoginPage extends HookConsumerWidget { } useEffect(() { - getAppInfo(); + unawaited(getAppInfo()); return null; }); @@ -55,7 +57,7 @@ class LoginPage extends HookConsumerWidget { ), ), onTap: () { - context.pushRoute(const AppLogRoute()); + unawaited(context.pushRoute(const AppLogRoute())); }, ), ], diff --git a/mobile/lib/pages/search/map/map_location_picker.page.dart b/mobile/lib/pages/search/map/map_location_picker.page.dart index 96f41a4d38..bb848b24bc 100644 --- a/mobile/lib/pages/search/map/map_location_picker.page.dart +++ b/mobile/lib/pages/search/map/map_location_picker.page.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math'; import 'package:auto_route/auto_route.dart'; @@ -37,7 +38,7 @@ class MapLocationPickerPage extends HookConsumerWidget { } void onClose([LatLng? selected]) { - context.maybePop(selected); + unawaited(context.maybePop(selected)); } Future getCurrentLocation() async { diff --git a/mobile/lib/pages/share_intent/share_intent.page.dart b/mobile/lib/pages/share_intent/share_intent.page.dart index ec88c4a9e4..db5e583d7a 100644 --- a/mobile/lib/pages/share_intent/share_intent.page.dart +++ b/mobile/lib/pages/share_intent/share_intent.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -65,7 +67,7 @@ class ShareIntentPage extends ConsumerWidget { ), leading: IconButton( onPressed: () { - context.navigateTo(const TabShellRoute()); + unawaited(context.navigateTo(const TabShellRoute())); }, icon: const Icon(Icons.arrow_back), ), diff --git a/mobile/lib/presentation/pages/download_info.page.dart b/mobile/lib/presentation/pages/download_info.page.dart index af44714b83..c2c63c7860 100644 --- a/mobile/lib/presentation/pages/download_info.page.dart +++ b/mobile/lib/presentation/pages/download_info.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -15,7 +17,7 @@ class DownloadInfoPage extends ConsumerWidget { final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList(); void onCancelDownload(String id) { - ref.watch(downloadStateProvider.notifier).cancelDownload(id); + unawaited(ref.watch(downloadStateProvider.notifier).cancelDownload(id)); } return Scaffold( diff --git a/mobile/lib/presentation/pages/drift_activities.page.dart b/mobile/lib/presentation/pages/drift_activities.page.dart index 59c9a8a1e1..ebf7c2efa7 100644 --- a/mobile/lib/presentation/pages/drift_activities.page.dart +++ b/mobile/lib/presentation/pages/drift_activities.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; @@ -25,13 +27,17 @@ class DriftActivitiesPage extends HookConsumerWidget { final activities = ref.watch(albumActivityProvider((album.id, assetId))); final listViewScrollController = useScrollController(); - void scrollToBottom() { - listViewScrollController.animateTo(0, duration: const Duration(milliseconds: 300), curve: Curves.fastOutSlowIn); + Future scrollToBottom() { + return listViewScrollController.animateTo( + 0, + duration: const Duration(milliseconds: 300), + curve: Curves.fastOutSlowIn, + ); } Future onAddComment(String comment) async { await activityNotifier.addComment(comment); - scrollToBottom(); + unawaited(scrollToBottom()); } return ProviderScope( diff --git a/mobile/lib/presentation/pages/drift_album.page.dart b/mobile/lib/presentation/pages/drift_album.page.dart index 47a4625f87..ab91b6f3c8 100644 --- a/mobile/lib/presentation/pages/drift_album.page.dart +++ b/mobile/lib/presentation/pages/drift_album.page.dart @@ -53,7 +53,7 @@ class _DriftAlbumsPageState extends ConsumerState { ), AlbumSelector( onAlbumSelected: (album) { - context.router.push(RemoteAlbumRoute(album: album)); + unawaited(context.router.push(RemoteAlbumRoute(album: album))); }, ), ], diff --git a/mobile/lib/presentation/pages/drift_album_options.page.dart b/mobile/lib/presentation/pages/drift_album_options.page.dart index 84060aa38c..37c0273fae 100644 --- a/mobile/lib/presentation/pages/drift_album_options.page.dart +++ b/mobile/lib/presentation/pages/drift_album_options.page.dart @@ -110,18 +110,20 @@ class DriftAlbumOptionsPage extends HookConsumerWidget { ]; } - showModalBottomSheet( - backgroundColor: context.colorScheme.surfaceContainer, - isScrollControlled: false, - context: context, - builder: (context) { - return SafeArea( - child: Padding( - padding: const EdgeInsets.only(top: 24.0), - child: Column(mainAxisSize: MainAxisSize.min, children: [...actions]), - ), - ); - }, + unawaited( + showModalBottomSheet( + backgroundColor: context.colorScheme.surfaceContainer, + isScrollControlled: false, + context: context, + builder: (context) { + return SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 24.0), + child: Column(mainAxisSize: MainAxisSize.min, children: [...actions]), + ), + ); + }, + ), ); } diff --git a/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart index 3e5b603451..cee0cdc334 100644 --- a/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart +++ b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -78,11 +80,13 @@ class _AssetPropertiesSectionState extends ConsumerState<_AssetPropertiesSection @override void initState() { super.initState(); - _buildAssetProperties(widget.asset).whenComplete(() { - if (mounted) { - setState(() {}); - } - }); + unawaited( + _buildAssetProperties(widget.asset).whenComplete(() { + if (mounted) { + setState(() {}); + } + }), + ); } @override diff --git a/mobile/lib/presentation/pages/drift_locked_folder.page.dart b/mobile/lib/presentation/pages/drift_locked_folder.page.dart index 9849558c94..e8130f7059 100644 --- a/mobile/lib/presentation/pages/drift_locked_folder.page.dart +++ b/mobile/lib/presentation/pages/drift_locked_folder.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -39,8 +41,8 @@ class _DriftLockedFolderPageState extends ConsumerState w return; } if (state == AppLifecycleState.paused) { - ref.read(authProvider.notifier).lockPinCode(); - context.navigateTo(const TabShellRoute()); + unawaited(ref.read(authProvider.notifier).lockPinCode()); + unawaited(context.navigateTo(const TabShellRoute())); return; } setState(() { diff --git a/mobile/lib/presentation/pages/drift_map.page.dart b/mobile/lib/presentation/pages/drift_map.page.dart index 97062b88ab..d36ccc350c 100644 --- a/mobile/lib/presentation/pages/drift_map.page.dart +++ b/mobile/lib/presentation/pages/drift_map.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -11,8 +13,8 @@ class DriftMapPage extends StatelessWidget { const DriftMapPage({super.key, this.initialLocation}); - void onSettingsPressed(BuildContext context) { - showModalBottomSheet( + Future onSettingsPressed(BuildContext context) { + return showModalBottomSheet( elevation: 0.0, showDragHandle: true, isScrollControlled: true, diff --git a/mobile/lib/presentation/pages/drift_memory.page.dart b/mobile/lib/presentation/pages/drift_memory.page.dart index b8f3c94a00..31371fe581 100644 --- a/mobile/lib/presentation/pages/drift_memory.page.dart +++ b/mobile/lib/presentation/pages/drift_memory.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -47,21 +49,21 @@ class DriftMemoryPage extends HookConsumerWidget { useEffect(() { // Memories is an immersive activity - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + unawaited(SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive)); return () { // Clean up to normal edge to edge when we are done - restoreEdgeToEdge(); + unawaited(restoreEdgeToEdge()); }; }); void toNextMemory() { - memoryPageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); + unawaited(memoryPageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn)); } void toPreviousMemory() { if (currentMemoryIndex.value > 0) { // Move to the previous memory page - memoryPageController.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); + unawaited(memoryPageController.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn)); // Wait for the next frame to ensure the page is built SchedulerBinding.instance.addPostFrameCallback((_) { @@ -88,7 +90,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Go to the next asset final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.nextPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); + unawaited(controller.nextPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500))); } else { // Go to the next memory since we are at the end of our assets toNextMemory(); @@ -100,7 +102,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Go to the previous asset final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.previousPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); + unawaited(controller.previousPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500))); } else { // Go to the previous memory since we are at the end of our assets toPreviousMemory(); @@ -153,7 +155,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Precache the next page right away if we are on the first page if (currentAssetPage.value == 0) { - Future.delayed(const Duration(milliseconds: 200)).then((_) => precacheAsset(1)); + unawaited(Future.delayed(const Duration(milliseconds: 200)).then((_) => precacheAsset(1))); } Future onAssetChanged(int otherIndex) async { @@ -198,7 +200,7 @@ class DriftMemoryPage extends HookConsumerWidget { final offset = notification.metrics.pixels; if (isEpiloguePage && (offset > notification.metrics.maxScrollExtent + 150)) { - context.maybePop(); + unawaited(context.maybePop()); return true; } } @@ -328,8 +330,8 @@ class DriftMemoryPage extends HookConsumerWidget { // auto_route doesn't invoke pop scope, so // turn off full screen mode here // https://github.com/Milad-Akarie/auto_route_library/issues/1799 - context.maybePop(); - restoreEdgeToEdge(); + unawaited(context.maybePop()); + unawaited(restoreEdgeToEdge()); }, shape: const CircleBorder(), color: Colors.white.withValues(alpha: 0.2), diff --git a/mobile/lib/presentation/pages/drift_people_collection.page.dart b/mobile/lib/presentation/pages/drift_people_collection.page.dart index f39b5e15c7..416b7d587a 100644 --- a/mobile/lib/presentation/pages/drift_people_collection.page.dart +++ b/mobile/lib/presentation/pages/drift_people_collection.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -86,7 +88,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState { } } - void showOptionSheet(BuildContext context) { - showModalBottomSheet( + Future showOptionSheet(BuildContext context) { + return showModalBottomSheet( context: context, backgroundColor: context.colorScheme.surface, isScrollControlled: false, diff --git a/mobile/lib/presentation/pages/drift_slideshow.page.dart b/mobile/lib/presentation/pages/drift_slideshow.page.dart index 9b7c10c891..81c09bea67 100644 --- a/mobile/lib/presentation/pages/drift_slideshow.page.dart +++ b/mobile/lib/presentation/pages/drift_slideshow.page.dart @@ -67,7 +67,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si _updateNextIndex(); ref.listenManual(appConfigProvider.select((s) => s.slideshow), _onConfigChanged); - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + unawaited(SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive)); unawaited(WakelockPlus.enable()); } @@ -94,9 +94,9 @@ class _DriftSlideshowPageState extends ConsumerState with Si if (asset.isImage) { _createTimer(); } else if (ref.read(videoPlayerProvider(asset.heroTag)).status == VideoPlaybackStatus.paused) { - ref.read(videoPlayerProvider(asset.heroTag).notifier).play(); + unawaited(ref.read(videoPlayerProvider(asset.heroTag).notifier).play()); } else { - _nextPage(); + unawaited(_nextPage()); } _updateNextIndex(); @@ -113,7 +113,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si final asset = widget.timeline.getAssetSafe(_index)!; if (!asset.isImage) { - ref.read(videoPlayerProvider(asset.heroTag).notifier).pause(); + unawaited(ref.read(videoPlayerProvider(asset.heroTag).notifier).pause()); } setState(() { @@ -147,7 +147,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si }; if (!widget.timeline.hasRange(_nextIndex, 1)) { - widget.timeline.preloadAssets(_nextIndex); + unawaited(widget.timeline.preloadAssets(_nextIndex)); } } @@ -184,14 +184,16 @@ class _DriftSlideshowPageState extends ConsumerState with Si _crossfadeFromIndex = previousIndex; _crossfadeToIndex = page; }); - _crossfadeController.forward(from: 0.0).whenComplete(() { - if (mounted) { - setState(() { - _crossfadeFromIndex = null; - _crossfadeToIndex = null; - }); - } - }); + unawaited( + _crossfadeController.forward(from: 0.0).whenComplete(() { + if (mounted) { + setState(() { + _crossfadeFromIndex = null; + _crossfadeToIndex = null; + }); + } + }), + ); } Widget _getCrossfadeLayer(BuildContext context, int index, {required bool isIncoming}) { @@ -238,7 +240,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si _timer = Timer(Duration(milliseconds: _config.duration * 1000 - _stopwatch.elapsedMilliseconds), () { _stopwatch.stop(); _stopwatch.reset(); - _nextPage(); + unawaited(_nextPage()); }); _stopwatch.start(); @@ -376,9 +378,9 @@ class _DriftSlideshowPageState extends ConsumerState with Si final position = ref.read(videoPlayerProvider(asset.heroTag)).position; if (status == VideoPlaybackStatus.completed && isCurrent && position.inMicroseconds > 0) { - _nextPage(); + unawaited(_nextPage()); } else if (status == VideoPlaybackStatus.playing) { - ref.read(videoPlayerProvider(asset.heroTag).notifier).setLoop(false); + unawaited(ref.read(videoPlayerProvider(asset.heroTag).notifier).setLoop(false)); } return PhotoView.customChild( @@ -418,7 +420,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si IconButton( onPressed: () { _pause(); - context.pushRoute(SettingsSubRoute(section: SettingSection.assetViewer)); + unawaited(context.pushRoute(SettingsSubRoute(section: SettingSection.assetViewer))); }, icon: const Icon(Icons.settings), ), @@ -512,7 +514,7 @@ class _SlideshowProgressBarState extends State<_SlideshowProgressBar> with Singl animationBehavior: AnimationBehavior.preserve, )..value = (widget.elapsedMs / widget.durationMs).clamp(0.0, 1.0); if (!widget.paused) { - _controller.forward(); + unawaited(_controller.forward()); } } diff --git a/mobile/lib/presentation/pages/drift_user_selection.page.dart b/mobile/lib/presentation/pages/drift_user_selection.page.dart index 41394014a0..19a450b435 100644 --- a/mobile/lib/presentation/pages/drift_user_selection.page.dart +++ b/mobile/lib/presentation/pages/drift_user_selection.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -53,7 +55,7 @@ class DriftUserSelectionPage extends HookConsumerWidget { final sharedUsersList = useState>({}); void addNewUsersHandler() { - context.maybePop(sharedUsersList.value.map((e) => e.id).toList()); + unawaited(context.maybePop(sharedUsersList.value.map((e) => e.id).toList())); } Widget buildTileIcon(UserDto user) { @@ -122,12 +124,12 @@ class DriftUserSelectionPage extends HookConsumerWidget { leading: IconButton( icon: const Icon(Icons.close_rounded), onPressed: () { - context.maybePop(null); + unawaited(context.maybePop(null)); }, ), actions: [ TextButton( - onPressed: sharedUsersList.value.isEmpty ? null : addNewUsersHandler, + onPressed: sharedUsersList.value.isEmpty ? null : () => addNewUsersHandler(), child: const Text("add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(), ), ], diff --git a/mobile/lib/presentation/pages/search/drift_search.page.dart b/mobile/lib/presentation/pages/search/drift_search.page.dart index 4d04967b28..8d6122804a 100644 --- a/mobile/lib/presentation/pages/search/drift_search.page.dart +++ b/mobile/lib/presentation/pages/search/drift_search.page.dart @@ -105,20 +105,22 @@ class DriftSearchPage extends HookConsumerWidget { return null; } - Future.microtask(() { - textSearchController.clear(); - peopleCurrentFilterWidget.value = null; - dateRangeCurrentFilterWidget.value = null; - cameraCurrentFilterWidget.value = null; - tagCurrentFilterWidget.value = null; - mediaTypeCurrentFilterWidget.value = null; - ratingCurrentFilterWidget.value = null; - displayOptionCurrentFilterWidget.value = null; - locationCurrentFilterWidget.value = preFilter.location.city != null - ? Text(preFilter.location.city!, style: context.textTheme.labelLarge) - : null; - search(preFilter); - }); + unawaited( + Future.microtask(() { + textSearchController.clear(); + peopleCurrentFilterWidget.value = null; + dateRangeCurrentFilterWidget.value = null; + cameraCurrentFilterWidget.value = null; + tagCurrentFilterWidget.value = null; + mediaTypeCurrentFilterWidget.value = null; + ratingCurrentFilterWidget.value = null; + displayOptionCurrentFilterWidget.value = null; + locationCurrentFilterWidget.value = preFilter.location.city != null + ? Text(preFilter.location.city!, style: context.textTheme.labelLarge) + : null; + search(preFilter); + }), + ); return null; }, [preFilter]); @@ -141,17 +143,19 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(people: people)); } - showFilterBottomSheet( - context: context, - isScrollControlled: true, - child: FractionallySizedBox( - heightFactor: 0.8, - child: FilterBottomSheetScaffold( - title: 'search_filter_people_title'.t(context: context), - expanded: true, - onSearch: handleApply, - onClear: handleClear, - child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people), + unawaited( + showFilterBottomSheet( + context: context, + isScrollControlled: true, + child: FractionallySizedBox( + heightFactor: 0.8, + child: FilterBottomSheetScaffold( + title: 'search_filter_people_title'.t(context: context), + expanded: true, + onSearch: handleApply, + onClear: handleClear, + child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people), + ), ), ), ); @@ -176,17 +180,19 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(tagIds: tagIds)); } - showFilterBottomSheet( - context: context, - isScrollControlled: true, - child: FractionallySizedBox( - heightFactor: 0.8, - child: FilterBottomSheetScaffold( - title: 'search_filter_tags_title'.t(context: context), - expanded: true, - onSearch: handleApply, - onClear: handleClear, - child: TagPicker(onSelectExistingTag: handleOnSelect, filter: (filter.value.tagIds ?? []).toSet()), + unawaited( + showFilterBottomSheet( + context: context, + isScrollControlled: true, + child: FractionallySizedBox( + heightFactor: 0.8, + child: FilterBottomSheetScaffold( + title: 'search_filter_tags_title'.t(context: context), + expanded: true, + onSearch: handleApply, + onClear: handleClear, + child: TagPicker(onSelectExistingTag: handleOnSelect, filter: (filter.value.tagIds ?? []).toSet()), + ), ), ), ); @@ -216,21 +222,23 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(location: location)); } - showFilterBottomSheet( - context: context, - isScrollControlled: true, - isDismissible: true, - child: FilterBottomSheetScaffold( - title: 'search_filter_location_title'.t(context: context), - onSearch: handleApply, - onClear: handleClear, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: Container( - padding: EdgeInsets.only(bottom: context.viewInsets.bottom), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: LocationPicker(onSelected: handleOnSelect, filter: filter.value.location), + unawaited( + showFilterBottomSheet( + context: context, + isScrollControlled: true, + isDismissible: true, + child: FilterBottomSheetScaffold( + title: 'search_filter_location_title'.t(context: context), + onSearch: handleApply, + onClear: handleClear, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Container( + padding: EdgeInsets.only(bottom: context.viewInsets.bottom), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: LocationPicker(onSelected: handleOnSelect, filter: filter.value.location), + ), ), ), ), @@ -259,17 +267,19 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(camera: camera)); } - showFilterBottomSheet( - context: context, - isScrollControlled: true, - isDismissible: true, - child: FilterBottomSheetScaffold( - title: 'search_filter_camera_title'.t(context: context), - onSearch: handleApply, - onClear: handleClear, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera), + unawaited( + showFilterBottomSheet( + context: context, + isScrollControlled: true, + isDismissible: true, + child: FilterBottomSheetScaffold( + title: 'search_filter_camera_title'.t(context: context), + onSearch: handleApply, + onClear: handleClear, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera), + ), ), ), ); @@ -339,22 +349,24 @@ class DriftSearchPage extends HookConsumerWidget { } void showQuickDatePicker() { - showFilterBottomSheet( - context: context, - child: FilterBottomSheetScaffold( - title: "pick_date_range".tr(), - expanded: true, - onClear: () => datePicked(null), - child: QuickDatePicker( - currentInput: dateInputFilter.value, - onRequestPicker: () { - ContextHelper(context).pop(); - showDatePicker(); - }, - onSelect: (date) { - ContextHelper(context).pop(); - datePicked(date); - }, + unawaited( + showFilterBottomSheet( + context: context, + child: FilterBottomSheetScaffold( + title: "pick_date_range".tr(), + expanded: true, + onClear: () => datePicked(null), + child: QuickDatePicker( + currentInput: dateInputFilter.value, + onRequestPicker: () { + ContextHelper(context).pop(); + unawaited(showDatePicker()); + }, + onSelect: (date) { + ContextHelper(context).pop(); + datePicked(date); + }, + ), ), ), ); @@ -383,13 +395,15 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(mediaType: mediaType)); } - showFilterBottomSheet( - context: context, - child: FilterBottomSheetScaffold( - title: 'search_filter_media_type_title'.t(context: context), - onSearch: handleApply, - onClear: handleClear, - child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType), + unawaited( + showFilterBottomSheet( + context: context, + child: FilterBottomSheetScaffold( + title: 'search_filter_media_type_title'.t(context: context), + onSearch: handleApply, + onClear: handleClear, + child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType), + ), ), ); } @@ -417,14 +431,16 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(rating: rating)); } - showFilterBottomSheet( - context: context, - isScrollControlled: true, - child: FilterBottomSheetScaffold( - title: 'rating'.t(context: context), - onSearch: handleApply, - onClear: handleClear, - child: StarRatingPicker(onSelect: handleOnSelected, filter: filter.value.rating), + unawaited( + showFilterBottomSheet( + context: context, + isScrollControlled: true, + child: FilterBottomSheetScaffold( + title: 'rating'.t(context: context), + onSearch: handleApply, + onClear: handleClear, + child: StarRatingPicker(onSelect: handleOnSelected, filter: filter.value.rating), + ), ), ); } @@ -462,13 +478,15 @@ class DriftSearchPage extends HookConsumerWidget { search(filter.value.copyWith(display: display)); } - showFilterBottomSheet( - context: context, - child: FilterBottomSheetScaffold( - title: 'display_options'.t(context: context), - onSearch: handleApply, - onClear: handleClear, - child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display), + unawaited( + showFilterBottomSheet( + context: context, + child: FilterBottomSheetScaffold( + title: 'display_options'.t(context: context), + onSearch: handleApply, + onClear: handleClear, + child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display), + ), ), ); } @@ -697,7 +715,7 @@ class DriftSearchPage extends HookConsumerWidget { if (filter.value.isEmpty) const _SearchSuggestions() else - _SearchResultGrid(onScrollEnd: loadMoreSearchResults), + _SearchResultGrid(onScrollEnd: () => loadMoreSearchResults()), ], ), ); diff --git a/mobile/lib/presentation/pages/search/paginated_search.provider.dart b/mobile/lib/presentation/pages/search/paginated_search.provider.dart index fa2d5a06cf..e9839f31ea 100644 --- a/mobile/lib/presentation/pages/search/paginated_search.provider.dart +++ b/mobile/lib/presentation/pages/search/paginated_search.provider.dart @@ -70,7 +70,7 @@ class PaginatedSearchNotifier extends StateNotifier { @override void dispose() { - _assetCountController.close(); + unawaited(_assetCountController.close()); super.dispose(); } } diff --git a/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart index 86d3fa0749..bcd3b20df6 100644 --- a/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -36,11 +38,11 @@ class _AddActionButtonState extends ConsumerState { case AddToMenuItem.album: _openAlbumSelector(); case AddToMenuItem.archive: - performArchiveAction(context, ref, source: ActionSource.viewer); + unawaited(performArchiveAction(context, ref, source: ActionSource.viewer)); case AddToMenuItem.unarchive: - performUnArchiveAction(context, ref, source: ActionSource.viewer); + unawaited(performUnArchiveAction(context, ref, source: ActionSource.viewer)); case AddToMenuItem.lockedFolder: - performMoveToLockFolderAction(context, ref, source: ActionSource.viewer); + unawaited(performMoveToLockFolderAction(context, ref, source: ActionSource.viewer)); } } @@ -112,21 +114,23 @@ class _AddActionButtonState extends ConsumerState { AlbumSelector(onAlbumSelected: (album) => _addCurrentAssetToAlbum(album)), ]; - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (_) { - return BaseBottomSheet( - actions: const [], - slivers: slivers, - initialChildSize: 0.6, - minChildSize: 0.3, - maxChildSize: 0.95, - expand: false, - backgroundColor: context.isDarkTheme ? Colors.black : Colors.white, - ); - }, + unawaited( + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) { + return BaseBottomSheet( + actions: const [], + slivers: slivers, + initialChildSize: 0.6, + minChildSize: 0.3, + maxChildSize: 0.95, + expand: false, + backgroundColor: context.isDarkTheme ? Colors.black : Colors.white, + ); + }, + ), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart index 7a4f84fb4f..9465f50500 100644 --- a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -21,7 +23,7 @@ class CastActionButton extends ConsumerWidget { iconColor: isCasting ? context.primaryColor : null, // null = default color label: "cast".t(context: context), onPressed: () { - showDialog(context: context, builder: (context) => const CastDialog()); + unawaited(showDialog(context: context, builder: (context) => const CastDialog())); }, iconOnly: iconOnly, menuItem: menuItem, diff --git a/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart index efa7f5c6d0..264e489db3 100644 --- a/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -33,7 +35,7 @@ class DownloadStatusFloatingButton extends ConsumerWidget { : context.colorScheme.surfaceBright, elevation: 2, onPressed: () { - context.pushRoute(const DownloadInfoRoute()); + unawaited(context.pushRoute(const DownloadInfoRoute())); }, child: Stack( alignment: AlignmentDirectional.center, diff --git a/mobile/lib/presentation/widgets/action_buttons/set_profile_picture_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/set_profile_picture_action_button.widget.dart index c8dbb7cb1f..5b41715022 100644 --- a/mobile/lib/presentation/widgets/action_buttons/set_profile_picture_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/set_profile_picture_action_button.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -13,12 +15,12 @@ class SetProfilePictureActionButton extends ConsumerWidget { const SetProfilePictureActionButton({super.key, required this.asset, this.iconOnly = false, this.menuItem = false}); - void _onTap(BuildContext context) { + Future _onTap(BuildContext context) async { if (!context.mounted) { return; } - context.pushRoute(ProfilePictureCropRoute(asset: asset)); + await context.pushRoute(ProfilePictureCropRoute(asset: asset)); } @override @@ -28,7 +30,7 @@ class SetProfilePictureActionButton extends ConsumerWidget { label: "set_as_profile_picture".t(context: context), iconOnly: iconOnly, menuItem: menuItem, - onPressed: () => _onTap(context), + onPressed: () => unawaited(_onTap(context)), maxWidth: 100, ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart index ef520ea941..eadcf0a81e 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart @@ -138,31 +138,33 @@ class ShareActionButton extends ConsumerWidget { await showDialog( context: context, builder: (BuildContext buildContext) { - ref - .read(actionProvider.notifier) - .shareAssets( - source, - context, - fileType: fileType, - cancelCompleter: cancelCompleter, - onAssetDownloadProgress: (value) => progress.value = value, - ) - .then((ActionResult result) { - if (cancelCompleter.isCompleted || !context.mounted) { - return; - } + unawaited( + ref + .read(actionProvider.notifier) + .shareAssets( + source, + context, + fileType: fileType, + cancelCompleter: cancelCompleter, + onAssetDownloadProgress: (value) => progress.value = value, + ) + .then((ActionResult result) { + if (cancelCompleter.isCompleted || !context.mounted) { + return; + } - if (!result.success) { - ImmichToast.show( - context: context, - msg: context.t.scaffold_body_error_occurred, - gravity: ToastGravity.BOTTOM, - toastType: ToastType.error, - ); - } + if (!result.success) { + ImmichToast.show( + context: context, + msg: context.t.scaffold_body_error_occurred, + gravity: ToastGravity.BOTTOM, + toastType: ToastType.error, + ); + } - buildContext.pop(); - }); + buildContext.pop(); + }), + ); return preparingDialog; }, diff --git a/mobile/lib/presentation/widgets/action_buttons/slideshow_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/slideshow_action_button.widget.dart index 479cf2dfe9..fdbc7a8cda 100644 --- a/mobile/lib/presentation/widgets/action_buttons/slideshow_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/slideshow_action_button.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -12,12 +14,12 @@ class SlideshowActionButton extends ConsumerWidget { const SlideshowActionButton({super.key, this.iconOnly = false, this.menuItem = false}); - void _onTap(BuildContext context, WidgetRef ref) { + Future _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { return; } - context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider))); + await context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider))); } @override @@ -27,7 +29,7 @@ class SlideshowActionButton extends ConsumerWidget { label: "slideshow".t(context: context), iconOnly: iconOnly, menuItem: menuItem, - onPressed: () => _onTap(context, ref), + onPressed: () => unawaited(_onTap(context, ref)), maxWidth: 100, ); } diff --git a/mobile/lib/presentation/widgets/album/album_selector.widget.dart b/mobile/lib/presentation/widgets/album/album_selector.widget.dart index ba6c6da560..bf5de5611d 100644 --- a/mobile/lib/presentation/widgets/album/album_selector.widget.dart +++ b/mobile/lib/presentation/widgets/album/album_selector.widget.dart @@ -63,7 +63,7 @@ class _AlbumSelectorState extends ConsumerState { isGrid = albumConfig.isGrid; }); - ref.read(remoteAlbumProvider.notifier).refresh(); + unawaited(ref.read(remoteAlbumProvider.notifier).refresh()); }); searchController.addListener(() { @@ -81,7 +81,7 @@ class _AlbumSelectorState extends ConsumerState { final userId = ref.read(currentUserProvider)?.id; filter = filter.copyWith(query: searchTerm, userId: userId, mode: filterMode); - filterAlbums(); + unawaited(filterAlbums()); } Future onRefresh() async { @@ -92,7 +92,7 @@ class _AlbumSelectorState extends ConsumerState { setState(() { isGrid = !isGrid; }); - ref.read(settingsProvider).write(.albumIsGrid, isGrid); + unawaited(ref.read(settingsProvider).write(.albumIsGrid, isGrid)); } void changeFilter(QuickFilterMode mode) { @@ -100,7 +100,7 @@ class _AlbumSelectorState extends ConsumerState { filter = filter.copyWith(mode: mode); }); - filterAlbums(); + unawaited(filterAlbums()); } Future changeSort(AlbumSort sort) async { @@ -121,7 +121,7 @@ class _AlbumSelectorState extends ConsumerState { searchController.clear(); }); - filterAlbums(); + unawaited(filterAlbums()); } Future sortAlbums() async { diff --git a/mobile/lib/presentation/widgets/album/pending_uploads_banner.widget.dart b/mobile/lib/presentation/widgets/album/pending_uploads_banner.widget.dart index 2701316e75..5622ed6b1b 100644 --- a/mobile/lib/presentation/widgets/album/pending_uploads_banner.widget.dart +++ b/mobile/lib/presentation/widgets/album/pending_uploads_banner.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -45,8 +47,8 @@ class PendingUploadsBanner extends ConsumerWidget { ); } - static void _openSheet(BuildContext context, String albumId) { - showModalBottomSheet( + static Future _openSheet(BuildContext context, String albumId) { + return showModalBottomSheet( context: context, showDragHandle: true, builder: (_) => _PendingUploadsSheet(albumId: albumId), @@ -97,7 +99,7 @@ class _PendingUploadsBannerContent extends StatelessWidget { return Material( color: hasFailures ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainerHigh, child: InkWell( - onTap: () => PendingUploadsBanner._openSheet(context, albumId), + onTap: () => unawaited(PendingUploadsBanner._openSheet(context, albumId)), child: Column( mainAxisSize: MainAxisSize.min, children: [ diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_details/location_details.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_details/location_details.widget.dart index 379f0975b1..8edfca5bf1 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_details/location_details.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_details/location_details.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; @@ -48,7 +50,7 @@ class _LocationDetailsState extends ConsumerState { if (widget.exifInfo != oldWidget.exifInfo) { final exif = widget.exifInfo; if (exif != null && exif.hasCoordinates) { - _mapController?.moveCamera(CameraUpdate.newLatLng(LatLng(exif.latitude!, exif.longitude!))); + unawaited(_mapController?.moveCamera(CameraUpdate.newLatLng(LatLng(exif.latitude!, exif.longitude!)))); } } } diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_details/people_details.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_details/people_details.widget.dart index 278da294c0..72db236b3c 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_details/people_details.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_details/people_details.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -74,7 +76,7 @@ class PeopleDetails extends ConsumerWidget { return; } ContextHelper(context).pop(); - context.pushRoute(DriftPersonRoute(person: person)); + unawaited(context.pushRoute(DriftPersonRoute(person: person))); }, onNameTap: () => showNameEditModal(person), ), diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart index 1ef22a891f..7233356402 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart @@ -87,8 +87,8 @@ class _AssetPageState extends ConsumerState { @override void dispose() { _scrollController.dispose(); - _scaleBoundarySub?.cancel(); - _eventSubscription?.cancel(); + unawaited(_scaleBoundarySub?.cancel()); + unawaited(_eventSubscription?.cancel()); super.dispose(); } @@ -112,7 +112,7 @@ class _AssetPageState extends ConsumerState { return; } _viewer.setShowingDetails(true); - _scrollController.animateTo(_snapOffset, duration: Durations.medium2, curve: Curves.easeOutCubic); + unawaited(_scrollController.animateTo(_snapOffset, duration: Durations.medium2, curve: Curves.easeOutCubic)); } bool _willClose(double scrollVelocity) => @@ -199,7 +199,7 @@ class _AssetPageState extends ConsumerState { case _DragIntent.dismiss: const popThreshold = 75.0; if (details.localPosition.dy - start!.localPosition.dy > popThreshold) { - context.maybePop(); + unawaited(context.maybePop()); return; } _viewController?.animateMultiple( @@ -292,14 +292,14 @@ class _AssetPageState extends ConsumerState { } void _listenForScaleBoundaries(PhotoViewControllerBase? controller) { - _scaleBoundarySub?.cancel(); + unawaited(_scaleBoundarySub?.cancel()); _scaleBoundarySub = null; if (controller == null || controller.scaleBoundaries != null) { return; } _scaleBoundarySub = controller.outputStateStream.listen((_) { if (controller.scaleBoundaries != null) { - _scaleBoundarySub?.cancel(); + unawaited(_scaleBoundarySub?.cancel()); _scaleBoundarySub = null; if (mounted) { setState(() {}); diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart index 3952dafdb2..23cc6119fb 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart @@ -107,7 +107,7 @@ class _AssetViewerState extends ConsumerState { final maxPage = _totalAssets - 1; if (target >= 0 && target <= maxPage) { _pageController.jumpToPage(target); - _onAssetChanged(target); + unawaited(_onAssetChanged(target)); } } @@ -126,14 +126,14 @@ class _AssetViewerState extends ConsumerState { WidgetsBinding.instance.addPostFrameCallback(_onAssetInit); final assetViewer = ref.read(assetViewerProvider); - _setSystemUIMode(assetViewer.showingControls, assetViewer.showingDetails); + unawaited(_setSystemUIMode(assetViewer.showingControls, assetViewer.showingDetails)); } @override void dispose() { _pageController.dispose(); _preloader.dispose(); - _reloadSubscription?.cancel(); + unawaited(_reloadSubscription?.cancel()); _stackChildrenKeepAlive?.close(); unawaited(restoreEdgeToEdge()); @@ -157,7 +157,7 @@ class _AssetViewerState extends ConsumerState { final page = _pageController.page?.round(); if (page != null && page != _currentPage) { - _onAssetChanged(page); + unawaited(_onAssetChanged(page)); } return false; } @@ -223,7 +223,7 @@ class _AssetViewerState extends ConsumerState { case ViewerReloadAssetEvent(): _onViewerReloadEvent(); case final ViewerStackAssetDeletedEvent event: - _onViewerStackAssetDeletedEvent(event); + unawaited(_onViewerStackAssetDeletedEvent(event)); default: } } @@ -235,8 +235,8 @@ class _AssetViewerState extends ConsumerState { final index = _pageController.page?.round() ?? 0; final target = index >= _totalAssets - 1 ? index - 1 : index + 1; - _pageController.animateToPage(target, duration: Durations.medium1, curve: Curves.easeInOut); - _onAssetChanged(target); + unawaited(_pageController.animateToPage(target, duration: Durations.medium1, curve: Curves.easeInOut)); + unawaited(_onAssetChanged(target)); } Future _onViewerStackAssetDeletedEvent(ViewerStackAssetDeletedEvent event) async { @@ -271,7 +271,7 @@ class _AssetViewerState extends ConsumerState { final totalAssets = timelineService.totalAssets; if (totalAssets == 0) { - context.maybePop(); + unawaited(context.maybePop()); return; } @@ -281,14 +281,14 @@ class _AssetViewerState extends ConsumerState { if (index != _currentPage) { _pageController.jumpToPage(index); - _onAssetChanged(index); + unawaited(_onAssetChanged(index)); } else if (currentAsset is RemoteAsset && currentAsset.stackId != null && assetIndex == null) { final timelineAsset = timelineService.getAssetSafe(index); if (timelineAsset is! RemoteAsset || currentAsset.stackId != timelineAsset.stackId) { - _onAssetChanged(index); + unawaited(_onAssetChanged(index)); } } else if (currentAsset != null && assetIndex == null) { - _onAssetChanged(index); + unawaited(_onAssetChanged(index)); } if (_totalAssets != totalAssets) { @@ -298,9 +298,9 @@ class _AssetViewerState extends ConsumerState { } } - void _setSystemUIMode(bool controls, bool details) { + Future _setSystemUIMode(bool controls, bool details) { final immersive = !controls || (CurrentPlatform.isIOS && details); - unawaited(immersive ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky) : restoreEdgeToEdge()); + return immersive ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky) : restoreEdgeToEdge(); } @override @@ -324,7 +324,7 @@ class _AssetViewerState extends ConsumerState { ref.listen(assetViewerProvider.select((value) => (value.showingControls, value.showingDetails)), (_, state) { final (controls, details) = state; - _setSystemUIMode(controls, details); + unawaited(_setSystemUIMode(controls, details)); }); return AnnotatedRegion( diff --git a/mobile/lib/presentation/widgets/asset_viewer/ocr_overlay.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/ocr_overlay.widget.dart index a9291f3173..576d4937b6 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/ocr_overlay.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/ocr_overlay.widget.dart @@ -82,7 +82,7 @@ class _OcrOverlayState extends ConsumerState { } void _detachController() { - _controllerSub?.cancel(); + unawaited(_controllerSub?.cancel()); _controllerSub = null; } diff --git a/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart index 69e84ee03d..ac6f79a155 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -26,7 +28,7 @@ class SheetTile extends ConsumerWidget { }); void copyTitle(BuildContext context, WidgetRef ref) { - Clipboard.setData(ClipboardData(text: title)); + unawaited(Clipboard.setData(ClipboardData(text: title))); ImmichToast.show( context: context, msg: 'copied_to_clipboard'.t(context: context), diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart index 6f2398046f..63b5663d9d 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart @@ -66,7 +66,7 @@ class _NativeVideoViewerState extends ConsumerState with Widg if (!widget.isCurrent) { _loadTimer?.cancel(); - _notifier.pause(); + unawaited(_notifier.pause()); return; } @@ -293,7 +293,7 @@ class _NativeVideoViewerState extends ConsumerState with Widg _controller = nc; if (widget.isCurrent) { - _loadVideo(); + unawaited(_loadVideo()); } } diff --git a/mobile/lib/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart index 878a1c9405..9c9f8f7139 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -52,11 +54,13 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { IconButton( icon: const Icon(Icons.chat_outlined), onPressed: () { - context.router.push( - DriftActivitiesRoute( - album: album, - assetId: asset is RemoteAsset ? asset.id : null, - assetName: asset.name, + unawaited( + context.router.push( + DriftActivitiesRoute( + album: album, + assetId: asset is RemoteAsset ? asset.id : null, + assetName: asset.name, + ), ), ); }, diff --git a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart index d5ed3f6c96..a066e0167e 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -53,10 +55,12 @@ class _BaseDraggableScrollableSheetState extends ConsumerState } if (previous?.isInteracting != true && next.isInteracting) { - _controller.animateTo( - widget.minChildSize, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, + unawaited( + _controller.animateTo( + widget.minChildSize, + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + ), ); } }); diff --git a/mobile/lib/presentation/widgets/feature_message/feature_message_dialog.widget.dart b/mobile/lib/presentation/widgets/feature_message/feature_message_dialog.widget.dart index 2c89c68d99..d748452c0e 100644 --- a/mobile/lib/presentation/widgets/feature_message/feature_message_dialog.widget.dart +++ b/mobile/lib/presentation/widgets/feature_message/feature_message_dialog.widget.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math' as math; import 'package:easy_localization/easy_localization.dart'; @@ -60,7 +61,7 @@ class _FeatureMessageDialogState extends State<_FeatureMessageDialog> with Singl Navigator.of(context).pop(); return; } - _controller.nextPage(duration: const Duration(milliseconds: 320), curve: Curves.easeOutCubic); + unawaited(_controller.nextPage(duration: const Duration(milliseconds: 320), curve: Curves.easeOutCubic)); } List _borderColors(BuildContext context) { diff --git a/mobile/lib/presentation/widgets/images/full_image.widget.dart b/mobile/lib/presentation/widgets/images/full_image.widget.dart index 78fc0a6a21..8c92ac2818 100644 --- a/mobile/lib/presentation/widgets/images/full_image.widget.dart +++ b/mobile/lib/presentation/widgets/images/full_image.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; @@ -30,7 +32,7 @@ class FullImage extends StatelessWidget { height: size.height, fit: fit, errorBuilder: (context, error, stackTrace) { - provider.evict(); + unawaited(provider.evict()); return const Icon(Icons.image_not_supported_outlined, size: 32); }, ); diff --git a/mobile/lib/presentation/widgets/images/image_provider.dart b/mobile/lib/presentation/widgets/images/image_provider.dart index 9cc386e302..927734ca25 100644 --- a/mobile/lib/presentation/widgets/images/image_provider.dart +++ b/mobile/lib/presentation/widgets/images/image_provider.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; @@ -43,10 +44,12 @@ mixin CancellableImageProviderMixin on CancellableImageProvide return cachedImage; } - completer.operation.valueOrCancellation().whenComplete(() { - cachedStream.removeListener(listener); - cachedOperation = null; - }); + unawaited( + completer.operation.valueOrCancellation().whenComplete(() { + cachedStream.removeListener(listener); + cachedOperation = null; + }), + ); cachedOperation = completer.operation; return null; } @@ -138,7 +141,7 @@ mixin CancellableImageProviderMixin on CancellableImageProvide final operation = cachedOperation; if (operation != null) { cachedOperation = null; - operation.cancel(); + unawaited(operation.cancel()); } if (hasActiveWork) { diff --git a/mobile/lib/presentation/widgets/images/thumbnail.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail.widget.dart index 847fa4e381..90bb79cced 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail.widget.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; @@ -130,9 +131,9 @@ class _ThumbnailState extends State with SingleTickerProviderStateMix if ((synchronousCall && _providerImage == null) || !_isVisible()) { _fadeController.value = 1.0; } else if (_fadeController.isAnimating) { - _fadeController.forward(); + unawaited(_fadeController.forward()); } else { - _fadeController.forward(from: 0.0); + unawaited(_fadeController.forward(from: 0.0)); } setState(() { diff --git a/mobile/lib/presentation/widgets/map/map.state.dart b/mobile/lib/presentation/widgets/map/map.state.dart index f1b4f80ec1..eedf3aadf5 100644 --- a/mobile/lib/presentation/widgets/map/map.state.dart +++ b/mobile/lib/presentation/widgets/map/map.state.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/events.model.dart'; @@ -87,32 +89,32 @@ class MapStateNotifier extends Notifier { } void switchFavoriteOnly(bool isFavoriteOnly) { - ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly); + unawaited(ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly)); state = state.copyWith(onlyFavorites: isFavoriteOnly); EventStream.shared.emit(const MapMarkerReloadEvent()); } void switchIncludeArchived(bool isIncludeArchived) { - ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived); + unawaited(ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived)); state = state.copyWith(includeArchived: isIncludeArchived); EventStream.shared.emit(const MapMarkerReloadEvent()); } void switchWithPartners(bool isWithPartners) { - ref.read(settingsProvider).write(.mapWithPartners, isWithPartners); + unawaited(ref.read(settingsProvider).write(.mapWithPartners, isWithPartners)); state = state.copyWith(withPartners: isWithPartners); EventStream.shared.emit(const MapMarkerReloadEvent()); } void setRelativeTime(int relativeDays) { - ref.read(settingsProvider).write(.mapRelativeDate, relativeDays); + unawaited(ref.read(settingsProvider).write(.mapRelativeDate, relativeDays)); state = state.copyWith(relativeDays: relativeDays); EventStream.shared.emit(const MapMarkerReloadEvent()); } void setCustomTimeRange(TimeRange range) { - ref.read(settingsProvider).write(.mapCustomFrom, range.from); - ref.read(settingsProvider).write(.mapCustomTo, range.to); + unawaited(ref.read(settingsProvider).write(.mapCustomFrom, range.from)); + unawaited(ref.read(settingsProvider).write(.mapCustomTo, range.to)); state = state.copyWith(timeRange: range); EventStream.shared.emit(const MapMarkerReloadEvent()); } diff --git a/mobile/lib/presentation/widgets/map/map.widget.dart b/mobile/lib/presentation/widgets/map/map.widget.dart index a68a475ad4..918d64054b 100644 --- a/mobile/lib/presentation/widgets/map/map.widget.dart +++ b/mobile/lib/presentation/widgets/map/map.widget.dart @@ -66,7 +66,7 @@ class _DriftMapState extends ConsumerState { void dispose() { _debouncer.dispose(); bottomSheetOffset.dispose(); - _eventSubscription?.cancel(); + unawaited(_eventSubscription?.cancel()); super.dispose(); } diff --git a/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart b/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart index 62889b10cb..b0b7816889 100644 --- a/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart +++ b/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -33,7 +35,7 @@ class DriftMemoryLane extends ConsumerWidget { if (memories[index].assets.isNotEmpty) { DriftMemoryPage.setMemory(ref, memories[index]); } - context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)); + unawaited(context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index))); }, children: memories .map((memory) => DriftMemoryCard(key: Key(memory.id), memory: memory)) diff --git a/mobile/lib/presentation/widgets/timeline/header.widget.dart b/mobile/lib/presentation/widgets/timeline/header.widget.dart index d73d024efb..76176041fa 100644 --- a/mobile/lib/presentation/widgets/timeline/header.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/header.widget.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -105,7 +107,7 @@ class _BulkSelectIconButton extends ConsumerWidget { ? const SizedBox.shrink() : IconButton( onPressed: () { - ref.read(multiSelectProvider.notifier).toggleBucketSelection(assetOffset, bucket.assetCount); + unawaited(ref.read(multiSelectProvider.notifier).toggleBucketSelection(assetOffset, bucket.assetCount)); ref.read(hapticFeedbackProvider.notifier).heavyImpact(); }, icon: isAllSelected diff --git a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart index f5e3493a8e..eb081a1e6a 100644 --- a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart @@ -152,7 +152,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi void _resetThumbTimer() { _fadeOutTimer?.cancel(); _fadeOutTimer = Timer(kTimelineScrubberFadeOutDuration, () { - _thumbAnimationController.reverse(); + unawaited(_thumbAnimationController.reverse()); _fadeOutTimer = null; }); } @@ -177,10 +177,10 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi if (notification is ScrollUpdateNotification) { _thumbTopOffset = _currentOffset; if (_labelAnimation.status != AnimationStatus.reverse) { - _labelAnimationController.reverse(); + unawaited(_labelAnimationController.reverse()); } if (_thumbAnimationController.status != AnimationStatus.forward) { - _thumbAnimationController.forward(); + unawaited(_thumbAnimationController.forward()); } } _resetThumbTimer(); @@ -210,7 +210,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi void _onDragStart(DragStartDetails _) { setState(() { _isDragging = true; - _labelAnimationController.forward(); + unawaited(_labelAnimationController.forward()); _fadeOutTimer?.cancel(); _lastLabel = null; }); @@ -226,7 +226,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi } if (_thumbAnimationController.status != AnimationStatus.forward) { - _thumbAnimationController.forward(); + unawaited(_thumbAnimationController.forward()); } final dragPosition = _calculateDragPosition(details); @@ -344,7 +344,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi } void _onDragEnd(DragEndDetails _) { - _labelAnimationController.reverse(); + unawaited(_labelAnimationController.reverse()); setState(() { _isDragging = false; }); diff --git a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart index 5bd39deb8a..9e65dcb72c 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart @@ -258,7 +258,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi void dispose() { WidgetsBinding.instance.removeObserver(this); _scrollController.dispose(); - _eventSubscription?.cancel(); + unawaited(_eventSubscription?.cancel()); super.dispose(); } @@ -269,9 +269,11 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi final timelineState = ref.read(timelineStateProvider.notifier); timelineState.setScrubbing(true); - _scrollController - .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) - .whenComplete(() => timelineState.setScrubbing(false)); + unawaited( + _scrollController + .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) + .whenComplete(() => timelineState.setScrubbing(false)), + ); } void _scrollToDate(DateTime date) { @@ -303,13 +305,15 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi // Scroll to the segment with a small offset to show the header final targetOffset = fallbackSegment.startOffset - 50; timelineState.setScrubbing(true); - _scrollController - .animateTo( - targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), - duration: const Duration(milliseconds: 500), - curve: Curves.easeInOut, - ) - .whenComplete(() => timelineState.setScrubbing(false)); + unawaited( + _scrollController + .animateTo( + targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOut, + ) + .whenComplete(() => timelineState.setScrubbing(false)), + ); } else { timelineState.setScrubbing(false); } @@ -344,8 +348,8 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi }); } - void _dragScroll(ScrollDirection direction) { - _scrollController.animateTo( + Future _dragScroll(ScrollDirection direction) { + return _scrollController.animateTo( _scrollController.offset + (direction == ScrollDirection.forward ? 175 : -175), duration: const Duration(milliseconds: 125), curve: Curves.easeOut, @@ -488,7 +492,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi _restoreAssetIndex = targetAssetIndex; }); - ref.read(settingsProvider).write(.timelineTilesPerRow, _perRow); + unawaited(ref.read(settingsProvider).write(.timelineTilesPerRow, _perRow)); } }; }, @@ -498,7 +502,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi onStart: !isReadonlyModeEnabled ? _setDragStartIndex : null, onAssetEnter: _handleDragAssetEnter, onEnd: !isReadonlyModeEnabled ? _stopDrag : null, - onScroll: _dragScroll, + onScroll: (direction) => unawaited(_dragScroll(direction)), onScrollStart: () { // Minimize the bottom sheet when drag selection starts ref.read(timelineStateProvider.notifier).setScrolling(true); diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index 2b52973c0a..8678f7c32e 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -120,7 +120,7 @@ class AppLifeCycleNotifier extends StateNotifier { if (syncSuccess) { await Future.wait([ _safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) { - _resumeBackup(); + unawaited(_resumeBackup()); }), _resumeBackup(), // TODO: Bring back when the soft freeze issue is addressed diff --git a/mobile/lib/providers/asset_viewer/asset_viewer.provider.dart b/mobile/lib/providers/asset_viewer/asset_viewer.provider.dart index 6808860ffc..7b1d5d2caa 100644 --- a/mobile/lib/providers/asset_viewer/asset_viewer.provider.dart +++ b/mobile/lib/providers/asset_viewer/asset_viewer.provider.dart @@ -88,7 +88,7 @@ class AssetViewerStateNotifier extends Notifier { } void reset() { - _assetSubscription?.cancel(); + unawaited(_assetSubscription?.cancel()); _assetSubscription = null; state = const AssetViewerState(); } @@ -102,7 +102,7 @@ class AssetViewerStateNotifier extends Notifier { } void _watchCurrentAsset(BaseAsset asset) { - _assetSubscription?.cancel(); + unawaited(_assetSubscription?.cancel()); _assetSubscription = ref.read(assetServiceProvider).watchAsset(asset).listen((updated) { if (updated != null) { state = state.copyWith(currentAsset: updated); diff --git a/mobile/lib/providers/asset_viewer/share_intent_upload.provider.dart b/mobile/lib/providers/asset_viewer/share_intent_upload.provider.dart index 51119f4ba2..47d67c9674 100644 --- a/mobile/lib/providers/asset_viewer/share_intent_upload.provider.dart +++ b/mobile/lib/providers/asset_viewer/share_intent_upload.provider.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -33,7 +34,7 @@ class ShareIntentUploadStateNotifier extends StateNotifier route.name == "ShareIntentRoute"); clearAttachments(); addAttachments(attachments); - router.push(ShareIntentRoute(attachments: attachments)); + unawaited(router.push(ShareIntentRoute(attachments: attachments))); } void addAttachments(List attachments) { diff --git a/mobile/lib/providers/asset_viewer/video_player_provider.dart b/mobile/lib/providers/asset_viewer/video_player_provider.dart index 463a1ac3d2..74d697a2ea 100644 --- a/mobile/lib/providers/asset_viewer/video_player_provider.dart +++ b/mobile/lib/providers/asset_viewer/video_player_provider.dart @@ -50,7 +50,7 @@ class VideoPlayerNotifier extends StateNotifier { void dispose() { _bufferingTimer?.cancel(); _seekTimer?.cancel(); - WakelockPlus.disable(); + unawaited(WakelockPlus.disable()); _controller = null; super.dispose(); @@ -121,7 +121,7 @@ class VideoPlayerNotifier extends StateNotifier { } _seekTimer = Timer(const Duration(milliseconds: 150), () { - _controller?.seekTo(state.position.inMilliseconds); + unawaited(_controller?.seekTo(state.position.inMilliseconds)); }); } @@ -130,11 +130,11 @@ class VideoPlayerNotifier extends StateNotifier { switch (state.status) { case VideoPlaybackStatus.paused: - play(); + unawaited(play()); case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering: - pause(); + unawaited(pause()); case VideoPlaybackStatus.completed: - restart(); + unawaited(restart()); } } @@ -145,7 +145,7 @@ class VideoPlayerNotifier extends StateNotifier { } _holdStatus = state.status; - pause(); + unawaited(pause()); } /// Restores playback to the status before [hold] was called. @@ -155,7 +155,7 @@ class VideoPlayerNotifier extends StateNotifier { switch (status) { case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering: - play(); + unawaited(play()); default: } } @@ -238,7 +238,7 @@ class VideoPlayerNotifier extends StateNotifier { final newStatus = _mapStatus(playbackInfo.status); switch (newStatus) { case VideoPlaybackStatus.playing: - WakelockPlus.enable(); + unawaited(WakelockPlus.enable()); _startBufferingTimer(); default: onNativePlaybackEnded(); @@ -250,7 +250,7 @@ class VideoPlayerNotifier extends StateNotifier { } void onNativePlaybackEnded() { - WakelockPlus.disable(); + unawaited(WakelockPlus.disable()); _bufferingTimer?.cancel(); } diff --git a/mobile/lib/providers/backup/backup_album.provider.dart b/mobile/lib/providers/backup/backup_album.provider.dart index f81f905c2f..25a4204928 100644 --- a/mobile/lib/providers/backup/backup_album.provider.dart +++ b/mobile/lib/providers/backup/backup_album.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/services/local_album.service.dart'; @@ -10,7 +12,7 @@ final backupAlbumProvider = StateNotifierProvider> { BackupAlbumNotifier(this._localAlbumService) : super([]) { - getAll(); + unawaited(getAll()); } final LocalAlbumService _localAlbumService; diff --git a/mobile/lib/providers/cast.provider.dart b/mobile/lib/providers/cast.provider.dart index 943ac930ec..776888146b 100644 --- a/mobile/lib/providers/cast.provider.dart +++ b/mobile/lib/providers/cast.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + 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'; @@ -51,7 +53,7 @@ class CastNotifier extends StateNotifier { } void loadMedia(RemoteAsset asset, bool reload) { - _gCastService.loadMedia(asset, reload); + unawaited(_gCastService.loadMedia(asset, reload)); } Future connect(CastDestinationType type, dynamic device) async { diff --git a/mobile/lib/providers/cleanup.provider.dart b/mobile/lib/providers/cleanup.provider.dart index 378ceb010f..4316b4eb00 100644 --- a/mobile/lib/providers/cleanup.provider.dart +++ b/mobile/lib/providers/cleanup.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -87,18 +89,18 @@ class CleanupNotifier extends StateNotifier { state = state.copyWith(selectedDate: date, assetsToDelete: []); if (date != null) { final daysAgo = DateTime.now().difference(date).inDays; - _settingsRepository.write(.cleanupCutoffDaysAgo, daysAgo); + unawaited(_settingsRepository.write(.cleanupCutoffDaysAgo, daysAgo)); } } void setKeepMediaType(AssetKeepType keepMediaType) { state = state.copyWith(keepMediaType: keepMediaType, assetsToDelete: []); - _settingsRepository.write(.cleanupKeepMediaType, keepMediaType); + unawaited(_settingsRepository.write(.cleanupKeepMediaType, keepMediaType)); } void setKeepFavorites(bool keepFavorites) { state = state.copyWith(keepFavorites: keepFavorites, assetsToDelete: []); - _settingsRepository.write(.cleanupKeepFavorites, keepFavorites); + unawaited(_settingsRepository.write(.cleanupKeepFavorites, keepFavorites)); } void toggleKeepAlbum(String albumId) { @@ -118,7 +120,7 @@ class CleanupNotifier extends StateNotifier { } void _persistExcludedAlbumIds(Set albumIds) { - _settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList()); + unawaited(_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList())); } void cleanupStaleAlbumIds(Set existingAlbumIds) { @@ -144,7 +146,7 @@ class CleanupNotifier extends StateNotifier { _persistExcludedAlbumIds(keepAlbumIds); } - _settingsRepository.write(.cleanupDefaultsInitialized, true); + unawaited(_settingsRepository.write(.cleanupDefaultsInitialized, true)); } Future scanAssets() async { diff --git a/mobile/lib/providers/gallery_permission.provider.dart b/mobile/lib/providers/gallery_permission.provider.dart index 315c67a214..6d4703c834 100644 --- a/mobile/lib/providers/gallery_permission.provider.dart +++ b/mobile/lib/providers/gallery_permission.provider.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; @@ -9,7 +10,7 @@ class GalleryPermissionNotifier extends StateNotifier { : super(PermissionStatus.denied) // Denied is the initial state { // Sets the initial state - getGalleryPermissionStatus(); + unawaited(getGalleryPermissionStatus()); } bool get hasPermission => state.isGranted || state.isLimited; diff --git a/mobile/lib/providers/haptic_feedback.provider.dart b/mobile/lib/providers/haptic_feedback.provider.dart index e1ce5c8d0d..850935163d 100644 --- a/mobile/lib/providers/haptic_feedback.provider.dart +++ b/mobile/lib/providers/haptic_feedback.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; @@ -15,31 +17,31 @@ class HapticNotifier extends StateNotifier { void selectionClick() { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { - HapticFeedback.selectionClick(); + unawaited(HapticFeedback.selectionClick()); } } void lightImpact() { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { - HapticFeedback.lightImpact(); + unawaited(HapticFeedback.lightImpact()); } } void mediumImpact() { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { - HapticFeedback.mediumImpact(); + unawaited(HapticFeedback.mediumImpact()); } } void heavyImpact() { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { - HapticFeedback.heavyImpact(); + unawaited(HapticFeedback.heavyImpact()); } } void vibrate() { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { - HapticFeedback.vibrate(); + unawaited(HapticFeedback.vibrate()); } } } diff --git a/mobile/lib/providers/infrastructure/readonly_mode.provider.dart b/mobile/lib/providers/infrastructure/readonly_mode.provider.dart index d503919c90..be94a8a341 100644 --- a/mobile/lib/providers/infrastructure/readonly_mode.provider.dart +++ b/mobile/lib/providers/infrastructure/readonly_mode.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; @@ -16,11 +18,11 @@ class ReadOnlyModeNotifier extends Notifier { void setMode(bool value) { final isLoggedIn = ref.read(authProvider).isAuthenticated; - _appSettingService.setSetting(AppSettingsEnum.readonlyModeEnabled, value); + unawaited(_appSettingService.setSetting(AppSettingsEnum.readonlyModeEnabled, value)); state = value; if (value && isLoggedIn) { - ref.read(appRouterProvider).navigate(const MainTimelineRoute()); + unawaited(ref.read(appRouterProvider).navigate(const MainTimelineRoute())); } } diff --git a/mobile/lib/providers/local_auth.provider.dart b/mobile/lib/providers/local_auth.provider.dart index d2860975bb..58bd4fb0f8 100644 --- a/mobile/lib/providers/local_auth.provider.dart +++ b/mobile/lib/providers/local_auth.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -21,9 +23,11 @@ class LocalAuthNotifier extends StateNotifier { LocalAuthNotifier(this._localAuthService, this._secureStorageService) : super(const BiometricStatus(availableBiometrics: [], canAuthenticate: false)) { - _localAuthService.getStatus().then((value) { - state = state.copyWith(canAuthenticate: value.canAuthenticate, availableBiometrics: value.availableBiometrics); - }); + unawaited( + _localAuthService.getStatus().then((value) { + state = state.copyWith(canAuthenticate: value.canAuthenticate, availableBiometrics: value.availableBiometrics); + }), + ); } Future registerBiometric(BuildContext context, String pinCode) async { diff --git a/mobile/lib/providers/map/map_state.provider.dart b/mobile/lib/providers/map/map_state.provider.dart index b643264dca..12e9e59fac 100644 --- a/mobile/lib/providers/map/map_state.provider.dart +++ b/mobile/lib/providers/map/map_state.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/models/map/map_state.model.dart'; @@ -26,12 +28,12 @@ class MapStateNotifier extends Notifier { } void switchTheme(ThemeMode mode) { - ref.read(settingsProvider).write(.mapThemeMode, mode); + unawaited(ref.read(settingsProvider).write(.mapThemeMode, mode)); state = state.copyWith(themeMode: mode); } void switchFavoriteOnly(bool isFavoriteOnly) { - ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly); + unawaited(ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly)); state = state.copyWith(showFavoriteOnly: isFavoriteOnly, shouldRefetchMarkers: true); } @@ -40,17 +42,17 @@ class MapStateNotifier extends Notifier { } void switchIncludeArchived(bool isIncludeArchived) { - ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived); + unawaited(ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived)); state = state.copyWith(includeArchived: isIncludeArchived, shouldRefetchMarkers: true); } void switchWithPartners(bool isWithPartners) { - ref.read(settingsProvider).write(.mapWithPartners, isWithPartners); + unawaited(ref.read(settingsProvider).write(.mapWithPartners, isWithPartners)); state = state.copyWith(withPartners: isWithPartners, shouldRefetchMarkers: true); } void setRelativeTime(int relativeTime) { - ref.read(settingsProvider).write(.mapRelativeDate, relativeTime); + unawaited(ref.read(settingsProvider).write(.mapRelativeDate, relativeTime)); state = state.copyWith(relativeTime: relativeTime, shouldRefetchMarkers: true); } } diff --git a/mobile/lib/providers/permission.provider.dart b/mobile/lib/providers/permission.provider.dart index b7011e1357..dc82285122 100644 --- a/mobile/lib/providers/permission.provider.dart +++ b/mobile/lib/providers/permission.provider.dart @@ -10,7 +10,7 @@ class NotificationPermissionNotifier extends StateNotifier { NotificationPermissionNotifier() : super(Platform.isAndroid ? PermissionStatus.granted : PermissionStatus.restricted) { // Sets the initial state - getNotificationPermission().then((p) => state = p); + unawaited(getNotificationPermission().then((p) => state = p)); } /// Requests the notification permission diff --git a/mobile/lib/providers/server_info.provider.dart b/mobile/lib/providers/server_info.provider.dart index bf83b36f54..c25e496a04 100644 --- a/mobile/lib/providers/server_info.provider.dart +++ b/mobile/lib/providers/server_info.provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/models/server_info/server_config.model.dart'; @@ -77,7 +79,7 @@ class ServerInfoNotifier extends StateNotifier { void handleReleaseInfo(ServerVersion serverVersion, ServerVersion? latestVersion) { // Update local server version - _checkServerVersionMismatch(serverVersion, latestVersion: latestVersion); + unawaited(_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion)); } Future getServerFeatures() async { diff --git a/mobile/lib/providers/shared_link.provider.dart b/mobile/lib/providers/shared_link.provider.dart index fb44aea203..096919f28a 100644 --- a/mobile/lib/providers/shared_link.provider.dart +++ b/mobile/lib/providers/shared_link.provider.dart @@ -8,7 +8,7 @@ class SharedLinksNotifier extends StateNotifier>> { final SharedLinkService _sharedLinkService; SharedLinksNotifier(this._sharedLinkService) : super(const AsyncLoading()) { - fetchLinks(); + unawaited(fetchLinks()); } Future fetchLinks() async { diff --git a/mobile/lib/providers/user.provider.dart b/mobile/lib/providers/user.provider.dart index 622847b0c2..2feb39ce5c 100644 --- a/mobile/lib/providers/user.provider.dart +++ b/mobile/lib/providers/user.provider.dart @@ -22,7 +22,7 @@ class CurrentUserProvider extends StateNotifier { @override void dispose() { - streamSub.cancel(); + unawaited(streamSub.cancel()); super.dispose(); } } diff --git a/mobile/lib/providers/websocket.provider.dart b/mobile/lib/providers/websocket.provider.dart index a7c08457af..2eb8ddc2b4 100644 --- a/mobile/lib/providers/websocket.provider.dart +++ b/mobile/lib/providers/websocket.provider.dart @@ -143,8 +143,8 @@ class WebsocketNotifier extends StateNotifier { } void _handleOnConfigUpdate(dynamic _) { - _ref.read(serverInfoProvider.notifier).getServerFeatures(); - _ref.read(serverInfoProvider.notifier).getServerConfig(); + unawaited(_ref.read(serverInfoProvider.notifier).getServerFeatures()); + unawaited(_ref.read(serverInfoProvider.notifier).getServerConfig()); } void _handleReleaseUpdates(dynamic data) { @@ -203,7 +203,7 @@ class WebsocketNotifier extends StateNotifier { unawaited( _ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) { if (isSyncAlbumEnabled) { - _ref.read(backgroundSyncProvider).syncLinkedAlbum(); + unawaited(_ref.read(backgroundSyncProvider).syncLinkedAlbum()); } }), ); @@ -224,7 +224,7 @@ class WebsocketNotifier extends StateNotifier { unawaited( _ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) { if (isSyncAlbumEnabled) { - _ref.read(backgroundSyncProvider).syncLinkedAlbum(); + unawaited(_ref.read(backgroundSyncProvider).syncLinkedAlbum()); } }), ); diff --git a/mobile/lib/routing/app_navigation_observer.dart b/mobile/lib/routing/app_navigation_observer.dart index 57304af44f..f126788008 100644 --- a/mobile/lib/routing/app_navigation_observer.dart +++ b/mobile/lib/routing/app_navigation_observer.dart @@ -13,10 +13,12 @@ class AppNavigationObserver extends AutoRouterObserver { @override void didPush(Route route, Route? previousRoute) { - Future(() { - ref.read(currentRouteNameProvider.notifier).state = route.settings.name; - ref.read(previousRouteNameProvider.notifier).state = previousRoute?.settings.name; - ref.read(previousRouteDataProvider.notifier).state = previousRoute?.settings; - }); + unawaited( + Future(() { + ref.read(currentRouteNameProvider.notifier).state = route.settings.name; + ref.read(previousRouteNameProvider.notifier).state = previousRoute?.settings.name; + ref.read(previousRouteDataProvider.notifier).state = previousRoute?.settings; + }), + ); } } diff --git a/mobile/lib/services/background_upload.service.dart b/mobile/lib/services/background_upload.service.dart index 5b379ff890..5312107f6c 100644 --- a/mobile/lib/services/background_upload.service.dart +++ b/mobile/lib/services/background_upload.service.dart @@ -135,12 +135,12 @@ class BackgroundUploadService { if (!_taskStatusController.isClosed) { _taskStatusController.add(update); } - _handleTaskStatusUpdate(update); + unawaited(_handleTaskStatusUpdate(update)); } void dispose() { - _taskStatusController.close(); - _taskProgressController.close(); + unawaited(_taskStatusController.close()); + unawaited(_taskProgressController.close()); } /// Enqueue tasks to the background upload queue diff --git a/mobile/lib/services/map.service.dart b/mobile/lib/services/map.service.dart index 5b50e8a890..b439af8668 100644 --- a/mobile/lib/services/map.service.dart +++ b/mobile/lib/services/map.service.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:immich_mobile/mixins/error_logger.mixin.dart'; import 'package:immich_mobile/models/map/map_marker.model.dart'; import 'package:immich_mobile/services/api.service.dart'; @@ -11,7 +13,7 @@ class MapService with ErrorLoggerMixin { final logger = Logger("MapService"); MapService(this._apiService) { - _setMapUserAgentHeader(); + unawaited(_setMapUserAgentHeader()); } Future _setMapUserAgentHeader() async { diff --git a/mobile/lib/services/share_intent_service.dart b/mobile/lib/services/share_intent_service.dart index fca5c4a188..a5ab5d8bc9 100644 --- a/mobile/lib/services/share_intent_service.dart +++ b/mobile/lib/services/share_intent_service.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart'; import 'package:immich_mobile/repositories/share_handler.repository.dart'; @@ -12,6 +14,6 @@ class ShareIntentService { void init() { shareHandlerRepository.onSharedMedia = onSharedMedia; - shareHandlerRepository.init(); + unawaited(shareHandlerRepository.init()); } } diff --git a/mobile/lib/utils/async_mutex.dart b/mobile/lib/utils/async_mutex.dart index b97ab9b052..6c54c1220d 100644 --- a/mobile/lib/utils/async_mutex.dart +++ b/mobile/lib/utils/async_mutex.dart @@ -12,10 +12,12 @@ class AsyncMutex { Future run(Future Function() operation) { final completer = Completer(); _enqueued++; - _running.whenComplete(() { - _enqueued--; - completer.complete(Future.sync(operation)); - }); + unawaited( + _running.whenComplete(() { + _enqueued--; + completer.complete(Future.sync(operation)); + }), + ); return _running = completer.future; } } diff --git a/mobile/lib/utils/hooks/app_settings_update_hook.dart b/mobile/lib/utils/hooks/app_settings_update_hook.dart index c498b60b06..9d7cc4b064 100644 --- a/mobile/lib/utils/hooks/app_settings_update_hook.dart +++ b/mobile/lib/utils/hooks/app_settings_update_hook.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/cupertino.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:immich_mobile/entities/store.entity.dart'; @@ -7,7 +9,7 @@ ValueNotifier useAppSettingsState(AppSettingsEnum key) { final notifier = useState(Store.get(key.storeKey, key.defaultValue)); // Listen to changes to the notifier and update app settings - useValueChanged(notifier.value, (_, __) => Store.put(key.storeKey, notifier.value)); + useValueChanged(notifier.value, (_, __) => unawaited(Store.put(key.storeKey, notifier.value))); return notifier; } diff --git a/mobile/lib/utils/image_converter.dart b/mobile/lib/utils/image_converter.dart index d0fd4f873f..1a3a00130a 100644 --- a/mobile/lib/utils/image_converter.dart +++ b/mobile/lib/utils/image_converter.dart @@ -15,13 +15,15 @@ Future imageToUint8List(Image image) async { .resolve(ImageConfiguration.empty) .addListener( ImageStreamListener((ImageInfo info, bool _) { - info.image.toByteData(format: ImageByteFormat.png).then((byteData) { - if (byteData != null) { - completer.complete(byteData.buffer.asUint8List()); - } else { - completer.completeError('Failed to convert image to bytes'); - } - }); + unawaited( + info.image.toByteData(format: ImageByteFormat.png).then((byteData) { + if (byteData != null) { + completer.complete(byteData.buffer.asUint8List()); + } else { + completer.completeError('Failed to convert image to bytes'); + } + }), + ); }, onError: (exception, stackTrace) => completer.completeError(exception)), ); return completer.future; diff --git a/mobile/lib/widgets/asset_viewer/animated_play_pause.dart b/mobile/lib/widgets/asset_viewer/animated_play_pause.dart index 4be7f49b5a..bad8a6345c 100644 --- a/mobile/lib/widgets/asset_viewer/animated_play_pause.dart +++ b/mobile/lib/widgets/asset_viewer/animated_play_pause.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ui'; import 'package:flutter/material.dart'; @@ -27,9 +28,9 @@ class AnimatedPlayPauseState extends State with SingleTickerP super.didUpdateWidget(oldWidget); if (widget.playing != oldWidget.playing) { if (widget.playing) { - animationController.forward(); + unawaited(animationController.forward()); } else { - animationController.reverse(); + unawaited(animationController.reverse()); } } } diff --git a/mobile/lib/widgets/backup/drift_album_info_list_tile.dart b/mobile/lib/widgets/backup/drift_album_info_list_tile.dart index 85f655ec86..999b64e9de 100644 --- a/mobile/lib/widgets/backup/drift_album_info_list_tile.dart +++ b/mobile/lib/widgets/backup/drift_album_info_list_tile.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -54,7 +56,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget { ref.watch(hapticFeedbackProvider.notifier).selectionClick(); if (isExcluded) { - ref.read(backupAlbumProvider.notifier).deselectAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).deselectAlbum(album)); } else { if (album.id == 'isAll' || album.name == 'Recents') { ImmichToast.show( @@ -66,7 +68,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget { return; } - ref.read(backupAlbumProvider.notifier).excludeAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).excludeAlbum(album)); } }, child: ListTile( @@ -75,9 +77,9 @@ class DriftAlbumInfoListTile extends HookConsumerWidget { onTap: () { ref.read(hapticFeedbackProvider.notifier).selectionClick(); if (isSelected) { - ref.read(backupAlbumProvider.notifier).deselectAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).deselectAlbum(album)); } else { - ref.read(backupAlbumProvider.notifier).selectAlbum(album); + unawaited(ref.read(backupAlbumProvider.notifier).selectAlbum(album)); } }, leading: buildIcon(), @@ -85,7 +87,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget { subtitle: buildSubtitle(), trailing: IconButton( onPressed: () { - context.pushRoute(LocalTimelineRoute(album: album)); + unawaited(context.pushRoute(LocalTimelineRoute(album: album))); }, icon: Icon(Icons.image_outlined, color: context.primaryColor, size: 24), splashRadius: 25, diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart index 22c860becf..085f4e2120 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart @@ -38,8 +38,8 @@ class ImmichAppBarDialog extends HookConsumerWidget { final isReadonlyModeEnabled = ref.watch(readonlyModeProvider); useEffect(() { - ref.read(backupProvider.notifier).updateDiskInfo(); - ref.read(currentUserProvider.notifier).refresh(); + unawaited(ref.read(backupProvider.notifier).updateDiskInfo()); + unawaited(ref.read(currentUserProvider.notifier).refresh()); return null; }, []); @@ -180,7 +180,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { InkWell( onTap: () { ContextHelper(context).pop(); - launchUrl(Uri.parse('https://docs.immich.app'), mode: LaunchMode.externalApplication); + unawaited(launchUrl(Uri.parse('https://docs.immich.app'), mode: LaunchMode.externalApplication)); }, child: Text("documentation", style: context.textTheme.bodySmall).tr(), ), @@ -188,7 +188,9 @@ class ImmichAppBarDialog extends HookConsumerWidget { InkWell( onTap: () { ContextHelper(context).pop(); - launchUrl(Uri.parse('https://github.com/immich-app/immich'), mode: LaunchMode.externalApplication); + unawaited( + launchUrl(Uri.parse('https://github.com/immich-app/immich'), mode: LaunchMode.externalApplication), + ); }, child: Text("profile_drawer_github", style: context.textTheme.bodySmall).tr(), ), diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_server_info.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_server_info.dart index fbec03bbbd..348e3aa14c 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_server_info.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_server_info.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; @@ -31,7 +33,7 @@ class AppBarServerInfo extends HookConsumerWidget { } useEffect(() { - getPackageInfo(); + unawaited(getPackageInfo()); return null; }, []); @@ -87,7 +89,7 @@ class _ServerInfoItem extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (icon != null) ...[icon as Widget, const SizedBox(width: 8)], + if (icon != null) ...[icon! as Widget, const SizedBox(width: 8)], Text( label, style: TextStyle( diff --git a/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart b/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart index c29475351e..806ac87c19 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; @@ -20,7 +21,7 @@ class ServerUpdateNotification extends HookConsumerWidget { final Color infoColor = context.isDarkTheme ? context.primaryColor.withAlpha(55) : context.primaryColor.withAlpha(25); - void openUpdateLink() { + Future openUpdateLink() { String url; if (serverInfoState.versionStatus == VersionStatus.serverOutOfDate) { url = kImmichLatestRelease; @@ -35,7 +36,7 @@ class ServerUpdateNotification extends HookConsumerWidget { } } - launchUrlString(url, mode: LaunchMode.externalApplication); + return launchUrlString(url, mode: LaunchMode.externalApplication); } return SizedBox( @@ -68,7 +69,7 @@ class ServerUpdateNotification extends HookConsumerWidget { serverInfoState.versionStatus == VersionStatus.clientOutOfDate) ...[ const SizedBox(width: 8), TextButton( - onPressed: openUpdateLink, + onPressed: () => unawaited(openUpdateLink()), style: TextButton.styleFrom( padding: const EdgeInsets.all(4), minimumSize: Size.zero, diff --git a/mobile/lib/widgets/common/dropdown_search_menu.dart b/mobile/lib/widgets/common/dropdown_search_menu.dart index bf0c75c8aa..54568c392a 100644 --- a/mobile/lib/widgets/common/dropdown_search_menu.dart +++ b/mobile/lib/widgets/common/dropdown_search_menu.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -114,7 +116,7 @@ class DropdownSearchMenu extends HookWidget { final bool highlight = AutocompleteHighlightedOption.of(context) == index; if (highlight) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { - Scrollable.ensureVisible(context, alignment: 0.5); + unawaited(Scrollable.ensureVisible(context, alignment: 0.5)); }, debugLabel: 'AutocompleteOptions.ensureVisible'); } return Container( diff --git a/mobile/lib/widgets/common/immich_loading_indicator.dart b/mobile/lib/widgets/common/immich_loading_indicator.dart index 52f957f7e7..1fdc5213df 100644 --- a/mobile/lib/widgets/common/immich_loading_indicator.dart +++ b/mobile/lib/widgets/common/immich_loading_indicator.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:immich_mobile/widgets/common/immich_logo.dart'; @@ -9,11 +11,12 @@ class ImmichLoadingIndicator extends HookWidget { @override Widget build(BuildContext context) { - final logoAnimationController = useAnimationController(duration: const Duration(seconds: 6)) - ..reverse() - ..repeat(); + final logoAnimationController = useAnimationController(duration: const Duration(seconds: 6)); + unawaited(logoAnimationController.reverse()); + unawaited(logoAnimationController.repeat()); - final borderAnimationController = useAnimationController(duration: const Duration(seconds: 6))..repeat(); + final borderAnimationController = useAnimationController(duration: const Duration(seconds: 6)); + unawaited(borderAnimationController.repeat()); return Container( height: 80, diff --git a/mobile/lib/widgets/common/immich_sliver_app_bar.dart b/mobile/lib/widgets/common/immich_sliver_app_bar.dart index 22528b05d5..c5bce92cff 100644 --- a/mobile/lib/widgets/common/immich_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/immich_sliver_app_bar.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math' as math; import 'package:auto_route/auto_route.dart'; @@ -304,13 +305,13 @@ class _SyncStatusIndicatorState extends ConsumerState<_SyncStatusIndicator> with // Control animations based on sync status if (isSyncing) { if (!_rotationController.isAnimating) { - _rotationController.repeat(); + unawaited(_rotationController.repeat()); } _dismissalController.reset(); } else { _rotationController.stop(); if (_dismissalController.status == AnimationStatus.dismissed) { - _dismissalController.forward(); + unawaited(_dismissalController.forward()); } } diff --git a/mobile/lib/widgets/common/mesmerizing_sliver_app_bar.dart b/mobile/lib/widgets/common/mesmerizing_sliver_app_bar.dart index 90dfd9c82a..0ceb98aa76 100644 --- a/mobile/lib/widgets/common/mesmerizing_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/mesmerizing_sliver_app_bar.dart @@ -134,7 +134,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S Future.delayed(const Duration(milliseconds: 100), () { if (mounted) { - _slideController.forward(); + unawaited(_slideController.forward()); } }); } @@ -228,7 +228,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> { @override void dispose() { - _reloadSubscription?.cancel(); + unawaited(_reloadSubscription?.cancel()); super.dispose(); } @@ -311,13 +311,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic void _startAnimationCycle() { if (_isZoomingIn) { - _zoomController.forward().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.forward().then((_) { + unawaited(_loadNextAsset()); + }), + ); } else { - _zoomController.reverse().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.reverse().then((_) { + unawaited(_loadNextAsset()); + }), + ); } } diff --git a/mobile/lib/widgets/common/person_sliver_app_bar.dart b/mobile/lib/widgets/common/person_sliver_app_bar.dart index 80dded2130..0e6829243c 100644 --- a/mobile/lib/widgets/common/person_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/person_sliver_app_bar.dart @@ -169,7 +169,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S Future.delayed(const Duration(milliseconds: 100), () { if (mounted) { - _slideController.forward(); + unawaited(_slideController.forward()); } }); } @@ -335,7 +335,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> { @override void dispose() { - _reloadSubscription?.cancel(); + unawaited(_reloadSubscription?.cancel()); super.dispose(); } @@ -416,13 +416,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic void _startAnimationCycle() { if (_isZoomingIn) { - _zoomController.forward().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.forward().then((_) { + unawaited(_loadNextAsset()); + }), + ); } else { - _zoomController.reverse().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.reverse().then((_) { + unawaited(_loadNextAsset()); + }), + ); } } diff --git a/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart b/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart index 4d2dc5ef88..09a0367039 100644 --- a/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart @@ -172,7 +172,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S Future.delayed(const Duration(milliseconds: 100), () { if (mounted) { - _slideController.forward(); + unawaited(_slideController.forward()); } }); } @@ -309,7 +309,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> { @override void dispose() { - _reloadSubscription?.cancel(); + unawaited(_reloadSubscription?.cancel()); super.dispose(); } @@ -390,13 +390,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic void _startAnimationCycle() { if (_isZoomingIn) { - _zoomController.forward().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.forward().then((_) { + unawaited(_loadNextAsset()); + }), + ); } else { - _zoomController.reverse().then((_) { - _loadNextAsset(); - }); + unawaited( + _zoomController.reverse().then((_) { + unawaited(_loadNextAsset()); + }), + ); } } diff --git a/mobile/lib/widgets/forms/login/login_form.dart b/mobile/lib/widgets/forms/login/login_form.dart index 4c9b56646f..969c311bfb 100644 --- a/mobile/lib/widgets/forms/login/login_form.dart +++ b/mobile/lib/widgets/forms/login/login_form.dart @@ -70,7 +70,8 @@ class LoginForm extends HookConsumerWidget { final isOauthEnable = useState(false); final isPasswordLoginEnable = useState(false); final oAuthButtonLabel = useState('OAuth'); - final logoAnimationController = useAnimationController(duration: const Duration(seconds: 60))..repeat(); + final logoAnimationController = useAnimationController(duration: const Duration(seconds: 60)); + unawaited(logoAnimationController.repeat()); final serverInfo = ref.watch(serverInfoProvider); final warningMessage = useState(null); final loginFormKey = GlobalKey(); @@ -358,7 +359,7 @@ class LoginForm extends HookConsumerWidget { } SingleChildRenderObjectWidget buildVersionCompatWarning() { - checkVersionMismatch(); + unawaited(checkVersionMismatch()); if (warningMessage.value == null) { return const SizedBox.shrink(); diff --git a/mobile/lib/widgets/photo_view/src/controller/photo_view_controller.dart b/mobile/lib/widgets/photo_view/src/controller/photo_view_controller.dart index b9475a9ee2..08c300e9ae 100644 --- a/mobile/lib/widgets/photo_view/src/controller/photo_view_controller.dart +++ b/mobile/lib/widgets/photo_view/src/controller/photo_view_controller.dart @@ -209,7 +209,7 @@ class PhotoViewController implements PhotoViewControllerBase return; } _scaleAnimation = Tween(begin: from, end: to).animate(_scaleAnimationController); - _scaleAnimationController - ..value = 0.0 - ..fling(velocity: 0.4); + _scaleAnimationController.value = 0.0; + unawaited(_scaleAnimationController.fling(velocity: 0.4)); } void animatePosition(Offset from, Offset to) { @@ -250,9 +251,8 @@ class PhotoViewCoreState extends State return; } _positionAnimation = Tween(begin: from, end: to).animate(_positionAnimationController); - _positionAnimationController - ..value = 0.0 - ..fling(velocity: 0.4); + _positionAnimationController.value = 0.0; + unawaited(_positionAnimationController.fling(velocity: 0.4)); } void animateRotation(double from, double to) { @@ -260,9 +260,8 @@ class PhotoViewCoreState extends State return; } _rotationAnimation = Tween(begin: from, end: to).animate(_rotationAnimationController); - _rotationAnimationController - ..value = 0.0 - ..fling(velocity: 0.4); + _rotationAnimationController.value = 0.0; + unawaited(_rotationAnimationController.fling(velocity: 0.4)); } void onAnimationStatus(AnimationStatus status) { diff --git a/mobile/lib/widgets/photo_view/src/photo_view_wrappers.dart b/mobile/lib/widgets/photo_view/src/photo_view_wrappers.dart index db66cb962d..e55df57105 100644 --- a/mobile/lib/widgets/photo_view/src/photo_view_wrappers.dart +++ b/mobile/lib/widgets/photo_view/src/photo_view_wrappers.dart @@ -82,7 +82,6 @@ class _ImageWrapperState extends State { ImageStreamListener? _imageStreamListener; ImageStream? _imageStream; ImageChunkEvent? _loadingProgress; - ImageInfo? _imageInfo; bool _loading = true; Size? _imageSize; Object? _lastException; @@ -138,7 +137,6 @@ class _ImageWrapperState extends State { void setupCB() { _imageSize = Size(info.image.width.toDouble(), info.image.height.toDouble()); _loading = false; - _imageInfo = _imageInfo; _loadingProgress = null; _lastException = null; diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index 1c1d42639f..dbf54fd082 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; @@ -35,13 +36,16 @@ class AdvancedSettings extends HookConsumerWidget { final preferRemote = useState(ref.read(appConfigProvider).image.preferRemote); useValueChanged( preferRemote.value, - (_, __) => ref.read(settingsProvider).write(.imagePreferRemote, preferRemote.value), + (_, __) => unawaited(ref.read(settingsProvider).write(.imagePreferRemote, preferRemote.value)), ); final readonlyModeEnabled = useAppSettingsState(AppSettingsEnum.readonlyModeEnabled); final logLevel = Level.LEVELS[levelId.value].name; - useValueChanged(levelId.value, (_, __) => LogService.I.setLogLevel(Level.LEVELS[levelId.value].toLogLevel())); + useValueChanged( + levelId.value, + (_, __) => unawaited(LogService.I.setLogLevel(Level.LEVELS[levelId.value].toLogLevel())), + ); Future checkAndroidVersion() async { if (Platform.isAndroid) { @@ -54,12 +58,12 @@ class AdvancedSettings extends HookConsumerWidget { } useEffect(() { - () async { + unawaited(() async { isManageMediaSupported.value = await checkAndroidVersion(); if (isManageMediaSupported.value) { manageMediaAndroidPermission.value = await ref.read(permissionRepositoryProvider).hasManageMediaPermission(); } - }(); + }()); return null; }, []); diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart index f915df04f8..eda0d819d5 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -15,7 +17,7 @@ class LayoutSettings extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final tilesPerRow = useState(ref.read(appConfigProvider.select((s) => s.timeline.tilesPerRow))); useValueChanged(tilesPerRow.value, (_, __) { - ref.read(settingsProvider).write(.timelineTilesPerRow, tilesPerRow.value); + unawaited(ref.read(settingsProvider).write(.timelineTilesPerRow, tilesPerRow.value)); }); return Column( diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart index 3ac72d6612..1f3f4bbcf0 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -21,7 +23,7 @@ class AssetListSettings extends HookConsumerWidget { valueNotifier: storageIndicator, title: 'theme_setting_asset_list_storage_indicator_title'.tr(), onChanged: (value) { - ref.read(settingsProvider).write(.timelineStorageIndicator, value); + unawaited(ref.read(settingsProvider).write(.timelineStorageIndicator, value)); ref.invalidate(appSettingsServiceProvider); ref.invalidate(settingsProvider); }, diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart index f65af6af9d..e3173dcdc7 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -14,7 +16,7 @@ class ImageViewerQualitySetting extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final isOriginal = useState(ref.read(appConfigProvider).image.loadOriginal); useValueChanged(isOriginal.value, (_, __) { - ref.read(settingsProvider).write(.imageLoadOriginal, isOriginal.value); + unawaited(ref.read(settingsProvider).write(.imageLoadOriginal, isOriginal.value)); }); return Column( diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart index 730521e3c1..c785e8fed4 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -13,7 +15,7 @@ class ImageViewerTapToNavigateSetting extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final tapToNavigate = useState(ref.read(appConfigProvider).viewer.tapToNavigate); useValueChanged(tapToNavigate.value, (_, __) { - ref.read(settingsProvider).write(.viewerTapToNavigate, tapToNavigate.value); + unawaited(ref.read(settingsProvider).write(.viewerTapToNavigate, tapToNavigate.value)); }); return Column( diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart index af361943ec..ec52d23ca8 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -22,16 +24,16 @@ class SlideshowSettings extends HookConsumerWidget { final useDirection = useState(slideshow.direction); useValueChanged(useRepeat.value, (_, __) { - ref.read(settingsProvider).write(.slideshowRepeat, useRepeat.value); + unawaited(ref.read(settingsProvider).write(.slideshowRepeat, useRepeat.value)); }); useValueChanged(useDuration.value, (_, __) { - ref.read(settingsProvider).write(.slideshowDuration, useDuration.value); + unawaited(ref.read(settingsProvider).write(.slideshowDuration, useDuration.value)); }); useValueChanged(useLook.value, (_, __) { - ref.read(settingsProvider).write(.slideshowLook, useLook.value); + unawaited(ref.read(settingsProvider).write(.slideshowLook, useLook.value)); }); useValueChanged(useDirection.value, (_, __) { - ref.read(settingsProvider).write(.slideshowDirection, useDirection.value); + unawaited(ref.read(settingsProvider).write(.slideshowDirection, useDirection.value)); }); return Column( diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart index 81929d95b9..2b302e0427 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -17,13 +19,13 @@ class VideoViewerSettings extends HookConsumerWidget { final useOriginalVideo = useState(viewer.loadOriginalVideo); useValueChanged(useAutoPlayVideo.value, (_, __) { - ref.read(settingsProvider).write(.viewerAutoPlayVideo, useAutoPlayVideo.value); + unawaited(ref.read(settingsProvider).write(.viewerAutoPlayVideo, useAutoPlayVideo.value)); }); useValueChanged(useLoopVideo.value, (_, __) { - ref.read(settingsProvider).write(.viewerLoopVideo, useLoopVideo.value); + unawaited(ref.read(settingsProvider).write(.viewerLoopVideo, useLoopVideo.value)); }); useValueChanged(useOriginalVideo.value, (_, __) { - ref.read(settingsProvider).write(.viewerLoadOriginalVideo, useOriginalVideo.value); + unawaited(ref.read(settingsProvider).write(.viewerLoadOriginalVideo, useOriginalVideo.value)); }); return Column( diff --git a/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart b/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart index 44a1a1d7a9..f0f6435f90 100644 --- a/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart @@ -232,7 +232,7 @@ class _BackupOnlyWhenChargingButton extends ConsumerWidget { titleKey: "charging", subtitleKey: "charging_requirement_mobile_backup", onChanged: (value) { - fgService.configure(requireCharging: value); + unawaited(fgService.configure(requireCharging: value)); }, ); } diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index 7bd604ae5e..1871dc8a62 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -132,7 +132,7 @@ class SyncStatusAndActions extends HookConsumerWidget { leading: const Icon(Icons.sync), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), onTap: () { - ref.read(backgroundSyncProvider).syncLocal(full: true); + unawaited(ref.read(backgroundSyncProvider).syncLocal(full: true)); }, ), SettingListTile( @@ -141,7 +141,7 @@ class SyncStatusAndActions extends HookConsumerWidget { leading: const Icon(Icons.cloud_sync), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), onTap: () { - ref.read(backgroundSyncProvider).syncRemote(); + unawaited(ref.read(backgroundSyncProvider).syncRemote()); }, ), if (CurrentPlatform.isIOS && serverVersion.isAtLeast(major: 2, minor: 5)) @@ -158,7 +158,7 @@ class SyncStatusAndActions extends HookConsumerWidget { subtitle: "tap_to_run_job".t(context: context), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), onTap: () { - ref.read(backgroundSyncProvider).hashAssets(); + unawaited(ref.read(backgroundSyncProvider).hashAssets()); }, ), const Divider(height: 1), diff --git a/mobile/lib/widgets/settings/free_up_space_settings.dart b/mobile/lib/widgets/settings/free_up_space_settings.dart index dbec3a2dcb..72e85ac821 100644 --- a/mobile/lib/widgets/settings/free_up_space_settings.dart +++ b/mobile/lib/widgets/settings/free_up_space_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -30,9 +32,9 @@ class _FreeUpSpaceSettingsState extends ConsumerState { @override void initState() { super.initState(); - WakelockPlus.enable(); + unawaited(WakelockPlus.enable()); WidgetsBinding.instance.addPostFrameCallback((_) { - _initializeAlbumDefaults(); + unawaited(_initializeAlbumDefaults()); }); } @@ -68,7 +70,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState { void _goToScanStep() { ref.read(hapticFeedbackProvider.notifier).mediumImpact(); setState(() => _currentStep = CleanupStep.scan); - _scanAssets(); + unawaited(_scanAssets()); } void _setPresetDate(int daysAgo) { @@ -169,13 +171,13 @@ class _FreeUpSpaceSettingsState extends ConsumerState { void _showAssetsPreview(List assets) { ref.read(hapticFeedbackProvider.notifier).mediumImpact(); - context.pushRoute(CleanupPreviewRoute(assets: assets)); + unawaited(context.pushRoute(CleanupPreviewRoute(assets: assets))); } @override void dispose() { super.dispose(); - WakelockPlus.disable(); + unawaited(WakelockPlus.disable()); } @override diff --git a/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart b/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart index e8310caed4..162f1252a8 100644 --- a/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart +++ b/mobile/lib/widgets/settings/networking_settings/endpoint_input.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -53,7 +55,7 @@ class EndpointInputState extends ConsumerState { void _onOutFocus() { if (!focusNode.hasFocus && isInputValid) { - validateAuxilaryServerUrl(); + unawaited(validateAuxilaryServerUrl()); } } diff --git a/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart b/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart index f3c2b6c97f..68278e0e1d 100644 --- a/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart +++ b/mobile/lib/widgets/settings/networking_settings/external_network_preference.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -44,13 +46,13 @@ class ExternalNetworkPreference extends HookConsumerWidget { entries.value.insert(newIndex, entry); entries.value = [...entries.value]; - saveEndpointList(); + unawaited(saveEndpointList()); } void handleDismiss(int index) { entries.value = [...entries.value..removeAt(index)]; - saveEndpointList(); + unawaited(saveEndpointList()); } Widget proxyDecorator(Widget child, int _, Animation animation) { diff --git a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart index 7e6e169de7..e7510053e3 100644 --- a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart +++ b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -21,7 +23,7 @@ class NetworkingSettings extends HookConsumerWidget { final currentEndpoint = getServerUrl(); final featureEnabled = useState(ref.read(appConfigProvider).network.autoEndpointSwitching); useValueChanged(featureEnabled.value, (_, __) { - ref.read(settingsProvider).write(.networkAutoEndpointSwitching, featureEnabled.value); + unawaited(ref.read(settingsProvider).write(.networkAutoEndpointSwitching, featureEnabled.value)); }); Future checkWifiReadPermission() async { @@ -83,7 +85,7 @@ class NetworkingSettings extends HookConsumerWidget { useEffect(() { if (featureEnabled.value == true) { - checkWifiReadPermission(); + unawaited(checkWifiReadPermission()); } return null; }, [featureEnabled.value]); diff --git a/mobile/lib/widgets/settings/notification_setting.dart b/mobile/lib/widgets/settings/notification_setting.dart index ee2e15f52b..8c858a231b 100644 --- a/mobile/lib/widgets/settings/notification_setting.dart +++ b/mobile/lib/widgets/settings/notification_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -17,20 +19,22 @@ class NotificationSetting extends HookConsumerWidget { void openAppNotificationSettings(BuildContext ctx) { ctx.pop(); - openAppSettings(); + unawaited(openAppSettings()); } // When permissions are permanently denied, you need to go to settings to // allow them void showPermissionsDialog() { - showDialog( - context: context, - builder: (ctx) => AlertDialog( - content: const Text('notification_permission_dialog_content').tr(), - actions: [ - TextButton(child: const Text('cancel').tr(), onPressed: () => ctx.pop()), - TextButton(onPressed: () => openAppNotificationSettings(ctx), child: const Text('settings').tr()), - ], + unawaited( + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: const Text('notification_permission_dialog_content').tr(), + actions: [ + TextButton(child: const Text('cancel').tr(), onPressed: () => ctx.pop()), + TextButton(onPressed: () => openAppNotificationSettings(ctx), child: const Text('settings').tr()), + ], + ), ), ); } diff --git a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart index 1defd2df44..b0624dca23 100644 --- a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -26,16 +28,16 @@ class PrimaryColorSetting extends HookConsumerWidget { } void onUseSystemColorChange(bool newValue) { - ref.read(settingsProvider).write(.themeDynamic, newValue); + unawaited(ref.read(settingsProvider).write(.themeDynamic, newValue)); popBottomSheet(); } void onPrimaryColorChange(ImmichColorPreset colorPreset) { - ref.read(settingsProvider).write(.themePrimaryColor, colorPreset); + unawaited(ref.read(settingsProvider).write(.themePrimaryColor, colorPreset)); //turn off system color setting if (themeConfig.dynamicTheme) { - ref.read(settingsProvider).write(.themeDynamic, false); + unawaited(ref.read(settingsProvider).write(.themeDynamic, false)); } popBottomSheet(); } diff --git a/mobile/lib/widgets/settings/preference_settings/share_setting.dart b/mobile/lib/widgets/settings/preference_settings/share_setting.dart index 2435810566..1881703023 100644 --- a/mobile/lib/widgets/settings/preference_settings/share_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/share_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -19,7 +21,7 @@ class ShareSetting extends HookConsumerWidget { void onChanged(ShareAssetType? value) { if (value != null) { fileType.value = value; - ref.read(settingsProvider).write(SettingsKey.shareFileType, value); + unawaited(ref.read(settingsProvider).write(SettingsKey.shareFileType, value)); } } diff --git a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart index ffeeceae02..ec84d7be01 100644 --- a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -22,7 +24,7 @@ class ThemeSetting extends HookConsumerWidget { void onThemeChange(bool isDark) { currentTheme.value = isDark ? ThemeMode.dark : ThemeMode.light; - ref.read(settingsProvider).write(.themeMode, currentTheme.value); + unawaited(ref.read(settingsProvider).write(.themeMode, currentTheme.value)); } void onSystemThemeChange(bool isSystem) { @@ -39,11 +41,11 @@ class ThemeSetting extends HookConsumerWidget { currentTheme.value = ThemeMode.dark; } } - ref.read(settingsProvider).write(.themeMode, currentTheme.value); + unawaited(ref.read(settingsProvider).write(.themeMode, currentTheme.value)); } void onSurfaceColorSettingChange(bool useColorfulInterface) { - ref.read(settingsProvider).write(.themeColorfulInterface, useColorfulInterface); + unawaited(ref.read(settingsProvider).write(.themeColorfulInterface, useColorfulInterface)); colorfulInterface.value = useColorfulInterface; } diff --git a/mobile/lib/wm_executor.dart b/mobile/lib/wm_executor.dart index e873c5f76d..aac6d3e174 100644 --- a/mobile/lib/wm_executor.dart +++ b/mobile/lib/wm_executor.dart @@ -145,7 +145,7 @@ class _Executor extends Mixinable<_Executor> with _ExecutorLogger { void _schedule() { final availableWorker = _pool.firstWhereOrNull((worker) => worker.taskId == null && worker.initialized); if (availableWorker == null) { - _ensureWorkersInitialized(); + unawaited(_ensureWorkersInitialized()); return; } if (_queue.isEmpty) { @@ -153,26 +153,28 @@ class _Executor extends Mixinable<_Executor> with _ExecutorLogger { } final task = _queue.removeFirst(); - availableWorker - .work(task) - .then( - (value) { - //might be completed by cancel and it is normal. - //Assuming that worker finished with error and cleaned gracefully - task.complete(value, null, null); - }, - onError: (error, st) { - task.complete(null, error, st); - }, - ) - .whenComplete(() { - if (_dynamicSpawning && _queue.isEmpty) { - // Retire the idle worker; shutdown() nulls its fields so the husk - // stays pooled and is revived by initialize() if work arrives. - unawaited(availableWorker.shutdown()); - } - _schedule(); - }); + unawaited( + availableWorker + .work(task) + .then( + (value) { + //might be completed by cancel and it is normal. + //Assuming that worker finished with error and cleaned gracefully + task.complete(value, null, null); + }, + onError: (error, st) { + task.complete(null, error, st); + }, + ) + .whenComplete(() { + if (_dynamicSpawning && _queue.isEmpty) { + // Retire the idle worker; shutdown() nulls its fields so the husk + // stays pooled and is revived by initialize() if work arrives. + unawaited(availableWorker.shutdown()); + } + _schedule(); + }), + ); } @override diff --git a/mobile/packages/ui/test/formatted_text_test.dart b/mobile/packages/ui/test/formatted_text_test.dart index c3901cd802..5f26822855 100644 --- a/mobile/packages/ui/test/formatted_text_test.dart +++ b/mobile/packages/ui/test/formatted_text_test.dart @@ -59,7 +59,7 @@ void main() { ); final text = tester.widget(find.byType(Text)); - final richText = text.textSpan as TextSpan; + final richText = text.textSpan! as TextSpan; expect(richText.style?.fontSize, 16); expect(richText.style?.color, Colors.purple); diff --git a/mobile/test/presentation/widgets/timeline/timeline_args_test.dart b/mobile/test/presentation/widgets/timeline/timeline_args_test.dart index 0828e8e989..5c03998bfc 100644 --- a/mobile/test/presentation/widgets/timeline/timeline_args_test.dart +++ b/mobile/test/presentation/widgets/timeline/timeline_args_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: close_sinks + import 'dart:async'; import 'package:flutter/material.dart'; diff --git a/mobile/test/services/deep_link_service_test.dart b/mobile/test/services/deep_link_service_test.dart index ff090367ea..16fa392f27 100644 --- a/mobile/test/services/deep_link_service_test.dart +++ b/mobile/test/services/deep_link_service_test.dart @@ -115,7 +115,7 @@ void main() { final route = await sut.handleMyImmichApp(link('/albums/$_albumId/photos/$_assetId'), ref); expect(route, isA()); - expect((route!.args as AssetViewerRouteArgs).currentAlbum, _album); + expect((route!.args! as AssetViewerRouteArgs).currentAlbum, _album); }); test('still opens the viewer when the album cannot be resolved', () async { @@ -125,7 +125,7 @@ void main() { final route = await sut.handleMyImmichApp(link('/albums/$_albumId/photos/$_assetId'), ref); expect(route, isA()); - expect((route!.args as AssetViewerRouteArgs).currentAlbum, isNull); + expect((route!.args! as AssetViewerRouteArgs).currentAlbum, isNull); }); test('plain photo link has no album', () async { @@ -134,7 +134,7 @@ void main() { final route = await sut.handleMyImmichApp(link('/photos/$_assetId'), ref); expect(route, isA()); - expect((route!.args as AssetViewerRouteArgs).currentAlbum, isNull); + expect((route!.args! as AssetViewerRouteArgs).currentAlbum, isNull); verifyNever(() => remoteAlbumService.get(any())); }); }