You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	deps(mobile): flutter 3.16 (#6677)
* dep(mobile): update flutter and deps * chore: dart analyzer * chore: update flutter workflow version * chore: dart format * fix: gallery_viewer PopScope --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/build-mobile.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-mobile.yml
									
									
									
									
										vendored
									
									
								
							| @@ -45,7 +45,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: "stable" | ||||
|           flutter-version: "3.13.6" | ||||
|           flutter-version: "3.16.9" | ||||
|           cache: true | ||||
|  | ||||
|       - name: Create the Keystore | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: "stable" | ||||
|           flutter-version: "3.13.6" | ||||
|           flutter-version: "3.16.9" | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         run: dart pub get | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -204,7 +204,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: "stable" | ||||
|           flutter-version: "3.13.6" | ||||
|           flutter-version: "3.16.9" | ||||
|       - name: Run tests | ||||
|         working-directory: ./mobile | ||||
|         run: flutter test -j 1 | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| { | ||||
|   "flutter": "3.13.6" | ||||
|   "flutter": "3.16.9" | ||||
| } | ||||
							
								
								
									
										2
									
								
								mobile/.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								mobile/.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|   "dart.flutterSdkPath": ".fvm\\versions\\3.13.6", | ||||
|   "dart.flutterSdkPath": ".fvm\\versions\\3.16.9", | ||||
|   "search.exclude": { | ||||
|     "**/.fvm": true | ||||
|   }, | ||||
|   | ||||
| @@ -34,7 +34,7 @@ if (keystorePropertiesFile.exists()) { | ||||
|  | ||||
|  | ||||
| android { | ||||
|     compileSdkVersion 33 | ||||
|     compileSdkVersion 34 | ||||
|  | ||||
|     compileOptions { | ||||
|         sourceCompatibility JavaVersion.VERSION_1_8 | ||||
|   | ||||
| @@ -52,7 +52,10 @@ class ImmichTestLoginHelper { | ||||
|   } | ||||
|  | ||||
|   Future<void> pressLoginButton() async { | ||||
|     await pumpUntilFound(tester, find.textContaining("login_form_button_text".tr())); | ||||
|     await pumpUntilFound( | ||||
|       tester, | ||||
|       find.textContaining("login_form_button_text".tr()), | ||||
|     ); | ||||
|     final button = find.textContaining("login_form_button_text".tr()); | ||||
|     await tester.tap(button); | ||||
|   } | ||||
| @@ -62,7 +65,7 @@ class ImmichTestLoginHelper { | ||||
|   } | ||||
|  | ||||
|   Future<void> assertLoginFailed({int timeoutSeconds = 15}) async { | ||||
|       await pumpUntilFound(tester, find.text("login_form_failed_login".tr())); | ||||
|     await pumpUntilFound(tester, find.text("login_form_failed_login".tr())); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -80,9 +83,9 @@ enum LoginCredentials { | ||||
|   ), | ||||
|  | ||||
|   wrongInstanceUrl( | ||||
|   "https://does-not-exist.preview.immich.app", | ||||
|   "demo@immich.app", | ||||
|   "demo", | ||||
|     "https://does-not-exist.preview.immich.app", | ||||
|     "demo@immich.app", | ||||
|     "demo", | ||||
|   ); | ||||
|  | ||||
|   const LoginCredentials(this.server, this.email, this.password); | ||||
|   | ||||
| @@ -34,7 +34,7 @@ abstract class _$AlbumActivity | ||||
|   late final String albumId; | ||||
|   late final String? assetId; | ||||
| 
 | ||||
|   Future<List<Activity>> build( | ||||
|   FutureOr<List<Activity>> build( | ||||
|     String albumId, [ | ||||
|     String? assetId, | ||||
|   ]); | ||||
| @@ -136,7 +136,7 @@ class AlbumActivityProvider extends AutoDisposeAsyncNotifierProviderImpl< | ||||
|   final String? assetId; | ||||
| 
 | ||||
|   @override | ||||
|   Future<List<Activity>> runNotifierBuild( | ||||
|   FutureOr<List<Activity>> runNotifierBuild( | ||||
|     covariant AlbumActivity notifier, | ||||
|   ) { | ||||
|     return notifier.build( | ||||
|   | ||||
| @@ -19,9 +19,9 @@ class AddToAlbumBottomSheet extends HookConsumerWidget { | ||||
|   final List<Asset> assets; | ||||
|  | ||||
|   const AddToAlbumBottomSheet({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.assets, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -13,12 +13,12 @@ class AddToAlbumSliverList extends HookConsumerWidget { | ||||
|   final bool enabled; | ||||
|  | ||||
|   const AddToAlbumSliverList({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.onAddToAlbum, | ||||
|     required this.albums, | ||||
|     required this.sharedAlbums, | ||||
|     this.enabled = true, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -7,11 +7,11 @@ class AlbumActionOutlinedButton extends StatelessWidget { | ||||
|   final IconData iconData; | ||||
|  | ||||
|   const AlbumActionOutlinedButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     this.onPressed, | ||||
|     required this.labelText, | ||||
|     required this.iconData, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -13,11 +13,11 @@ class AlbumThumbnailCard extends StatelessWidget { | ||||
|   final bool showOwner; | ||||
|  | ||||
|   const AlbumThumbnailCard({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.album, | ||||
|     this.onTap, | ||||
|     this.showOwner = false, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Album album; | ||||
|  | ||||
|   | ||||
| @@ -11,10 +11,10 @@ import 'package:openapi/api.dart'; | ||||
|  | ||||
| class AlbumThumbnailListTile extends StatelessWidget { | ||||
|   const AlbumThumbnailListTile({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.album, | ||||
|     this.onTap, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Album album; | ||||
|   final void Function()? onTap; | ||||
|   | ||||
| @@ -6,12 +6,12 @@ import 'package:immich_mobile/modules/album/providers/album_title.provider.dart' | ||||
|  | ||||
| class AlbumTitleTextField extends ConsumerWidget { | ||||
|   const AlbumTitleTextField({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.isAlbumTitleEmpty, | ||||
|     required this.albumTitleTextFieldFocusNode, | ||||
|     required this.albumTitleController, | ||||
|     required this.isAlbumTitleTextFieldFocus, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final ValueNotifier<bool> isAlbumTitleEmpty; | ||||
|   final FocusNode albumTitleTextFieldFocusNode; | ||||
|   | ||||
| @@ -16,14 +16,14 @@ import 'package:immich_mobile/shared/views/immich_loading_overlay.dart'; | ||||
| class AlbumViewerAppbar extends HookConsumerWidget | ||||
|     implements PreferredSizeWidget { | ||||
|   const AlbumViewerAppbar({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.album, | ||||
|     required this.userId, | ||||
|     required this.titleFocusNode, | ||||
|     this.onAddPhotos, | ||||
|     this.onAddUsers, | ||||
|     required this.onActivities, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Album album; | ||||
|   final String userId; | ||||
|   | ||||
| @@ -10,10 +10,10 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { | ||||
|   final Album album; | ||||
|   final FocusNode titleFocusNode; | ||||
|   const AlbumViewerEditableTitle({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.album, | ||||
|     required this.titleFocusNode, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -6,8 +6,7 @@ import 'package:immich_mobile/shared/ui/immich_image.dart'; | ||||
| class SharedAlbumThumbnailImage extends HookConsumerWidget { | ||||
|   final Asset asset; | ||||
|  | ||||
|   const SharedAlbumThumbnailImage({Key? key, required this.asset}) | ||||
|       : super(key: key); | ||||
|   const SharedAlbumThumbnailImage({super.key, required this.asset}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -31,7 +31,7 @@ import 'package:immich_mobile/shared/views/immich_loading_overlay.dart'; | ||||
| class AlbumViewerPage extends HookConsumerWidget { | ||||
|   final int albumId; | ||||
|  | ||||
|   const AlbumViewerPage({Key? key, required this.albumId}) : super(key: key); | ||||
|   const AlbumViewerPage({super.key, required this.albumId}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -15,11 +15,11 @@ import 'package:isar/isar.dart'; | ||||
| @RoutePage<AssetSelectionPageResult?>() | ||||
| class AssetSelectionPage extends HookConsumerWidget { | ||||
|   const AssetSelectionPage({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.existingAssets, | ||||
|     this.canDeselect = false, | ||||
|     required this.query, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Set<Asset> existingAssets; | ||||
|   final QueryBuilder<Asset, Asset, QAfterSortBy>? query; | ||||
|   | ||||
| @@ -21,10 +21,10 @@ class CreateAlbumPage extends HookConsumerWidget { | ||||
|   final List<Asset>? initialAssets; | ||||
|  | ||||
|   const CreateAlbumPage({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.isSharedAlbum, | ||||
|     this.initialAssets, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import 'package:immich_mobile/shared/ui/immich_app_bar.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class LibraryPage extends HookConsumerWidget { | ||||
|   const LibraryPage({Key? key}) : super(key: key); | ||||
|   const LibraryPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -14,8 +14,7 @@ import 'package:immich_mobile/shared/ui/user_circle_avatar.dart'; | ||||
| class SelectAdditionalUserForSharingPage extends HookConsumerWidget { | ||||
|   final Album album; | ||||
|  | ||||
|   const SelectAdditionalUserForSharingPage({Key? key, required this.album}) | ||||
|       : super(key: key); | ||||
|   const SelectAdditionalUserForSharingPage({super.key, required this.album}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -15,8 +15,7 @@ import 'package:immich_mobile/shared/ui/user_circle_avatar.dart'; | ||||
|  | ||||
| @RoutePage<List<String>>() | ||||
| class SelectUserForSharingPage extends HookConsumerWidget { | ||||
|   const SelectUserForSharingPage({Key? key, required this.assets}) | ||||
|       : super(key: key); | ||||
|   const SelectUserForSharingPage({super.key, required this.assets}); | ||||
|  | ||||
|   final Set<Asset> assets; | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ import 'package:immich_mobile/shared/ui/immich_image.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class SharingPage extends HookConsumerWidget { | ||||
|   const SharingPage({Key? key}) : super(key: key); | ||||
|   const SharingPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ class AssetDescriptionNotifier extends StateNotifier<String> { | ||||
|  | ||||
|   AssetDescriptionNotifier( | ||||
|     this._db, | ||||
|     this._service,  | ||||
|     this._service, | ||||
|     this._asset, | ||||
|   ) : super('') { | ||||
|     _fetchLocalDescription(); | ||||
| @@ -34,9 +34,7 @@ class AssetDescriptionNotifier extends StateNotifier<String> { | ||||
|     } | ||||
|  | ||||
|     // Subscribe to local changes | ||||
|     final exifInfo = await _db | ||||
|         .exifInfos | ||||
|         .get(localExifId); | ||||
|     final exifInfo = await _db.exifInfos.get(localExifId); | ||||
|  | ||||
|     // Guard | ||||
|     if (exifInfo?.description == null) { | ||||
| @@ -75,13 +73,11 @@ class AssetDescriptionNotifier extends StateNotifier<String> { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     return _service | ||||
|         .setDescription(description, remoteAssetId, localExifId); | ||||
|     return _service.setDescription(description, remoteAssetId, localExifId); | ||||
|   } | ||||
| } | ||||
|  | ||||
| final assetDescriptionProvider = StateNotifierProvider | ||||
|     .autoDispose | ||||
| final assetDescriptionProvider = StateNotifierProvider.autoDispose | ||||
|     .family<AssetDescriptionNotifier, String, Asset>( | ||||
|   (ref, asset) => AssetDescriptionNotifier( | ||||
|     ref.watch(dbProvider), | ||||
| @@ -89,5 +85,3 @@ final assetDescriptionProvider = StateNotifierProvider | ||||
|     asset, | ||||
|   ), | ||||
| ); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -24,11 +24,13 @@ class ImageViewerService { | ||||
|     try { | ||||
|       // Download LivePhotos image and motion part | ||||
|       if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) { | ||||
|         var imageResponse = await _apiService.assetApi.downloadFileOldWithHttpInfo( | ||||
|         var imageResponse = | ||||
|             await _apiService.assetApi.downloadFileOldWithHttpInfo( | ||||
|           asset.remoteId!, | ||||
|         ); | ||||
|  | ||||
|         var motionReponse = await _apiService.assetApi.downloadFileOldWithHttpInfo( | ||||
|         var motionReponse = | ||||
|             await _apiService.assetApi.downloadFileOldWithHttpInfo( | ||||
|           asset.livePhotoVideoId!, | ||||
|         ); | ||||
|  | ||||
|   | ||||
| @@ -7,8 +7,7 @@ import 'package:immich_mobile/shared/models/asset.dart'; | ||||
| class AdvancedBottomSheet extends HookConsumerWidget { | ||||
|   final Asset assetDetail; | ||||
|  | ||||
|   const AdvancedBottomSheet({Key? key, required this.assetDetail}) | ||||
|       : super(key: key); | ||||
|   const AdvancedBottomSheet({super.key, required this.assetDetail}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -3,11 +3,11 @@ import 'package:flutter/material.dart'; | ||||
| /// A widget that animates implicitly between a play and a pause icon. | ||||
| class AnimatedPlayPause extends StatefulWidget { | ||||
|   const AnimatedPlayPause({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.playing, | ||||
|     this.size, | ||||
|     this.color, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final double? size; | ||||
|   final bool playing; | ||||
|   | ||||
| @@ -3,14 +3,14 @@ import 'package:immich_mobile/modules/asset_viewer/ui/animated_play_pause.dart'; | ||||
|  | ||||
| class CenterPlayButton extends StatelessWidget { | ||||
|   const CenterPlayButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.backgroundColor, | ||||
|     this.iconColor, | ||||
|     required this.show, | ||||
|     required this.isPlaying, | ||||
|     required this.isFinished, | ||||
|     this.onPressed, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Color backgroundColor; | ||||
|   final Color? iconColor; | ||||
|   | ||||
| @@ -19,7 +19,7 @@ import 'package:url_launcher/url_launcher.dart'; | ||||
| class ExifBottomSheet extends HookConsumerWidget { | ||||
|   final Asset asset; | ||||
|  | ||||
|   const ExifBottomSheet({Key? key, required this.asset}) : super(key: key); | ||||
|   const ExifBottomSheet({super.key, required this.asset}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import 'package:immich_mobile/shared/providers/asset.provider.dart'; | ||||
|  | ||||
| class TopControlAppBar extends HookConsumerWidget { | ||||
|   const TopControlAppBar({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.asset, | ||||
|     required this.onMoreInfoPressed, | ||||
|     required this.onDownloadPressed, | ||||
| @@ -20,7 +20,7 @@ class TopControlAppBar extends HookConsumerWidget { | ||||
|     required this.isOwner, | ||||
|     required this.onActivitiesPressed, | ||||
|     required this.isPartner, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Asset asset; | ||||
|   final Function onMoreInfoPressed; | ||||
|   | ||||
| @@ -12,8 +12,8 @@ import 'package:video_player/video_player.dart'; | ||||
|  | ||||
| class VideoPlayerControls extends ConsumerStatefulWidget { | ||||
|   const VideoPlayerControls({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   VideoPlayerControlsState createState() => VideoPlayerControlsState(); | ||||
|   | ||||
| @@ -751,15 +751,16 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     return Scaffold( | ||||
|       backgroundColor: Colors.black, | ||||
|       body: WillPopScope( | ||||
|         onWillPop: () async { | ||||
|           // Change immersive mode back to normal "edgeToEdge" mode | ||||
|           await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); | ||||
|           return true; | ||||
|         }, | ||||
|         child: Stack( | ||||
|     return PopScope( | ||||
|       canPop: false, | ||||
|       onPopInvoked: (_) { | ||||
|         // Change immersive mode back to normal "edgeToEdge" mode | ||||
|         SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); | ||||
|         context.pop(); | ||||
|       }, | ||||
|       child: Scaffold( | ||||
|         backgroundColor: Colors.black, | ||||
|         body: Stack( | ||||
|           children: [ | ||||
|             PhotoViewGallery.builder( | ||||
|               scaleStateChangedCallback: (state) { | ||||
|   | ||||
| @@ -26,14 +26,14 @@ class VideoViewerPage extends HookConsumerWidget { | ||||
|   final VoidCallback? onPaused; | ||||
|  | ||||
|   const VideoViewerPage({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.asset, | ||||
|     required this.isMotionVideo, | ||||
|     required this.onVideoEnded, | ||||
|     this.onPlaying, | ||||
|     this.onPaused, | ||||
|     this.placeholder, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -112,7 +112,7 @@ class VideoPlayer extends StatefulWidget { | ||||
|   final Widget? placeholder; | ||||
|  | ||||
|   const VideoPlayer({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     this.url, | ||||
|     this.jwtToken, | ||||
|     this.file, | ||||
| @@ -121,7 +121,7 @@ class VideoPlayer extends StatefulWidget { | ||||
|     this.onPlaying, | ||||
|     this.onPaused, | ||||
|     this.placeholder, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   State<VideoPlayer> createState() => _VideoPlayerState(); | ||||
|   | ||||
| @@ -15,24 +15,27 @@ class IOSBackgroundSettings { | ||||
|   }); | ||||
| } | ||||
|  | ||||
| class IOSBackgroundSettingsNotifier extends StateNotifier<IOSBackgroundSettings?> { | ||||
| class IOSBackgroundSettingsNotifier | ||||
|     extends StateNotifier<IOSBackgroundSettings?> { | ||||
|   final BackgroundService _service; | ||||
|   IOSBackgroundSettingsNotifier(this._service) : super(null); | ||||
|  | ||||
|   IOSBackgroundSettings? get settings => state; | ||||
|  | ||||
|   Future<IOSBackgroundSettings> refresh() async { | ||||
|     final lastFetchTime = await _service.getIOSBackupLastRun(IosBackgroundTask.fetch); | ||||
|     final lastProcessingTime = await _service.getIOSBackupLastRun(IosBackgroundTask.processing); | ||||
|     final lastFetchTime = | ||||
|         await _service.getIOSBackupLastRun(IosBackgroundTask.fetch); | ||||
|     final lastProcessingTime = | ||||
|         await _service.getIOSBackupLastRun(IosBackgroundTask.processing); | ||||
|     int numberOfProcesses = await _service.getIOSBackupNumberOfProcesses(); | ||||
|     final appRefreshEnabled = await _service.getIOSBackgroundAppRefreshEnabled(); | ||||
|     final appRefreshEnabled = | ||||
|         await _service.getIOSBackgroundAppRefreshEnabled(); | ||||
|  | ||||
|     // If this is enabled and there are no background processes, | ||||
|     // the user just enabled app refresh in Settings. | ||||
|     // But we don't have any background services running, since it was disabled | ||||
|     // before. | ||||
|     if (await _service.isBackgroundBackupEnabled() && | ||||
|         numberOfProcesses == 0) { | ||||
|     if (await _service.isBackgroundBackupEnabled() && numberOfProcesses == 0) { | ||||
|       // We need to restart the background service | ||||
|       await _service.enableService(); | ||||
|       numberOfProcesses = await _service.getIOSBackupNumberOfProcesses(); | ||||
| @@ -48,10 +51,9 @@ class IOSBackgroundSettingsNotifier extends StateNotifier<IOSBackgroundSettings? | ||||
|     state = settings; | ||||
|     return settings; | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| final iOSBackgroundSettingsProvider = StateNotifierProvider<IOSBackgroundSettingsNotifier, IOSBackgroundSettings?>( | ||||
| final iOSBackgroundSettingsProvider = StateNotifierProvider< | ||||
|     IOSBackgroundSettingsNotifier, IOSBackgroundSettings?>( | ||||
|   (ref) => IOSBackgroundSettingsNotifier(ref.watch(backgroundServiceProvider)), | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -429,10 +429,10 @@ class BackupService { | ||||
| class MultipartRequest extends http.MultipartRequest { | ||||
|   /// Creates a new [MultipartRequest]. | ||||
|   MultipartRequest( | ||||
|     String method, | ||||
|     Uri url, { | ||||
|     super.method, | ||||
|     super.url, { | ||||
|     required this.onProgress, | ||||
|   }) : super(method, url); | ||||
|   }); | ||||
|  | ||||
|   final void Function(int bytes, int totalBytes) onProgress; | ||||
|  | ||||
|   | ||||
| @@ -14,8 +14,7 @@ class AlbumInfoCard extends HookConsumerWidget { | ||||
|   final Uint8List? imageData; | ||||
|   final AvailableAlbum albumInfo; | ||||
|  | ||||
|   const AlbumInfoCard({Key? key, this.imageData, required this.albumInfo}) | ||||
|       : super(key: key); | ||||
|   const AlbumInfoCard({super.key, this.imageData, required this.albumInfo}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -14,8 +14,7 @@ class AlbumInfoListTile extends HookConsumerWidget { | ||||
|   final Uint8List? imageData; | ||||
|   final AvailableAlbum albumInfo; | ||||
|  | ||||
|   const AlbumInfoListTile({Key? key, this.imageData, required this.albumInfo}) | ||||
|       : super(key: key); | ||||
|   const AlbumInfoListTile({super.key, this.imageData, required this.albumInfo}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -7,11 +7,11 @@ class BackupInfoCard extends StatelessWidget { | ||||
|   final String subtitle; | ||||
|   final String info; | ||||
|   const BackupInfoCard({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.title, | ||||
|     required this.subtitle, | ||||
|     required this.info, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import 'package:photo_manager/photo_manager.dart'; | ||||
| @RoutePage() | ||||
| class AlbumPreviewPage extends HookConsumerWidget { | ||||
|   final AssetPathEntity album; | ||||
|   const AlbumPreviewPage({Key? key, required this.album}) : super(key: key); | ||||
|   const AlbumPreviewPage({super.key, required this.album}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class BackupAlbumSelectionPage extends HookConsumerWidget { | ||||
|   const BackupAlbumSelectionPage({Key? key}) : super(key: key); | ||||
|   const BackupAlbumSelectionPage({super.key}); | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     // final availableAlbums = ref.watch(backupProvider).availableAlbums; | ||||
|   | ||||
| @@ -20,7 +20,7 @@ import 'package:immich_mobile/modules/backup/ui/backup_info_card.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class BackupControllerPage extends HookConsumerWidget { | ||||
|   const BackupControllerPage({Key? key}) : super(key: key); | ||||
|   const BackupControllerPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import 'package:wakelock_plus/wakelock_plus.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class BackupOptionsPage extends HookConsumerWidget { | ||||
|   const BackupOptionsPage({Key? key}) : super(key: key); | ||||
|   const BackupOptionsPage({super.key}); | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     BackUpState backupState = ref.watch(backupProvider); | ||||
|   | ||||
| @@ -5,10 +5,11 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; | ||||
| import 'package:immich_mobile/modules/backup/providers/error_backup_list.provider.dart'; | ||||
| import 'package:intl/intl.dart'; | ||||
| import 'package:photo_manager/photo_manager.dart'; | ||||
| import 'package:photo_manager_image_provider/photo_manager_image_provider.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class FailedBackupStatusPage extends HookConsumerWidget { | ||||
|   const FailedBackupStatusPage({Key? key}) : super(key: key); | ||||
|   const FailedBackupStatusPage({super.key}); | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final errorBackupList = ref.watch(errorBackupListProvider); | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import 'package:immich_mobile/shared/ui/asset_grid/multiselect_grid.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class FavoritesPage extends HookConsumerWidget { | ||||
|   const FavoritesPage({Key? key}) : super(key: key); | ||||
|   const FavoritesPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -4,10 +4,10 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; | ||||
|  | ||||
| class DisableMultiSelectButton extends ConsumerWidget { | ||||
|   const DisableMultiSelectButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.onPressed, | ||||
|     required this.selectedItemCount, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final Function onPressed; | ||||
|   final int selectedItemCount; | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|   final Function(bool scrolling) scrollStateListener; | ||||
|  | ||||
|   DraggableScrollbar.semicircle({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     Key? scrollThumbKey, | ||||
|     this.alwaysVisibleScrollThumb = false, | ||||
|     required this.child, | ||||
| @@ -76,8 +76,7 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|           heightScrollThumb * 0.6, | ||||
|           scrollThumbKey, | ||||
|           alwaysVisibleScrollThumb, | ||||
|         ), | ||||
|         super(key: key); | ||||
|         ); | ||||
|  | ||||
|   @override | ||||
|   DraggableScrollbarState createState() => DraggableScrollbarState(); | ||||
| @@ -170,12 +169,12 @@ class ScrollLabel extends StatelessWidget { | ||||
|       BoxConstraints.tightFor(width: 72.0, height: 28.0); | ||||
|  | ||||
|   const ScrollLabel({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     required this.animation, | ||||
|     required this.backgroundColor, | ||||
|     this.constraints = _defaultConstraints, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
| @@ -509,10 +508,10 @@ class SlideFadeTransition extends StatelessWidget { | ||||
|   final Widget child; | ||||
|  | ||||
|   const SlideFadeTransition({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.animation, | ||||
|     required this.child, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -9,13 +9,13 @@ import 'package:immich_mobile/modules/settings/services/app_settings.service.dar | ||||
|  | ||||
| class GroupDividerTitle extends HookConsumerWidget { | ||||
|   const GroupDividerTitle({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.text, | ||||
|     required this.multiselectEnabled, | ||||
|     required this.onSelect, | ||||
|     required this.onDeselect, | ||||
|     required this.selected, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final String text; | ||||
|   final bool multiselectEnabled; | ||||
|   | ||||
| @@ -389,15 +389,6 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<bool> onWillPop() async { | ||||
|     if (widget.selectionActive && _selectedAssets.isNotEmpty) { | ||||
|       _deselectAll(); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
| @@ -438,8 +429,9 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return WillPopScope( | ||||
|       onWillPop: onWillPop, | ||||
|     return PopScope( | ||||
|       canPop: !(widget.selectionActive && _selectedAssets.isNotEmpty), | ||||
|       onPopInvoked: (didPop) => !didPop ? _deselectAll() : null, | ||||
|       child: Stack( | ||||
|         children: [ | ||||
|           _buildAssetGrid(), | ||||
|   | ||||
| @@ -23,7 +23,7 @@ class ThumbnailImage extends StatelessWidget { | ||||
|   final int heroOffset; | ||||
|  | ||||
|   const ThumbnailImage({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.asset, | ||||
|     required this.index, | ||||
|     required this.loadAsset, | ||||
| @@ -36,7 +36,7 @@ class ThumbnailImage extends StatelessWidget { | ||||
|     this.onDeselect, | ||||
|     this.onSelect, | ||||
|     this.heroOffset = 0, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -33,7 +33,7 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|   final SelectionAssetState selectionAssetState; | ||||
|  | ||||
|   const ControlBottomAppBar({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.onShare, | ||||
|     this.onFavorite, | ||||
|     this.onArchive, | ||||
| @@ -51,7 +51,7 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|     this.enabled = true, | ||||
|     this.unarchive = false, | ||||
|     this.unfavorite = false, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -6,9 +6,8 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; | ||||
| import 'package:immich_mobile/shared/ui/confirm_dialog.dart'; | ||||
|  | ||||
| class DeleteDialog extends ConfirmDialog { | ||||
|   const DeleteDialog({Key? key, String? alert, required Function onDelete}) | ||||
|   const DeleteDialog({super.key, String? alert, required Function onDelete}) | ||||
|       : super( | ||||
|           key: key, | ||||
|           title: "delete_dialog_title", | ||||
|           content: alert ?? "delete_dialog_alert", | ||||
|           cancel: "delete_dialog_cancel", | ||||
|   | ||||
| @@ -52,7 +52,7 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|   final bool alwaysVisibleScrollThumb; | ||||
|  | ||||
|   DraggableScrollbar({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     this.alwaysVisibleScrollThumb = false, | ||||
|     required this.heightScrollThumb, | ||||
|     required this.backgroundColor, | ||||
| @@ -64,11 +64,10 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|     this.scrollbarTimeToFade = const Duration(milliseconds: 600), | ||||
|     this.labelTextBuilder, | ||||
|     this.labelConstraints, | ||||
|   })  : assert(child.scrollDirection == Axis.vertical), | ||||
|         super(key: key); | ||||
|   }) : assert(child.scrollDirection == Axis.vertical); | ||||
|  | ||||
|   DraggableScrollbar.rrect({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     Key? scrollThumbKey, | ||||
|     this.alwaysVisibleScrollThumb = false, | ||||
|     required this.child, | ||||
| @@ -82,11 +81,10 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|     this.labelConstraints, | ||||
|   })  : assert(child.scrollDirection == Axis.vertical), | ||||
|         scrollThumbBuilder = | ||||
|             _thumbRRectBuilder(scrollThumbKey, alwaysVisibleScrollThumb), | ||||
|         super(key: key); | ||||
|             _thumbRRectBuilder(scrollThumbKey, alwaysVisibleScrollThumb); | ||||
|  | ||||
|   DraggableScrollbar.arrows({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     Key? scrollThumbKey, | ||||
|     this.alwaysVisibleScrollThumb = false, | ||||
|     required this.child, | ||||
| @@ -100,11 +98,10 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|     this.labelConstraints, | ||||
|   })  : assert(child.scrollDirection == Axis.vertical), | ||||
|         scrollThumbBuilder = | ||||
|             _thumbArrowBuilder(scrollThumbKey, alwaysVisibleScrollThumb), | ||||
|         super(key: key); | ||||
|             _thumbArrowBuilder(scrollThumbKey, alwaysVisibleScrollThumb); | ||||
|  | ||||
|   DraggableScrollbar.semicircle({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     Key? scrollThumbKey, | ||||
|     this.alwaysVisibleScrollThumb = false, | ||||
|     required this.child, | ||||
| @@ -121,8 +118,7 @@ class DraggableScrollbar extends StatefulWidget { | ||||
|           heightScrollThumb * 0.6, | ||||
|           scrollThumbKey, | ||||
|           alwaysVisibleScrollThumb, | ||||
|         ), | ||||
|         super(key: key); | ||||
|         ); | ||||
|  | ||||
|   @override | ||||
|   DraggableScrollbarState createState() => DraggableScrollbarState(); | ||||
| @@ -288,12 +284,12 @@ class ScrollLabel extends StatelessWidget { | ||||
|       BoxConstraints.tightFor(width: 72.0, height: 28.0); | ||||
|  | ||||
|   const ScrollLabel({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     required this.animation, | ||||
|     required this.backgroundColor, | ||||
|     this.constraints = _defaultConstraints, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
| @@ -625,10 +621,10 @@ class SlideFadeTransition extends StatelessWidget { | ||||
|   final Widget child; | ||||
|  | ||||
|   const SlideFadeTransition({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.animation, | ||||
|     required this.child, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -1,12 +1,10 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:immich_mobile/shared/ui/confirm_dialog.dart'; | ||||
|  | ||||
| class UploadDialog extends ConfirmDialog { | ||||
|   final Function onUpload; | ||||
|  | ||||
|   const UploadDialog({Key? key, required this.onUpload}) | ||||
|   const UploadDialog({super.key, required this.onUpload}) | ||||
|       : super( | ||||
|           key: key, | ||||
|           title: 'upload_dialog_title', | ||||
|           content: 'upload_dialog_info', | ||||
|           cancel: 'upload_dialog_cancel', | ||||
|   | ||||
| @@ -20,7 +20,7 @@ import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class HomePage extends HookConsumerWidget { | ||||
|   const HomePage({Key? key}) : super(key: key); | ||||
|   const HomePage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -63,7 +63,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> { | ||||
|     if (Platform.isIOS) { | ||||
|       var iosInfo = await deviceInfoPlugin.iosInfo; | ||||
|       _apiService.authenticationApi.apiClient | ||||
|           .addDefaultHeader('deviceModel', iosInfo.utsname.machine ?? ''); | ||||
|           .addDefaultHeader('deviceModel', iosInfo.utsname.machine); | ||||
|       _apiService.authenticationApi.apiClient | ||||
|           .addDefaultHeader('deviceType', 'iOS'); | ||||
|     } else { | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import 'package:immich_mobile/shared/providers/websocket.provider.dart'; | ||||
| import 'package:immich_mobile/shared/ui/immich_toast.dart'; | ||||
|  | ||||
| class ChangePasswordForm extends HookConsumerWidget { | ||||
|   const ChangePasswordForm({Key? key}) : super(key: key); | ||||
|   const ChangePasswordForm({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -128,7 +128,7 @@ class ChangePasswordForm extends HookConsumerWidget { | ||||
| class PasswordInput extends StatelessWidget { | ||||
|   final TextEditingController controller; | ||||
|  | ||||
|   const PasswordInput({Key? key, required this.controller}) : super(key: key); | ||||
|   const PasswordInput({super.key, required this.controller}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
| @@ -149,10 +149,10 @@ class ConfirmPasswordInput extends StatelessWidget { | ||||
|   final TextEditingController confirmController; | ||||
|  | ||||
|   const ConfirmPasswordInput({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.originalController, | ||||
|     required this.confirmController, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   String? _validateInput(String? email) { | ||||
|     if (confirmController.value != originalController.value) { | ||||
| @@ -181,10 +181,10 @@ class ChangePasswordButton extends ConsumerWidget { | ||||
|   final TextEditingController passwordController; | ||||
|   final VoidCallback onPressed; | ||||
|   const ChangePasswordButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.passwordController, | ||||
|     required this.onPressed, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import 'package:openapi/api.dart'; | ||||
| import 'package:permission_handler/permission_handler.dart'; | ||||
|  | ||||
| class LoginForm extends HookConsumerWidget { | ||||
|   const LoginForm({Key? key}) : super(key: key); | ||||
|   const LoginForm({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -426,11 +426,11 @@ class ServerEndpointInput extends StatelessWidget { | ||||
|   final Function()? onSubmit; | ||||
|  | ||||
|   const ServerEndpointInput({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.controller, | ||||
|     required this.focusNode, | ||||
|     this.onSubmit, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   String? _validateInput(String? url) { | ||||
|     if (url == null || url.isEmpty) return null; | ||||
| @@ -474,11 +474,11 @@ class EmailInput extends StatelessWidget { | ||||
|   final Function()? onSubmit; | ||||
|  | ||||
|   const EmailInput({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.controller, | ||||
|     this.focusNode, | ||||
|     this.onSubmit, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   String? _validateInput(String? email) { | ||||
|     if (email == null || email == '') return null; | ||||
| @@ -521,11 +521,11 @@ class PasswordInput extends StatelessWidget { | ||||
|   final Function()? onSubmit; | ||||
|  | ||||
|   const PasswordInput({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.controller, | ||||
|     this.focusNode, | ||||
|     this.onSubmit, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
| @@ -554,9 +554,9 @@ class LoginButton extends ConsumerWidget { | ||||
|   final Function() onPressed; | ||||
|  | ||||
|   const LoginButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.onPressed, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -581,12 +581,12 @@ class OAuthLoginButton extends ConsumerWidget { | ||||
|   final Function() onPressed; | ||||
|  | ||||
|   const OAuthLoginButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.serverEndpointController, | ||||
|     required this.isLoading, | ||||
|     required this.buttonLabel, | ||||
|     required this.onPressed, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -606,7 +606,7 @@ class OAuthLoginButton extends ConsumerWidget { | ||||
| } | ||||
|  | ||||
| class LoadingIcon extends StatelessWidget { | ||||
|   const LoadingIcon({Key? key}) : super(key: key); | ||||
|   const LoadingIcon({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import 'package:immich_mobile/modules/login/ui/change_password_form.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class ChangePasswordPage extends HookConsumerWidget { | ||||
|   const ChangePasswordPage({Key? key}) : super(key: key); | ||||
|   const ChangePasswordPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import 'package:package_info_plus/package_info_plus.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class LoginPage extends HookConsumerWidget { | ||||
|   const LoginPage({Key? key}) : super(key: key); | ||||
|   const LoginPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -92,7 +92,7 @@ class _AssetMarkerIcon extends StatelessWidget { | ||||
|                       "Authorization": | ||||
|                           "Bearer ${Store.get(StoreKey.accessToken)}", | ||||
|                     }, | ||||
|                     errorListener: () => | ||||
|                     errorListener: (_) => | ||||
|                         const Icon(Icons.image_not_supported_outlined), | ||||
|                   ), | ||||
|                 ), | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import 'package:immich_mobile/shared/models/user.dart'; | ||||
| import 'package:immich_mobile/shared/ui/user_avatar.dart'; | ||||
|  | ||||
| class PartnerList extends HookConsumerWidget { | ||||
|   const PartnerList({Key? key, required this.partner}) : super(key: key); | ||||
|   const PartnerList({super.key, required this.partner}); | ||||
|  | ||||
|   final List<User> partner; | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import 'package:immich_mobile/shared/ui/immich_toast.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class PartnerDetailPage extends HookConsumerWidget { | ||||
|   const PartnerDetailPage({Key? key, required this.partner}) : super(key: key); | ||||
|   const PartnerDetailPage({super.key, required this.partner}); | ||||
|  | ||||
|   final User partner; | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import 'package:immich_mobile/shared/ui/user_avatar.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class PartnerPage extends HookConsumerWidget { | ||||
|   const PartnerPage({Key? key}) : super(key: key); | ||||
|   const PartnerPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /// A wrapper for [CuratedLocationsResponseDto] objects | ||||
| /// and [CuratedObjectsResponseDto] to be displayed in  | ||||
| /// and [CuratedObjectsResponseDto] to be displayed in | ||||
| /// a view | ||||
| class CuratedContent { | ||||
|   /// The label to show associated with this curated object | ||||
|   | ||||
| @@ -3,10 +3,11 @@ import 'package:immich_mobile/shared/models/asset.dart'; | ||||
| import 'package:immich_mobile/shared/providers/db.provider.dart'; | ||||
| import 'package:isar/isar.dart'; | ||||
|  | ||||
| final allMotionPhotosProvider = FutureProvider<List<Asset>>( (ref) async { | ||||
|   return ref.watch(dbProvider) | ||||
|     .assets | ||||
|     .filter() | ||||
|     .livePhotoVideoIdIsNotNull() | ||||
|     .findAll(); | ||||
| final allMotionPhotosProvider = FutureProvider<List<Asset>>((ref) async { | ||||
|   return ref | ||||
|       .watch(dbProvider) | ||||
|       .assets | ||||
|       .filter() | ||||
|       .livePhotoVideoIdIsNotNull() | ||||
|       .findAll(); | ||||
| }); | ||||
|   | ||||
| @@ -3,8 +3,9 @@ import 'package:immich_mobile/shared/models/asset.dart'; | ||||
| import 'package:immich_mobile/shared/providers/db.provider.dart'; | ||||
| import 'package:isar/isar.dart'; | ||||
|  | ||||
| final recentlyAddedProvider = FutureProvider<List<Asset>>( (ref) async { | ||||
|   return ref.watch(dbProvider) | ||||
| final recentlyAddedProvider = FutureProvider<List<Asset>>((ref) async { | ||||
|   return ref | ||||
|       .watch(dbProvider) | ||||
|       .assets | ||||
|       .where() | ||||
|       .sortByFileCreatedAtDesc() | ||||
|   | ||||
| @@ -8,10 +8,10 @@ import 'package:immich_mobile/modules/search/providers/search_page_state.provide | ||||
| class ImmichSearchBar extends HookConsumerWidget | ||||
|     implements PreferredSizeWidget { | ||||
|   const ImmichSearchBar({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.searchFocusNode, | ||||
|     required this.onSubmitted, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final FocusNode searchFocusNode; | ||||
|   final Function(String) onSubmitted; | ||||
|   | ||||
| @@ -5,8 +5,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; | ||||
| import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; | ||||
|  | ||||
| class SearchSuggestionList extends ConsumerWidget { | ||||
|   const SearchSuggestionList({Key? key, required this.onSubmitted}) | ||||
|       : super(key: key); | ||||
|   const SearchSuggestionList({super.key, required this.onSubmitted}); | ||||
|  | ||||
|   final Function(String) onSubmitted; | ||||
|   @override | ||||
|   | ||||
| @@ -7,13 +7,13 @@ import 'package:immich_mobile/extensions/string_extensions.dart'; | ||||
| // ignore: must_be_immutable | ||||
| class ThumbnailWithInfo extends StatelessWidget { | ||||
|   ThumbnailWithInfo({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.textInfo, | ||||
|     this.imageUrl, | ||||
|     this.noImageIcon, | ||||
|     this.borderRadius = 10, | ||||
|     required this.onTap, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final String textInfo; | ||||
|   final String? imageUrl; | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import 'package:immich_mobile/shared/ui/scaffold_error_body.dart'; | ||||
| @RoutePage() | ||||
| // ignore: must_be_immutable | ||||
| class SearchPage extends HookConsumerWidget { | ||||
|   SearchPage({Key? key}) : super(key: key); | ||||
|   SearchPage({super.key}); | ||||
|  | ||||
|   FocusNode searchFocusNode = FocusNode(); | ||||
|  | ||||
|   | ||||
| @@ -28,9 +28,9 @@ SearchType _getSearchType(String searchTerm) { | ||||
| @RoutePage() | ||||
| class SearchResultPage extends HookConsumerWidget { | ||||
|   const SearchResultPage({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.searchTerm, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final String searchTerm; | ||||
|  | ||||
|   | ||||
| @@ -4,11 +4,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:permission_handler/permission_handler.dart'; | ||||
|  | ||||
| class NotificationPermissionNotifier extends StateNotifier<PermissionStatus> { | ||||
|   NotificationPermissionNotifier() : | ||||
|     super(Platform.isAndroid | ||||
|       ? PermissionStatus.granted | ||||
|       : PermissionStatus.restricted, | ||||
|     ) { | ||||
|   NotificationPermissionNotifier() | ||||
|       : super( | ||||
|           Platform.isAndroid | ||||
|               ? PermissionStatus.granted | ||||
|               : PermissionStatus.restricted, | ||||
|         ) { | ||||
|     // Sets the initial state | ||||
|     getNotificationPermission().then((p) => state = p); | ||||
|   } | ||||
| @@ -16,9 +17,9 @@ class NotificationPermissionNotifier extends StateNotifier<PermissionStatus> { | ||||
|   /// Requests the notification permission | ||||
|   /// Note: In Android, this is always granted | ||||
|   Future<PermissionStatus> requestNotificationPermission() async { | ||||
|      final permission = await Permission.notification.request(); | ||||
|      state = permission; | ||||
|      return permission; | ||||
|     final permission = await Permission.notification.request(); | ||||
|     state = permission; | ||||
|     return permission; | ||||
|   } | ||||
|  | ||||
|   /// Whether the user has the permission or not | ||||
| @@ -37,8 +38,9 @@ class NotificationPermissionNotifier extends StateNotifier<PermissionStatus> { | ||||
|   Future<bool> hasOrAskForNotificationPermission() { | ||||
|     return requestNotificationPermission().then((p) => p.isGranted); | ||||
|   } | ||||
|  | ||||
| } | ||||
| final notificationPermissionProvider | ||||
|   = StateNotifierProvider<NotificationPermissionNotifier, PermissionStatus> | ||||
|     ((ref) => NotificationPermissionNotifier()); | ||||
|  | ||||
| final notificationPermissionProvider = | ||||
|     StateNotifierProvider<NotificationPermissionNotifier, PermissionStatus>( | ||||
|   (ref) => NotificationPermissionNotifier(), | ||||
| ); | ||||
|   | ||||
| @@ -9,8 +9,8 @@ import 'package:immich_mobile/modules/settings/services/app_settings.service.dar | ||||
|  | ||||
| class LayoutSettings extends HookConsumerWidget { | ||||
|   const LayoutSettings({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -7,8 +7,8 @@ import 'asset_list_tiles_per_row.dart'; | ||||
|  | ||||
| class AssetListSettings extends StatelessWidget { | ||||
|   const AssetListSettings({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import 'package:immich_mobile/modules/settings/services/app_settings.service.dar | ||||
|  | ||||
| class StorageIndicator extends HookConsumerWidget { | ||||
|   const StorageIndicator({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import 'package:immich_mobile/modules/settings/services/app_settings.service.dar | ||||
|  | ||||
| class TilesPerRow extends HookConsumerWidget { | ||||
|   const TilesPerRow({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -9,8 +9,8 @@ import 'package:immich_mobile/modules/settings/ui/settings_switch_list_tile.dart | ||||
|  | ||||
| class ImageViewerQualitySetting extends HookConsumerWidget { | ||||
|   const ImageViewerQualitySetting({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -11,8 +11,8 @@ import 'package:permission_handler/permission_handler.dart'; | ||||
|  | ||||
| class NotificationSetting extends HookConsumerWidget { | ||||
|   const NotificationSetting({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -9,8 +9,8 @@ import 'package:immich_mobile/utils/immich_app_theme.dart'; | ||||
|  | ||||
| class ThemeSetting extends HookConsumerWidget { | ||||
|   const ThemeSetting({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import 'package:immich_mobile/modules/settings/ui/theme_setting/theme_setting.da | ||||
|  | ||||
| @RoutePage() | ||||
| class SettingsPage extends HookConsumerWidget { | ||||
|   const SettingsPage({Key? key}) : super(key: key); | ||||
|   const SettingsPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
| @@ -43,7 +43,7 @@ class SettingsPage extends HookConsumerWidget { | ||||
|               const LocalStorageSettings(), | ||||
|               const AdvancedSettings(), | ||||
|             ], | ||||
|           ).toList(), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class SharedLinkPage extends HookConsumerWidget { | ||||
|   const SharedLinkPage({Key? key}) : super(key: key); | ||||
|   const SharedLinkPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -13,7 +13,6 @@ class AuthGuard extends AutoRouteGuard { | ||||
|   AuthGuard(this._apiService); | ||||
|   @override | ||||
|   void onNavigation(NavigationResolver resolver, StackRouter router) async { | ||||
|  | ||||
|     resolver.next(true); | ||||
|  | ||||
|     try { | ||||
|   | ||||
| @@ -8,7 +8,9 @@ class DuplicateGuard extends AutoRouteGuard { | ||||
|   void onNavigation(NavigationResolver resolver, StackRouter router) async { | ||||
|     // Duplicate navigation | ||||
|     if (resolver.route.name == router.current.name) { | ||||
|       debugPrint('DuplicateGuard: Preventing duplicate route navigation for ${resolver.route.name}'); | ||||
|       debugPrint( | ||||
|         'DuplicateGuard: Preventing duplicate route navigation for ${resolver.route.name}', | ||||
|       ); | ||||
|       resolver.next(false); | ||||
|     } else { | ||||
|       resolver.next(true); | ||||
|   | ||||
| @@ -95,15 +95,15 @@ class StoreValue { | ||||
|  | ||||
|   T? _extract<T>(StoreKey<T> key) { | ||||
|     switch (key.type) { | ||||
|       case int: | ||||
|       case const (int): | ||||
|         return intValue as T?; | ||||
|       case bool: | ||||
|       case const (bool): | ||||
|         return intValue == null ? null : (intValue! == 1) as T; | ||||
|       case DateTime: | ||||
|       case const (DateTime): | ||||
|         return intValue == null | ||||
|             ? null | ||||
|             : DateTime.fromMicrosecondsSinceEpoch(intValue!) as T; | ||||
|       case String: | ||||
|       case const (String): | ||||
|         return strValue as T?; | ||||
|       default: | ||||
|         if (key.fromDb != null) { | ||||
| @@ -117,16 +117,16 @@ class StoreValue { | ||||
|     int? i; | ||||
|     String? s; | ||||
|     switch (key.type) { | ||||
|       case int: | ||||
|       case const (int): | ||||
|         i = value as int?; | ||||
|         break; | ||||
|       case bool: | ||||
|       case const (bool): | ||||
|         i = value == null ? null : (value == true ? 1 : 0); | ||||
|         break; | ||||
|       case DateTime: | ||||
|       case const (DateTime): | ||||
|         i = value == null ? null : (value as DateTime).microsecondsSinceEpoch; | ||||
|         break; | ||||
|       case String: | ||||
|       case const (String): | ||||
|         s = value as String?; | ||||
|         break; | ||||
|       default: | ||||
|   | ||||
| @@ -3,5 +3,5 @@ import 'package:immich_mobile/shared/providers/user.provider.dart'; | ||||
|  | ||||
| final isAdminProvider = Provider<bool>((ref) { | ||||
|   final currentUser = ref.watch(currentUserProvider); | ||||
|   return currentUser?.isAdmin ?? false;  // Default to non-admin if no user | ||||
|   return currentUser?.isAdmin ?? false; // Default to non-admin if no user | ||||
| }); | ||||
|   | ||||
| @@ -11,8 +11,8 @@ import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; | ||||
|  | ||||
| class AppBarProfileInfoBox extends HookConsumerWidget { | ||||
|   const AppBarProfileInfoBox({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -10,8 +10,8 @@ import 'package:package_info_plus/package_info_plus.dart'; | ||||
|  | ||||
| class AppBarServerInfo extends HookConsumerWidget { | ||||
|   const AppBarServerInfo({ | ||||
|     Key? key, | ||||
|   }) : super(key: key); | ||||
|     super.key, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|   | ||||
| @@ -30,7 +30,7 @@ import 'package:immich_mobile/utils/selection_handlers.dart'; | ||||
|  | ||||
| class MultiselectGrid extends HookConsumerWidget { | ||||
|   const MultiselectGrid({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.renderListProvider, | ||||
|     this.onRefresh, | ||||
|     this.buildLoadingIndicator, | ||||
| @@ -43,7 +43,7 @@ class MultiselectGrid extends HookConsumerWidget { | ||||
|     this.editEnabled = false, | ||||
|     this.unarchive = false, | ||||
|     this.unfavorite = false, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final ProviderListenable<AsyncValue<RenderList>> renderListProvider; | ||||
|   final Future<void> Function()? onRefresh; | ||||
|   | ||||
| @@ -10,13 +10,13 @@ class ConfirmDialog extends StatelessWidget { | ||||
|   final String ok; | ||||
|  | ||||
|   const ConfirmDialog({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.onOk, | ||||
|     required this.title, | ||||
|     required this.content, | ||||
|     this.cancel = "delete_dialog_cancel", | ||||
|     this.ok = "backup_controller_page_background_battery_info_ok", | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -19,12 +19,12 @@ class CustomDraggingHandle extends StatelessWidget { | ||||
|  | ||||
| class ControlBoxButton extends StatelessWidget { | ||||
|   const ControlBoxButton({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.label, | ||||
|     required this.iconData, | ||||
|     this.onPressed, | ||||
|     this.onLongPressed, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final String label; | ||||
|   final IconData iconData; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import 'package:immich_mobile/shared/models/store.dart'; | ||||
| import 'package:immich_mobile/utils/image_url_builder.dart'; | ||||
| import 'package:photo_manager/photo_manager.dart'; | ||||
| import 'package:openapi/api.dart' as api; | ||||
| import 'package:photo_manager_image_provider/photo_manager_image_provider.dart'; | ||||
|  | ||||
| /// Renders an Asset using local data if available, else remote data | ||||
| class ImmichImage extends StatelessWidget { | ||||
|   | ||||
| @@ -5,9 +5,9 @@ class ImmichLoadingIndicator extends StatelessWidget { | ||||
|   final double? borderRadius; | ||||
|  | ||||
|   const ImmichLoadingIndicator({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     this.borderRadius, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -21,5 +21,4 @@ class ImmichLogo extends StatelessWidget { | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -233,7 +233,7 @@ class PhotoView extends StatefulWidget { | ||||
|   /// | ||||
|   /// Internally, the image is rendered within an [Image] widget. | ||||
|   const PhotoView({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.imageProvider, | ||||
|     required this.index, | ||||
|     this.loadingBuilder, | ||||
| @@ -264,8 +264,7 @@ class PhotoView extends StatefulWidget { | ||||
|     this.errorBuilder, | ||||
|     this.enablePanAlways, | ||||
|   })  : child = null, | ||||
|         childSize = null, | ||||
|         super(key: key); | ||||
|         childSize = null; | ||||
|  | ||||
|   /// Creates a widget that displays a zoomable child. | ||||
|   /// | ||||
| @@ -274,7 +273,7 @@ class PhotoView extends StatefulWidget { | ||||
|   /// Instead of a [imageProvider], this constructor will receive a [child] and a [childSize]. | ||||
|   /// | ||||
|   const PhotoView.customChild({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     this.childSize, | ||||
|     this.backgroundDecoration, | ||||
| @@ -305,8 +304,7 @@ class PhotoView extends StatefulWidget { | ||||
|         imageProvider = null, | ||||
|         gaplessPlayback = false, | ||||
|         loadingBuilder = null, | ||||
|         index = 0, | ||||
|         super(key: key); | ||||
|         index = 0; | ||||
|  | ||||
|   /// Given a [imageProvider] it resolves into an zoomable image widget using. It | ||||
|   /// is required | ||||
|   | ||||
| @@ -107,7 +107,7 @@ typedef PhotoViewGalleryBuilder = PhotoViewGalleryPageOptions Function( | ||||
| class PhotoViewGallery extends StatefulWidget { | ||||
|   /// Construct a gallery with static items through a list of [PhotoViewGalleryPageOptions]. | ||||
|   const PhotoViewGallery({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.pageOptions, | ||||
|     this.loadingBuilder, | ||||
|     this.backgroundDecoration, | ||||
| @@ -123,14 +123,13 @@ class PhotoViewGallery extends StatefulWidget { | ||||
|     this.customSize, | ||||
|     this.allowImplicitScrolling = false, | ||||
|   })  : itemCount = null, | ||||
|         builder = null, | ||||
|         super(key: key); | ||||
|         builder = null; | ||||
|  | ||||
|   /// Construct a gallery with dynamic items. | ||||
|   /// | ||||
|   /// The builder must return a [PhotoViewGalleryPageOptions]. | ||||
|   const PhotoViewGallery.builder({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.itemCount, | ||||
|     required this.builder, | ||||
|     this.loadingBuilder, | ||||
| @@ -148,8 +147,7 @@ class PhotoViewGallery extends StatefulWidget { | ||||
|     this.allowImplicitScrolling = false, | ||||
|   })  : pageOptions = null, | ||||
|         assert(itemCount != null), | ||||
|         assert(builder != null), | ||||
|         super(key: key); | ||||
|         assert(builder != null); | ||||
|  | ||||
|   /// A list of options to describe the items in the gallery | ||||
|   final List<PhotoViewGalleryPageOptions>? pageOptions; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ const _defaultDecoration = BoxDecoration( | ||||
| /// to user gestures, updates to  the controller state and mounts the entire PhotoView Layout | ||||
| class PhotoViewCore extends StatefulWidget { | ||||
|   const PhotoViewCore({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.imageProvider, | ||||
|     required this.backgroundDecoration, | ||||
|     required this.gaplessPlayback, | ||||
| @@ -47,11 +47,10 @@ class PhotoViewCore extends StatefulWidget { | ||||
|     required this.filterQuality, | ||||
|     required this.disableGestures, | ||||
|     required this.enablePanAlways, | ||||
|   })  : customChild = null, | ||||
|         super(key: key); | ||||
|   }) : customChild = null; | ||||
|  | ||||
|   const PhotoViewCore.customChild({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     required this.customChild, | ||||
|     required this.backgroundDecoration, | ||||
|     this.heroAttributes, | ||||
| @@ -73,8 +72,7 @@ class PhotoViewCore extends StatefulWidget { | ||||
|     required this.disableGestures, | ||||
|     required this.enablePanAlways, | ||||
|   })  : imageProvider = null, | ||||
|         gaplessPlayback = false, | ||||
|         super(key: key); | ||||
|         gaplessPlayback = false; | ||||
|  | ||||
|   final Decoration? backgroundDecoration; | ||||
|   final ImageProvider? imageProvider; | ||||
| @@ -359,15 +357,15 @@ class PhotoViewCoreState extends State<PhotoViewCore> | ||||
|             onScaleStart: onScaleStart, | ||||
|             onScaleUpdate: onScaleUpdate, | ||||
|             onScaleEnd: onScaleEnd, | ||||
|             onDragStart:  widget.onDragStart != null | ||||
|                ? (details) => widget.onDragStart!(context, details, value) | ||||
|                : null, | ||||
|             onDragEnd:  widget.onDragEnd != null | ||||
|                ? (details) => widget.onDragEnd!(context, details, value) | ||||
|                : null, | ||||
|             onDragStart: widget.onDragStart != null | ||||
|                 ? (details) => widget.onDragStart!(context, details, value) | ||||
|                 : null, | ||||
|             onDragEnd: widget.onDragEnd != null | ||||
|                 ? (details) => widget.onDragEnd!(context, details, value) | ||||
|                 : null, | ||||
|             onDragUpdate: widget.onDragUpdate != null | ||||
|                ? (details) => widget.onDragUpdate!(context, details, value) | ||||
|                : null, | ||||
|                 ? (details) => widget.onDragUpdate!(context, details, value) | ||||
|                 : null, | ||||
|             hitDetector: this, | ||||
|             onTapUp: widget.onTapUp != null | ||||
|                 ? (details) => widget.onTapUp!(context, details, value) | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import 'photo_view_hit_corners.dart'; | ||||
| /// for the gist | ||||
| class PhotoViewGestureDetector extends StatelessWidget { | ||||
|   const PhotoViewGestureDetector({ | ||||
|     Key? key, | ||||
|     super.key, | ||||
|     this.hitDetector, | ||||
|     this.onScaleStart, | ||||
|     this.onScaleUpdate, | ||||
| @@ -20,7 +20,7 @@ class PhotoViewGestureDetector extends StatelessWidget { | ||||
|     this.onTapUp, | ||||
|     this.onTapDown, | ||||
|     this.behavior, | ||||
|   }) : super(key: key); | ||||
|   }); | ||||
|  | ||||
|   final GestureDoubleTapCallback? onDoubleTap; | ||||
|   final HitCornersDetector? hitDetector; | ||||
| @@ -63,14 +63,14 @@ class PhotoViewGestureDetector extends StatelessWidget { | ||||
|     } | ||||
|  | ||||
|     if (onDragStart != null || onDragEnd != null || onDragUpdate != null) { | ||||
|       gestures[VerticalDragGestureRecognizer] =  | ||||
|       gestures[VerticalDragGestureRecognizer] = | ||||
|           GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>( | ||||
|         () => VerticalDragGestureRecognizer(debugOwner: this), | ||||
|         (VerticalDragGestureRecognizer instance) { | ||||
|           instance | ||||
|               ..onStart = onDragStart | ||||
|               ..onUpdate = onDragUpdate | ||||
|               ..onEnd = onDragEnd; | ||||
|             ..onStart = onDragStart | ||||
|             ..onUpdate = onDragUpdate | ||||
|             ..onEnd = onDragEnd; | ||||
|         }, | ||||
|       ); | ||||
|     } | ||||
| @@ -86,11 +86,11 @@ class PhotoViewGestureDetector extends StatelessWidget { | ||||
|     gestures[PhotoViewGestureRecognizer] = | ||||
|         GestureRecognizerFactoryWithHandlers<PhotoViewGestureRecognizer>( | ||||
|       () => PhotoViewGestureRecognizer( | ||||
|           hitDetector: hitDetector, | ||||
|           debugOwner: this, | ||||
|           validateAxis: axis, | ||||
|           touchSlopFactor: touchSlopFactor, | ||||
|         ), | ||||
|         hitDetector: hitDetector, | ||||
|         debugOwner: this, | ||||
|         validateAxis: axis, | ||||
|         touchSlopFactor: touchSlopFactor, | ||||
|       ), | ||||
|       (PhotoViewGestureRecognizer instance) { | ||||
|         instance | ||||
|           ..onStart = onScaleStart | ||||
| @@ -110,11 +110,11 @@ class PhotoViewGestureDetector extends StatelessWidget { | ||||
| class PhotoViewGestureRecognizer extends ScaleGestureRecognizer { | ||||
|   PhotoViewGestureRecognizer({ | ||||
|     this.hitDetector, | ||||
|     Object? debugOwner, | ||||
|     super.debugOwner, | ||||
|     this.validateAxis, | ||||
|     this.touchSlopFactor = 1, | ||||
|     PointerDeviceKind? kind, | ||||
|   }) : super(debugOwner: debugOwner, supportedDevices: null); | ||||
|   }) : super(supportedDevices: null); | ||||
|   final HitCornersDetector? hitDetector; | ||||
|   final Axis? validateAxis; | ||||
|   final double touchSlopFactor; | ||||
| @@ -236,11 +236,11 @@ class PhotoViewGestureRecognizer extends ScaleGestureRecognizer { | ||||
| /// ``` | ||||
| class PhotoViewGestureDetectorScope extends InheritedWidget { | ||||
|   const PhotoViewGestureDetectorScope({ | ||||
|     super.key,  | ||||
|     super.key, | ||||
|     this.axis, | ||||
|     this.touchSlopFactor = .2, | ||||
|     required Widget child, | ||||
|   }) : super(child: child); | ||||
|     required super.child, | ||||
|   }); | ||||
|  | ||||
|   static PhotoViewGestureDetectorScope? of(BuildContext context) { | ||||
|     final PhotoViewGestureDetectorScope? scope = context | ||||
| @@ -254,11 +254,12 @@ class PhotoViewGestureDetectorScope extends InheritedWidget { | ||||
|   // 0: most reactive but will not let tap recognizers accept gestures | ||||
|   // <1: less reactive but gives the most leeway to other recognizers | ||||
|   // 1: will not be able to compete with a `HorizontalDragGestureRecognizer` up the widget tree | ||||
|   final double touchSlopFactor;   | ||||
|   final double touchSlopFactor; | ||||
|  | ||||
|   @override | ||||
|   bool updateShouldNotify(PhotoViewGestureDetectorScope oldWidget) { | ||||
|     return axis != oldWidget.axis && touchSlopFactor != oldWidget.touchSlopFactor; | ||||
|     return axis != oldWidget.axis && | ||||
|         touchSlopFactor != oldWidget.touchSlopFactor; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -269,16 +270,14 @@ class PhotoViewGestureDetectorScope extends InheritedWidget { | ||||
| class PhotoViewPageViewScrollPhysics extends ScrollPhysics { | ||||
|   const PhotoViewPageViewScrollPhysics({ | ||||
|     this.touchSlopFactor = 0.1, | ||||
|     ScrollPhysics? parent, | ||||
|   }) : super(parent: parent); | ||||
|  | ||||
|     super.parent, | ||||
|   }); | ||||
|  | ||||
|   // in [0, 1] | ||||
|   // 0: most reactive but will not let PhotoView recognizers accept gestures | ||||
|   // 1: less reactive but gives the most leeway to PhotoView recognizers | ||||
|   final double touchSlopFactor; | ||||
|  | ||||
|  | ||||
|   @override | ||||
|   PhotoViewPageViewScrollPhysics applyTo(ScrollPhysics? ancestor) { | ||||
|     return PhotoViewPageViewScrollPhysics( | ||||
| @@ -287,7 +286,6 @@ class PhotoViewPageViewScrollPhysics extends ScrollPhysics { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   @override | ||||
|   double get dragStartDistanceMotionThreshold => kTouchSlop * touchSlopFactor; | ||||
| } | ||||
|   | ||||
| @@ -26,7 +26,11 @@ mixin HitCornersDetector on PhotoViewControllerDelegate { | ||||
|     return HitCorners(y <= cornersY.min, y >= cornersY.max); | ||||
|   } | ||||
|  | ||||
|   bool _shouldMoveAxis(HitCorners hitCorners, double mainAxisMove, double crossAxisMove) { | ||||
|   bool _shouldMoveAxis( | ||||
|     HitCorners hitCorners, | ||||
|     double mainAxisMove, | ||||
|     double crossAxisMove, | ||||
|   ) { | ||||
|     if (mainAxisMove == 0) { | ||||
|       return false; | ||||
|     } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class PhotoViewDefaultError extends StatelessWidget { | ||||
|   const PhotoViewDefaultError({Key? key, required this.decoration}) | ||||
|       : super(key: key); | ||||
|   const PhotoViewDefaultError({super.key, required this.decoration}); | ||||
|  | ||||
|   final BoxDecoration decoration; | ||||
|  | ||||
| @@ -22,7 +21,7 @@ class PhotoViewDefaultError extends StatelessWidget { | ||||
| } | ||||
|  | ||||
| class PhotoViewDefaultLoading extends StatelessWidget { | ||||
|   const PhotoViewDefaultLoading({Key? key, this.event}) : super(key: key); | ||||
|   const PhotoViewDefaultLoading({super.key, this.event}); | ||||
|  | ||||
|   final ImageChunkEvent? event; | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user