From ffed7696c7ebc402c6c28dca6e6ecbd757024cf9 Mon Sep 17 00:00:00 2001 From: Miguel Ruivo Date: Fri, 12 Jun 2020 02:19:25 +0100 Subject: [PATCH] Adds onLoadingFile parameter to handle file processing status --- file_picker/CHANGELOG.md | 5 +- file_picker/README.md | 7 ++- .../plugin/filepicker/FilePickerDelegate.java | 31 ++++++++++ .../plugin/filepicker/FilePickerPlugin.java | 14 +++++ .../example/lib/src/file_picker_demo.dart | 51 ++++++++++++----- file_picker/ios/Classes/FilePickerPlugin.h | 2 +- file_picker/ios/Classes/FilePickerPlugin.m | 56 ++++++++++++++----- file_picker/lib/file_picker.dart | 45 +++++++++++++-- file_picker/pubspec.yaml | 5 +- file_picker_web/CHANGELOG.md | 8 +++ file_picker_web/README.md | 2 +- file_picker_web/example/lib/main.dart | 2 +- file_picker_web/lib/file_picker_web.dart | 1 + file_picker_web/pubspec.yaml | 8 +-- 14 files changed, 192 insertions(+), 45 deletions(-) diff --git a/file_picker/CHANGELOG.md b/file_picker/CHANGELOG.md index e02e0d7..8481d88 100644 --- a/file_picker/CHANGELOG.md +++ b/file_picker/CHANGELOG.md @@ -1,5 +1,8 @@ +## 1.11.0 +Adds `onFileLoading` handler for every picking method that will provide picking status: `FilePickerStatus.loading` and `FilePickerStatus.done` so you can, for example, display a custom loader. + ## 1.10.0 -**Android & iOS:** Adds `getDirectoryPath()` method that allows you to select and pick directory paths. Android, requires SDK 21 or above for this to work, and iOS requires iOS 11 or above. +Adds `getDirectoryPath()` method that allows you to select and pick directory paths. Android, requires SDK 21 or above for this to work, and iOS requires iOS 11 or above. ## 1.9.0+1 Adds a temporary workaround on Android where it can trigger `onRequestPermissionsResult` twice, related to Flutter issue [49365](https://github.com/flutter/flutter/issues/49365) for anyone affected in Flutter versions below 1.14.6. diff --git a/file_picker/README.md b/file_picker/README.md index b405a9e..78096ae 100644 --- a/file_picker/README.md +++ b/file_picker/README.md @@ -7,7 +7,7 @@ Awesome Flutter - Build Status + Build Status Buy me a coffee @@ -35,15 +35,18 @@ If you have any feature that you want to see in this package, please feel free t ## Documentation See the **[File Picker Wiki](https://github.com/miguelpruivo/flutter_file_picker/wiki)** for every detail on about how to install, setup and use it. +### File Picker Wiki + 1. [Installation](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/Installation) 2. [Setup](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/Setup) * [Android](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/Setup#android) * [iOS](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/Setup#ios) + * [Web](https://github.com/miguelpruivo/flutter_file_picker/wiki/Setup#--web) * [Desktop (go-flutter)](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/Setup/_edit#desktop-go-flutter) 3. [API](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/api) * [Filters](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#filters) + * [Parameters](https://github.com/miguelpruivo/flutter_file_picker/wiki/API#parameters) * [Methods](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#methods) -4. [Example App](https://github.com/miguelpruivo/flutter_file_picker/blob/master/example/lib/src/file_picker_demo.dart) 5. [Troubleshooting](https://github.com/miguelpruivo/flutter_file_picker/wiki/Troubleshooting) ## Usage diff --git a/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerDelegate.java b/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerDelegate.java index dcaaffc..80bccd3 100644 --- a/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerDelegate.java +++ b/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerDelegate.java @@ -7,6 +7,9 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.provider.DocumentsContract; import android.util.Log; @@ -16,6 +19,7 @@ import androidx.core.app.ActivityCompat; import java.io.File; import java.util.ArrayList; +import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; @@ -30,6 +34,7 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener private boolean isMultipleSelection = false; private String type; private String[] allowedExtensions; + private EventChannel.EventSink eventSink; public FilePickerDelegate(final Activity activity) { this( @@ -51,6 +56,10 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener ); } + public void setEventHandler(final EventChannel.EventSink eventSink) { + this.eventSink = eventSink; + } + @VisibleForTesting FilePickerDelegate(final Activity activity, final MethodChannel.Result result, final PermissionManager permissionManager) { this.activity = activity; @@ -63,6 +72,11 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener public boolean onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { + + if (eventSink != null) { + eventSink.success(true); + } + new Thread(new Runnable() { @Override public void run() { @@ -217,6 +231,10 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener } private void finishWithSuccess(final Object data) { + if (eventSink != null) { + this.dispatchEventStatus(false); + } + // Temporary fix, remove this null-check after Flutter Engine 1.14 has landed on stable if (this.pendingResult != null) { this.pendingResult.success(data); @@ -228,10 +246,23 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener if (this.pendingResult == null) { return; } + + if (eventSink != null) { + this.dispatchEventStatus(false); + } this.pendingResult.error(errorCode, errorMessage, null); this.clearPendingResult(); } + private void dispatchEventStatus(final boolean status) { + new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(final Message message) { + eventSink.success(status); + } + }.obtainMessage().sendToTarget(); + } + private void clearPendingResult() { this.pendingResult = null; diff --git a/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java b/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java index cfad235..c1c3121 100644 --- a/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java +++ b/file_picker/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java @@ -19,6 +19,7 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter; import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; @@ -31,6 +32,7 @@ public class FilePickerPlugin implements MethodChannel.MethodCallHandler, Flutte private static final String TAG = "FilePicker"; private static final String CHANNEL = "miguelruivo.flutter.plugins.filepicker"; + private static final String EVENT_CHANNEL = "miguelruivo.flutter.plugins.filepickerevent"; private class LifeCycleObserver implements Application.ActivityLifecycleCallbacks, DefaultLifecycleObserver { @@ -249,6 +251,17 @@ public class FilePickerPlugin implements MethodChannel.MethodCallHandler, Flutte this.delegate = new FilePickerDelegate(activity); this.channel = new MethodChannel(messenger, CHANNEL); this.channel.setMethodCallHandler(this); + new EventChannel(messenger, EVENT_CHANNEL).setStreamHandler(new EventChannel.StreamHandler() { + @Override + public void onListen(final Object arguments, final EventChannel.EventSink events) { + delegate.setEventHandler(events); + } + + @Override + public void onCancel(final Object arguments) { + delegate.setEventHandler(null); + } + }); this.observer = new LifeCycleObserver(activity); if (registrar != null) { // V1 embedding setup for activity listeners. @@ -273,6 +286,7 @@ public class FilePickerPlugin implements MethodChannel.MethodCallHandler, Flutte this.delegate = null; this.channel.setMethodCallHandler(null); this.channel = null; + this.delegate.setEventHandler(null); this.application.unregisterActivityLifecycleCallbacks(this.observer); this.application = null; } diff --git a/file_picker/example/lib/src/file_picker_demo.dart b/file_picker/example/lib/src/file_picker_demo.dart index ad3d13d..d412dae 100644 --- a/file_picker/example/lib/src/file_picker_demo.dart +++ b/file_picker/example/lib/src/file_picker_demo.dart @@ -31,11 +31,17 @@ 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()); @@ -43,7 +49,9 @@ class _FilePickerDemoState extends State { if (!mounted) return; setState(() { _loadingPath = false; - _fileName = _path != null ? _path.split('/').last : _paths != null ? _paths.keys.toString() : '...'; + _fileName = _path != null + ? _path.split('/').last + : _paths != null ? _paths.keys.toString() : '...'; }); } @@ -52,7 +60,9 @@ class _FilePickerDemoState extends State { _scaffoldKey.currentState.showSnackBar( SnackBar( backgroundColor: result ? Colors.green : Colors.red, - content: Text((result ? 'Temporary files removed with success.' : 'Failed to clean temporary files')), + content: Text((result + ? 'Temporary files removed with success.' + : 'Failed to clean temporary files')), ), ); }); @@ -124,7 +134,8 @@ class _FilePickerDemoState extends State { maxLength: 15, autovalidate: true, controller: _controller, - decoration: InputDecoration(labelText: 'File extension'), + decoration: + InputDecoration(labelText: 'File extension'), keyboardType: TextInputType.text, textCapitalization: TextCapitalization.none, ) @@ -133,8 +144,10 @@ class _FilePickerDemoState extends State { new ConstrainedBox( constraints: BoxConstraints.tightFor(width: 200.0), child: new SwitchListTile.adaptive( - title: new Text('Pick multiple files', textAlign: TextAlign.right), - onChanged: (bool value) => setState(() => _multiPick = value), + title: new Text('Pick multiple files', + textAlign: TextAlign.right), + onChanged: (bool value) => + setState(() => _multiPick = value), value: _multiPick, ), ), @@ -159,18 +172,28 @@ class _FilePickerDemoState extends State { ), new Builder( builder: (BuildContext context) => _loadingPath - ? Padding(padding: const EdgeInsets.only(bottom: 10.0), child: const CircularProgressIndicator()) + ? Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: const CircularProgressIndicator()) : _path != null || _paths != null ? new Container( padding: const EdgeInsets.only(bottom: 30.0), height: MediaQuery.of(context).size.height * 0.50, child: new Scrollbar( child: new ListView.separated( - itemCount: _paths != null && _paths.isNotEmpty ? _paths.length : 1, + itemCount: _paths != null && _paths.isNotEmpty + ? _paths.length + : 1, itemBuilder: (BuildContext context, int index) { - final bool isMultiPath = _paths != null && _paths.isNotEmpty; - final String name = 'File $index: ' + (isMultiPath ? _paths.keys.toList()[index] : _fileName ?? '...'); - final path = isMultiPath ? _paths.values.toList()[index].toString() : _path; + final bool isMultiPath = + _paths != null && _paths.isNotEmpty; + final String name = 'File $index: ' + + (isMultiPath + ? _paths.keys.toList()[index] + : _fileName ?? '...'); + final path = isMultiPath + ? _paths.values.toList()[index].toString() + : _path; return new ListTile( title: new Text( @@ -179,7 +202,9 @@ class _FilePickerDemoState extends State { subtitle: new Text(path), ); }, - separatorBuilder: (BuildContext context, int index) => new Divider(), + separatorBuilder: + (BuildContext context, int index) => + new Divider(), )), ) : new Container(), diff --git a/file_picker/ios/Classes/FilePickerPlugin.h b/file_picker/ios/Classes/FilePickerPlugin.h index fecbd3f..bef242e 100644 --- a/file_picker/ios/Classes/FilePickerPlugin.h +++ b/file_picker/ios/Classes/FilePickerPlugin.h @@ -4,5 +4,5 @@ #import #import -@interface FilePickerPlugin : NSObject +@interface FilePickerPlugin : NSObject @end diff --git a/file_picker/ios/Classes/FilePickerPlugin.m b/file_picker/ios/Classes/FilePickerPlugin.m index c87c305..42fc31d 100644 --- a/file_picker/ios/Classes/FilePickerPlugin.m +++ b/file_picker/ios/Classes/FilePickerPlugin.m @@ -6,6 +6,7 @@ @interface FilePickerPlugin() @property (nonatomic) FlutterResult result; +@property (nonatomic) FlutterEventSink eventSink; @property (nonatomic) UIViewController *viewController; @property (nonatomic) UIImagePickerController *galleryPickerController; @property (nonatomic) UIDocumentPickerViewController *documentPickerController; @@ -21,13 +22,17 @@ methodChannelWithName:@"miguelruivo.flutter.plugins.filepicker" binaryMessenger:[registrar messenger]]; + FlutterEventChannel* eventChannel = [FlutterEventChannel + eventChannelWithName:@"miguelruivo.flutter.plugins.filepickerevent" + binaryMessenger:[registrar messenger]]; + UIViewController *viewController = [UIApplication sharedApplication].delegate.window.rootViewController; FilePickerPlugin* instance = [[FilePickerPlugin alloc] initWithViewController:viewController]; [registrar addMethodCallDelegate:instance channel:channel]; + [eventChannel setStreamHandler:instance]; } - - (instancetype)initWithViewController:(UIViewController *)viewController { self = [super init]; if(self) { @@ -37,6 +42,16 @@ return self; } +- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events { + _eventSink = events; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + _eventSink = nil; + return nil; +} + - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if (_result) { result([FlutterError errorWithCode:@"multiple_request" @@ -143,16 +158,20 @@ - (void) resolveMultiPickFromGallery:(MediaType)type { DKImagePickerController * dkImagePickerController = [[DKImagePickerController alloc] init]; - // Create alert dialog for asset caching UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleAlert]; - [alert.view setCenter: _viewController.view.center]; - [alert.view addConstraint: [NSLayoutConstraint constraintWithItem:alert.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]]; - UIActivityIndicatorView* indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; - indicator.hidesWhenStopped = YES; - [indicator setCenter: alert.view.center]; - indicator.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin); - [alert.view addSubview: indicator]; + + if(_eventSink == nil) { + // Create alert dialog for asset caching + [alert.view setCenter: _viewController.view.center]; + [alert.view addConstraint: [NSLayoutConstraint constraintWithItem:alert.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]]; + + // Create a default loader if user don't provide a status handler + indicator.hidesWhenStopped = YES; + [indicator setCenter: alert.view.center]; + indicator.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin); + [alert.view addSubview: indicator]; + } dkImagePickerController.exportsWhenCompleted = YES; dkImagePickerController.showsCancelButton = YES; @@ -164,11 +183,22 @@ if(status == DKImagePickerControllerExportStatusExporting && dkImagePickerController.selectedAssets.count > 0){ Log("Exporting assets, this operation may take a while if remote (iCloud) assets are being cached."); - [indicator startAnimating]; - [self->_viewController showViewController:alert sender:nil]; + + if(self->_eventSink != nil){ + self->_eventSink([NSNumber numberWithBool:YES]); + } else { + [indicator startAnimating]; + [self->_viewController showViewController:alert sender:nil]; + } + } else { - [indicator stopAnimating]; - [alert dismissViewControllerAnimated:YES completion:nil]; + if(self->_eventSink != nil) { + self->_eventSink([NSNumber numberWithBool:NO]); + } else { + [indicator stopAnimating]; + [alert dismissViewControllerAnimated:YES completion:nil]; + } + } }]; diff --git a/file_picker/lib/file_picker.dart b/file_picker/lib/file_picker.dart index cb43eb9..3c20de7 100644 --- a/file_picker/lib/file_picker.dart +++ b/file_picker/lib/file_picker.dart @@ -3,7 +3,8 @@ import 'dart:io'; import 'package:file_picker_platform_interface/file_picker_platform_interface.dart'; -export 'package:file_picker_platform_interface/file_picker_platform_interface.dart' show FileType; +export 'package:file_picker_platform_interface/file_picker_platform_interface.dart' + show FileType; final FilePickerPlatform _filePickerPlatform = FilePickerPlatform.instance; @@ -14,11 +15,21 @@ class FilePicker { /// /// 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. - static Future getFilePath({FileType type = FileType.any, List allowedExtensions}) async => + static Future getFilePath({ + FileType type = FileType.any, + List allowedExtensions, + Function(FilePickerStatus) onFileLoading, + }) async => await _filePickerPlatform.getFiles( type: type, allowedExtensions: allowedExtensions, + onFileLoading: onFileLoading, ); /// Returns an iterable `Map` where the `key` is the name of the file @@ -26,22 +37,37 @@ class FilePicker { /// /// 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 + /// that will give you the current status of picking. + /// /// 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}) async => + static Future> getMultiFilePath({ + FileType type = FileType.any, + List allowedExtensions, + Function(FilePickerStatus) onFileLoading, + }) async => await _filePickerPlatform.getFiles( type: type, allowMultiple: true, allowedExtensions: allowedExtensions, + onFileLoading: onFileLoading, ); /// 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. - static Future getFile({FileType type = FileType.any, List allowedExtensions}) async { + static Future getFile({ + FileType type = FileType.any, + List allowedExtensions, + Function(FilePickerStatus) onFileLoading, + }) async { final String filePath = await _filePickerPlatform.getFiles( type: type, allowedExtensions: allowedExtensions, + onFileLoading: onFileLoading, ); return filePath != null ? File(filePath) : null; } @@ -50,14 +76,21 @@ class FilePicker { /// /// 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}) async { + static Future> getMultiFile({ + FileType type = FileType.any, + List allowedExtensions, + Function(FilePickerStatus) onFileLoading, + }) async { final Map paths = await _filePickerPlatform.getFiles( type: type, allowMultiple: true, allowedExtensions: allowedExtensions, + onFileLoading: onFileLoading, ); - return paths != null && paths.isNotEmpty ? paths.values.map((path) => File(path)).toList() : null; + return paths != null && paths.isNotEmpty + ? paths.values.map((path) => File(path)).toList() + : null; } /// Selects a directory and returns its absolute path. diff --git a/file_picker/pubspec.yaml b/file_picker/pubspec.yaml index e15edf5..c6a6c1b 100644 --- a/file_picker/pubspec.yaml +++ b/file_picker/pubspec.yaml @@ -1,14 +1,13 @@ 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.10.0 +version: 1.11.0 dependencies: flutter: sdk: flutter flutter_plugin_android_lifecycle: ^1.0.6 - file_picker_platform_interface: ^1.1.0 - file_picker_web: ^1.0.0 + file_picker_platform_interface: ^1.2.0 environment: sdk: ">=2.0.0 <3.0.0" diff --git a/file_picker_web/CHANGELOG.md b/file_picker_web/CHANGELOG.md index 1a9c02d..bf753e4 100644 --- a/file_picker_web/CHANGELOG.md +++ b/file_picker_web/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.0.1+1 + +Updates homepage & description. + +## 1.0.1 + +Updates API to support `onFileLoading` from FilePickerInterface. + ## 1.0.0 Adds public API documentation and updates file_picker_platform_interface dependency. diff --git a/file_picker_web/README.md b/file_picker_web/README.md index 2c636a1..ed83cd0 100644 --- a/file_picker_web/README.md +++ b/file_picker_web/README.md @@ -18,7 +18,7 @@ This is what the above means to your `pubspec.yaml`: ... dependencies: ... - file_picker_web: ^0.0.1 + file_picker_web: ^1.0.0 ... ``` diff --git a/file_picker_web/example/lib/main.dart b/file_picker_web/example/lib/main.dart index 658fdbc..279b607 100644 --- a/file_picker_web/example/lib/main.dart +++ b/file_picker_web/example/lib/main.dart @@ -16,7 +16,7 @@ class _MyAppState extends State { List _files = []; void _pickFiles() async { - _files = await FilePicker.getFile() ?? []; + _files = await FilePicker.getMultiFile() ?? []; setState(() {}); } diff --git a/file_picker_web/lib/file_picker_web.dart b/file_picker_web/lib/file_picker_web.dart index 160665e..efd6410 100644 --- a/file_picker_web/lib/file_picker_web.dart +++ b/file_picker_web/lib/file_picker_web.dart @@ -40,6 +40,7 @@ class FilePicker extends FilePickerPlatform { FileType type = FileType.any, List allowedExtensions, bool allowMultiple = false, + Function(FilePickerStatus) onFileLoading, }) async { final Completer> pickedFiles = Completer>(); html.InputElement uploadInput = html.FileUploadInputElement(); diff --git a/file_picker_web/pubspec.yaml b/file_picker_web/pubspec.yaml index f9c4159..65a7e73 100644 --- a/file_picker_web/pubspec.yaml +++ b/file_picker_web/pubspec.yaml @@ -1,14 +1,14 @@ name: file_picker_web -description: Web platform implementation of file_picker -homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker/file_picker_web -version: 1.0.0 +description: Web platform implementation of file_picker. Provides a way to pick files with filter support for Web. +homepage: https://github.com/miguelpruivo/flutter_file_picker/tree/master/file_picker_web +version: 1.0.1+1 environment: sdk: ">=2.7.0 <3.0.0" flutter: ">=1.10.0" dependencies: - file_picker_platform_interface: ^1.0.0 + file_picker_platform_interface: ^1.2.0 flutter: sdk: flutter flutter_web_plugins: