mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 09:59:00 -07: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:
parent
0522058fdf
commit
27488ceb67
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
Loading…
Reference in New Issue
Block a user