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:
shenlong 2024-01-27 16:14:32 +00:00 committed by GitHub
parent 0522058fdf
commit 27488ceb67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
116 changed files with 627 additions and 624 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,3 @@
{
"flutter": "3.13.6"
"flutter": "3.16.9"
}

View File

@ -1,5 +1,5 @@
{
"dart.flutterSdkPath": ".fvm\\versions\\3.13.6",
"dart.flutterSdkPath": ".fvm\\versions\\3.16.9",
"search.exclude": {
"**/.fvm": true
},

View File

@ -34,7 +34,7 @@ if (keystorePropertiesFile.exists()) {
android {
compileSdkVersion 33
compileSdkVersion 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8

View File

@ -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);

View File

@ -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(

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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,
),
);

View File

@ -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!,
);

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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) {

View File

@ -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();

View File

@ -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)),
);

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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(),

View File

@ -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) {

View File

@ -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) {

View File

@ -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",

View File

@ -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) {

View File

@ -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',

View File

@ -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) {

View File

@ -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 {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -92,7 +92,7 @@ class _AssetMarkerIcon extends StatelessWidget {
"Authorization":
"Bearer ${Store.get(StoreKey.accessToken)}",
},
errorListener: () =>
errorListener: (_) =>
const Icon(Icons.image_not_supported_outlined),
),
),

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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();
});

View File

@ -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()

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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(),
);

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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(),
),
],
),
);

View File

@ -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) {

View File

@ -13,7 +13,6 @@ class AuthGuard extends AutoRouteGuard {
AuthGuard(this._apiService);
@override
void onNavigation(NavigationResolver resolver, StackRouter router) async {
resolver.next(true);
try {

View File

@ -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);

View File

@ -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:

View File

@ -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
});

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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 {

View File

@ -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) {

View File

@ -21,5 +21,4 @@ class ImmichLogo extends StatelessWidget {
),
);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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