From 7f58cbeb63854304fa2b577c691d02e9779792c3 Mon Sep 17 00:00:00 2001 From: Miguel Ruivo Date: Thu, 11 Jun 2020 22:35:10 +0100 Subject: [PATCH] Adds Adds FilePickerStatus event handler to FilePickerPlatform --- file_picker_platform_interface/CHANGELOG.md | 4 +++ .../lib/file_picker_platform_interface.dart | 16 +++++++-- .../lib/method_channel_file_picker.dart | 34 +++++++++++++++---- file_picker_platform_interface/pubspec.yaml | 2 +- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/file_picker_platform_interface/CHANGELOG.md b/file_picker_platform_interface/CHANGELOG.md index e17155d..6b9a59a 100644 --- a/file_picker_platform_interface/CHANGELOG.md +++ b/file_picker_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.2.0] - Adds FilePickerStatus + +Adds `onFiledLoading` that will provide an event handler with `FilePickerStatus` when picking files. + ## [1.1.0] - Adds directory pick Implements `getDirectoryPath()` 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 c199d8b..0ae6e27 100644 --- a/file_picker_platform_interface/lib/file_picker_platform_interface.dart +++ b/file_picker_platform_interface/lib/file_picker_platform_interface.dart @@ -11,6 +11,11 @@ enum FileType { custom, } +enum FilePickerStatus { + picking, + done, +} + /// The interface that implementations of file_picker must implement. /// /// Platform implementations should extend this class rather than implement it as `file_picker` @@ -38,6 +43,10 @@ abstract class FilePickerPlatform extends PlatformInterface { /// Default [type] set to `FileType.any` with [allowMultiple] set to `false` /// Optionally, [allowedExtensions] might be provided (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. + /// /// 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. @@ -45,6 +54,7 @@ abstract class FilePickerPlatform extends PlatformInterface { FileType type = FileType.any, List allowedExtensions, bool allowMultiple = false, + Function(FilePickerStatus) onFileLoading, }) async => throw UnimplementedError('getFiles() has not been implemented.'); @@ -55,11 +65,13 @@ abstract class FilePickerPlatform extends PlatformInterface { /// 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. - Future clearTemporaryFiles() async => throw UnimplementedError('clearTemporaryFiles() has not been implemented.'); + Future clearTemporaryFiles() async => throw UnimplementedError( + 'clearTemporaryFiles() has not been implemented.'); /// 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. - Future getDirectoryPath() async => throw UnimplementedError('getDirectoryPath() has not been implemented.'); + Future getDirectoryPath() async => + throw UnimplementedError('getDirectoryPath() 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 c2443d6..d417639 100644 --- a/file_picker_platform_interface/lib/method_channel_file_picker.dart +++ b/file_picker_platform_interface/lib/method_channel_file_picker.dart @@ -1,24 +1,32 @@ +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'file_picker_platform_interface.dart'; -const MethodChannel _channel = MethodChannel('miguelruivo.flutter.plugins.filepicker'); +const MethodChannel _channel = + MethodChannel('miguelruivo.flutter.plugins.filepicker'); +const EventChannel _eventChannel = + EventChannel('miguelruivo.flutter.plugins.filepickerevent'); /// An implementation of [FilePickerPlatform] that uses method channels. class MethodChannelFilePicker extends FilePickerPlatform { static const String _tag = 'MethodChannelFilePicker'; + static StreamSubscription _eventSubscription; @override Future getFiles({ FileType type = FileType.any, List allowedExtensions, bool allowMultiple = false, + Function(FilePickerStatus) onFileLoading, }) => - _getPath(type, allowMultiple, allowedExtensions); + _getPath(type, allowMultiple, allowedExtensions, onFileLoading); @override - Future clearTemporaryFiles() async => _channel.invokeMethod('clear'); + Future clearTemporaryFiles() async => + _channel.invokeMethod('clear'); @override Future getDirectoryPath() async { @@ -37,12 +45,24 @@ class MethodChannelFilePicker extends FilePickerPlatform { FileType fileType, bool allowMultipleSelection, List allowedExtensions, + Function(FilePickerStatus) onFileLoading, ) async { final String type = describeEnum(fileType); if (type != 'custom' && (allowedExtensions?.isNotEmpty ?? false)) { - throw Exception('If you are using a custom extension filter, please use the FileType.custom instead.'); + throw Exception( + 'If you are using a custom extension filter, please use the FileType.custom instead.'); } try { + _eventSubscription?.cancel(); + if (onFileLoading != null) { + _eventSubscription = _eventChannel.receiveBroadcastStream().listen( + (data) => onFileLoading((data as bool) + ? FilePickerStatus.picking + : FilePickerStatus.done), + onError: (error) => throw Exception(error), + ); + } + dynamic result = await _channel.invokeMethod(type, { 'allowMultipleSelection': allowMultipleSelection, 'allowedExtensions': allowedExtensions, @@ -51,14 +71,16 @@ class MethodChannelFilePicker extends FilePickerPlatform { if (result is String) { result = [result]; } - return Map.fromIterable(result, key: (path) => path.split('/').last, value: (path) => path); + return Map.fromIterable(result, + key: (path) => path.split('/').last, value: (path) => path); } return result; } on PlatformException catch (e) { print('[$_tag] Platform exception: $e'); rethrow; } catch (e) { - print('[$_tag] Unsupported operation. Method not found. The exception thrown was: $e'); + print( + '[$_tag] Unsupported operation. Method not found. The exception thrown was: $e'); rethrow; } } diff --git a/file_picker_platform_interface/pubspec.yaml b/file_picker_platform_interface/pubspec.yaml index e0357e5..9a7434f 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 homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker/file_picker_platform_interface -version: 1.1.0 +version: 1.2.0 environment: sdk: ">=2.1.0 <3.0.0"