diff --git a/lib/ui/shared/dialogs/save_image_dialog.dart b/lib/ui/shared/dialogs/save_image_dialog.dart index 3e6280bf..9d33535c 100644 --- a/lib/ui/shared/dialogs/save_image_dialog.dart +++ b/lib/ui/shared/dialogs/save_image_dialog.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; - +import 'package:file_picker/file_picker.dart'; import 'package:paintroid/core/enums/image_format.dart'; import 'package:paintroid/core/models/image_meta_data.dart'; import 'package:paintroid/ui/shared/image_format_info.dart'; @@ -25,6 +25,8 @@ class SaveImageDialog extends StatefulWidget { class _SaveImageDialogState extends State { final TextEditingController nameFieldController = TextEditingController(); + final TextEditingController savePathController = + TextEditingController(text: 'default/save/path'); final formKey = GlobalKey(debugLabel: 'SaveImageDialog Form'); var selectedFormat = ImageFormat.jpg; var imageQualityValue = 100; @@ -32,23 +34,31 @@ class _SaveImageDialogState extends State { @override void initState() { super.initState(); - if (widget.savingProject) { selectedFormat = ImageFormat.catrobatImage; } } - void _dismissDialogWithData() { + Future _dismissDialogWithData() async { + final directoryPath = savePathController.text; + if (directoryPath.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please specify a valid save path.'))); + return; + } + late ImageMetaData data; switch (selectedFormat) { case ImageFormat.png: - data = PngMetaData(nameFieldController.text); + data = PngMetaData('$directoryPath/${nameFieldController.text}.png'); break; case ImageFormat.jpg: - data = JpgMetaData(nameFieldController.text, imageQualityValue); + data = JpgMetaData( + '$directoryPath/${nameFieldController.text}.jpg', imageQualityValue); break; case ImageFormat.catrobatImage: - data = CatrobatImageMetaData(nameFieldController.text); + data = CatrobatImageMetaData( + '$directoryPath/${nameFieldController.text}.catrobat'); break; } Navigator.of(context).pop(data); @@ -81,6 +91,14 @@ class _SaveImageDialogState extends State { height: 16, color: PaintroidTheme.of(context).onSurfaceVariantColor, ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: _savePathTextField, + ), + Divider( + height: 16, + color: PaintroidTheme.of(context).onSurfaceVariantColor, + ), if (!widget.savingProject) Column( children: [ @@ -120,10 +138,10 @@ class _SaveImageDialogState extends State { TextButton get _saveButton { return TextButton( - onPressed: () { + onPressed: () async { final formState = formKey.currentState; if (formState != null && formState.validate()) { - _dismissDialogWithData(); + await _dismissDialogWithData(); } }, child: Text( @@ -184,6 +202,41 @@ class _SaveImageDialogState extends State { ); } + Padding get _savePathTextField { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: TextFormField( + controller: savePathController, + decoration: InputDecoration( + labelStyle: const TextStyle(fontWeight: FontWeight.bold), + hintText: 'Enter custom save path or use default', + suffixIcon: IconButton( + icon: const Icon(Icons.folder_open), + onPressed: () async { + final directoryPath = await FilePicker.platform.getDirectoryPath(); + if (directoryPath != null) { + setState(() { + savePathController.text = directoryPath; + }); + } + }, + ), + filled: true, + fillColor: PaintroidTheme.of(context).secondaryContainerColor, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + ), + validator: (path) { + if (path == null || path.isEmpty) { + return 'Please specify a save path'; + } + return null; + }, + ), + ); + } + Row get _imageFormatDropdown { return Row( children: [ diff --git a/pubspec.lock b/pubspec.lock index 01c51cd8..2d8cd2f0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -284,10 +284,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.3" file: dependency: transitive description: @@ -1377,13 +1377,13 @@ packages: source: hosted version: "3.0.3" win32: - dependency: transitive + dependency: "direct main" description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.8.0" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c267575f..fdc76060 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: file_picker: ^5.3.1 floor: ^1.2.0 sqflite: ^2.3.0 + win32: 5.8.0 colorpicker: path: packages/colorpicker