diff --git a/file_picker/CHANGELOG.md b/file_picker/CHANGELOG.md index 330eba9..2925f3c 100644 --- a/file_picker/CHANGELOG.md +++ b/file_picker/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.13.0 +Adds `allowCompression` property that will define if media (video & image) files are allowed to be compressed by OS when picked. On Android this has no effect as it already returns the original file or an integral copy. + ## 1.12.0 Adds `getDirectoryPath()` desktop (go) implementation. diff --git a/file_picker/example/lib/src/file_picker_demo.dart b/file_picker/example/lib/src/file_picker_demo.dart index d412dae..47ac026 100644 --- a/file_picker/example/lib/src/file_picker_demo.dart +++ b/file_picker/example/lib/src/file_picker_demo.dart @@ -31,17 +31,19 @@ class _FilePickerDemoState extends State { if (_multiPick) { _path = null; _paths = await FilePicker.getMultiFilePath( - type: _pickingType, - allowedExtensions: (_extension?.isNotEmpty ?? false) - ? _extension?.replaceAll(' ', '')?.split(',') - : null); + type: _pickingType, + allowedExtensions: (_extension?.isNotEmpty ?? false) + ? _extension?.replaceAll(' ', '')?.split(',') + : null, + ); } else { _paths = null; _path = await FilePicker.getFilePath( - type: _pickingType, - allowedExtensions: (_extension?.isNotEmpty ?? false) - ? _extension?.replaceAll(' ', '')?.split(',') - : null); + type: _pickingType, + allowedExtensions: (_extension?.isNotEmpty ?? false) + ? _extension?.replaceAll(' ', '')?.split(',') + : null, + ); } } on PlatformException catch (e) { print("Unsupported operation" + e.toString()); diff --git a/file_picker/ios/Classes/FilePickerPlugin.m b/file_picker/ios/Classes/FilePickerPlugin.m index 42fc31d..ab65a33 100644 --- a/file_picker/ios/Classes/FilePickerPlugin.m +++ b/file_picker/ios/Classes/FilePickerPlugin.m @@ -87,7 +87,7 @@ [self resolvePickDocumentWithMultiPick:isMultiplePick pickDirectory:NO]; } } else if([call.method isEqualToString:@"video"] || [call.method isEqualToString:@"image"] || [call.method isEqualToString:@"media"]) { - [self resolvePickMedia:[FileUtils resolveMediaType:call.method] withMultiPick:isMultiplePick]; + [self resolvePickMedia:[FileUtils resolveMediaType:call.method] withMultiPick:isMultiplePick withCompressionAllowed:[arguments valueForKey:@"allowCompression"]]; } else if([call.method isEqualToString:@"audio"]) { [self resolvePickAudio]; } else { @@ -123,10 +123,10 @@ [_viewController presentViewController:self.documentPickerController animated:YES completion:nil]; } -- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick { +- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression { if(multiPick) { - [self resolveMultiPickFromGallery:type]; + [self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression]; return; } @@ -141,10 +141,16 @@ switch (type) { case IMAGE: self.galleryPickerController.mediaTypes = imageTypes; + if (@available(iOS 11.0, *)) { + self.galleryPickerController.imageExportPreset = allowCompression ? UIImagePickerControllerImageURLExportPresetCompatible : UIImagePickerControllerImageURLExportPresetCurrent; + } break; - + case VIDEO: self.galleryPickerController.mediaTypes = videoTypes; + if (@available(iOS 11.0, *)) { + self.galleryPickerController.videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough; + } break; default: @@ -155,7 +161,7 @@ [self.viewController presentViewController:self.galleryPickerController animated:YES completion:nil]; } -- (void) resolveMultiPickFromGallery:(MediaType)type { +- (void) resolveMultiPickFromGallery:(MediaType)type withCompressionAllowed:(BOOL)allowCompression { DKImagePickerController * dkImagePickerController = [[DKImagePickerController alloc] init]; UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleAlert]; @@ -173,6 +179,13 @@ [alert.view addSubview: indicator]; } + if (@available(iOS 11.0, *)) { + DKImageAssetExporterConfiguration * exportConfiguration = [[DKImageAssetExporterConfiguration alloc] init]; + exportConfiguration.imageExportPreset = allowCompression ? UIImagePickerControllerImageURLExportPresetCompatible : UIImagePickerControllerImageURLExportPresetCurrent; + exportConfiguration.videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough; + dkImagePickerController.exporter = [dkImagePickerController.exporter initWithConfiguration:exportConfiguration]; + } + dkImagePickerController.exportsWhenCompleted = YES; dkImagePickerController.showsCancelButton = YES; dkImagePickerController.sourceType = DKImagePickerControllerSourceTypePhoto; diff --git a/file_picker/lib/file_picker.dart b/file_picker/lib/file_picker.dart index 3c20de7..6d5c765 100644 --- a/file_picker/lib/file_picker.dart +++ b/file_picker/lib/file_picker.dart @@ -13,79 +13,95 @@ class FilePicker { /// Returns an absolute file path from the calling platform. /// - /// Extension filters are allowed with `FileType.custom`, when used, make sure to provide a `List` - /// of [allowedExtensions] (e.g. [`pdf`, `svg`, `jpg`].). + /// Extension filters are allowed with [FileType.custom], when used, make sure to provide a [List] + /// of `allowedExtensions` (e.g. [`pdf`, `svg`, `jpg`].). /// /// If you want to track picking status, for example, because some files may take some time to be /// cached (particularly those picked from cloud providers), you may want to set [onFileLoading] handler /// that will give you the current status of picking. /// - /// Defaults to `FileType.any` which will display all file types. + /// If you plan on picking images/videos and don't want them to be compressed automatically by OS, + /// you should set `allowCompression` to [false]. Calling this on Android won't have any effect, as + /// it already provides you the original file (or integral copy). + /// + /// Defaults to [FileType.any] which will display all file types. static Future getFilePath({ FileType type = FileType.any, List allowedExtensions, Function(FilePickerStatus) onFileLoading, + bool allowCompression, }) async => await _filePickerPlatform.getFiles( type: type, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, + allowCompression: allowCompression, ); - /// Returns an iterable `Map` where the `key` is the name of the file + /// Returns an iterable [Map] where the `key` is the name of the file /// and the `value` the path. /// - /// A `List` with [allowedExtensions] can be provided to filter the allowed files to picked. - /// If provided, make sure you select `FileType.custom` as type. + /// A [List] with `allowedExtensions` can be provided to filter the allowed files to picked. + /// If provided, make sure you select [FileType.custom] as type. /// /// If you want to track picking status, for example, because some files may take some time to be - /// cached (particularly those picked from cloud providers), you may want to set [onFileLoading] handler + /// cached (particularly those picked from cloud providers), you may want to set `onFileLoading` handler /// that will give you the current status of picking. /// + /// If you plan on picking images/videos and don't want them to be compressed automatically by OS, + /// you should set `allowCompression` to [false]. Calling this on Android won't have any effect, as + /// it already provides you the original file (or integral copy). + /// /// Defaults to `FileType.any`, which allows any combination of files to be multi selected at once. static Future> getMultiFilePath({ FileType type = FileType.any, List allowedExtensions, Function(FilePickerStatus) onFileLoading, + bool allowCompression, }) async => await _filePickerPlatform.getFiles( type: type, allowMultiple: true, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, + allowCompression: allowCompression, ); - /// Returns a `File` object from the selected file path. + /// Returns a [File] object from the selected file path. /// - /// This is an utility method that does the same of `getFilePath()` but saving some boilerplate if - /// you are planing to create a `File` for the returned path. + /// This is an utility method that does the same of [getFilePath] but saving some boilerplate if + /// you are planing to create a [File] for the returned path. static Future getFile({ FileType type = FileType.any, List allowedExtensions, Function(FilePickerStatus) onFileLoading, + bool allowCompression, }) async { final String filePath = await _filePickerPlatform.getFiles( type: type, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, + allowCompression: allowCompression, ); return filePath != null ? File(filePath) : null; } - /// Returns a `List` object from the selected files paths. + /// Returns a [List] object from the selected files paths. /// - /// This is an utility method that does the same of `getMultiFilePath()` but saving some boilerplate if - /// you are planing to create a list of `File`s for the returned paths. + /// This is an utility method that does the same of [getMultiFilePath] but saving some boilerplate if + /// you are planing to create a list of [File]`s for the returned paths. static Future> getMultiFile({ FileType type = FileType.any, List allowedExtensions, Function(FilePickerStatus) onFileLoading, + bool allowCompression, }) async { final Map paths = await _filePickerPlatform.getFiles( type: type, allowMultiple: true, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, + allowCompression: allowCompression, ); return paths != null && paths.isNotEmpty @@ -96,7 +112,7 @@ class FilePicker { /// Selects a directory and returns its absolute path. /// /// On Android, this requires to be running on SDK 21 or above, else won't work. - /// Returns `null` if folder path couldn't be resolved. + /// Returns [null] if folder path couldn't be resolved. static Future getDirectoryPath() async { return _filePickerPlatform.getDirectoryPath(); } @@ -107,7 +123,7 @@ class FilePicker { /// each platform and it isn't required to invoke this as the system should take care /// of it whenever needed. However, this will force the cleanup if you want to manage those on your own. /// - /// Returns `true` if the files were removed with success, `false` otherwise. + /// Returns [true] if the files were removed with success, [false] otherwise. static Future clearTemporaryFiles() async { return _filePickerPlatform.clearTemporaryFiles(); } diff --git a/file_picker/pubspec.yaml b/file_picker/pubspec.yaml index 1378c04..9e03500 100644 --- a/file_picker/pubspec.yaml +++ b/file_picker/pubspec.yaml @@ -1,14 +1,14 @@ name: file_picker description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support. homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker -version: 1.12.0 +version: 1.13.0 dependencies: flutter: sdk: flutter flutter_plugin_android_lifecycle: ^1.0.6 - file_picker_platform_interface: ^1.2.0 - + file_picker_platform_interface: ^1.3.0 + environment: sdk: ">=2.0.0 <3.0.0" flutter: ">=1.10.0 <2.0.0" diff --git a/file_picker_platform_interface/CHANGELOG.md b/file_picker_platform_interface/CHANGELOG.md index 6b9a59a..e768f87 100644 --- a/file_picker_platform_interface/CHANGELOG.md +++ b/file_picker_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.3.0] - Adds FilePickerStatus + +Adds `allowCompression` that will allow developers to set whether the picked media files (image/video) can be automatically compressed by OS or not. Defaults to `true`. + ## [1.2.0] - Adds FilePickerStatus Adds `onFiledLoading` that will provide an event handler with `FilePickerStatus` when picking files. diff --git a/file_picker_platform_interface/lib/file_picker_platform_interface.dart b/file_picker_platform_interface/lib/file_picker_platform_interface.dart index 0ae6e27..f1208a3 100644 --- a/file_picker_platform_interface/lib/file_picker_platform_interface.dart +++ b/file_picker_platform_interface/lib/file_picker_platform_interface.dart @@ -47,6 +47,9 @@ abstract class FilePickerPlatform extends PlatformInterface { /// cached (particularly those picked from cloud providers), you may want to set [onFileLoading] handler /// that will give you the current status of picking. /// + /// If you plan on picking images/videos and don't want them to be compressed automatically by OS, + /// you should set [allowCompression] to `false`. + /// /// Allows `dynamic` return as files may be resolved to different types, based /// on each platform implementation. For example, when using _dart:html_ with Flutter Web /// or _dart:io_ with Flutter, different `File` instances could be used. @@ -54,6 +57,7 @@ abstract class FilePickerPlatform extends PlatformInterface { FileType type = FileType.any, List allowedExtensions, bool allowMultiple = false, + bool allowCompression = true, Function(FilePickerStatus) onFileLoading, }) async => throw UnimplementedError('getFiles() has not been implemented.'); diff --git a/file_picker_platform_interface/lib/method_channel_file_picker.dart b/file_picker_platform_interface/lib/method_channel_file_picker.dart index d417639..61cf5db 100644 --- a/file_picker_platform_interface/lib/method_channel_file_picker.dart +++ b/file_picker_platform_interface/lib/method_channel_file_picker.dart @@ -20,9 +20,11 @@ class MethodChannelFilePicker extends FilePickerPlatform { FileType type = FileType.any, List allowedExtensions, bool allowMultiple = false, + bool allowCompression = true, Function(FilePickerStatus) onFileLoading, }) => - _getPath(type, allowMultiple, allowedExtensions, onFileLoading); + _getPath(type, allowMultiple, allowCompression, allowedExtensions, + onFileLoading); @override Future clearTemporaryFiles() async => @@ -44,6 +46,7 @@ class MethodChannelFilePicker extends FilePickerPlatform { Future _getPath( FileType fileType, bool allowMultipleSelection, + bool allowCompression, List allowedExtensions, Function(FilePickerStatus) onFileLoading, ) async { @@ -66,6 +69,7 @@ class MethodChannelFilePicker extends FilePickerPlatform { dynamic result = await _channel.invokeMethod(type, { 'allowMultipleSelection': allowMultipleSelection, 'allowedExtensions': allowedExtensions, + 'allowCompression': allowCompression, }); if (result != null && allowMultipleSelection) { if (result is String) { diff --git a/file_picker_platform_interface/pubspec.yaml b/file_picker_platform_interface/pubspec.yaml index 9a7434f..5f0faa9 100644 --- a/file_picker_platform_interface/pubspec.yaml +++ b/file_picker_platform_interface/pubspec.yaml @@ -1,7 +1,7 @@ name: file_picker_platform_interface -description: A common platform interface for the file_picker plugin +description: A common platform interface for the file_picker plugin that must be used to share commom features homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker/file_picker_platform_interface -version: 1.2.0 +version: 1.3.0 environment: sdk: ">=2.1.0 <3.0.0"