mirror of
https://github.com/immich-app/immich.git
synced 2026-01-11 04:35:25 -08:00
feat: show preview in a separate page
This commit is contained in:
@@ -745,6 +745,7 @@
|
||||
"cleanup_found_assets": "Found {count} backed up assets",
|
||||
"cleanup_icloud_shared_albums_excluded": "iCloud Shared Albums are excluded from the scan",
|
||||
"cleanup_no_assets_found": "No backed up assets found matching your criteria",
|
||||
"cleanup_preview_title": "Assets to remove ({count})",
|
||||
"cleanup_step3_description": "Scan for photos and videos that have been backed up to the server with the selected cutoff date and filter options",
|
||||
"cleanup_step4_summary": "{count} assets created before {date} are queued for removal from your device",
|
||||
"clear": "Clear",
|
||||
|
||||
44
mobile/lib/presentation/pages/cleanup_preview.page.dart
Normal file
44
mobile/lib/presentation/pages/cleanup_preview.page.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
|
||||
@RoutePage()
|
||||
class CleanupPreviewPage extends StatelessWidget {
|
||||
final List<LocalAsset> assets;
|
||||
|
||||
const CleanupPreviewPage({super.key, required this.assets});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
'cleanup_preview_title'.t(context: context, args: {'count': assets.length.toString()}),
|
||||
),
|
||||
centerTitle: true,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
backgroundColor: context.colorScheme.surface,
|
||||
),
|
||||
body: ProviderScope(
|
||||
overrides: [
|
||||
timelineServiceProvider.overrideWith((ref) {
|
||||
final timelineService = ref
|
||||
.watch(timelineFactoryProvider)
|
||||
.fromAssetsWithBuckets(assets.cast<BaseAsset>(), TimelineOrigin.search);
|
||||
ref.onDispose(timelineService.dispose);
|
||||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: const Timeline(appBar: null, bottomSheet: null, groupBy: GroupAssetsBy.day, readOnly: true),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@ import 'package:immich_mobile/presentation/pages/drift_album_options.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_archive.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_asset_selection_timeline.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_asset_troubleshoot.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/cleanup_preview.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_create_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_favorite.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_library.page.dart';
|
||||
@@ -338,6 +339,7 @@ class AppRouter extends RootStackRouter {
|
||||
AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: ImmichUIShowcaseRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: CleanupPreviewRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
// required to handle all deeplinks in deep_link.service.dart
|
||||
// auto_route_library#1722
|
||||
RedirectRoute(path: '*', redirectTo: '/'),
|
||||
|
||||
@@ -611,6 +611,43 @@ class ChangePasswordRoute extends PageRouteInfo<void> {
|
||||
);
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [CleanupPreviewPage]
|
||||
class CleanupPreviewRoute extends PageRouteInfo<CleanupPreviewRouteArgs> {
|
||||
CleanupPreviewRoute({
|
||||
Key? key,
|
||||
required List<LocalAsset> assets,
|
||||
List<PageRouteInfo>? children,
|
||||
}) : super(
|
||||
CleanupPreviewRoute.name,
|
||||
args: CleanupPreviewRouteArgs(key: key, assets: assets),
|
||||
initialChildren: children,
|
||||
);
|
||||
|
||||
static const String name = 'CleanupPreviewRoute';
|
||||
|
||||
static PageInfo page = PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<CleanupPreviewRouteArgs>();
|
||||
return CleanupPreviewPage(key: args.key, assets: args.assets);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class CleanupPreviewRouteArgs {
|
||||
const CleanupPreviewRouteArgs({this.key, required this.assets});
|
||||
|
||||
final Key? key;
|
||||
|
||||
final List<LocalAsset> assets;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CleanupPreviewRouteArgs{key: $key, assets: $assets}';
|
||||
}
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [CreateAlbumPage]
|
||||
class CreateAlbumRoute extends PageRouteInfo<CreateAlbumRouteArgs> {
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/cleanup.provider.dart';
|
||||
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
|
||||
enum CleanupStep { selectDate, filterOptions, scan, delete }
|
||||
|
||||
@@ -136,18 +134,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
|
||||
|
||||
void _showAssetsPreview(List<LocalAsset> assets) {
|
||||
ref.read(hapticFeedbackProvider.notifier).mediumImpact();
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => DraggableScrollableSheet(
|
||||
initialChildSize: 0.9,
|
||||
minChildSize: 0.5,
|
||||
maxChildSize: 0.95,
|
||||
expand: false,
|
||||
builder: (context, scrollController) => _CleanupAssetsPreview(assets: assets),
|
||||
),
|
||||
);
|
||||
context.pushRoute(CleanupPreviewRoute(assets: assets));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -648,64 +635,6 @@ class _DeleteConfirmationDialog extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _CleanupAssetsPreview extends StatelessWidget {
|
||||
final List<LocalAsset> assets;
|
||||
|
||||
const _CleanupAssetsPreview({required this.assets});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
const _DragHandle(),
|
||||
Expanded(
|
||||
child: ProviderScope(
|
||||
overrides: [
|
||||
timelineServiceProvider.overrideWith((ref) {
|
||||
final timelineService = ref
|
||||
.watch(timelineFactoryProvider)
|
||||
.fromAssetsWithBuckets(assets.cast<BaseAsset>(), TimelineOrigin.search);
|
||||
ref.onDispose(timelineService.dispose);
|
||||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: const Timeline(
|
||||
appBar: null,
|
||||
bottomSheet: null,
|
||||
withScrubber: false,
|
||||
groupBy: GroupAssetsBy.day,
|
||||
readOnly: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DragHandle extends StatelessWidget {
|
||||
const _DragHandle();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 38,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 32,
|
||||
height: 6,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
||||
color: context.colorScheme.onSurfaceVariant.withValues(alpha: 0.4),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DatePresetCard extends StatelessWidget {
|
||||
final String value;
|
||||
final String unit;
|
||||
|
||||
Reference in New Issue
Block a user