chore(mobile): Apply stricter linting rules for correctness (#30372)

* chore(mobile): Apply stricter linting rules for correctness

* Added discarded_futures rule
This commit is contained in:
Adam Gastineau
2026-07-30 19:39:24 +00:00
committed by GitHub
parent 6b99f02232
commit e7aace436d
125 changed files with 859 additions and 632 deletions
+11 -1
View File
@@ -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
@@ -23,7 +23,7 @@ class Onboarding {
}
factory Onboarding.fromMap(Map<String, Object?> 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<String, Object?> 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,
);
}
+1 -1
View File
@@ -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;
@@ -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;
@@ -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<int>(0, (acc, bucket) => acc + bucket.assetCount);
unawaited(
_mutex.run(() async {
final totalAssets = buckets.fold<int>(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());
}),
);
});
}
+2 -2
View File
@@ -32,7 +32,7 @@ class EventStream {
}
/// Closes the stream controller
void dispose() {
_controller.close();
Future<void> dispose() {
return _controller.close();
}
}
@@ -25,7 +25,7 @@ class AssetEditEntity extends Table with DriftDefaultsMixin {
}
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?> editParameterConverter = TypeConverter.jsonb(
fromJson: (json) => json as Map<String, Object?>,
fromJson: (json) => json! as Map<String, Object?>,
);
extension AssetEditEntityDataDomainEx on AssetEditEntityData {
@@ -17,5 +17,5 @@ class UserMetadataEntity extends Table with DriftDefaultsMixin {
}
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?> userMetadataConverter = TypeConverter.jsonb(
fromJson: (json) => json as Map<String, Object?>,
fromJson: (json) => json! as Map<String, Object?>,
);
@@ -358,12 +358,12 @@ class SyncStreamRepository extends DriftDatabaseRepository {
final map = metadata.value as Map<String, Object?>;
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,
+14 -12
View File
@@ -128,17 +128,17 @@ class ImmichAppState extends ConsumerState<ImmichApp> 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<ImmichApp> 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<ImmichApp> with WidgetsBindingObserve
@override
void reassemble() {
if (kDebugMode) {
NetworkRepository.init();
unawaited(NetworkRepository.init());
}
super.reassemble();
}
+19 -16
View File
@@ -43,7 +43,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
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<DriftBackupPage> {
@override
void dispose() {
super.dispose();
WakelockPlus.disable();
unawaited(WakelockPlus.disable());
}
@override
@@ -111,7 +111,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
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<DriftBackupPage> {
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<void> 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<void>(
Future<void> showBatteryOptimizationInfo() {
return showDialog<void>(
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(
@@ -214,34 +214,36 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
splashRadius: 16,
icon: Icon(Icons.info, size: 20, color: context.primaryColor),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
elevation: 5,
title: Text(
'backup_album_selection_page_selection_info',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: context.primaryColor,
unawaited(
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
).t(context: context),
content: SingleChildScrollView(
child: ListBody(
children: [
const Text(
'backup_album_selection_page_assets_scatter',
style: TextStyle(fontSize: 14),
).t(context: context),
],
elevation: 5,
title: Text(
'backup_album_selection_page_selection_info',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: context.primaryColor,
),
).t(context: context),
content: SingleChildScrollView(
child: ListBody(
children: [
const Text(
'backup_album_selection_page_assets_scatter',
style: TextStyle(fontSize: 14),
).t(context: context),
],
),
),
),
);
},
);
},
),
);
},
),
@@ -364,14 +366,14 @@ class _SelectedAlbumNameChips extends ConsumerWidget {
children: selectedBackupAlbums.asMap().entries.map((entry) {
final album = entry.value;
void removeSelection() {
ref.read(backupAlbumProvider.notifier).deselectAlbum(album);
Future<void> 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<void> 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));
}
}
}
+5 -3
View File
@@ -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),
),
@@ -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),
),
+3 -1
View File
@@ -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(
@@ -282,11 +282,13 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
@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<SplashScreenPage> {
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
+2 -2
View File
@@ -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();
}
@@ -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),
),
),
);
},
@@ -38,8 +38,8 @@ class PinAuthPage extends HookConsumerWidget {
}
}
void enableBiometricAuth() {
showDialog(
Future<void> 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),
@@ -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;
+4 -2
View File
@@ -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()));
},
),
],
@@ -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<void> getCurrentLocation() async {
@@ -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),
),
@@ -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(
@@ -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<void> scrollToBottom() {
return listViewScrollController.animateTo(
0,
duration: const Duration(milliseconds: 300),
curve: Curves.fastOutSlowIn,
);
}
Future<void> onAddComment(String comment) async {
await activityNotifier.addComment(comment);
scrollToBottom();
unawaited(scrollToBottom());
}
return ProviderScope(
@@ -53,7 +53,7 @@ class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
),
AlbumSelector(
onAlbumSelected: (album) {
context.router.push(RemoteAlbumRoute(album: album));
unawaited(context.router.push(RemoteAlbumRoute(album: album)));
},
),
],
@@ -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]),
),
);
},
),
);
}
@@ -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
@@ -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<DriftLockedFolderPage> 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(() {
@@ -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<void> onSettingsPressed(BuildContext context) {
return showModalBottomSheet(
elevation: 0.0,
showDragHandle: true,
isScrollControlled: true,
@@ -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<void> 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),
@@ -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<DriftPeopleCollectio
children: [
GestureDetector(
onTap: () {
context.pushRoute(DriftPersonRoute(person: person));
unawaited(context.pushRoute(DriftPersonRoute(person: person)));
},
child: Material(
shape: const CircleBorder(side: BorderSide.none),
@@ -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';
@@ -49,8 +51,8 @@ class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
}
}
void showOptionSheet(BuildContext context) {
showModalBottomSheet(
Future<void> showOptionSheet(BuildContext context) {
return showModalBottomSheet(
context: context,
backgroundColor: context.colorScheme.surface,
isScrollControlled: false,
@@ -67,7 +67,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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<DriftSlideshowPage> 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());
}
}
@@ -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<Set<UserDto>>({});
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(),
),
],
@@ -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()),
],
),
);
@@ -70,7 +70,7 @@ class PaginatedSearchNotifier extends StateNotifier<SearchState> {
@override
void dispose() {
_assetCountController.close();
unawaited(_assetCountController.close());
super.dispose();
}
}
@@ -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<AddActionButton> {
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<AddActionButton> {
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,
);
},
),
);
}
@@ -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,
@@ -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,
@@ -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<void> _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,
);
}
@@ -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;
},
@@ -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<void> _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,
);
}
@@ -63,7 +63,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
isGrid = albumConfig.isGrid;
});
ref.read(remoteAlbumProvider.notifier).refresh();
unawaited(ref.read(remoteAlbumProvider.notifier).refresh());
});
searchController.addListener(() {
@@ -81,7 +81,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
final userId = ref.read(currentUserProvider)?.id;
filter = filter.copyWith(query: searchTerm, userId: userId, mode: filterMode);
filterAlbums();
unawaited(filterAlbums());
}
Future<void> onRefresh() async {
@@ -92,7 +92,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
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<AlbumSelector> {
filter = filter.copyWith(mode: mode);
});
filterAlbums();
unawaited(filterAlbums());
}
Future<void> changeSort(AlbumSort sort) async {
@@ -121,7 +121,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
searchController.clear();
});
filterAlbums();
unawaited(filterAlbums());
}
Future<void> sortAlbums() async {
@@ -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<void> _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: [
@@ -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<LocationDetails> {
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!))));
}
}
}
@@ -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),
),
@@ -87,8 +87,8 @@ class _AssetPageState extends ConsumerState<AssetPage> {
@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<AssetPage> {
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<AssetPage> {
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<AssetPage> {
}
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(() {});
@@ -107,7 +107,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
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<AssetViewer> {
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<AssetViewer> {
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<AssetViewer> {
case ViewerReloadAssetEvent():
_onViewerReloadEvent();
case final ViewerStackAssetDeletedEvent event:
_onViewerStackAssetDeletedEvent(event);
unawaited(_onViewerStackAssetDeletedEvent(event));
default:
}
}
@@ -235,8 +235,8 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
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<void> _onViewerStackAssetDeletedEvent(ViewerStackAssetDeletedEvent event) async {
@@ -271,7 +271,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final totalAssets = timelineService.totalAssets;
if (totalAssets == 0) {
context.maybePop();
unawaited(context.maybePop());
return;
}
@@ -281,14 +281,14 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
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<AssetViewer> {
}
}
void _setSystemUIMode(bool controls, bool details) {
Future<void> _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<AssetViewer> {
ref.listen(assetViewerProvider.select((value) => (value.showingControls, value.showingDetails)), (_, state) {
final (controls, details) = state;
_setSystemUIMode(controls, details);
unawaited(_setSystemUIMode(controls, details));
});
return AnnotatedRegion(
@@ -82,7 +82,7 @@ class _OcrOverlayState extends ConsumerState<OcrOverlay> {
}
void _detachController() {
_controllerSub?.cancel();
unawaited(_controllerSub?.cancel());
_controllerSub = null;
}
@@ -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),
@@ -66,7 +66,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
if (!widget.isCurrent) {
_loadTimer?.cancel();
_notifier.pause();
unawaited(_notifier.pause());
return;
}
@@ -293,7 +293,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
_controller = nc;
if (widget.isCurrent) {
_loadVideo();
unawaited(_loadVideo());
}
}
@@ -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,
),
),
);
},
@@ -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<BaseBottomSheet>
}
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,
),
);
}
});
@@ -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<Color> _borderColors(BuildContext context) {
@@ -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);
},
);
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
@@ -43,10 +44,12 @@ mixin CancellableImageProviderMixin<T extends Object> 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<T extends Object> on CancellableImageProvide
final operation = cachedOperation;
if (operation != null) {
cachedOperation = null;
operation.cancel();
unawaited(operation.cancel());
}
if (hasActiveWork) {
@@ -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<Thumbnail> 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(() {
@@ -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<MapState> {
}
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());
}
@@ -66,7 +66,7 @@ class _DriftMapState extends ConsumerState<DriftMap> {
void dispose() {
_debouncer.dispose();
bottomSheetOffset.dispose();
_eventSubscription?.cancel();
unawaited(_eventSubscription?.cancel());
super.dispose();
}
@@ -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))
@@ -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
@@ -152,7 +152,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
void _resetThumbTimer() {
_fadeOutTimer?.cancel();
_fadeOutTimer = Timer(kTimelineScrubberFadeOutDuration, () {
_thumbAnimationController.reverse();
unawaited(_thumbAnimationController.reverse());
_fadeOutTimer = null;
});
}
@@ -177,10 +177,10 @@ class ScrubberState extends ConsumerState<Scrubber> 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<Scrubber> 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<Scrubber> with TickerProviderStateMixi
}
if (_thumbAnimationController.status != AnimationStatus.forward) {
_thumbAnimationController.forward();
unawaited(_thumbAnimationController.forward());
}
final dragPosition = _calculateDragPosition(details);
@@ -344,7 +344,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
}
void _onDragEnd(DragEndDetails _) {
_labelAnimationController.reverse();
unawaited(_labelAnimationController.reverse());
setState(() {
_isDragging = false;
});
@@ -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<void> _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);
@@ -120,7 +120,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
if (syncSuccess) {
await Future.wait([
_safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) {
_resumeBackup();
unawaited(_resumeBackup());
}),
_resumeBackup(),
// TODO: Bring back when the soft freeze issue is addressed
@@ -88,7 +88,7 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
}
void reset() {
_assetSubscription?.cancel();
unawaited(_assetSubscription?.cancel());
_assetSubscription = null;
state = const AssetViewerState();
}
@@ -102,7 +102,7 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
}
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);
@@ -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<List<ShareIntentAttac
router.removeWhere((route) => route.name == "ShareIntentRoute");
clearAttachments();
addAttachments(attachments);
router.push(ShareIntentRoute(attachments: attachments));
unawaited(router.push(ShareIntentRoute(attachments: attachments)));
}
void addAttachments(List<ShareIntentAttachment> attachments) {
@@ -50,7 +50,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
void dispose() {
_bufferingTimer?.cancel();
_seekTimer?.cancel();
WakelockPlus.disable();
unawaited(WakelockPlus.disable());
_controller = null;
super.dispose();
@@ -121,7 +121,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
}
_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<VideoPlayerState> {
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<VideoPlayerState> {
}
_holdStatus = state.status;
pause();
unawaited(pause());
}
/// Restores playback to the status before [hold] was called.
@@ -155,7 +155,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
switch (status) {
case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering:
play();
unawaited(play());
default:
}
}
@@ -238,7 +238,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
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<VideoPlayerState> {
}
void onNativePlaybackEnded() {
WakelockPlus.disable();
unawaited(WakelockPlus.disable());
_bufferingTimer?.cancel();
}
@@ -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, List<Loca
class BackupAlbumNotifier extends StateNotifier<List<LocalAlbum>> {
BackupAlbumNotifier(this._localAlbumService) : super([]) {
getAll();
unawaited(getAll());
}
final LocalAlbumService _localAlbumService;
+3 -1
View File
@@ -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<CastManagerState> {
}
void loadMedia(RemoteAsset asset, bool reload) {
_gCastService.loadMedia(asset, reload);
unawaited(_gCastService.loadMedia(asset, reload));
}
Future<void> connect(CastDestinationType type, dynamic device) async {
+7 -5
View File
@@ -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<CleanupState> {
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<CleanupState> {
}
void _persistExcludedAlbumIds(Set<String> albumIds) {
_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList());
unawaited(_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList()));
}
void cleanupStaleAlbumIds(Set<String> existingAlbumIds) {
@@ -144,7 +146,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
_persistExcludedAlbumIds(keepAlbumIds);
}
_settingsRepository.write(.cleanupDefaultsInitialized, true);
unawaited(_settingsRepository.write(.cleanupDefaultsInitialized, true));
}
Future<void> scanAssets() async {
@@ -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<PermissionStatus> {
: super(PermissionStatus.denied) // Denied is the initial state
{
// Sets the initial state
getGalleryPermissionStatus();
unawaited(getGalleryPermissionStatus());
}
bool get hasPermission => state.isGranted || state.isLimited;
@@ -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> {
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());
}
}
}
@@ -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<bool> {
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()));
}
}
@@ -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<BiometricStatus> {
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<bool> registerBiometric(BuildContext context, String pinCode) async {
@@ -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<MapState> {
}
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<MapState> {
}
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);
}
}
@@ -10,7 +10,7 @@ class NotificationPermissionNotifier extends StateNotifier<PermissionStatus> {
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
@@ -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<ServerInfo> {
void handleReleaseInfo(ServerVersion serverVersion, ServerVersion? latestVersion) {
// Update local server version
_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion);
unawaited(_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion));
}
Future<void> getServerFeatures() async {
@@ -8,7 +8,7 @@ class SharedLinksNotifier extends StateNotifier<AsyncValue<List<SharedLink>>> {
final SharedLinkService _sharedLinkService;
SharedLinksNotifier(this._sharedLinkService) : super(const AsyncLoading()) {
fetchLinks();
unawaited(fetchLinks());
}
Future<void> fetchLinks() async {
+1 -1
View File
@@ -22,7 +22,7 @@ class CurrentUserProvider extends StateNotifier<UserDto?> {
@override
void dispose() {
streamSub.cancel();
unawaited(streamSub.cancel());
super.dispose();
}
}
+4 -4
View File
@@ -143,8 +143,8 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
}
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<WebsocketState> {
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<WebsocketState> {
unawaited(
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
if (isSyncAlbumEnabled) {
_ref.read(backgroundSyncProvider).syncLinkedAlbum();
unawaited(_ref.read(backgroundSyncProvider).syncLinkedAlbum());
}
}),
);
@@ -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;
}),
);
}
}
@@ -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
+3 -1
View File
@@ -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<void> _setMapUserAgentHeader() async {
@@ -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());
}
}
+6 -4
View File
@@ -12,10 +12,12 @@ class AsyncMutex {
Future<T> run<T>(Future<T> Function() operation) {
final completer = Completer<T>();
_enqueued++;
_running.whenComplete(() {
_enqueued--;
completer.complete(Future<T>.sync(operation));
});
unawaited(
_running.whenComplete(() {
_enqueued--;
completer.complete(Future<T>.sync(operation));
}),
);
return _running = completer.future;
}
}
@@ -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<T> useAppSettingsState<T>(AppSettingsEnum<T> key) {
final notifier = useState<T>(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;
}
+9 -7
View File
@@ -15,13 +15,15 @@ Future<Uint8List> 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;
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
@@ -27,9 +28,9 @@ class AnimatedPlayPauseState extends State<AnimatedPlayPause> with SingleTickerP
super.didUpdateWidget(oldWidget);
if (widget.playing != oldWidget.playing) {
if (widget.playing) {
animationController.forward();
unawaited(animationController.forward());
} else {
animationController.reverse();
unawaited(animationController.reverse());
}
}
}
@@ -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,
@@ -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(),
),
@@ -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(
@@ -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<void> 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,
@@ -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<T> 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(
@@ -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,
@@ -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());
}
}
@@ -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());
}),
);
}
}
@@ -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());
}),
);
}
}
@@ -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());
}),
);
}
}
@@ -70,7 +70,8 @@ class LoginForm extends HookConsumerWidget {
final isOauthEnable = useState<bool>(false);
final isPasswordLoginEnable = useState<bool>(false);
final oAuthButtonLabel = useState<String>('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<String?>(null);
final loginFormKey = GlobalKey<FormState>();
@@ -358,7 +359,7 @@ class LoginForm extends HookConsumerWidget {
}
SingleChildRenderObjectWidget buildVersionCompatWarning() {
checkVersionMismatch();
unawaited(checkVersionMismatch());
if (warningMessage.value == null) {
return const SizedBox.shrink();

Some files were not shown because too many files have changed in this diff Show More