diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index c092b79bd1..d8aa678e33 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -574,6 +574,11 @@ "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89", "viewer_unstack": "Un-Stack", + "edit_image_title": "Edit", + "crop": "Crop", + "save_to_gallery": "Save to gallery", + "error_saving_image": "Error: {}", + "image_saved_successfully": "Image saved", "sync_albums": "Sync albums", "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", diff --git a/mobile/assets/i18n/es-US.json b/mobile/assets/i18n/es-US.json index 9a17fba787..394139767e 100644 --- a/mobile/assets/i18n/es-US.json +++ b/mobile/assets/i18n/es-US.json @@ -575,4 +575,4 @@ "viewer_remove_from_stack": "Eliminar de la pila", "viewer_stack_use_as_main_asset": "Utilizar como recurso principal", "viewer_unstack": "Desapilar" -} \ No newline at end of file +} diff --git a/mobile/lib/pages/editing/crop.page.dart b/mobile/lib/pages/editing/crop.page.dart index a3ac34dfa0..729b59ded5 100644 --- a/mobile/lib/pages/editing/crop.page.dart +++ b/mobile/lib/pages/editing/crop.page.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:crop_image/crop_image.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.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:easy_localization/easy_localization.dart'; import 'package:auto_route/auto_route.dart'; /// A widget for cropping an image. @@ -25,13 +27,14 @@ class CropImagePage extends HookWidget { return Scaffold( appBar: AppBar( - backgroundColor: Theme.of(context).bottomAppBarTheme.color, - leading: CloseButton(color: Theme.of(context).iconTheme.color), + backgroundColor: context.scaffoldBackgroundColor, + title: Text("crop".tr()), + leading: CloseButton(color: context.primaryColor), actions: [ IconButton( icon: Icon( Icons.done_rounded, - color: Theme.of(context).iconTheme.color, + color: context.primaryColor, size: 24, ), onPressed: () async { @@ -47,13 +50,14 @@ class CropImagePage extends HookWidget { ), ], ), + backgroundColor: context.scaffoldBackgroundColor, body: LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { return Column( children: [ Container( padding: const EdgeInsets.only(top: 20), - width: double.infinity, + width: constraints.maxWidth * 0.9, height: constraints.maxHeight * 0.6, child: CropImage( controller: cropController, @@ -65,7 +69,7 @@ class CropImagePage extends HookWidget { child: Container( width: double.infinity, decoration: BoxDecoration( - color: Theme.of(context).bottomAppBarTheme.color, + color: context.scaffoldBackgroundColor, borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), @@ -196,7 +200,7 @@ class _AspectRatioButton extends StatelessWidget { icon: Icon( iconData, color: aspectRatio.value == ratio - ? Colors.indigo + ? context.primaryColor : Theme.of(context).iconTheme.color, ), onPressed: () { @@ -205,7 +209,7 @@ class _AspectRatioButton extends StatelessWidget { cropController.aspectRatio = ratio; }, ), - Text(label, style: Theme.of(context).textTheme.bodyMedium), + Text(label, style: context.textTheme.displayMedium), ], ); } diff --git a/mobile/lib/pages/editing/edit.page.dart b/mobile/lib/pages/editing/edit.page.dart index b9017e940b..c81e84877b 100644 --- a/mobile/lib/pages/editing/edit.page.dart +++ b/mobile/lib/pages/editing/edit.page.dart @@ -7,13 +7,15 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/widgets/common/immich_image.dart'; 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'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:path/path.dart' as p; /// A stateless widget that provides functionality for editing an image. /// @@ -71,11 +73,17 @@ class EditImagePage extends ConsumerWidget { ); await ref.read(albumProvider.notifier).getDeviceAlbums(); Navigator.of(context).popUntil((route) => route.isFirst); + ImmichToast.show( + durationInSecond: 3, + context: context, + msg: 'Image Saved!', + gravity: ToastGravity.CENTER, + ); } catch (e) { ImmichToast.show( durationInSecond: 6, context: context, - msg: 'Error: $e', + msg: "error_saving_image".tr(args: [e.toString()]), gravity: ToastGravity.CENTER, ); } @@ -88,11 +96,12 @@ class EditImagePage extends ConsumerWidget { return Scaffold( appBar: AppBar( - backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + title: Text("edit_image_title".tr()), + backgroundColor: context.scaffoldBackgroundColor, leading: IconButton( icon: Icon( Icons.close_rounded, - color: Theme.of(context).iconTheme.color, + color: context.primaryColor, size: 24, ), onPressed: () => @@ -104,31 +113,48 @@ class EditImagePage extends ConsumerWidget { ? () => _saveEditedImage(context, asset, image, ref) : null, child: Text( - 'Save to gallery', + "save_to_gallery".tr(), style: TextStyle( - color: - isEdited ? Theme.of(context).iconTheme.color : Colors.grey, + color: isEdited ? context.primaryColor : Colors.grey, ), ), ), ], ), - body: Column( - children: [ - Expanded( - child: image, + backgroundColor: context.scaffoldBackgroundColor, + body: Center( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.7, + maxWidth: MediaQuery.of(context).size.width * 0.9, ), - Container( - height: 80, - color: Theme.of(context).bottomAppBarTheme.color, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(7), + child: Image( + image: image.image, + fit: BoxFit.contain, + ), + ), ), - ], + ), ), bottomNavigationBar: Container( - height: 80, - margin: const EdgeInsets.only(bottom: 20, right: 10, left: 10, top: 10), + height: 70, + margin: const EdgeInsets.only(bottom: 60, right: 10, left: 10, top: 10), decoration: BoxDecoration( - color: Theme.of(context).bottomAppBarTheme.color, + color: context.scaffoldBackgroundColor, borderRadius: BorderRadius.circular(30), ), child: Column( @@ -140,6 +166,7 @@ class EditImagePage extends ConsumerWidget { ? Icons.crop_rotate_rounded : Icons.crop_rotate_rounded, color: Theme.of(context).iconTheme.color, + size: 25, ), onPressed: () { context.pushRoute( @@ -147,7 +174,7 @@ class EditImagePage extends ConsumerWidget { ); }, ), - Text('Crop', style: Theme.of(context).textTheme.displayMedium), + Text("crop".tr(), style: context.textTheme.displayMedium), ], ), ), diff --git a/mobile/lib/utils/hooks/crop_controller_hook.dart b/mobile/lib/utils/hooks/crop_controller_hook.dart index b03d9ccdb0..04bc978754 100644 --- a/mobile/lib/utils/hooks/crop_controller_hook.dart +++ b/mobile/lib/utils/hooks/crop_controller_hook.dart @@ -6,7 +6,7 @@ import 'dart:ui'; // Import the dart:ui library for Rect CropController useCropController() { return useMemoized( () => CropController( - defaultCrop: const Rect.fromLTRB(0.1, 0.1, 0.9, 0.9), + defaultCrop: const Rect.fromLTRB(0, 0, 1, 1), ), ); }