From 843345df4ffc45f6808d47973e2c02da1d30b015 Mon Sep 17 00:00:00 2001 From: Yuvraj P Date: Sat, 24 Aug 2024 16:30:31 -0400 Subject: [PATCH] fix(mobile): Fix for incorrectly naming edited files and structure change (#11741) * Fix null name * Fix null name and Fix button * Remove extension correctly * Refactoring the code and formatting * formatting * Fix for the extension name --- mobile/lib/pages/editing/crop.page.dart | 12 ++- mobile/lib/pages/editing/edit.page.dart | 100 +++++++++--------- mobile/lib/routing/router.gr.dart | 35 +++--- .../asset_viewer/bottom_gallery_bar.dart | 9 +- 4 files changed, 88 insertions(+), 68 deletions(-) diff --git a/mobile/lib/pages/editing/crop.page.dart b/mobile/lib/pages/editing/crop.page.dart index 8a21cdf769..a3ac34dfa0 100644 --- a/mobile/lib/pages/editing/crop.page.dart +++ b/mobile/lib/pages/editing/crop.page.dart @@ -3,6 +3,7 @@ import 'package:crop_image/crop_image.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/utils/hooks/crop_controller_hook.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'edit.page.dart'; import 'package:auto_route/auto_route.dart'; @@ -14,7 +15,8 @@ import 'package:auto_route/auto_route.dart'; @RoutePage() class CropImagePage extends HookWidget { final Image image; - const CropImagePage({super.key, required this.image}); + final Asset asset; + const CropImagePage({super.key, required this.image, required this.asset}); @override Widget build(BuildContext context) { @@ -34,7 +36,13 @@ class CropImagePage extends HookWidget { ), onPressed: () async { final croppedImage = await cropController.croppedImage(); - context.pushRoute(EditImageRoute(image: croppedImage)); + context.pushRoute( + EditImageRoute( + asset: asset, + image: croppedImage, + isEdited: true, + ), + ); }, ), ], diff --git a/mobile/lib/pages/editing/edit.page.dart b/mobile/lib/pages/editing/edit.page.dart index 22fb345e0f..b9017e940b 100644 --- a/mobile/lib/pages/editing/edit.page.dart +++ b/mobile/lib/pages/editing/edit.page.dart @@ -12,6 +12,7 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:auto_route/auto_route.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:photo_manager/photo_manager.dart'; +import 'package:path/path.dart' as p; import 'package:immich_mobile/providers/album/album.provider.dart'; /// A stateless widget that provides functionality for editing an image. @@ -24,18 +25,16 @@ import 'package:immich_mobile/providers/album/album.provider.dart'; @immutable @RoutePage() class EditImagePage extends ConsumerWidget { - final Asset? asset; - final Image? image; + final Asset asset; + final Image image; + final bool isEdited; const EditImagePage({ super.key, - this.image, - this.asset, - }) : assert( - (image != null && asset == null) || (image == null && asset != null), - 'Must supply one of asset or image', - ); - + required this.asset, + required this.image, + required this.isEdited, + }); Future _imageToUint8List(Image image) async { final Completer completer = Completer(); image.image.resolve(const ImageConfiguration()).addListener( @@ -58,19 +57,34 @@ class EditImagePage extends ConsumerWidget { return completer.future; } + Future _saveEditedImage( + BuildContext context, + Asset asset, + Image image, + WidgetRef ref, + ) async { + try { + final Uint8List imageData = await _imageToUint8List(image); + await PhotoManager.editor.saveImage( + imageData, + title: "${p.withoutExtension(asset.fileName)}_edited.jpg", + ); + await ref.read(albumProvider.notifier).getDeviceAlbums(); + Navigator.of(context).popUntil((route) => route.isFirst); + } catch (e) { + ImmichToast.show( + durationInSecond: 6, + context: context, + msg: 'Error: $e', + gravity: ToastGravity.CENTER, + ); + } + } + @override Widget build(BuildContext context, WidgetRef ref) { - final ImageProvider provider = (asset != null) - ? ImmichImage.imageProvider(asset: asset!) - : (image != null) - ? image!.image - : throw Exception('Invalid image source type'); - - final Image imageWidget = (asset != null) - ? Image(image: ImmichImage.imageProvider(asset: asset!)) - : (image != null) - ? image! - : throw Exception('Invalid image source type'); + final Image imageWidget = + Image(image: ImmichImage.imageProvider(asset: asset)); return Scaffold( appBar: AppBar( @@ -85,44 +99,24 @@ class EditImagePage extends ConsumerWidget { Navigator.of(context).popUntil((route) => route.isFirst), ), actions: [ - if (image != null) - TextButton( - onPressed: () async { - try { - final Uint8List imageData = await _imageToUint8List(image!); - ImmichToast.show( - durationInSecond: 3, - context: context, - msg: 'Image Saved!', - gravity: ToastGravity.CENTER, - ); - - await PhotoManager.editor.saveImage( - imageData, - title: '${asset!.fileName}_edited.jpg', - ); - await ref.read(albumProvider.notifier).getDeviceAlbums(); - Navigator.of(context).popUntil((route) => route.isFirst); - } catch (e) { - ImmichToast.show( - durationInSecond: 6, - context: context, - msg: 'Error: ${e.toString()}', - gravity: ToastGravity.BOTTOM, - ); - } - }, - child: Text( - 'Save to gallery', - style: Theme.of(context).textTheme.displayMedium, + TextButton( + onPressed: isEdited + ? () => _saveEditedImage(context, asset, image, ref) + : null, + child: Text( + 'Save to gallery', + style: TextStyle( + color: + isEdited ? Theme.of(context).iconTheme.color : Colors.grey, ), ), + ), ], ), body: Column( children: [ Expanded( - child: Image(image: provider), + child: image, ), Container( height: 80, @@ -148,7 +142,9 @@ class EditImagePage extends ConsumerWidget { color: Theme.of(context).iconTheme.color, ), onPressed: () { - context.pushRoute(CropImageRoute(image: imageWidget)); + context.pushRoute( + CropImageRoute(asset: asset, image: imageWidget), + ); }, ), Text('Crop', style: Theme.of(context).textTheme.displayMedium), diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index a4259676c7..90fc4cb0fe 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -613,12 +613,14 @@ class CropImageRoute extends PageRouteInfo { CropImageRoute({ Key? key, required Image image, + required Asset asset, List? children, }) : super( CropImageRoute.name, args: CropImageRouteArgs( key: key, image: image, + asset: asset, ), initialChildren: children, ); @@ -632,6 +634,7 @@ class CropImageRoute extends PageRouteInfo { return CropImagePage( key: args.key, image: args.image, + asset: args.asset, ); }, ); @@ -641,15 +644,18 @@ class CropImageRouteArgs { const CropImageRouteArgs({ this.key, required this.image, + required this.asset, }); final Key? key; final Image image; + final Asset asset; + @override String toString() { - return 'CropImageRouteArgs{key: $key, image: $image}'; + return 'CropImageRouteArgs{key: $key, image: $image, asset: $asset}'; } } @@ -658,15 +664,17 @@ class CropImageRouteArgs { class EditImageRoute extends PageRouteInfo { EditImageRoute({ Key? key, - Image? image, - Asset? asset, + required Asset asset, + required Image image, + required bool isEdited, List? children, }) : super( EditImageRoute.name, args: EditImageRouteArgs( key: key, - image: image, asset: asset, + image: image, + isEdited: isEdited, ), initialChildren: children, ); @@ -676,12 +684,12 @@ class EditImageRoute extends PageRouteInfo { static PageInfo page = PageInfo( name, builder: (data) { - final args = data.argsAs( - orElse: () => const EditImageRouteArgs()); + final args = data.argsAs(); return EditImagePage( key: args.key, - image: args.image, asset: args.asset, + image: args.image, + isEdited: args.isEdited, ); }, ); @@ -690,19 +698,22 @@ class EditImageRoute extends PageRouteInfo { class EditImageRouteArgs { const EditImageRouteArgs({ this.key, - this.image, - this.asset, + required this.asset, + required this.image, + required this.isEdited, }); final Key? key; - final Image? image; + final Asset asset; - final Asset? asset; + final Image image; + + final bool isEdited; @override String toString() { - return 'EditImageRouteArgs{key: $key, image: $image, asset: $asset}'; + return 'EditImageRouteArgs{key: $key, asset: $asset, image: $image, isEdited: $isEdited}'; } } diff --git a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart index 7d9e49bd29..7e6136c256 100644 --- a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart +++ b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart @@ -16,6 +16,7 @@ import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart' import 'package:immich_mobile/widgets/asset_viewer/video_controls.dart'; import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart'; import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/widgets/common/immich_image.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; @@ -184,6 +185,7 @@ class BottomGalleryBar extends ConsumerWidget { } void handleEdit() async { + final image = Image(image: ImmichImage.imageProvider(asset: asset)); if (asset.isOffline) { ImmichToast.show( durationInSecond: 1, @@ -195,8 +197,11 @@ class BottomGalleryBar extends ConsumerWidget { } Navigator.of(context).push( MaterialPageRoute( - builder: (context) => - EditImagePage(asset: asset), // Send the Asset object + builder: (context) => EditImagePage( + asset: asset, + image: image, + isEdited: false, + ), ), ); }