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: rules:
# Formatting # Formatting
avoid_print: true avoid_print: true
unawaited_futures: true
require_trailing_commas: true require_trailing_commas: true
unrelated_type_equality_checks: true unrelated_type_equality_checks: true
prefer_const_constructors: true prefer_const_constructors: true
@@ -50,6 +49,17 @@ linter:
avoid_multiple_declarations_per_line: true avoid_multiple_declarations_per_line: true
unnecessary_breaks: 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 # Known issues
avoid_slow_async_io: true avoid_slow_async_io: true
avoid_type_to_string: true avoid_type_to_string: true
@@ -23,7 +23,7 @@ class Onboarding {
} }
factory Onboarding.fromMap(Map<String, Object?> map) { factory Onboarding.fromMap(Map<String, Object?> map) {
return Onboarding(isOnboarded: map["isOnboarded"] as bool); return Onboarding(isOnboarded: map["isOnboarded"]! as bool);
} }
@override @override
@@ -195,9 +195,9 @@ class License {
factory License.fromMap(Map<String, Object?> map) { factory License.fromMap(Map<String, Object?> map) {
return License( return License(
activatedAt: DateTime.parse(map["activatedAt"] as String), activatedAt: DateTime.parse(map["activatedAt"]! as String),
activationKey: map["activationKey"] as String, activationKey: map["activationKey"]! as String,
licenseKey: map["licenseKey"] as String, licenseKey: map["licenseKey"]! as String,
); );
} }
+1 -1
View File
@@ -32,7 +32,7 @@ class HashService {
}) : _batchSize = batchSize ?? kBatchHashFileLimit { }) : _batchSize = batchSize ?? kBatchHashFileLimit {
// Stop the in-flight native hash call promptly on cancellation; the loops // Stop the in-flight native hash call promptly on cancellation; the loops
// below also observe [isCancelled] to bail between batches. // 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; bool get isCancelled => _cancellation?.isCompleted ?? false;
@@ -40,7 +40,7 @@ class LocalSyncService {
required this._permissionRepository, required this._permissionRepository,
this._cancellation, 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; bool get _isCancelled => _cancellation?.isCompleted ?? false;
@@ -106,32 +106,34 @@ class TimelineService {
TimelineService._({required this._assetSource, required this._bucketSource, required this.origin}) { TimelineService._({required this._assetSource, required this._bucketSource, required this.origin}) {
_bucketSubscription = _bucketSource().listen((buckets) { _bucketSubscription = _bucketSource().listen((buckets) {
_mutex.run(() async { unawaited(
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount); _mutex.run(() async {
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
if (totalAssets == 0) { if (totalAssets == 0) {
_bufferOffset = 0; _bufferOffset = 0;
_buffer = []; _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;
} else { } else {
offset = _bufferOffset; final int offset;
count = math.min(_buffer.length, totalAssets - _bufferOffset); 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 // change the state's total assets count only after the buffer is reloaded
_totalAssets = totalAssets; _totalAssets = totalAssets;
EventStream.shared.emit(const TimelineReloadEvent()); EventStream.shared.emit(const TimelineReloadEvent());
}); }),
);
}); });
} }
+2 -2
View File
@@ -32,7 +32,7 @@ class EventStream {
} }
/// Closes the stream controller /// Closes the stream controller
void dispose() { Future<void> dispose() {
_controller.close(); return _controller.close();
} }
} }
@@ -25,7 +25,7 @@ class AssetEditEntity extends Table with DriftDefaultsMixin {
} }
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?> editParameterConverter = TypeConverter.jsonb( 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 { extension AssetEditEntityDataDomainEx on AssetEditEntityData {
@@ -17,5 +17,5 @@ class UserMetadataEntity extends Table with DriftDefaultsMixin {
} }
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?> userMetadataConverter = TypeConverter.jsonb( 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 map = metadata.value as Map<String, Object?>;
final companion = RemoteAssetCloudIdEntityCompanion( final companion = RemoteAssetCloudIdEntityCompanion(
cloudId: Value(map['iCloudId']?.toString()), 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( 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), latitude: Value(map['latitude'] != null ? (double.tryParse(map['latitude']! as String)) : null),
longitude: Value(map['longitude'] != null ? (double.tryParse(map['longitude'] as String)) : null), longitude: Value(map['longitude'] != null ? (double.tryParse(map['longitude']! as String)) : null),
); );
batch.insert( batch.insert(
_db.remoteAssetCloudIdEntity, _db.remoteAssetCloudIdEntity,
+14 -12
View File
@@ -128,17 +128,17 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
switch (state) { switch (state) {
case AppLifecycleState.resumed: case AppLifecycleState.resumed:
dPrint(() => "[APP STATE] resumed"); dPrint(() => "[APP STATE] resumed");
ref.read(appStateProvider.notifier).handleAppResume(); unawaited(ref.read(appStateProvider.notifier).handleAppResume());
unawaited(ref.read(viewIntentHandlerProvider).onAppResumed()); unawaited(ref.read(viewIntentHandlerProvider).onAppResumed());
case AppLifecycleState.inactive: case AppLifecycleState.inactive:
dPrint(() => "[APP STATE] inactive"); dPrint(() => "[APP STATE] inactive");
ref.read(appStateProvider.notifier).handleAppInactivity(); ref.read(appStateProvider.notifier).handleAppInactivity();
case AppLifecycleState.paused: case AppLifecycleState.paused:
dPrint(() => "[APP STATE] paused"); dPrint(() => "[APP STATE] paused");
ref.read(appStateProvider.notifier).handleAppPause(); unawaited(ref.read(appStateProvider.notifier).handleAppPause());
case AppLifecycleState.detached: case AppLifecycleState.detached:
dPrint(() => "[APP STATE] detached"); dPrint(() => "[APP STATE] detached");
ref.read(appStateProvider.notifier).handleAppDetached(); unawaited(ref.read(appStateProvider.notifier).handleAppDetached());
case AppLifecycleState.hidden: case AppLifecycleState.hidden:
dPrint(() => "[APP STATE] hidden"); dPrint(() => "[APP STATE] hidden");
ref.read(appStateProvider.notifier).handleAppHidden(); ref.read(appStateProvider.notifier).handleAppHidden();
@@ -216,17 +216,19 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
@override @override
void initState() { void initState() {
super.initState(); super.initState();
initApp().then((_) => dPrint(() => "App Init Completed")); unawaited(initApp().then((_) => dPrint(() => "App Init Completed")));
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
// needs to be delayed so that EasyLocalization is working // needs to be delayed so that EasyLocalization is working
ref.read(backgroundWorkerFgServiceProvider).enable(); unawaited(ref.read(backgroundWorkerFgServiceProvider).enable());
if (Platform.isAndroid) { if (Platform.isAndroid) {
ref unawaited(
.read(backgroundWorkerFgServiceProvider) ref
.saveNotificationMessage( .read(backgroundWorkerFgServiceProvider)
StaticTranslations.instance.uploading_media, .saveNotificationMessage(
StaticTranslations.instance.backup_background_service_default_notification, StaticTranslations.instance.uploading_media,
); StaticTranslations.instance.backup_background_service_default_notification,
),
);
} }
}); });
@@ -243,7 +245,7 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
@override @override
void reassemble() { void reassemble() {
if (kDebugMode) { if (kDebugMode) {
NetworkRepository.init(); unawaited(NetworkRepository.init());
} }
super.reassemble(); super.reassemble();
} }
+19 -16
View File
@@ -43,7 +43,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
void initState() { void initState() {
super.initState(); super.initState();
WakelockPlus.enable(); unawaited(WakelockPlus.enable());
final currentUser = ref.read(currentUserProvider); final currentUser = ref.read(currentUserProvider);
if (currentUser == null) { if (currentUser == null) {
@@ -69,7 +69,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
WakelockPlus.disable(); unawaited(WakelockPlus.disable());
} }
@override @override
@@ -111,7 +111,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
title: Text("backup_controller_page_backup".t()), title: Text("backup_controller_page_backup".t()),
leading: IconButton( leading: IconButton(
onPressed: () { onPressed: () {
context.maybePop(true); unawaited(context.maybePop(true));
}, },
splashRadius: 24, splashRadius: 24,
icon: const Icon(Icons.arrow_back_ios_rounded), icon: const Icon(Icons.arrow_back_ios_rounded),
@@ -119,7 +119,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
actions: [ actions: [
IconButton( IconButton(
onPressed: () { onPressed: () {
context.pushRoute(const DriftBackupOptionsRoute()); unawaited(context.pushRoute(const DriftBackupOptionsRoute()));
}, },
icon: const Icon(Icons.settings_outlined), icon: const Icon(Icons.settings_outlined),
tooltip: "backup_options".t(context: context), tooltip: "backup_options".t(context: context),
@@ -207,8 +207,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
} }
} }
void showPermissionsDialog() { Future<void> showPermissionsDialog() {
showDialog( return showDialog(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
content: Text(context.t.notification_permission_dialog_content), content: Text(context.t.notification_permission_dialog_content),
@@ -225,7 +225,7 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
expanded: false, expanded: false,
onPressed: () { onPressed: () {
ContextHelper(context).pop(); ContextHelper(context).pop();
openAppSettings(); unawaited(openAppSettings());
}, },
), ),
], ],
@@ -233,8 +233,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
); );
} }
void showBatteryOptimizationInfo() { Future<void> showBatteryOptimizationInfo() {
showDialog<void>( return showDialog<void>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext ctx) { builder: (BuildContext ctx) {
@@ -246,7 +246,8 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
labelText: context.t.backup_controller_page_background_battery_info_link, labelText: context.t.backup_controller_page_background_battery_info_link,
variant: .ghost, variant: .ghost,
expanded: false, expanded: false,
onPressed: () => launchUrl(Uri.parse('https://dontkillmyapp.com'), mode: LaunchMode.externalApplication), onPressed: () =>
unawaited(launchUrl(Uri.parse('https://dontkillmyapp.com'), mode: LaunchMode.externalApplication)),
), ),
ImmichTextButton( ImmichTextButton(
labelText: context.t.backup_controller_page_background_battery_info_ok, 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), style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
onPressed: () { onPressed: () {
ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((p) { unawaited(
if (p == PermissionStatus.permanentlyDenied) { ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((p) {
showPermissionsDialog(); if (p == PermissionStatus.permanentlyDenied) {
} unawaited(showPermissionsDialog());
}); }
}),
);
}, },
), ),
if (notificationStatus != PermissionStatus.granted && batteryOptimizationStatus != PermissionStatus.granted) if (notificationStatus != PermissionStatus.granted && batteryOptimizationStatus != PermissionStatus.granted)
@@ -297,7 +300,7 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
onPressed: showBatteryOptimizationInfo, onPressed: () => unawaited(showBatteryOptimizationInfo()),
), ),
], ],
TextButton.icon( TextButton.icon(
@@ -214,34 +214,36 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
splashRadius: 16, splashRadius: 16,
icon: Icon(Icons.info, size: 20, color: context.primaryColor), icon: Icon(Icons.info, size: 20, color: context.primaryColor),
onPressed: () { onPressed: () {
showDialog( unawaited(
context: context, showDialog(
builder: (BuildContext context) { context: context,
return AlertDialog( builder: (BuildContext context) {
shape: const RoundedRectangleBorder( return AlertDialog(
borderRadius: BorderRadius.all(Radius.circular(10)), 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,
), ),
).t(context: context), elevation: 5,
content: SingleChildScrollView( title: Text(
child: ListBody( 'backup_album_selection_page_selection_info',
children: [ style: TextStyle(
const Text( fontSize: 16,
'backup_album_selection_page_assets_scatter', fontWeight: FontWeight.bold,
style: TextStyle(fontSize: 14), color: context.primaryColor,
).t(context: context), ),
], ).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) { children: selectedBackupAlbums.asMap().entries.map((entry) {
final album = entry.value; final album = entry.value;
void removeSelection() { Future<void> removeSelection() {
ref.read(backupAlbumProvider.notifier).deselectAlbum(album); return ref.read(backupAlbumProvider.notifier).deselectAlbum(album);
} }
return Padding( return Padding(
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0),
child: GestureDetector( child: GestureDetector(
onTap: removeSelection, onTap: () => unawaited(removeSelection()),
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut, curve: Curves.easeInOut,
@@ -387,7 +389,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget {
backgroundColor: context.primaryColor, backgroundColor: context.primaryColor,
deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white, deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white,
deleteIcon: const Icon(Icons.cancel_rounded, size: 15), 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) { children: excludedBackupAlbums.asMap().entries.map((entry) {
final album = entry.value; final album = entry.value;
void removeSelection() { Future<void> removeSelection() {
ref.read(backupAlbumProvider.notifier).deselectAlbum(album); return ref.read(backupAlbumProvider.notifier).deselectAlbum(album);
} }
return GestureDetector( return GestureDetector(
onTap: removeSelection, onTap: () => unawaited(removeSelection()),
child: Padding( child: Padding(
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0),
child: AnimatedContainer( child: AnimatedContainer(
@@ -427,7 +429,7 @@ class _ExcludedAlbumNameChips extends ConsumerWidget {
backgroundColor: Colors.red[300], backgroundColor: Colors.red[300],
deleteIconColor: context.scaffoldBackgroundColor, deleteIconColor: context.scaffoldBackgroundColor,
deleteIcon: const Icon(Icons.cancel_rounded, size: 15), 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) { for (final album in filteredAlbums) {
if (album.backupSelection != BackupSelection.selected) { 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) { for (final album in filteredAlbums) {
if (album.backupSelection == BackupSelection.selected) { 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:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -61,7 +63,7 @@ class AppLogPage extends HookConsumerWidget {
size: 20.0, size: 20.0,
), ),
onPressed: () { onPressed: () {
immichLogger.clearLogs(); unawaited(immichLogger.clearLogs());
shouldReload.value = !shouldReload.value; shouldReload.value = !shouldReload.value;
}, },
), ),
@@ -70,7 +72,7 @@ class AppLogPage extends HookConsumerWidget {
return IconButton( return IconButton(
icon: Icon(Icons.share_rounded, color: context.primaryColor, semanticLabel: "Share logs", size: 20.0), icon: Icon(Icons.share_rounded, color: context.primaryColor, semanticLabel: "Share logs", size: 20.0),
onPressed: () { onPressed: () {
ImmichLogger.shareLogs(iconContext); unawaited(ImmichLogger.shareLogs(iconContext));
}, },
); );
}, },
@@ -78,7 +80,7 @@ class AppLogPage extends HookConsumerWidget {
], ],
leading: IconButton( leading: IconButton(
onPressed: () { onPressed: () {
context.maybePop(); unawaited(context.maybePop());
}, },
icon: const Icon(Icons.arrow_back_ios_new_rounded, size: 20.0), 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:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -33,16 +35,18 @@ class AppLogDetailPage extends HookConsumerWidget {
), ),
IconButton( IconButton(
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: text)).then((_) { unawaited(
context.scaffoldMessenger.showSnackBar( Clipboard.setData(ClipboardData(text: text)).then((_) {
SnackBar( context.scaffoldMessenger.showSnackBar(
content: Text( SnackBar(
"copied_to_clipboard".tr(), content: Text(
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), "copied_to_clipboard".tr(),
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
),
), ),
), );
); }),
}); );
}, },
icon: Icon(Icons.copy, size: 16.0, 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:background_downloader/background_downloader.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.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(); final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList();
void onCancelDownload(String id) { void onCancelDownload(String id) {
ref.watch(downloadStateProvider.notifier).cancelDownload(id); unawaited(ref.watch(downloadStateProvider.notifier).cancelDownload(id));
} }
return Positioned( return Positioned(
@@ -282,11 +282,13 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
ref unawaited(
.read(authProvider.notifier) ref
.setOpenApiServiceEndpoint() .read(authProvider.notifier)
.then(logConnectionInfo) .setOpenApiServiceEndpoint()
.whenComplete(() => resumeSession()); .then(logConnectionInfo)
.whenComplete(() => resumeSession()),
);
} }
void logConnectionInfo(String? endpoint) { void logConnectionInfo(String? endpoint) {
@@ -327,7 +329,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
if (syncSuccess) { if (syncSuccess) {
await Future.wait([ await Future.wait([
backgroundManager.hashAssets().then((_) { backgroundManager.hashAssets().then((_) {
_resumeBackup(backupProvider); unawaited(_resumeBackup(backupProvider));
}), }),
_resumeBackup(backupProvider), _resumeBackup(backupProvider),
// TODO: Bring back when the soft freeze issue is addressed // 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 // Album page
if (index == kAlbumTabIndex) { if (index == kAlbumTabIndex) {
ref.read(remoteAlbumProvider.notifier).refresh(); unawaited(ref.read(remoteAlbumProvider.notifier).refresh());
} }
// Library page // Library page
@@ -168,7 +168,7 @@ class _BottomNavigationBarState extends ConsumerState<_BottomNavigationBar> {
@override @override
void dispose() { void dispose() {
_eventSubscription?.cancel(); unawaited(_eventSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -53,7 +55,7 @@ class FolderPage extends HookConsumerWidget {
useEffect(() { useEffect(() {
if (folder == null) { if (folder == null) {
ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value); unawaited(ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value));
} }
return null; return null;
}, []); }, []);
@@ -72,7 +74,7 @@ class FolderPage extends HookConsumerWidget {
void onToggleSortOrder() { void onToggleSortOrder() {
final newOrder = sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc; 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; sortOrder.value = newOrder;
} }
@@ -118,7 +120,7 @@ class FolderContent extends HookConsumerWidget {
if (folder == null) { if (folder == null) {
return; return;
} }
ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder); unawaited(ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder));
return null; return null;
}, [folder]); }, [folder]);
@@ -176,12 +178,14 @@ class FolderContent extends HookConsumerWidget {
(index, asset) => LargeLeadingTile( (index, asset) => LargeLeadingTile(
onTap: () { onTap: () {
AssetViewer.setAsset(ref, asset); AssetViewer.setAsset(ref, asset);
context.pushRoute( unawaited(
AssetViewerRoute( context.pushRoute(
initialIndex: index, AssetViewerRoute(
timelineService: ref initialIndex: index,
.read(timelineFactoryProvider) timelineService: ref
.fromAssets(folderAssets, TimelineOrigin.folder), .read(timelineFactoryProvider)
.fromAssets(folderAssets, TimelineOrigin.folder),
),
), ),
); );
}, },
@@ -38,8 +38,8 @@ class PinAuthPage extends HookConsumerWidget {
} }
} }
void enableBiometricAuth() { Future<void> enableBiometricAuth() {
showDialog( return showDialog(
context: context, context: context,
builder: (buildContext) { builder: (buildContext) {
return SimpleDialog( return SimpleDialog(
@@ -53,7 +53,7 @@ class PinAuthPage extends HookConsumerWidget {
description: 'enable_biometric_auth_description'.tr(), description: 'enable_biometric_auth_description'.tr(),
onSuccess: (pinCode) { onSuccess: (pinCode) {
Navigator.pop(buildContext); Navigator.pop(buildContext);
registerBiometric(pinCode); unawaited(registerBiometric(pinCode));
}, },
autoFocus: true, autoFocus: true,
icon: Icons.fingerprint_rounded, icon: Icons.fingerprint_rounded,
@@ -83,7 +83,7 @@ class PinAuthPage extends HookConsumerWidget {
child: PinVerificationForm( child: PinVerificationForm(
autoFocus: true, autoFocus: true,
onSuccess: (_) { 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), padding: const EdgeInsets.only(right: 16.0),
child: TextButton.icon( child: TextButton.icon(
icon: const Icon(Icons.fingerprint, size: 28), icon: const Icon(Icons.fingerprint, size: 28),
onPressed: enableBiometricAuth, onPressed: () => unawaited(enableBiometricAuth()),
label: Text( label: Text(
'use_biometric'.tr(), 'use_biometric'.tr(),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor, fontSize: 18), 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:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -17,7 +19,7 @@ class SharedLinkPage extends HookConsumerWidget {
final sharedLinks = ref.watch(sharedLinksStateProvider); final sharedLinks = ref.watch(sharedLinksStateProvider);
useEffect(() { useEffect(() {
ref.read(sharedLinksStateProvider.notifier).fetchLinks(); unawaited(ref.read(sharedLinksStateProvider.notifier).fetchLinks());
return () { return () {
if (!context.mounted) { if (!context.mounted) {
return; return;
+4 -2
View File
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
@@ -22,7 +24,7 @@ class LoginPage extends HookConsumerWidget {
} }
useEffect(() { useEffect(() {
getAppInfo(); unawaited(getAppInfo());
return null; return null;
}); });
@@ -55,7 +57,7 @@ class LoginPage extends HookConsumerWidget {
), ),
), ),
onTap: () { onTap: () {
context.pushRoute(const AppLogRoute()); unawaited(context.pushRoute(const AppLogRoute()));
}, },
), ),
], ],
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
@@ -37,7 +38,7 @@ class MapLocationPickerPage extends HookConsumerWidget {
} }
void onClose([LatLng? selected]) { void onClose([LatLng? selected]) {
context.maybePop(selected); unawaited(context.maybePop(selected));
} }
Future<void> getCurrentLocation() async { Future<void> getCurrentLocation() async {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -65,7 +67,7 @@ class ShareIntentPage extends ConsumerWidget {
), ),
leading: IconButton( leading: IconButton(
onPressed: () { onPressed: () {
context.navigateTo(const TabShellRoute()); unawaited(context.navigateTo(const TabShellRoute()));
}, },
icon: const Icon(Icons.arrow_back), icon: const Icon(Icons.arrow_back),
), ),
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.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(); final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList();
void onCancelDownload(String id) { void onCancelDownload(String id) {
ref.watch(downloadStateProvider.notifier).cancelDownload(id); unawaited(ref.watch(downloadStateProvider.notifier).cancelDownload(id));
} }
return Scaffold( return Scaffold(
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store; 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 activities = ref.watch(albumActivityProvider((album.id, assetId)));
final listViewScrollController = useScrollController(); final listViewScrollController = useScrollController();
void scrollToBottom() { Future<void> scrollToBottom() {
listViewScrollController.animateTo(0, duration: const Duration(milliseconds: 300), curve: Curves.fastOutSlowIn); return listViewScrollController.animateTo(
0,
duration: const Duration(milliseconds: 300),
curve: Curves.fastOutSlowIn,
);
} }
Future<void> onAddComment(String comment) async { Future<void> onAddComment(String comment) async {
await activityNotifier.addComment(comment); await activityNotifier.addComment(comment);
scrollToBottom(); unawaited(scrollToBottom());
} }
return ProviderScope( return ProviderScope(
@@ -53,7 +53,7 @@ class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
), ),
AlbumSelector( AlbumSelector(
onAlbumSelected: (album) { onAlbumSelected: (album) {
context.router.push(RemoteAlbumRoute(album: album)); unawaited(context.router.push(RemoteAlbumRoute(album: album)));
}, },
), ),
], ],
@@ -110,18 +110,20 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
]; ];
} }
showModalBottomSheet( unawaited(
backgroundColor: context.colorScheme.surfaceContainer, showModalBottomSheet(
isScrollControlled: false, backgroundColor: context.colorScheme.surfaceContainer,
context: context, isScrollControlled: false,
builder: (context) { context: context,
return SafeArea( builder: (context) {
child: Padding( return SafeArea(
padding: const EdgeInsets.only(top: 24.0), child: Padding(
child: Column(mainAxisSize: MainAxisSize.min, children: [...actions]), 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:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -78,11 +80,13 @@ class _AssetPropertiesSectionState extends ConsumerState<_AssetPropertiesSection
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_buildAssetProperties(widget.asset).whenComplete(() { unawaited(
if (mounted) { _buildAssetProperties(widget.asset).whenComplete(() {
setState(() {}); if (mounted) {
} setState(() {});
}); }
}),
);
} }
@override @override
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -39,8 +41,8 @@ class _DriftLockedFolderPageState extends ConsumerState<DriftLockedFolderPage> w
return; return;
} }
if (state == AppLifecycleState.paused) { if (state == AppLifecycleState.paused) {
ref.read(authProvider.notifier).lockPinCode(); unawaited(ref.read(authProvider.notifier).lockPinCode());
context.navigateTo(const TabShellRoute()); unawaited(context.navigateTo(const TabShellRoute()));
return; return;
} }
setState(() { setState(() {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
@@ -11,8 +13,8 @@ class DriftMapPage extends StatelessWidget {
const DriftMapPage({super.key, this.initialLocation}); const DriftMapPage({super.key, this.initialLocation});
void onSettingsPressed(BuildContext context) { Future<void> onSettingsPressed(BuildContext context) {
showModalBottomSheet( return showModalBottomSheet(
elevation: 0.0, elevation: 0.0,
showDragHandle: true, showDragHandle: true,
isScrollControlled: true, isScrollControlled: true,
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
@@ -47,21 +49,21 @@ class DriftMemoryPage extends HookConsumerWidget {
useEffect(() { useEffect(() {
// Memories is an immersive activity // Memories is an immersive activity
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); unawaited(SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive));
return () { return () {
// Clean up to normal edge to edge when we are done // Clean up to normal edge to edge when we are done
restoreEdgeToEdge(); unawaited(restoreEdgeToEdge());
}; };
}); });
void toNextMemory() { 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() { void toPreviousMemory() {
if (currentMemoryIndex.value > 0) { if (currentMemoryIndex.value > 0) {
// Move to the previous memory page // 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 // Wait for the next frame to ensure the page is built
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
@@ -88,7 +90,7 @@ class DriftMemoryPage extends HookConsumerWidget {
// Go to the next asset // Go to the next asset
final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; 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 { } else {
// Go to the next memory since we are at the end of our assets // Go to the next memory since we are at the end of our assets
toNextMemory(); toNextMemory();
@@ -100,7 +102,7 @@ class DriftMemoryPage extends HookConsumerWidget {
// Go to the previous asset // Go to the previous asset
final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; 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 { } else {
// Go to the previous memory since we are at the end of our assets // Go to the previous memory since we are at the end of our assets
toPreviousMemory(); toPreviousMemory();
@@ -153,7 +155,7 @@ class DriftMemoryPage extends HookConsumerWidget {
// Precache the next page right away if we are on the first page // Precache the next page right away if we are on the first page
if (currentAssetPage.value == 0) { 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 { Future<void> onAssetChanged(int otherIndex) async {
@@ -198,7 +200,7 @@ class DriftMemoryPage extends HookConsumerWidget {
final offset = notification.metrics.pixels; final offset = notification.metrics.pixels;
if (isEpiloguePage && (offset > notification.metrics.maxScrollExtent + 150)) { if (isEpiloguePage && (offset > notification.metrics.maxScrollExtent + 150)) {
context.maybePop(); unawaited(context.maybePop());
return true; return true;
} }
} }
@@ -328,8 +330,8 @@ class DriftMemoryPage extends HookConsumerWidget {
// auto_route doesn't invoke pop scope, so // auto_route doesn't invoke pop scope, so
// turn off full screen mode here // turn off full screen mode here
// https://github.com/Milad-Akarie/auto_route_library/issues/1799 // https://github.com/Milad-Akarie/auto_route_library/issues/1799
context.maybePop(); unawaited(context.maybePop());
restoreEdgeToEdge(); unawaited(restoreEdgeToEdge());
}, },
shape: const CircleBorder(), shape: const CircleBorder(),
color: Colors.white.withValues(alpha: 0.2), color: Colors.white.withValues(alpha: 0.2),
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -86,7 +88,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectio
children: [ children: [
GestureDetector( GestureDetector(
onTap: () { onTap: () {
context.pushRoute(DriftPersonRoute(person: person)); unawaited(context.pushRoute(DriftPersonRoute(person: person)));
}, },
child: Material( child: Material(
shape: const CircleBorder(side: BorderSide.none), shape: const CircleBorder(side: BorderSide.none),
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -49,8 +51,8 @@ class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
} }
} }
void showOptionSheet(BuildContext context) { Future<void> showOptionSheet(BuildContext context) {
showModalBottomSheet( return showModalBottomSheet(
context: context, context: context,
backgroundColor: context.colorScheme.surface, backgroundColor: context.colorScheme.surface,
isScrollControlled: false, isScrollControlled: false,
@@ -67,7 +67,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
_updateNextIndex(); _updateNextIndex();
ref.listenManual(appConfigProvider.select((s) => s.slideshow), _onConfigChanged); ref.listenManual(appConfigProvider.select((s) => s.slideshow), _onConfigChanged);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); unawaited(SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive));
unawaited(WakelockPlus.enable()); unawaited(WakelockPlus.enable());
} }
@@ -94,9 +94,9 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
if (asset.isImage) { if (asset.isImage) {
_createTimer(); _createTimer();
} else if (ref.read(videoPlayerProvider(asset.heroTag)).status == VideoPlaybackStatus.paused) { } 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 { } else {
_nextPage(); unawaited(_nextPage());
} }
_updateNextIndex(); _updateNextIndex();
@@ -113,7 +113,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
final asset = widget.timeline.getAssetSafe(_index)!; final asset = widget.timeline.getAssetSafe(_index)!;
if (!asset.isImage) { if (!asset.isImage) {
ref.read(videoPlayerProvider(asset.heroTag).notifier).pause(); unawaited(ref.read(videoPlayerProvider(asset.heroTag).notifier).pause());
} }
setState(() { setState(() {
@@ -147,7 +147,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
}; };
if (!widget.timeline.hasRange(_nextIndex, 1)) { 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; _crossfadeFromIndex = previousIndex;
_crossfadeToIndex = page; _crossfadeToIndex = page;
}); });
_crossfadeController.forward(from: 0.0).whenComplete(() { unawaited(
if (mounted) { _crossfadeController.forward(from: 0.0).whenComplete(() {
setState(() { if (mounted) {
_crossfadeFromIndex = null; setState(() {
_crossfadeToIndex = null; _crossfadeFromIndex = null;
}); _crossfadeToIndex = null;
} });
}); }
}),
);
} }
Widget _getCrossfadeLayer(BuildContext context, int index, {required bool isIncoming}) { 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), () { _timer = Timer(Duration(milliseconds: _config.duration * 1000 - _stopwatch.elapsedMilliseconds), () {
_stopwatch.stop(); _stopwatch.stop();
_stopwatch.reset(); _stopwatch.reset();
_nextPage(); unawaited(_nextPage());
}); });
_stopwatch.start(); _stopwatch.start();
@@ -376,9 +378,9 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
final position = ref.read(videoPlayerProvider(asset.heroTag)).position; final position = ref.read(videoPlayerProvider(asset.heroTag)).position;
if (status == VideoPlaybackStatus.completed && isCurrent && position.inMicroseconds > 0) { if (status == VideoPlaybackStatus.completed && isCurrent && position.inMicroseconds > 0) {
_nextPage(); unawaited(_nextPage());
} else if (status == VideoPlaybackStatus.playing) { } 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( return PhotoView.customChild(
@@ -418,7 +420,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
IconButton( IconButton(
onPressed: () { onPressed: () {
_pause(); _pause();
context.pushRoute(SettingsSubRoute(section: SettingSection.assetViewer)); unawaited(context.pushRoute(SettingsSubRoute(section: SettingSection.assetViewer)));
}, },
icon: const Icon(Icons.settings), icon: const Icon(Icons.settings),
), ),
@@ -512,7 +514,7 @@ class _SlideshowProgressBarState extends State<_SlideshowProgressBar> with Singl
animationBehavior: AnimationBehavior.preserve, animationBehavior: AnimationBehavior.preserve,
)..value = (widget.elapsedMs / widget.durationMs).clamp(0.0, 1.0); )..value = (widget.elapsedMs / widget.durationMs).clamp(0.0, 1.0);
if (!widget.paused) { if (!widget.paused) {
_controller.forward(); unawaited(_controller.forward());
} }
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -53,7 +55,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
final sharedUsersList = useState<Set<UserDto>>({}); final sharedUsersList = useState<Set<UserDto>>({});
void addNewUsersHandler() { 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) { Widget buildTileIcon(UserDto user) {
@@ -122,12 +124,12 @@ class DriftUserSelectionPage extends HookConsumerWidget {
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.close_rounded), icon: const Icon(Icons.close_rounded),
onPressed: () { onPressed: () {
context.maybePop(null); unawaited(context.maybePop(null));
}, },
), ),
actions: [ actions: [
TextButton( 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(), child: const Text("add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
), ),
], ],
@@ -105,20 +105,22 @@ class DriftSearchPage extends HookConsumerWidget {
return null; return null;
} }
Future.microtask(() { unawaited(
textSearchController.clear(); Future.microtask(() {
peopleCurrentFilterWidget.value = null; textSearchController.clear();
dateRangeCurrentFilterWidget.value = null; peopleCurrentFilterWidget.value = null;
cameraCurrentFilterWidget.value = null; dateRangeCurrentFilterWidget.value = null;
tagCurrentFilterWidget.value = null; cameraCurrentFilterWidget.value = null;
mediaTypeCurrentFilterWidget.value = null; tagCurrentFilterWidget.value = null;
ratingCurrentFilterWidget.value = null; mediaTypeCurrentFilterWidget.value = null;
displayOptionCurrentFilterWidget.value = null; ratingCurrentFilterWidget.value = null;
locationCurrentFilterWidget.value = preFilter.location.city != null displayOptionCurrentFilterWidget.value = null;
? Text(preFilter.location.city!, style: context.textTheme.labelLarge) locationCurrentFilterWidget.value = preFilter.location.city != null
: null; ? Text(preFilter.location.city!, style: context.textTheme.labelLarge)
search(preFilter); : null;
}); search(preFilter);
}),
);
return null; return null;
}, [preFilter]); }, [preFilter]);
@@ -141,17 +143,19 @@ class DriftSearchPage extends HookConsumerWidget {
search(filter.value.copyWith(people: people)); search(filter.value.copyWith(people: people));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
isScrollControlled: true, context: context,
child: FractionallySizedBox( isScrollControlled: true,
heightFactor: 0.8, child: FractionallySizedBox(
child: FilterBottomSheetScaffold( heightFactor: 0.8,
title: 'search_filter_people_title'.t(context: context), child: FilterBottomSheetScaffold(
expanded: true, title: 'search_filter_people_title'.t(context: context),
onSearch: handleApply, expanded: true,
onClear: handleClear, onSearch: handleApply,
child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people), onClear: handleClear,
child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people),
),
), ),
), ),
); );
@@ -176,17 +180,19 @@ class DriftSearchPage extends HookConsumerWidget {
search(filter.value.copyWith(tagIds: tagIds)); search(filter.value.copyWith(tagIds: tagIds));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
isScrollControlled: true, context: context,
child: FractionallySizedBox( isScrollControlled: true,
heightFactor: 0.8, child: FractionallySizedBox(
child: FilterBottomSheetScaffold( heightFactor: 0.8,
title: 'search_filter_tags_title'.t(context: context), child: FilterBottomSheetScaffold(
expanded: true, title: 'search_filter_tags_title'.t(context: context),
onSearch: handleApply, expanded: true,
onClear: handleClear, onSearch: handleApply,
child: TagPicker(onSelectExistingTag: handleOnSelect, filter: (filter.value.tagIds ?? []).toSet()), 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)); search(filter.value.copyWith(location: location));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
isScrollControlled: true, context: context,
isDismissible: true, isScrollControlled: true,
child: FilterBottomSheetScaffold( isDismissible: true,
title: 'search_filter_location_title'.t(context: context), child: FilterBottomSheetScaffold(
onSearch: handleApply, title: 'search_filter_location_title'.t(context: context),
onClear: handleClear, onSearch: handleApply,
child: Padding( onClear: handleClear,
padding: const EdgeInsets.symmetric(vertical: 16.0), child: Padding(
child: Container( padding: const EdgeInsets.symmetric(vertical: 16.0),
padding: EdgeInsets.only(bottom: context.viewInsets.bottom), child: Container(
child: Padding( padding: EdgeInsets.only(bottom: context.viewInsets.bottom),
padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Padding(
child: LocationPicker(onSelected: handleOnSelect, filter: filter.value.location), 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)); search(filter.value.copyWith(camera: camera));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
isScrollControlled: true, context: context,
isDismissible: true, isScrollControlled: true,
child: FilterBottomSheetScaffold( isDismissible: true,
title: 'search_filter_camera_title'.t(context: context), child: FilterBottomSheetScaffold(
onSearch: handleApply, title: 'search_filter_camera_title'.t(context: context),
onClear: handleClear, onSearch: handleApply,
child: Padding( onClear: handleClear,
padding: const EdgeInsets.all(16.0), child: Padding(
child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera), padding: const EdgeInsets.all(16.0),
child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera),
),
), ),
), ),
); );
@@ -339,22 +349,24 @@ class DriftSearchPage extends HookConsumerWidget {
} }
void showQuickDatePicker() { void showQuickDatePicker() {
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
child: FilterBottomSheetScaffold( context: context,
title: "pick_date_range".tr(), child: FilterBottomSheetScaffold(
expanded: true, title: "pick_date_range".tr(),
onClear: () => datePicked(null), expanded: true,
child: QuickDatePicker( onClear: () => datePicked(null),
currentInput: dateInputFilter.value, child: QuickDatePicker(
onRequestPicker: () { currentInput: dateInputFilter.value,
ContextHelper(context).pop(); onRequestPicker: () {
showDatePicker(); ContextHelper(context).pop();
}, unawaited(showDatePicker());
onSelect: (date) { },
ContextHelper(context).pop(); onSelect: (date) {
datePicked(date); ContextHelper(context).pop();
}, datePicked(date);
},
),
), ),
), ),
); );
@@ -383,13 +395,15 @@ class DriftSearchPage extends HookConsumerWidget {
search(filter.value.copyWith(mediaType: mediaType)); search(filter.value.copyWith(mediaType: mediaType));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
child: FilterBottomSheetScaffold( context: context,
title: 'search_filter_media_type_title'.t(context: context), child: FilterBottomSheetScaffold(
onSearch: handleApply, title: 'search_filter_media_type_title'.t(context: context),
onClear: handleClear, onSearch: handleApply,
child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType), onClear: handleClear,
child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType),
),
), ),
); );
} }
@@ -417,14 +431,16 @@ class DriftSearchPage extends HookConsumerWidget {
search(filter.value.copyWith(rating: rating)); search(filter.value.copyWith(rating: rating));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
isScrollControlled: true, context: context,
child: FilterBottomSheetScaffold( isScrollControlled: true,
title: 'rating'.t(context: context), child: FilterBottomSheetScaffold(
onSearch: handleApply, title: 'rating'.t(context: context),
onClear: handleClear, onSearch: handleApply,
child: StarRatingPicker(onSelect: handleOnSelected, filter: filter.value.rating), onClear: handleClear,
child: StarRatingPicker(onSelect: handleOnSelected, filter: filter.value.rating),
),
), ),
); );
} }
@@ -462,13 +478,15 @@ class DriftSearchPage extends HookConsumerWidget {
search(filter.value.copyWith(display: display)); search(filter.value.copyWith(display: display));
} }
showFilterBottomSheet( unawaited(
context: context, showFilterBottomSheet(
child: FilterBottomSheetScaffold( context: context,
title: 'display_options'.t(context: context), child: FilterBottomSheetScaffold(
onSearch: handleApply, title: 'display_options'.t(context: context),
onClear: handleClear, onSearch: handleApply,
child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display), onClear: handleClear,
child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display),
),
), ),
); );
} }
@@ -697,7 +715,7 @@ class DriftSearchPage extends HookConsumerWidget {
if (filter.value.isEmpty) if (filter.value.isEmpty)
const _SearchSuggestions() const _SearchSuggestions()
else else
_SearchResultGrid(onScrollEnd: loadMoreSearchResults), _SearchResultGrid(onScrollEnd: () => loadMoreSearchResults()),
], ],
), ),
); );
@@ -70,7 +70,7 @@ class PaginatedSearchNotifier extends StateNotifier<SearchState> {
@override @override
void dispose() { void dispose() {
_assetCountController.close(); unawaited(_assetCountController.close());
super.dispose(); super.dispose();
} }
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -36,11 +38,11 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
case AddToMenuItem.album: case AddToMenuItem.album:
_openAlbumSelector(); _openAlbumSelector();
case AddToMenuItem.archive: case AddToMenuItem.archive:
performArchiveAction(context, ref, source: ActionSource.viewer); unawaited(performArchiveAction(context, ref, source: ActionSource.viewer));
case AddToMenuItem.unarchive: case AddToMenuItem.unarchive:
performUnArchiveAction(context, ref, source: ActionSource.viewer); unawaited(performUnArchiveAction(context, ref, source: ActionSource.viewer));
case AddToMenuItem.lockedFolder: 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)), AlbumSelector(onAlbumSelected: (album) => _addCurrentAssetToAlbum(album)),
]; ];
showModalBottomSheet( unawaited(
context: context, showModalBottomSheet(
isScrollControlled: true, context: context,
backgroundColor: Colors.transparent, isScrollControlled: true,
builder: (_) { backgroundColor: Colors.transparent,
return BaseBottomSheet( builder: (_) {
actions: const [], return BaseBottomSheet(
slivers: slivers, actions: const [],
initialChildSize: 0.6, slivers: slivers,
minChildSize: 0.3, initialChildSize: 0.6,
maxChildSize: 0.95, minChildSize: 0.3,
expand: false, maxChildSize: 0.95,
backgroundColor: context.isDarkTheme ? Colors.black : Colors.white, expand: false,
); backgroundColor: context.isDarkTheme ? Colors.black : Colors.white,
}, );
},
),
); );
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.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 iconColor: isCasting ? context.primaryColor : null, // null = default color
label: "cast".t(context: context), label: "cast".t(context: context),
onPressed: () { onPressed: () {
showDialog(context: context, builder: (context) => const CastDialog()); unawaited(showDialog(context: context, builder: (context) => const CastDialog()));
}, },
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -33,7 +35,7 @@ class DownloadStatusFloatingButton extends ConsumerWidget {
: context.colorScheme.surfaceBright, : context.colorScheme.surfaceBright,
elevation: 2, elevation: 2,
onPressed: () { onPressed: () {
context.pushRoute(const DownloadInfoRoute()); unawaited(context.pushRoute(const DownloadInfoRoute()));
}, },
child: Stack( child: Stack(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.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}); 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) { if (!context.mounted) {
return; return;
} }
context.pushRoute(ProfilePictureCropRoute(asset: asset)); await context.pushRoute(ProfilePictureCropRoute(asset: asset));
} }
@override @override
@@ -28,7 +30,7 @@ class SetProfilePictureActionButton extends ConsumerWidget {
label: "set_as_profile_picture".t(context: context), label: "set_as_profile_picture".t(context: context),
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,
onPressed: () => _onTap(context), onPressed: () => unawaited(_onTap(context)),
maxWidth: 100, maxWidth: 100,
); );
} }
@@ -138,31 +138,33 @@ class ShareActionButton extends ConsumerWidget {
await showDialog( await showDialog(
context: context, context: context,
builder: (BuildContext buildContext) { builder: (BuildContext buildContext) {
ref unawaited(
.read(actionProvider.notifier) ref
.shareAssets( .read(actionProvider.notifier)
source, .shareAssets(
context, source,
fileType: fileType, context,
cancelCompleter: cancelCompleter, fileType: fileType,
onAssetDownloadProgress: (value) => progress.value = value, cancelCompleter: cancelCompleter,
) onAssetDownloadProgress: (value) => progress.value = value,
.then((ActionResult result) { )
if (cancelCompleter.isCompleted || !context.mounted) { .then((ActionResult result) {
return; if (cancelCompleter.isCompleted || !context.mounted) {
} return;
}
if (!result.success) { if (!result.success) {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: context.t.scaffold_body_error_occurred, msg: context.t.scaffold_body_error_occurred,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
toastType: ToastType.error, toastType: ToastType.error,
); );
} }
buildContext.pop(); buildContext.pop();
}); }),
);
return preparingDialog; return preparingDialog;
}, },
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.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}); 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) { if (!context.mounted) {
return; return;
} }
context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider))); await context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider)));
} }
@override @override
@@ -27,7 +29,7 @@ class SlideshowActionButton extends ConsumerWidget {
label: "slideshow".t(context: context), label: "slideshow".t(context: context),
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,
onPressed: () => _onTap(context, ref), onPressed: () => unawaited(_onTap(context, ref)),
maxWidth: 100, maxWidth: 100,
); );
} }
@@ -63,7 +63,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
isGrid = albumConfig.isGrid; isGrid = albumConfig.isGrid;
}); });
ref.read(remoteAlbumProvider.notifier).refresh(); unawaited(ref.read(remoteAlbumProvider.notifier).refresh());
}); });
searchController.addListener(() { searchController.addListener(() {
@@ -81,7 +81,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
final userId = ref.read(currentUserProvider)?.id; final userId = ref.read(currentUserProvider)?.id;
filter = filter.copyWith(query: searchTerm, userId: userId, mode: filterMode); filter = filter.copyWith(query: searchTerm, userId: userId, mode: filterMode);
filterAlbums(); unawaited(filterAlbums());
} }
Future<void> onRefresh() async { Future<void> onRefresh() async {
@@ -92,7 +92,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
setState(() { setState(() {
isGrid = !isGrid; isGrid = !isGrid;
}); });
ref.read(settingsProvider).write(.albumIsGrid, isGrid); unawaited(ref.read(settingsProvider).write(.albumIsGrid, isGrid));
} }
void changeFilter(QuickFilterMode mode) { void changeFilter(QuickFilterMode mode) {
@@ -100,7 +100,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
filter = filter.copyWith(mode: mode); filter = filter.copyWith(mode: mode);
}); });
filterAlbums(); unawaited(filterAlbums());
} }
Future<void> changeSort(AlbumSort sort) async { Future<void> changeSort(AlbumSort sort) async {
@@ -121,7 +121,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
searchController.clear(); searchController.clear();
}); });
filterAlbums(); unawaited(filterAlbums());
} }
Future<void> sortAlbums() async { Future<void> sortAlbums() async {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.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) { static Future<void> _openSheet(BuildContext context, String albumId) {
showModalBottomSheet( return showModalBottomSheet(
context: context, context: context,
showDragHandle: true, showDragHandle: true,
builder: (_) => _PendingUploadsSheet(albumId: albumId), builder: (_) => _PendingUploadsSheet(albumId: albumId),
@@ -97,7 +99,7 @@ class _PendingUploadsBannerContent extends StatelessWidget {
return Material( return Material(
color: hasFailures ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainerHigh, color: hasFailures ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainerHigh,
child: InkWell( child: InkWell(
onTap: () => PendingUploadsBanner._openSheet(context, albumId), onTap: () => unawaited(PendingUploadsBanner._openSheet(context, albumId)),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
@@ -48,7 +50,7 @@ class _LocationDetailsState extends ConsumerState<LocationDetails> {
if (widget.exifInfo != oldWidget.exifInfo) { if (widget.exifInfo != oldWidget.exifInfo) {
final exif = widget.exifInfo; final exif = widget.exifInfo;
if (exif != null && exif.hasCoordinates) { 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:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -74,7 +76,7 @@ class PeopleDetails extends ConsumerWidget {
return; return;
} }
ContextHelper(context).pop(); ContextHelper(context).pop();
context.pushRoute(DriftPersonRoute(person: person)); unawaited(context.pushRoute(DriftPersonRoute(person: person)));
}, },
onNameTap: () => showNameEditModal(person), onNameTap: () => showNameEditModal(person),
), ),
@@ -87,8 +87,8 @@ class _AssetPageState extends ConsumerState<AssetPage> {
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose();
_scaleBoundarySub?.cancel(); unawaited(_scaleBoundarySub?.cancel());
_eventSubscription?.cancel(); unawaited(_eventSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -112,7 +112,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
return; return;
} }
_viewer.setShowingDetails(true); _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) => bool _willClose(double scrollVelocity) =>
@@ -199,7 +199,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
case _DragIntent.dismiss: case _DragIntent.dismiss:
const popThreshold = 75.0; const popThreshold = 75.0;
if (details.localPosition.dy - start!.localPosition.dy > popThreshold) { if (details.localPosition.dy - start!.localPosition.dy > popThreshold) {
context.maybePop(); unawaited(context.maybePop());
return; return;
} }
_viewController?.animateMultiple( _viewController?.animateMultiple(
@@ -292,14 +292,14 @@ class _AssetPageState extends ConsumerState<AssetPage> {
} }
void _listenForScaleBoundaries(PhotoViewControllerBase? controller) { void _listenForScaleBoundaries(PhotoViewControllerBase? controller) {
_scaleBoundarySub?.cancel(); unawaited(_scaleBoundarySub?.cancel());
_scaleBoundarySub = null; _scaleBoundarySub = null;
if (controller == null || controller.scaleBoundaries != null) { if (controller == null || controller.scaleBoundaries != null) {
return; return;
} }
_scaleBoundarySub = controller.outputStateStream.listen((_) { _scaleBoundarySub = controller.outputStateStream.listen((_) {
if (controller.scaleBoundaries != null) { if (controller.scaleBoundaries != null) {
_scaleBoundarySub?.cancel(); unawaited(_scaleBoundarySub?.cancel());
_scaleBoundarySub = null; _scaleBoundarySub = null;
if (mounted) { if (mounted) {
setState(() {}); setState(() {});
@@ -107,7 +107,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final maxPage = _totalAssets - 1; final maxPage = _totalAssets - 1;
if (target >= 0 && target <= maxPage) { if (target >= 0 && target <= maxPage) {
_pageController.jumpToPage(target); _pageController.jumpToPage(target);
_onAssetChanged(target); unawaited(_onAssetChanged(target));
} }
} }
@@ -126,14 +126,14 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
WidgetsBinding.instance.addPostFrameCallback(_onAssetInit); WidgetsBinding.instance.addPostFrameCallback(_onAssetInit);
final assetViewer = ref.read(assetViewerProvider); final assetViewer = ref.read(assetViewerProvider);
_setSystemUIMode(assetViewer.showingControls, assetViewer.showingDetails); unawaited(_setSystemUIMode(assetViewer.showingControls, assetViewer.showingDetails));
} }
@override @override
void dispose() { void dispose() {
_pageController.dispose(); _pageController.dispose();
_preloader.dispose(); _preloader.dispose();
_reloadSubscription?.cancel(); unawaited(_reloadSubscription?.cancel());
_stackChildrenKeepAlive?.close(); _stackChildrenKeepAlive?.close();
unawaited(restoreEdgeToEdge()); unawaited(restoreEdgeToEdge());
@@ -157,7 +157,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final page = _pageController.page?.round(); final page = _pageController.page?.round();
if (page != null && page != _currentPage) { if (page != null && page != _currentPage) {
_onAssetChanged(page); unawaited(_onAssetChanged(page));
} }
return false; return false;
} }
@@ -223,7 +223,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
case ViewerReloadAssetEvent(): case ViewerReloadAssetEvent():
_onViewerReloadEvent(); _onViewerReloadEvent();
case final ViewerStackAssetDeletedEvent event: case final ViewerStackAssetDeletedEvent event:
_onViewerStackAssetDeletedEvent(event); unawaited(_onViewerStackAssetDeletedEvent(event));
default: default:
} }
} }
@@ -235,8 +235,8 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final index = _pageController.page?.round() ?? 0; final index = _pageController.page?.round() ?? 0;
final target = index >= _totalAssets - 1 ? index - 1 : index + 1; final target = index >= _totalAssets - 1 ? index - 1 : index + 1;
_pageController.animateToPage(target, duration: Durations.medium1, curve: Curves.easeInOut); unawaited(_pageController.animateToPage(target, duration: Durations.medium1, curve: Curves.easeInOut));
_onAssetChanged(target); unawaited(_onAssetChanged(target));
} }
Future<void> _onViewerStackAssetDeletedEvent(ViewerStackAssetDeletedEvent event) async { Future<void> _onViewerStackAssetDeletedEvent(ViewerStackAssetDeletedEvent event) async {
@@ -271,7 +271,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final totalAssets = timelineService.totalAssets; final totalAssets = timelineService.totalAssets;
if (totalAssets == 0) { if (totalAssets == 0) {
context.maybePop(); unawaited(context.maybePop());
return; return;
} }
@@ -281,14 +281,14 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
if (index != _currentPage) { if (index != _currentPage) {
_pageController.jumpToPage(index); _pageController.jumpToPage(index);
_onAssetChanged(index); unawaited(_onAssetChanged(index));
} else if (currentAsset is RemoteAsset && currentAsset.stackId != null && assetIndex == null) { } else if (currentAsset is RemoteAsset && currentAsset.stackId != null && assetIndex == null) {
final timelineAsset = timelineService.getAssetSafe(index); final timelineAsset = timelineService.getAssetSafe(index);
if (timelineAsset is! RemoteAsset || currentAsset.stackId != timelineAsset.stackId) { if (timelineAsset is! RemoteAsset || currentAsset.stackId != timelineAsset.stackId) {
_onAssetChanged(index); unawaited(_onAssetChanged(index));
} }
} else if (currentAsset != null && assetIndex == null) { } else if (currentAsset != null && assetIndex == null) {
_onAssetChanged(index); unawaited(_onAssetChanged(index));
} }
if (_totalAssets != totalAssets) { 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); final immersive = !controls || (CurrentPlatform.isIOS && details);
unawaited(immersive ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky) : restoreEdgeToEdge()); return immersive ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky) : restoreEdgeToEdge();
} }
@override @override
@@ -324,7 +324,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
ref.listen(assetViewerProvider.select((value) => (value.showingControls, value.showingDetails)), (_, state) { ref.listen(assetViewerProvider.select((value) => (value.showingControls, value.showingDetails)), (_, state) {
final (controls, details) = state; final (controls, details) = state;
_setSystemUIMode(controls, details); unawaited(_setSystemUIMode(controls, details));
}); });
return AnnotatedRegion( return AnnotatedRegion(
@@ -82,7 +82,7 @@ class _OcrOverlayState extends ConsumerState<OcrOverlay> {
} }
void _detachController() { void _detachController() {
_controllerSub?.cancel(); unawaited(_controllerSub?.cancel());
_controllerSub = null; _controllerSub = null;
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -26,7 +28,7 @@ class SheetTile extends ConsumerWidget {
}); });
void copyTitle(BuildContext context, WidgetRef ref) { void copyTitle(BuildContext context, WidgetRef ref) {
Clipboard.setData(ClipboardData(text: title)); unawaited(Clipboard.setData(ClipboardData(text: title)));
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'copied_to_clipboard'.t(context: context), msg: 'copied_to_clipboard'.t(context: context),
@@ -66,7 +66,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
if (!widget.isCurrent) { if (!widget.isCurrent) {
_loadTimer?.cancel(); _loadTimer?.cancel();
_notifier.pause(); unawaited(_notifier.pause());
return; return;
} }
@@ -293,7 +293,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
_controller = nc; _controller = nc;
if (widget.isCurrent) { if (widget.isCurrent) {
_loadVideo(); unawaited(_loadVideo());
} }
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -52,11 +54,13 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
IconButton( IconButton(
icon: const Icon(Icons.chat_outlined), icon: const Icon(Icons.chat_outlined),
onPressed: () { onPressed: () {
context.router.push( unawaited(
DriftActivitiesRoute( context.router.push(
album: album, DriftActivitiesRoute(
assetId: asset is RemoteAsset ? asset.id : null, album: album,
assetName: asset.name, assetId: asset is RemoteAsset ? asset.id : null,
assetName: asset.name,
),
), ),
); );
}, },
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.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) { if (previous?.isInteracting != true && next.isInteracting) {
_controller.animateTo( unawaited(
widget.minChildSize, _controller.animateTo(
duration: const Duration(milliseconds: 200), widget.minChildSize,
curve: Curves.easeInOut, duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
),
); );
} }
}); });
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -60,7 +61,7 @@ class _FeatureMessageDialogState extends State<_FeatureMessageDialog> with Singl
Navigator.of(context).pop(); Navigator.of(context).pop();
return; 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) { List<Color> _borderColors(BuildContext context) {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
@@ -30,7 +32,7 @@ class FullImage extends StatelessWidget {
height: size.height, height: size.height,
fit: fit, fit: fit,
errorBuilder: (context, error, stackTrace) { errorBuilder: (context, error, stackTrace) {
provider.evict(); unawaited(provider.evict());
return const Icon(Icons.image_not_supported_outlined, size: 32); return const Icon(Icons.image_not_supported_outlined, size: 32);
}, },
); );
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui; import 'dart:ui' as ui;
@@ -43,10 +44,12 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
return cachedImage; return cachedImage;
} }
completer.operation.valueOrCancellation().whenComplete(() { unawaited(
cachedStream.removeListener(listener); completer.operation.valueOrCancellation().whenComplete(() {
cachedOperation = null; cachedStream.removeListener(listener);
}); cachedOperation = null;
}),
);
cachedOperation = completer.operation; cachedOperation = completer.operation;
return null; return null;
} }
@@ -138,7 +141,7 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
final operation = cachedOperation; final operation = cachedOperation;
if (operation != null) { if (operation != null) {
cachedOperation = null; cachedOperation = null;
operation.cancel(); unawaited(operation.cancel());
} }
if (hasActiveWork) { if (hasActiveWork) {
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -130,9 +131,9 @@ class _ThumbnailState extends State<Thumbnail> with SingleTickerProviderStateMix
if ((synchronousCall && _providerImage == null) || !_isVisible()) { if ((synchronousCall && _providerImage == null) || !_isVisible()) {
_fadeController.value = 1.0; _fadeController.value = 1.0;
} else if (_fadeController.isAnimating) { } else if (_fadeController.isAnimating) {
_fadeController.forward(); unawaited(_fadeController.forward());
} else { } else {
_fadeController.forward(from: 0.0); unawaited(_fadeController.forward(from: 0.0));
} }
setState(() { setState(() {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/events.model.dart'; import 'package:immich_mobile/domain/models/events.model.dart';
@@ -87,32 +89,32 @@ class MapStateNotifier extends Notifier<MapState> {
} }
void switchFavoriteOnly(bool isFavoriteOnly) { void switchFavoriteOnly(bool isFavoriteOnly) {
ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly); unawaited(ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly));
state = state.copyWith(onlyFavorites: isFavoriteOnly); state = state.copyWith(onlyFavorites: isFavoriteOnly);
EventStream.shared.emit(const MapMarkerReloadEvent()); EventStream.shared.emit(const MapMarkerReloadEvent());
} }
void switchIncludeArchived(bool isIncludeArchived) { void switchIncludeArchived(bool isIncludeArchived) {
ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived); unawaited(ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived));
state = state.copyWith(includeArchived: isIncludeArchived); state = state.copyWith(includeArchived: isIncludeArchived);
EventStream.shared.emit(const MapMarkerReloadEvent()); EventStream.shared.emit(const MapMarkerReloadEvent());
} }
void switchWithPartners(bool isWithPartners) { void switchWithPartners(bool isWithPartners) {
ref.read(settingsProvider).write(.mapWithPartners, isWithPartners); unawaited(ref.read(settingsProvider).write(.mapWithPartners, isWithPartners));
state = state.copyWith(withPartners: isWithPartners); state = state.copyWith(withPartners: isWithPartners);
EventStream.shared.emit(const MapMarkerReloadEvent()); EventStream.shared.emit(const MapMarkerReloadEvent());
} }
void setRelativeTime(int relativeDays) { void setRelativeTime(int relativeDays) {
ref.read(settingsProvider).write(.mapRelativeDate, relativeDays); unawaited(ref.read(settingsProvider).write(.mapRelativeDate, relativeDays));
state = state.copyWith(relativeDays: relativeDays); state = state.copyWith(relativeDays: relativeDays);
EventStream.shared.emit(const MapMarkerReloadEvent()); EventStream.shared.emit(const MapMarkerReloadEvent());
} }
void setCustomTimeRange(TimeRange range) { void setCustomTimeRange(TimeRange range) {
ref.read(settingsProvider).write(.mapCustomFrom, range.from); unawaited(ref.read(settingsProvider).write(.mapCustomFrom, range.from));
ref.read(settingsProvider).write(.mapCustomTo, range.to); unawaited(ref.read(settingsProvider).write(.mapCustomTo, range.to));
state = state.copyWith(timeRange: range); state = state.copyWith(timeRange: range);
EventStream.shared.emit(const MapMarkerReloadEvent()); EventStream.shared.emit(const MapMarkerReloadEvent());
} }
@@ -66,7 +66,7 @@ class _DriftMapState extends ConsumerState<DriftMap> {
void dispose() { void dispose() {
_debouncer.dispose(); _debouncer.dispose();
bottomSheetOffset.dispose(); bottomSheetOffset.dispose();
_eventSubscription?.cancel(); unawaited(_eventSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -33,7 +35,7 @@ class DriftMemoryLane extends ConsumerWidget {
if (memories[index].assets.isNotEmpty) { if (memories[index].assets.isNotEmpty) {
DriftMemoryPage.setMemory(ref, memories[index]); DriftMemoryPage.setMemory(ref, memories[index]);
} }
context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)); unawaited(context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)));
}, },
children: memories children: memories
.map((memory) => DriftMemoryCard(key: Key(memory.id), memory: memory)) .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:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -105,7 +107,7 @@ class _BulkSelectIconButton extends ConsumerWidget {
? const SizedBox.shrink() ? const SizedBox.shrink()
: IconButton( : IconButton(
onPressed: () { onPressed: () {
ref.read(multiSelectProvider.notifier).toggleBucketSelection(assetOffset, bucket.assetCount); unawaited(ref.read(multiSelectProvider.notifier).toggleBucketSelection(assetOffset, bucket.assetCount));
ref.read(hapticFeedbackProvider.notifier).heavyImpact(); ref.read(hapticFeedbackProvider.notifier).heavyImpact();
}, },
icon: isAllSelected icon: isAllSelected
@@ -152,7 +152,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
void _resetThumbTimer() { void _resetThumbTimer() {
_fadeOutTimer?.cancel(); _fadeOutTimer?.cancel();
_fadeOutTimer = Timer(kTimelineScrubberFadeOutDuration, () { _fadeOutTimer = Timer(kTimelineScrubberFadeOutDuration, () {
_thumbAnimationController.reverse(); unawaited(_thumbAnimationController.reverse());
_fadeOutTimer = null; _fadeOutTimer = null;
}); });
} }
@@ -177,10 +177,10 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
if (notification is ScrollUpdateNotification) { if (notification is ScrollUpdateNotification) {
_thumbTopOffset = _currentOffset; _thumbTopOffset = _currentOffset;
if (_labelAnimation.status != AnimationStatus.reverse) { if (_labelAnimation.status != AnimationStatus.reverse) {
_labelAnimationController.reverse(); unawaited(_labelAnimationController.reverse());
} }
if (_thumbAnimationController.status != AnimationStatus.forward) { if (_thumbAnimationController.status != AnimationStatus.forward) {
_thumbAnimationController.forward(); unawaited(_thumbAnimationController.forward());
} }
} }
_resetThumbTimer(); _resetThumbTimer();
@@ -210,7 +210,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
void _onDragStart(DragStartDetails _) { void _onDragStart(DragStartDetails _) {
setState(() { setState(() {
_isDragging = true; _isDragging = true;
_labelAnimationController.forward(); unawaited(_labelAnimationController.forward());
_fadeOutTimer?.cancel(); _fadeOutTimer?.cancel();
_lastLabel = null; _lastLabel = null;
}); });
@@ -226,7 +226,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
} }
if (_thumbAnimationController.status != AnimationStatus.forward) { if (_thumbAnimationController.status != AnimationStatus.forward) {
_thumbAnimationController.forward(); unawaited(_thumbAnimationController.forward());
} }
final dragPosition = _calculateDragPosition(details); final dragPosition = _calculateDragPosition(details);
@@ -344,7 +344,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
} }
void _onDragEnd(DragEndDetails _) { void _onDragEnd(DragEndDetails _) {
_labelAnimationController.reverse(); unawaited(_labelAnimationController.reverse());
setState(() { setState(() {
_isDragging = false; _isDragging = false;
}); });
@@ -258,7 +258,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
_scrollController.dispose(); _scrollController.dispose();
_eventSubscription?.cancel(); unawaited(_eventSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -269,9 +269,11 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi
final timelineState = ref.read(timelineStateProvider.notifier); final timelineState = ref.read(timelineStateProvider.notifier);
timelineState.setScrubbing(true); timelineState.setScrubbing(true);
_scrollController unawaited(
.animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) _scrollController
.whenComplete(() => timelineState.setScrubbing(false)); .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut)
.whenComplete(() => timelineState.setScrubbing(false)),
);
} }
void _scrollToDate(DateTime date) { 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 // Scroll to the segment with a small offset to show the header
final targetOffset = fallbackSegment.startOffset - 50; final targetOffset = fallbackSegment.startOffset - 50;
timelineState.setScrubbing(true); timelineState.setScrubbing(true);
_scrollController unawaited(
.animateTo( _scrollController
targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), .animateTo(
duration: const Duration(milliseconds: 500), targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent),
curve: Curves.easeInOut, duration: const Duration(milliseconds: 500),
) curve: Curves.easeInOut,
.whenComplete(() => timelineState.setScrubbing(false)); )
.whenComplete(() => timelineState.setScrubbing(false)),
);
} else { } else {
timelineState.setScrubbing(false); timelineState.setScrubbing(false);
} }
@@ -344,8 +348,8 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi
}); });
} }
void _dragScroll(ScrollDirection direction) { Future<void> _dragScroll(ScrollDirection direction) {
_scrollController.animateTo( return _scrollController.animateTo(
_scrollController.offset + (direction == ScrollDirection.forward ? 175 : -175), _scrollController.offset + (direction == ScrollDirection.forward ? 175 : -175),
duration: const Duration(milliseconds: 125), duration: const Duration(milliseconds: 125),
curve: Curves.easeOut, curve: Curves.easeOut,
@@ -488,7 +492,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> with WidgetsBi
_restoreAssetIndex = targetAssetIndex; _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, onStart: !isReadonlyModeEnabled ? _setDragStartIndex : null,
onAssetEnter: _handleDragAssetEnter, onAssetEnter: _handleDragAssetEnter,
onEnd: !isReadonlyModeEnabled ? _stopDrag : null, onEnd: !isReadonlyModeEnabled ? _stopDrag : null,
onScroll: _dragScroll, onScroll: (direction) => unawaited(_dragScroll(direction)),
onScrollStart: () { onScrollStart: () {
// Minimize the bottom sheet when drag selection starts // Minimize the bottom sheet when drag selection starts
ref.read(timelineStateProvider.notifier).setScrolling(true); ref.read(timelineStateProvider.notifier).setScrolling(true);
@@ -120,7 +120,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
if (syncSuccess) { if (syncSuccess) {
await Future.wait([ await Future.wait([
_safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) { _safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) {
_resumeBackup(); unawaited(_resumeBackup());
}), }),
_resumeBackup(), _resumeBackup(),
// TODO: Bring back when the soft freeze issue is addressed // TODO: Bring back when the soft freeze issue is addressed
@@ -88,7 +88,7 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
} }
void reset() { void reset() {
_assetSubscription?.cancel(); unawaited(_assetSubscription?.cancel());
_assetSubscription = null; _assetSubscription = null;
state = const AssetViewerState(); state = const AssetViewerState();
} }
@@ -102,7 +102,7 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
} }
void _watchCurrentAsset(BaseAsset asset) { void _watchCurrentAsset(BaseAsset asset) {
_assetSubscription?.cancel(); unawaited(_assetSubscription?.cancel());
_assetSubscription = ref.read(assetServiceProvider).watchAsset(asset).listen((updated) { _assetSubscription = ref.read(assetServiceProvider).watchAsset(asset).listen((updated) {
if (updated != null) { if (updated != null) {
state = state.copyWith(currentAsset: updated); state = state.copyWith(currentAsset: updated);
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -33,7 +34,7 @@ class ShareIntentUploadStateNotifier extends StateNotifier<List<ShareIntentAttac
router.removeWhere((route) => route.name == "ShareIntentRoute"); router.removeWhere((route) => route.name == "ShareIntentRoute");
clearAttachments(); clearAttachments();
addAttachments(attachments); addAttachments(attachments);
router.push(ShareIntentRoute(attachments: attachments)); unawaited(router.push(ShareIntentRoute(attachments: attachments)));
} }
void addAttachments(List<ShareIntentAttachment> attachments) { void addAttachments(List<ShareIntentAttachment> attachments) {
@@ -50,7 +50,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
void dispose() { void dispose() {
_bufferingTimer?.cancel(); _bufferingTimer?.cancel();
_seekTimer?.cancel(); _seekTimer?.cancel();
WakelockPlus.disable(); unawaited(WakelockPlus.disable());
_controller = null; _controller = null;
super.dispose(); super.dispose();
@@ -121,7 +121,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
} }
_seekTimer = Timer(const Duration(milliseconds: 150), () { _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) { switch (state.status) {
case VideoPlaybackStatus.paused: case VideoPlaybackStatus.paused:
play(); unawaited(play());
case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering: case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering:
pause(); unawaited(pause());
case VideoPlaybackStatus.completed: case VideoPlaybackStatus.completed:
restart(); unawaited(restart());
} }
} }
@@ -145,7 +145,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
} }
_holdStatus = state.status; _holdStatus = state.status;
pause(); unawaited(pause());
} }
/// Restores playback to the status before [hold] was called. /// Restores playback to the status before [hold] was called.
@@ -155,7 +155,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
switch (status) { switch (status) {
case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering: case VideoPlaybackStatus.playing || VideoPlaybackStatus.buffering:
play(); unawaited(play());
default: default:
} }
} }
@@ -238,7 +238,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
final newStatus = _mapStatus(playbackInfo.status); final newStatus = _mapStatus(playbackInfo.status);
switch (newStatus) { switch (newStatus) {
case VideoPlaybackStatus.playing: case VideoPlaybackStatus.playing:
WakelockPlus.enable(); unawaited(WakelockPlus.enable());
_startBufferingTimer(); _startBufferingTimer();
default: default:
onNativePlaybackEnded(); onNativePlaybackEnded();
@@ -250,7 +250,7 @@ class VideoPlayerNotifier extends StateNotifier<VideoPlayerState> {
} }
void onNativePlaybackEnded() { void onNativePlaybackEnded() {
WakelockPlus.disable(); unawaited(WakelockPlus.disable());
_bufferingTimer?.cancel(); _bufferingTimer?.cancel();
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/services/local_album.service.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>> { class BackupAlbumNotifier extends StateNotifier<List<LocalAlbum>> {
BackupAlbumNotifier(this._localAlbumService) : super([]) { BackupAlbumNotifier(this._localAlbumService) : super([]) {
getAll(); unawaited(getAll());
} }
final LocalAlbumService _localAlbumService; final LocalAlbumService _localAlbumService;
+3 -1
View File
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/models/cast/cast_manager_state.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) { void loadMedia(RemoteAsset asset, bool reload) {
_gCastService.loadMedia(asset, reload); unawaited(_gCastService.loadMedia(asset, reload));
} }
Future<void> connect(CastDestinationType type, dynamic device) async { 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:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.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: []); state = state.copyWith(selectedDate: date, assetsToDelete: []);
if (date != null) { if (date != null) {
final daysAgo = DateTime.now().difference(date).inDays; final daysAgo = DateTime.now().difference(date).inDays;
_settingsRepository.write(.cleanupCutoffDaysAgo, daysAgo); unawaited(_settingsRepository.write(.cleanupCutoffDaysAgo, daysAgo));
} }
} }
void setKeepMediaType(AssetKeepType keepMediaType) { void setKeepMediaType(AssetKeepType keepMediaType) {
state = state.copyWith(keepMediaType: keepMediaType, assetsToDelete: []); state = state.copyWith(keepMediaType: keepMediaType, assetsToDelete: []);
_settingsRepository.write(.cleanupKeepMediaType, keepMediaType); unawaited(_settingsRepository.write(.cleanupKeepMediaType, keepMediaType));
} }
void setKeepFavorites(bool keepFavorites) { void setKeepFavorites(bool keepFavorites) {
state = state.copyWith(keepFavorites: keepFavorites, assetsToDelete: []); state = state.copyWith(keepFavorites: keepFavorites, assetsToDelete: []);
_settingsRepository.write(.cleanupKeepFavorites, keepFavorites); unawaited(_settingsRepository.write(.cleanupKeepFavorites, keepFavorites));
} }
void toggleKeepAlbum(String albumId) { void toggleKeepAlbum(String albumId) {
@@ -118,7 +120,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
} }
void _persistExcludedAlbumIds(Set<String> albumIds) { void _persistExcludedAlbumIds(Set<String> albumIds) {
_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList()); unawaited(_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList()));
} }
void cleanupStaleAlbumIds(Set<String> existingAlbumIds) { void cleanupStaleAlbumIds(Set<String> existingAlbumIds) {
@@ -144,7 +146,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
_persistExcludedAlbumIds(keepAlbumIds); _persistExcludedAlbumIds(keepAlbumIds);
} }
_settingsRepository.write(.cleanupDefaultsInitialized, true); unawaited(_settingsRepository.write(.cleanupDefaultsInitialized, true));
} }
Future<void> scanAssets() async { Future<void> scanAssets() async {
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; 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 : super(PermissionStatus.denied) // Denied is the initial state
{ {
// Sets the initial state // Sets the initial state
getGalleryPermissionStatus(); unawaited(getGalleryPermissionStatus());
} }
bool get hasPermission => state.isGranted || state.isLimited; bool get hasPermission => state.isGranted || state.isLimited;
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
@@ -15,31 +17,31 @@ class HapticNotifier extends StateNotifier<void> {
void selectionClick() { void selectionClick() {
if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) {
HapticFeedback.selectionClick(); unawaited(HapticFeedback.selectionClick());
} }
} }
void lightImpact() { void lightImpact() {
if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) {
HapticFeedback.lightImpact(); unawaited(HapticFeedback.lightImpact());
} }
} }
void mediumImpact() { void mediumImpact() {
if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) {
HapticFeedback.mediumImpact(); unawaited(HapticFeedback.mediumImpact());
} }
} }
void heavyImpact() { void heavyImpact() {
if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) {
HapticFeedback.heavyImpact(); unawaited(HapticFeedback.heavyImpact());
} }
} }
void vibrate() { void vibrate() {
if (_ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableHapticFeedback)) { 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:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart';
@@ -16,11 +18,11 @@ class ReadOnlyModeNotifier extends Notifier<bool> {
void setMode(bool value) { void setMode(bool value) {
final isLoggedIn = ref.read(authProvider).isAuthenticated; final isLoggedIn = ref.read(authProvider).isAuthenticated;
_appSettingService.setSetting(AppSettingsEnum.readonlyModeEnabled, value); unawaited(_appSettingService.setSetting(AppSettingsEnum.readonlyModeEnabled, value));
state = value; state = value;
if (value && isLoggedIn) { 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:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -21,9 +23,11 @@ class LocalAuthNotifier extends StateNotifier<BiometricStatus> {
LocalAuthNotifier(this._localAuthService, this._secureStorageService) LocalAuthNotifier(this._localAuthService, this._secureStorageService)
: super(const BiometricStatus(availableBiometrics: [], canAuthenticate: false)) { : super(const BiometricStatus(availableBiometrics: [], canAuthenticate: false)) {
_localAuthService.getStatus().then((value) { unawaited(
state = state.copyWith(canAuthenticate: value.canAuthenticate, availableBiometrics: value.availableBiometrics); _localAuthService.getStatus().then((value) {
}); state = state.copyWith(canAuthenticate: value.canAuthenticate, availableBiometrics: value.availableBiometrics);
}),
);
} }
Future<bool> registerBiometric(BuildContext context, String pinCode) async { Future<bool> registerBiometric(BuildContext context, String pinCode) async {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/models/map/map_state.model.dart'; import 'package:immich_mobile/models/map/map_state.model.dart';
@@ -26,12 +28,12 @@ class MapStateNotifier extends Notifier<MapState> {
} }
void switchTheme(ThemeMode mode) { void switchTheme(ThemeMode mode) {
ref.read(settingsProvider).write(.mapThemeMode, mode); unawaited(ref.read(settingsProvider).write(.mapThemeMode, mode));
state = state.copyWith(themeMode: mode); state = state.copyWith(themeMode: mode);
} }
void switchFavoriteOnly(bool isFavoriteOnly) { void switchFavoriteOnly(bool isFavoriteOnly) {
ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly); unawaited(ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly));
state = state.copyWith(showFavoriteOnly: isFavoriteOnly, shouldRefetchMarkers: true); state = state.copyWith(showFavoriteOnly: isFavoriteOnly, shouldRefetchMarkers: true);
} }
@@ -40,17 +42,17 @@ class MapStateNotifier extends Notifier<MapState> {
} }
void switchIncludeArchived(bool isIncludeArchived) { void switchIncludeArchived(bool isIncludeArchived) {
ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived); unawaited(ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived));
state = state.copyWith(includeArchived: isIncludeArchived, shouldRefetchMarkers: true); state = state.copyWith(includeArchived: isIncludeArchived, shouldRefetchMarkers: true);
} }
void switchWithPartners(bool isWithPartners) { void switchWithPartners(bool isWithPartners) {
ref.read(settingsProvider).write(.mapWithPartners, isWithPartners); unawaited(ref.read(settingsProvider).write(.mapWithPartners, isWithPartners));
state = state.copyWith(withPartners: isWithPartners, shouldRefetchMarkers: true); state = state.copyWith(withPartners: isWithPartners, shouldRefetchMarkers: true);
} }
void setRelativeTime(int relativeTime) { void setRelativeTime(int relativeTime) {
ref.read(settingsProvider).write(.mapRelativeDate, relativeTime); unawaited(ref.read(settingsProvider).write(.mapRelativeDate, relativeTime));
state = state.copyWith(relativeTime: relativeTime, shouldRefetchMarkers: true); state = state.copyWith(relativeTime: relativeTime, shouldRefetchMarkers: true);
} }
} }
@@ -10,7 +10,7 @@ class NotificationPermissionNotifier extends StateNotifier<PermissionStatus> {
NotificationPermissionNotifier() NotificationPermissionNotifier()
: super(Platform.isAndroid ? PermissionStatus.granted : PermissionStatus.restricted) { : super(Platform.isAndroid ? PermissionStatus.granted : PermissionStatus.restricted) {
// Sets the initial state // Sets the initial state
getNotificationPermission().then((p) => state = p); unawaited(getNotificationPermission().then((p) => state = p));
} }
/// Requests the notification permission /// Requests the notification permission
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/models/server_info/server_config.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) { void handleReleaseInfo(ServerVersion serverVersion, ServerVersion? latestVersion) {
// Update local server version // Update local server version
_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion); unawaited(_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion));
} }
Future<void> getServerFeatures() async { Future<void> getServerFeatures() async {
@@ -8,7 +8,7 @@ class SharedLinksNotifier extends StateNotifier<AsyncValue<List<SharedLink>>> {
final SharedLinkService _sharedLinkService; final SharedLinkService _sharedLinkService;
SharedLinksNotifier(this._sharedLinkService) : super(const AsyncLoading()) { SharedLinksNotifier(this._sharedLinkService) : super(const AsyncLoading()) {
fetchLinks(); unawaited(fetchLinks());
} }
Future<void> fetchLinks() async { Future<void> fetchLinks() async {
+1 -1
View File
@@ -22,7 +22,7 @@ class CurrentUserProvider extends StateNotifier<UserDto?> {
@override @override
void dispose() { void dispose() {
streamSub.cancel(); unawaited(streamSub.cancel());
super.dispose(); super.dispose();
} }
} }
+4 -4
View File
@@ -143,8 +143,8 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
} }
void _handleOnConfigUpdate(dynamic _) { void _handleOnConfigUpdate(dynamic _) {
_ref.read(serverInfoProvider.notifier).getServerFeatures(); unawaited(_ref.read(serverInfoProvider.notifier).getServerFeatures());
_ref.read(serverInfoProvider.notifier).getServerConfig(); unawaited(_ref.read(serverInfoProvider.notifier).getServerConfig());
} }
void _handleReleaseUpdates(dynamic data) { void _handleReleaseUpdates(dynamic data) {
@@ -203,7 +203,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
unawaited( unawaited(
_ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) { _ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) {
if (isSyncAlbumEnabled) { if (isSyncAlbumEnabled) {
_ref.read(backgroundSyncProvider).syncLinkedAlbum(); unawaited(_ref.read(backgroundSyncProvider).syncLinkedAlbum());
} }
}), }),
); );
@@ -224,7 +224,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
unawaited( unawaited(
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) { _ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
if (isSyncAlbumEnabled) { if (isSyncAlbumEnabled) {
_ref.read(backgroundSyncProvider).syncLinkedAlbum(); unawaited(_ref.read(backgroundSyncProvider).syncLinkedAlbum());
} }
}), }),
); );
@@ -13,10 +13,12 @@ class AppNavigationObserver extends AutoRouterObserver {
@override @override
void didPush(Route route, Route? previousRoute) { void didPush(Route route, Route? previousRoute) {
Future(() { unawaited(
ref.read(currentRouteNameProvider.notifier).state = route.settings.name; Future(() {
ref.read(previousRouteNameProvider.notifier).state = previousRoute?.settings.name; ref.read(currentRouteNameProvider.notifier).state = route.settings.name;
ref.read(previousRouteDataProvider.notifier).state = previousRoute?.settings; ref.read(previousRouteNameProvider.notifier).state = previousRoute?.settings.name;
}); ref.read(previousRouteDataProvider.notifier).state = previousRoute?.settings;
}),
);
} }
} }
@@ -135,12 +135,12 @@ class BackgroundUploadService {
if (!_taskStatusController.isClosed) { if (!_taskStatusController.isClosed) {
_taskStatusController.add(update); _taskStatusController.add(update);
} }
_handleTaskStatusUpdate(update); unawaited(_handleTaskStatusUpdate(update));
} }
void dispose() { void dispose() {
_taskStatusController.close(); unawaited(_taskStatusController.close());
_taskProgressController.close(); unawaited(_taskProgressController.close());
} }
/// Enqueue tasks to the background upload queue /// 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/mixins/error_logger.mixin.dart';
import 'package:immich_mobile/models/map/map_marker.model.dart'; import 'package:immich_mobile/models/map/map_marker.model.dart';
import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/services/api.service.dart';
@@ -11,7 +13,7 @@ class MapService with ErrorLoggerMixin {
final logger = Logger("MapService"); final logger = Logger("MapService");
MapService(this._apiService) { MapService(this._apiService) {
_setMapUserAgentHeader(); unawaited(_setMapUserAgentHeader());
} }
Future<void> _setMapUserAgentHeader() async { Future<void> _setMapUserAgentHeader() async {
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart'; import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
import 'package:immich_mobile/repositories/share_handler.repository.dart'; import 'package:immich_mobile/repositories/share_handler.repository.dart';
@@ -12,6 +14,6 @@ class ShareIntentService {
void init() { void init() {
shareHandlerRepository.onSharedMedia = onSharedMedia; 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) { Future<T> run<T>(Future<T> Function() operation) {
final completer = Completer<T>(); final completer = Completer<T>();
_enqueued++; _enqueued++;
_running.whenComplete(() { unawaited(
_enqueued--; _running.whenComplete(() {
completer.complete(Future<T>.sync(operation)); _enqueued--;
}); completer.complete(Future<T>.sync(operation));
}),
);
return _running = completer.future; return _running = completer.future;
} }
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:immich_mobile/entities/store.entity.dart'; 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)); final notifier = useState<T>(Store.get(key.storeKey, key.defaultValue));
// Listen to changes to the notifier and update app settings // 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; return notifier;
} }
+9 -7
View File
@@ -15,13 +15,15 @@ Future<Uint8List> imageToUint8List(Image image) async {
.resolve(ImageConfiguration.empty) .resolve(ImageConfiguration.empty)
.addListener( .addListener(
ImageStreamListener((ImageInfo info, bool _) { ImageStreamListener((ImageInfo info, bool _) {
info.image.toByteData(format: ImageByteFormat.png).then((byteData) { unawaited(
if (byteData != null) { info.image.toByteData(format: ImageByteFormat.png).then((byteData) {
completer.complete(byteData.buffer.asUint8List()); if (byteData != null) {
} else { completer.complete(byteData.buffer.asUint8List());
completer.completeError('Failed to convert image to bytes'); } else {
} completer.completeError('Failed to convert image to bytes');
}); }
}),
);
}, onError: (exception, stackTrace) => completer.completeError(exception)), }, onError: (exception, stackTrace) => completer.completeError(exception)),
); );
return completer.future; return completer.future;
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -27,9 +28,9 @@ class AnimatedPlayPauseState extends State<AnimatedPlayPause> with SingleTickerP
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.playing != oldWidget.playing) { if (widget.playing != oldWidget.playing) {
if (widget.playing) { if (widget.playing) {
animationController.forward(); unawaited(animationController.forward());
} else { } else {
animationController.reverse(); unawaited(animationController.reverse());
} }
} }
} }
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
@@ -54,7 +56,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget {
ref.watch(hapticFeedbackProvider.notifier).selectionClick(); ref.watch(hapticFeedbackProvider.notifier).selectionClick();
if (isExcluded) { if (isExcluded) {
ref.read(backupAlbumProvider.notifier).deselectAlbum(album); unawaited(ref.read(backupAlbumProvider.notifier).deselectAlbum(album));
} else { } else {
if (album.id == 'isAll' || album.name == 'Recents') { if (album.id == 'isAll' || album.name == 'Recents') {
ImmichToast.show( ImmichToast.show(
@@ -66,7 +68,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget {
return; return;
} }
ref.read(backupAlbumProvider.notifier).excludeAlbum(album); unawaited(ref.read(backupAlbumProvider.notifier).excludeAlbum(album));
} }
}, },
child: ListTile( child: ListTile(
@@ -75,9 +77,9 @@ class DriftAlbumInfoListTile extends HookConsumerWidget {
onTap: () { onTap: () {
ref.read(hapticFeedbackProvider.notifier).selectionClick(); ref.read(hapticFeedbackProvider.notifier).selectionClick();
if (isSelected) { if (isSelected) {
ref.read(backupAlbumProvider.notifier).deselectAlbum(album); unawaited(ref.read(backupAlbumProvider.notifier).deselectAlbum(album));
} else { } else {
ref.read(backupAlbumProvider.notifier).selectAlbum(album); unawaited(ref.read(backupAlbumProvider.notifier).selectAlbum(album));
} }
}, },
leading: buildIcon(), leading: buildIcon(),
@@ -85,7 +87,7 @@ class DriftAlbumInfoListTile extends HookConsumerWidget {
subtitle: buildSubtitle(), subtitle: buildSubtitle(),
trailing: IconButton( trailing: IconButton(
onPressed: () { onPressed: () {
context.pushRoute(LocalTimelineRoute(album: album)); unawaited(context.pushRoute(LocalTimelineRoute(album: album)));
}, },
icon: Icon(Icons.image_outlined, color: context.primaryColor, size: 24), icon: Icon(Icons.image_outlined, color: context.primaryColor, size: 24),
splashRadius: 25, splashRadius: 25,
@@ -38,8 +38,8 @@ class ImmichAppBarDialog extends HookConsumerWidget {
final isReadonlyModeEnabled = ref.watch(readonlyModeProvider); final isReadonlyModeEnabled = ref.watch(readonlyModeProvider);
useEffect(() { useEffect(() {
ref.read(backupProvider.notifier).updateDiskInfo(); unawaited(ref.read(backupProvider.notifier).updateDiskInfo());
ref.read(currentUserProvider.notifier).refresh(); unawaited(ref.read(currentUserProvider.notifier).refresh());
return null; return null;
}, []); }, []);
@@ -180,7 +180,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
InkWell( InkWell(
onTap: () { onTap: () {
ContextHelper(context).pop(); 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(), child: Text("documentation", style: context.textTheme.bodySmall).tr(),
), ),
@@ -188,7 +188,9 @@ class ImmichAppBarDialog extends HookConsumerWidget {
InkWell( InkWell(
onTap: () { onTap: () {
ContextHelper(context).pop(); 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(), 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:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
@@ -31,7 +33,7 @@ class AppBarServerInfo extends HookConsumerWidget {
} }
useEffect(() { useEffect(() {
getPackageInfo(); unawaited(getPackageInfo());
return null; return null;
}, []); }, []);
@@ -87,7 +89,7 @@ class _ServerInfoItem extends StatelessWidget {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if (icon != null) ...[icon as Widget, const SizedBox(width: 8)], if (icon != null) ...[icon! as Widget, const SizedBox(width: 8)],
Text( Text(
label, label,
style: TextStyle( style: TextStyle(
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -20,7 +21,7 @@ class ServerUpdateNotification extends HookConsumerWidget {
final Color infoColor = context.isDarkTheme final Color infoColor = context.isDarkTheme
? context.primaryColor.withAlpha(55) ? context.primaryColor.withAlpha(55)
: context.primaryColor.withAlpha(25); : context.primaryColor.withAlpha(25);
void openUpdateLink() { Future<void> openUpdateLink() {
String url; String url;
if (serverInfoState.versionStatus == VersionStatus.serverOutOfDate) { if (serverInfoState.versionStatus == VersionStatus.serverOutOfDate) {
url = kImmichLatestRelease; url = kImmichLatestRelease;
@@ -35,7 +36,7 @@ class ServerUpdateNotification extends HookConsumerWidget {
} }
} }
launchUrlString(url, mode: LaunchMode.externalApplication); return launchUrlString(url, mode: LaunchMode.externalApplication);
} }
return SizedBox( return SizedBox(
@@ -68,7 +69,7 @@ class ServerUpdateNotification extends HookConsumerWidget {
serverInfoState.versionStatus == VersionStatus.clientOutOfDate) ...[ serverInfoState.versionStatus == VersionStatus.clientOutOfDate) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
TextButton( TextButton(
onPressed: openUpdateLink, onPressed: () => unawaited(openUpdateLink()),
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
minimumSize: Size.zero, minimumSize: Size.zero,
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -114,7 +116,7 @@ class DropdownSearchMenu<T> extends HookWidget {
final bool highlight = AutocompleteHighlightedOption.of(context) == index; final bool highlight = AutocompleteHighlightedOption.of(context) == index;
if (highlight) { if (highlight) {
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) { SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
Scrollable.ensureVisible(context, alignment: 0.5); unawaited(Scrollable.ensureVisible(context, alignment: 0.5));
}, debugLabel: 'AutocompleteOptions.ensureVisible'); }, debugLabel: 'AutocompleteOptions.ensureVisible');
} }
return Container( return Container(
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:immich_mobile/widgets/common/immich_logo.dart'; import 'package:immich_mobile/widgets/common/immich_logo.dart';
@@ -9,11 +11,12 @@ class ImmichLoadingIndicator extends HookWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final logoAnimationController = useAnimationController(duration: const Duration(seconds: 6)) final logoAnimationController = useAnimationController(duration: const Duration(seconds: 6));
..reverse() unawaited(logoAnimationController.reverse());
..repeat(); 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( return Container(
height: 80, height: 80,
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
@@ -304,13 +305,13 @@ class _SyncStatusIndicatorState extends ConsumerState<_SyncStatusIndicator> with
// Control animations based on sync status // Control animations based on sync status
if (isSyncing) { if (isSyncing) {
if (!_rotationController.isAnimating) { if (!_rotationController.isAnimating) {
_rotationController.repeat(); unawaited(_rotationController.repeat());
} }
_dismissalController.reset(); _dismissalController.reset();
} else { } else {
_rotationController.stop(); _rotationController.stop();
if (_dismissalController.status == AnimationStatus.dismissed) { 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), () { Future.delayed(const Duration(milliseconds: 100), () {
if (mounted) { if (mounted) {
_slideController.forward(); unawaited(_slideController.forward());
} }
}); });
} }
@@ -228,7 +228,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
@override @override
void dispose() { void dispose() {
_reloadSubscription?.cancel(); unawaited(_reloadSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -311,13 +311,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
void _startAnimationCycle() { void _startAnimationCycle() {
if (_isZoomingIn) { if (_isZoomingIn) {
_zoomController.forward().then((_) { unawaited(
_loadNextAsset(); _zoomController.forward().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} else { } else {
_zoomController.reverse().then((_) { unawaited(
_loadNextAsset(); _zoomController.reverse().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} }
} }
@@ -169,7 +169,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
if (mounted) { if (mounted) {
_slideController.forward(); unawaited(_slideController.forward());
} }
}); });
} }
@@ -335,7 +335,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
@override @override
void dispose() { void dispose() {
_reloadSubscription?.cancel(); unawaited(_reloadSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -416,13 +416,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
void _startAnimationCycle() { void _startAnimationCycle() {
if (_isZoomingIn) { if (_isZoomingIn) {
_zoomController.forward().then((_) { unawaited(
_loadNextAsset(); _zoomController.forward().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} else { } else {
_zoomController.reverse().then((_) { unawaited(
_loadNextAsset(); _zoomController.reverse().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} }
} }
@@ -172,7 +172,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
if (mounted) { if (mounted) {
_slideController.forward(); unawaited(_slideController.forward());
} }
}); });
} }
@@ -309,7 +309,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
@override @override
void dispose() { void dispose() {
_reloadSubscription?.cancel(); unawaited(_reloadSubscription?.cancel());
super.dispose(); super.dispose();
} }
@@ -390,13 +390,17 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
void _startAnimationCycle() { void _startAnimationCycle() {
if (_isZoomingIn) { if (_isZoomingIn) {
_zoomController.forward().then((_) { unawaited(
_loadNextAsset(); _zoomController.forward().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} else { } else {
_zoomController.reverse().then((_) { unawaited(
_loadNextAsset(); _zoomController.reverse().then((_) {
}); unawaited(_loadNextAsset());
}),
);
} }
} }
@@ -70,7 +70,8 @@ class LoginForm extends HookConsumerWidget {
final isOauthEnable = useState<bool>(false); final isOauthEnable = useState<bool>(false);
final isPasswordLoginEnable = useState<bool>(false); final isPasswordLoginEnable = useState<bool>(false);
final oAuthButtonLabel = useState<String>('OAuth'); 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 serverInfo = ref.watch(serverInfoProvider);
final warningMessage = useState<String?>(null); final warningMessage = useState<String?>(null);
final loginFormKey = GlobalKey<FormState>(); final loginFormKey = GlobalKey<FormState>();
@@ -358,7 +359,7 @@ class LoginForm extends HookConsumerWidget {
} }
SingleChildRenderObjectWidget buildVersionCompatWarning() { SingleChildRenderObjectWidget buildVersionCompatWarning() {
checkVersionMismatch(); unawaited(checkVersionMismatch());
if (warningMessage.value == null) { if (warningMessage.value == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();

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