From ba19a7eccfac06e3e839f869063dbbe53cc287c9 Mon Sep 17 00:00:00 2001 From: Miguel Ruivo Date: Thu, 24 Sep 2020 21:59:18 +0100 Subject: [PATCH] Adds mobile Safari support (Web) and conditional imports for backwards compatibility with Xcode 11 (iOS) --- CHANGELOG.md | 4 ++ ios/Classes/FilePickerPlugin.h | 11 ++++- lib/src/file_picker_web.dart | 88 ++++++++++++++++++++++++---------- pubspec.yaml | 2 +- 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 124db69..df26a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.2 +Web: Adds mobile Safari support and other minor improvements. +iOS: Adds conditional import for backwards compatibility with Xcode 11. + ## 2.0.1+2 iOS: Addresses an issue that could prevent users from viewing picked media elements (pictures/videos) from gallery on iOS 14. diff --git a/ios/Classes/FilePickerPlugin.h b/ios/Classes/FilePickerPlugin.h index 595e021..89dbadc 100644 --- a/ios/Classes/FilePickerPlugin.h +++ b/ios/Classes/FilePickerPlugin.h @@ -2,8 +2,15 @@ #import #import #import -#import #import -@interface FilePickerPlugin : NSObject +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 +#import +#endif + +@interface FilePickerPlugin : NSObject= __IPHONE_14_0 +, PHPickerViewControllerDelegate +#endif +> @end diff --git a/lib/src/file_picker_web.dart b/lib/src/file_picker_web.dart index 025b92f..7840438 100644 --- a/lib/src/file_picker_web.dart +++ b/lib/src/file_picker_web.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'dart:convert'; -import 'dart:html' as html; +import 'dart:html'; import 'dart:typed_data'; import 'package:file_picker/file_picker.dart'; @@ -10,13 +9,32 @@ import 'file_picker_result.dart'; import 'platform_file.dart'; class FilePickerWeb extends FilePicker { - FilePickerWeb._(); + Element _target; + final String _kFilePickerInputsDomId = '__file_picker_web-file-input'; + static final FilePickerWeb platform = FilePickerWeb._(); + FilePickerWeb._() { + _target = _ensureInitialized(_kFilePickerInputsDomId); + } + static void registerWith(Registrar registrar) { FilePicker.platform = platform; } + /// Initializes a DOM container where we can host input elements. + Element _ensureInitialized(String id) { + Element target = querySelector('#$id'); + if (target == null) { + final Element targetElement = Element.tag('flt-file-picker-inputs') + ..id = id; + + querySelector('body').children.add(targetElement); + target = targetElement; + } + return target; + } + @override Future pickFiles({ FileType type = FileType.any, @@ -30,40 +48,60 @@ class FilePickerWeb extends FilePicker { Completer>(); String accept = _fileType(type, allowedExtensions); - html.InputElement uploadInput = html.FileUploadInputElement(); + InputElement uploadInput = FileUploadInputElement(); uploadInput.draggable = true; uploadInput.multiple = allowMultiple; uploadInput.accept = accept; - uploadInput.click(); - uploadInput.onChange.listen((e) { - final files = uploadInput.files; - final reader = html.FileReader(); + bool changeEventTriggered = false; + void changeEventListener(e) { + if (changeEventTriggered) { + return; + } + changeEventTriggered = true; - List pickedFiles = []; + final List files = uploadInput.files; + final List pickedFiles = []; - reader.onLoadEnd.listen((e) { - final Uint8List bytes = - Base64Decoder().convert(reader.result.toString().split(",").last); - - pickedFiles.add( - PlatformFile( - name: uploadInput.value.replaceAll('\\', '/'), - path: uploadInput.value, - size: bytes.length ~/ 1024, - bytes: withData ? bytes : null, - ), - ); + void addPickedFile(File file, Uint8List bytes, String path) { + pickedFiles.add(PlatformFile( + name: file.name, + path: path, + size: bytes != null ? bytes.length ~/ 1024 : -1, + bytes: bytes, + )); if (pickedFiles.length >= files.length) { filesCompleter.complete(pickedFiles); } - }); + } - files.forEach((element) { - reader.readAsDataUrl(element); + files.forEach((File file) { + if (!withData) { + final FileReader reader = FileReader(); + reader.onLoadEnd.listen((e) { + addPickedFile(file, null, reader.result); + }); + reader.readAsDataUrl(file); + return; + } + + final FileReader reader = FileReader(); + reader.onLoadEnd.listen((e) { + addPickedFile(file, reader.result, null); + }); + reader.readAsArrayBuffer(file); }); - }); + } + + uploadInput.onChange.listen(changeEventListener); + uploadInput.addEventListener('change', changeEventListener); + + //Add input element to the page body + _target.children.clear(); + _target.children.add(uploadInput); + uploadInput.click(); + return FilePickerResult(await filesCompleter.future); } diff --git a/pubspec.yaml b/pubspec.yaml index 2b86df1..a83e27a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ 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: 2.0.1+2 +version: 2.0.2 dependencies: flutter: