From 003752f6b10a83e36e0a29f6974cb41bde005cf0 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 10:20:06 +0100 Subject: [PATCH 01/13] Initial version of x_file package --- .../method_channel_file_selector.dart | 1 + .../file_selector_interface.dart | 1 + .../lib/src/types/types.dart | 2 -- .../lib/src/types/x_file/x_file.dart | 3 -- .../pubspec.yaml | 2 ++ packages/x_file/CHANGELOG.md | 3 ++ packages/x_file/LICENSE | 25 ++++++++++++++ packages/x_file/lib/cross_file.dart | 1 + packages/x_file/lib/src/cross_file.dart | 3 ++ .../x_file => x_file/lib/src/types}/base.dart | 0 .../x_file => x_file/lib/src/types}/html.dart | 2 +- .../lib/src/types}/interface.dart | 0 .../x_file => x_file/lib/src/types}/io.dart | 0 .../lib/src/web_helpers/web_helpers.dart | 34 +++++++++++++++++++ packages/x_file/pubspec.yaml | 20 +++++++++++ .../test/assets/hello.txt | 0 .../test/cross_file_html_test.dart} | 2 +- .../test/cross_file_io_test.dart} | 2 +- 18 files changed, 93 insertions(+), 8 deletions(-) delete mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart create mode 100644 packages/x_file/CHANGELOG.md create mode 100644 packages/x_file/LICENSE create mode 100644 packages/x_file/lib/cross_file.dart create mode 100644 packages/x_file/lib/src/cross_file.dart rename packages/{file_selector/file_selector_platform_interface/lib/src/types/x_file => x_file/lib/src/types}/base.dart (100%) rename packages/{file_selector/file_selector_platform_interface/lib/src/types/x_file => x_file/lib/src/types}/html.dart (98%) rename packages/{file_selector/file_selector_platform_interface/lib/src/types/x_file => x_file/lib/src/types}/interface.dart (100%) rename packages/{file_selector/file_selector_platform_interface/lib/src/types/x_file => x_file/lib/src/types}/io.dart (100%) create mode 100644 packages/x_file/lib/src/web_helpers/web_helpers.dart create mode 100644 packages/x_file/pubspec.yaml rename packages/{file_selector/file_selector_platform_interface => x_file}/test/assets/hello.txt (100%) rename packages/{file_selector/file_selector_platform_interface/test/x_file_html_test.dart => x_file/test/cross_file_html_test.dart} (97%) rename packages/{file_selector/file_selector_platform_interface/test/x_file_io_test.dart => x_file/test/cross_file_io_test.dart} (97%) diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart index 8681a1dbffa6..a09c7de92be3 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart @@ -6,6 +6,7 @@ import 'package:flutter/services.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:meta/meta.dart'; +import 'package:x_file/x_file.dart'; const MethodChannel _channel = MethodChannel('plugins.flutter.io/file_selector'); diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart index cf23d5f01eab..87395676b76f 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:x_file/x_file.dart'; import '../method_channel/method_channel_file_selector.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart index 8848c6751ba3..d3a72cd2f9fa 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart @@ -1,3 +1 @@ -export 'x_file/x_file.dart'; - export 'x_type_group/x_type_group.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart deleted file mode 100644 index 4545c605875a..000000000000 --- a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'interface.dart' - if (dart.library.html) 'html.dart' - if (dart.library.io) 'io.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/pubspec.yaml b/packages/file_selector/file_selector_platform_interface/pubspec.yaml index ca5c2bd189ae..2fc60c1f178b 100644 --- a/packages/file_selector/file_selector_platform_interface/pubspec.yaml +++ b/packages/file_selector/file_selector_platform_interface/pubspec.yaml @@ -11,6 +11,8 @@ dependencies: meta: ^1.0.5 http: ^0.12.0+1 plugin_platform_interface: ^1.0.1 + x_file: + path: ../../x_file dev_dependencies: test: ^1.15.0 diff --git a/packages/x_file/CHANGELOG.md b/packages/x_file/CHANGELOG.md new file mode 100644 index 000000000000..07d40a432b80 --- /dev/null +++ b/packages/x_file/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial open-source release \ No newline at end of file diff --git a/packages/x_file/LICENSE b/packages/x_file/LICENSE new file mode 100644 index 000000000000..2c91f1438173 --- /dev/null +++ b/packages/x_file/LICENSE @@ -0,0 +1,25 @@ +Copyright 2020 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/packages/x_file/lib/cross_file.dart b/packages/x_file/lib/cross_file.dart new file mode 100644 index 000000000000..e4074d629042 --- /dev/null +++ b/packages/x_file/lib/cross_file.dart @@ -0,0 +1 @@ +export 'src/cross_file.dart'; diff --git a/packages/x_file/lib/src/cross_file.dart b/packages/x_file/lib/src/cross_file.dart new file mode 100644 index 000000000000..efe379f59d01 --- /dev/null +++ b/packages/x_file/lib/src/cross_file.dart @@ -0,0 +1,3 @@ +export 'types/interface.dart' + if (dart.library.html) 'types/html.dart' + if (dart.library.io) 'types/io.dart'; \ No newline at end of file diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart b/packages/x_file/lib/src/types/base.dart similarity index 100% rename from packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart rename to packages/x_file/lib/src/types/base.dart diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart b/packages/x_file/lib/src/types/html.dart similarity index 98% rename from packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart rename to packages/x_file/lib/src/types/html.dart index fe898eb4ca62..8dbf6841cad6 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart +++ b/packages/x_file/lib/src/types/html.dart @@ -5,7 +5,7 @@ import 'package:http/http.dart' as http show readBytes; import 'package:meta/meta.dart'; import 'dart:html'; -import '../../web_helpers/web_helpers.dart'; +import '../web_helpers/web_helpers.dart'; import './base.dart'; /// A XFile that works on web. diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart b/packages/x_file/lib/src/types/interface.dart similarity index 100% rename from packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart rename to packages/x_file/lib/src/types/interface.dart diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart b/packages/x_file/lib/src/types/io.dart similarity index 100% rename from packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart rename to packages/x_file/lib/src/types/io.dart diff --git a/packages/x_file/lib/src/web_helpers/web_helpers.dart b/packages/x_file/lib/src/web_helpers/web_helpers.dart new file mode 100644 index 000000000000..9e40e562bc9a --- /dev/null +++ b/packages/x_file/lib/src/web_helpers/web_helpers.dart @@ -0,0 +1,34 @@ +import 'dart:html'; + +/// Create anchor element with download attribute +AnchorElement createAnchorElement(String href, String suggestedName) { + final element = AnchorElement(href: href); + + if (suggestedName == null) { + element.download = 'download'; + } else { + element.download = suggestedName; + } + + return element; +} + +/// Add an element to a container and click it +void addElementToContainerAndClick(Element container, Element element) { + // Add the element and click it + // All previous elements will be removed before adding the new one + container.children.add(element); + element.click(); +} + +/// Initializes a DOM container where we can host elements. +Element ensureInitialized(String id) { + var target = querySelector('#${id}'); + if (target == null) { + final Element targetElement = Element.tag('flt-x-file')..id = id; + + querySelector('body').children.add(targetElement); + target = targetElement; + } + return target; +} diff --git a/packages/x_file/pubspec.yaml b/packages/x_file/pubspec.yaml new file mode 100644 index 000000000000..1089d68b536a --- /dev/null +++ b/packages/x_file/pubspec.yaml @@ -0,0 +1,20 @@ + +name: cross_file +description: An abstraction to allow working with files across multiple platforms. +homepage: https://github.com/flutter/plugins/tree/master/packages/x_file +version: 1.0.0 + +dependencies: + flutter: + sdk: flutter + http: ^0.12.0+1 + meta: ^1.0.5 + +dev_dependencies: + flutter_test: + sdk: flutter + pedantic: ^1.8.0 + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.22.0 <2.0.0" \ No newline at end of file diff --git a/packages/file_selector/file_selector_platform_interface/test/assets/hello.txt b/packages/x_file/test/assets/hello.txt similarity index 100% rename from packages/file_selector/file_selector_platform_interface/test/assets/hello.txt rename to packages/x_file/test/assets/hello.txt diff --git a/packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart b/packages/x_file/test/cross_file_html_test.dart similarity index 97% rename from packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart rename to packages/x_file/test/cross_file_html_test.dart index f888a0486ca7..118c6259d0e0 100644 --- a/packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart +++ b/packages/x_file/test/cross_file_html_test.dart @@ -9,7 +9,7 @@ import 'dart:html' as html; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:cross_file/cross_file.dart'; import 'dart:html'; diff --git a/packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart b/packages/x_file/test/cross_file_io_test.dart similarity index 97% rename from packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart rename to packages/x_file/test/cross_file_io_test.dart index b669324462b2..65edea1ea45d 100644 --- a/packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart +++ b/packages/x_file/test/cross_file_io_test.dart @@ -9,7 +9,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:cross_file/cross_file.dart'; // Please note that executing this test with command // `flutter test test/x_file_io_test.dart` will set the directory From ff1be084ea67713f6cc712e63018de82579f4fe3 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 10:25:49 +0100 Subject: [PATCH 02/13] Renamed from x_file to cross_file --- packages/{x_file => cross_file}/CHANGELOG.md | 0 packages/{x_file => cross_file}/LICENSE | 0 .../lib/cross_file.dart | 0 .../lib/src/cross_file.dart | 0 .../lib/src/types/base.dart | 16 ++++++------ .../lib/src/types/html.dart | 26 +++++++++---------- .../lib/src/types/interface.dart | 26 +++++++++---------- .../lib/src/types/io.dart | 12 ++++----- .../lib/src/web_helpers/web_helpers.dart | 0 packages/{x_file => cross_file}/pubspec.yaml | 0 .../test/assets/hello.txt | 0 .../test/cross_file_html_test.dart | 22 ++++++++-------- .../test/cross_file_io_test.dart | 4 +-- 13 files changed, 53 insertions(+), 53 deletions(-) rename packages/{x_file => cross_file}/CHANGELOG.md (100%) rename packages/{x_file => cross_file}/LICENSE (100%) rename packages/{x_file => cross_file}/lib/cross_file.dart (100%) rename packages/{x_file => cross_file}/lib/src/cross_file.dart (100%) rename packages/{x_file => cross_file}/lib/src/types/base.dart (88%) rename packages/{x_file => cross_file}/lib/src/types/html.dart (84%) rename packages/{x_file => cross_file}/lib/src/types/interface.dart (62%) rename packages/{x_file => cross_file}/lib/src/types/io.dart (90%) rename packages/{x_file => cross_file}/lib/src/web_helpers/web_helpers.dart (100%) rename packages/{x_file => cross_file}/pubspec.yaml (100%) rename packages/{x_file => cross_file}/test/assets/hello.txt (100%) rename packages/{x_file => cross_file}/test/cross_file_html_test.dart (80%) rename packages/{x_file => cross_file}/test/cross_file_io_test.dart (97%) diff --git a/packages/x_file/CHANGELOG.md b/packages/cross_file/CHANGELOG.md similarity index 100% rename from packages/x_file/CHANGELOG.md rename to packages/cross_file/CHANGELOG.md diff --git a/packages/x_file/LICENSE b/packages/cross_file/LICENSE similarity index 100% rename from packages/x_file/LICENSE rename to packages/cross_file/LICENSE diff --git a/packages/x_file/lib/cross_file.dart b/packages/cross_file/lib/cross_file.dart similarity index 100% rename from packages/x_file/lib/cross_file.dart rename to packages/cross_file/lib/cross_file.dart diff --git a/packages/x_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/cross_file.dart similarity index 100% rename from packages/x_file/lib/src/cross_file.dart rename to packages/cross_file/lib/src/cross_file.dart diff --git a/packages/x_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart similarity index 88% rename from packages/x_file/lib/src/types/base.dart rename to packages/cross_file/lib/src/types/base.dart index 7ea050ff28db..eb5aa8c82758 100644 --- a/packages/x_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -1,19 +1,19 @@ import 'dart:convert'; import 'dart:typed_data'; -/// The interface for a XFile. +/// The interface for a CrossFile. /// -/// A XFile is a container that wraps the path of a selected +/// A CrossFile is a container that wraps the path of a selected /// file by the user and (in some platforms, like web) the bytes /// with the contents of the file. /// /// This class is a very limited subset of dart:io [File], so all /// the methods should seem familiar. -abstract class XFileBase { - /// Construct a XFile - XFileBase(String path); +abstract class CrossFileBase { + /// Construct a CrossFile + CrossFileBase(String path); - /// Save the XFile at the indicated file path. + /// Save the CrossFile at the indicated file path. void saveTo(String path) async { throw UnimplementedError('saveTo has not been implemented.'); } @@ -26,7 +26,7 @@ abstract class XFileBase { /// /// Accessing the data contained in the picked file by its path /// is platform-dependant (and won't work on web), so use the - /// byte getters in the XFile instance instead. + /// byte getters in the CrossFile instance instead. String get path { throw UnimplementedError('.path has not been implemented.'); } @@ -75,7 +75,7 @@ abstract class XFileBase { throw UnimplementedError('openRead() has not been implemented.'); } - /// Get the last-modified time for the XFile + /// Get the last-modified time for the CrossFile Future lastModified() { throw UnimplementedError('openRead() has not been implemented.'); } diff --git a/packages/x_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart similarity index 84% rename from packages/x_file/lib/src/types/html.dart rename to packages/cross_file/lib/src/types/html.dart index 8dbf6841cad6..92217dc37eb4 100644 --- a/packages/x_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -8,10 +8,10 @@ import 'dart:html'; import '../web_helpers/web_helpers.dart'; import './base.dart'; -/// A XFile that works on web. +/// A CrossFile that works on web. /// /// It wraps the bytes of a selected file. -class XFile extends XFileBase { +class CrossFile extends CrossFileBase { String path; final String mimeType; @@ -21,40 +21,40 @@ class XFile extends XFileBase { final DateTime _lastModified; Element _target; - final XFileTestOverrides _overrides; + final CrossFileTestOverrides _overrides; bool get _hasTestOverrides => _overrides != null; - /// Construct a XFile object from its ObjectUrl. + /// Construct a CrossFile object from its ObjectUrl. /// /// Optionally, this can be initialized with `bytes` and `length` /// so no http requests are performed to retrieve files later. /// /// `name` needs to be passed from the outside, since we only have /// access to it while we create the ObjectUrl. - XFile( + CrossFile( this.path, { this.mimeType, this.name, int length, Uint8List bytes, DateTime lastModified, - @visibleForTesting XFileTestOverrides overrides, + @visibleForTesting CrossFileTestOverrides overrides, }) : _data = bytes, _length = length, _overrides = overrides, _lastModified = lastModified, super(path); - /// Construct an XFile from its data - XFile.fromData( + /// Construct an CrossFile from its data + CrossFile.fromData( Uint8List bytes, { this.mimeType, this.name, int length, DateTime lastModified, this.path, - @visibleForTesting XFileTestOverrides overrides, + @visibleForTesting CrossFileTestOverrides overrides, }) : _data = bytes, _length = length, _overrides = overrides, @@ -102,14 +102,14 @@ class XFile extends XFileBase { yield bytes.sublist(start ?? 0, end ?? bytes.length); } - /// Saves the data of this XFile at the location indicated by path. + /// Saves the data of this CrossFile at the location indicated by path. /// For the web implementation, the path variable is ignored. void saveTo(String path) async { // Create a DOM container where we can host the anchor. _target = ensureInitialized('__x_file_dom_element'); // Create an tag with the appropriate download attributes and click it - // May be overridden with XFileTestOverrides + // May be overridden with CrossFileTestOverrides final AnchorElement element = (_hasTestOverrides && _overrides.createAnchorElement != null) ? _overrides.createAnchorElement(this.path, this.name) @@ -123,10 +123,10 @@ class XFile extends XFileBase { /// Overrides some functions to allow testing @visibleForTesting -class XFileTestOverrides { +class CrossFileTestOverrides { /// For overriding the creation of the file input element. Element Function(String href, String suggestedName) createAnchorElement; /// Default constructor for overrides - XFileTestOverrides({this.createAnchorElement}); + CrossFileTestOverrides({this.createAnchorElement}); } diff --git a/packages/x_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart similarity index 62% rename from packages/x_file/lib/src/types/interface.dart rename to packages/cross_file/lib/src/types/interface.dart index f5fe388e0899..2b2b25e65f80 100644 --- a/packages/x_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -3,11 +3,11 @@ import 'package:meta/meta.dart'; import './base.dart'; -/// A XFile is a cross-platform, simplified File abstraction. +/// A CrossFile is a cross-platform, simplified File abstraction. /// /// It wraps the bytes of a selected file, and its (platform-dependant) path. -class XFile extends XFileBase { - /// Construct a XFile object from its path. +class CrossFile extends CrossFileBase { + /// Construct a CrossFile object from its path. /// /// Optionally, this can be initialized with `bytes` and `length` /// so no http requests are performed to retrieve data later. @@ -15,40 +15,40 @@ class XFile extends XFileBase { /// `name` may be passed from the outside, for those cases where the effective /// `path` of the file doesn't match what the user sees when selecting it /// (like in web) - XFile( + CrossFile( String path, { String mimeType, String name, int length, Uint8List bytes, DateTime lastModified, - @visibleForTesting XFileTestOverrides overrides, + @visibleForTesting CrossFileTestOverrides overrides, }) : super(path) { throw UnimplementedError( - 'XFile is not available in your current platform.'); + 'CrossFile is not available in your current platform.'); } - /// Construct a XFile object from its data - XFile.fromData( + /// Construct a CrossFile object from its data + CrossFile.fromData( Uint8List bytes, { String mimeType, String name, int length, DateTime lastModified, String path, - @visibleForTesting XFileTestOverrides overrides, + @visibleForTesting CrossFileTestOverrides overrides, }) : super(path) { throw UnimplementedError( - 'XFile is not available in your current platform.'); + 'CrossFile is not available in your current platform.'); } } -/// Overrides some functions of XFile for testing purposes +/// Overrides some functions of CrossFile for testing purposes @visibleForTesting -class XFileTestOverrides { +class CrossFileTestOverrides { /// For overriding the creation of the file input element. dynamic Function(String href, String suggestedName) createAnchorElement; /// Default constructor for overrides - XFileTestOverrides({this.createAnchorElement}); + CrossFileTestOverrides({this.createAnchorElement}); } diff --git a/packages/x_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart similarity index 90% rename from packages/x_file/lib/src/types/io.dart rename to packages/cross_file/lib/src/types/io.dart index 753732df2811..6df7562e4daf 100644 --- a/packages/x_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -4,8 +4,8 @@ import 'dart:typed_data'; import './base.dart'; -/// A XFile backed by a dart:io File. -class XFile extends XFileBase { +/// A CrossFile backed by a dart:io File. +class CrossFile extends CrossFileBase { final File _file; final String mimeType; final DateTime _lastModified; @@ -13,8 +13,8 @@ class XFile extends XFileBase { final Uint8List _bytes; - /// Construct a XFile object backed by a dart:io File. - XFile( + /// Construct a CrossFile object backed by a dart:io File. + CrossFile( String path, { this.mimeType, String name, @@ -26,8 +26,8 @@ class XFile extends XFileBase { _lastModified = lastModified, super(path); - /// Construct an XFile from its data - XFile.fromData( + /// Construct an CrossFile from its data + CrossFile.fromData( Uint8List bytes, { this.mimeType, String path, diff --git a/packages/x_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/lib/src/web_helpers/web_helpers.dart similarity index 100% rename from packages/x_file/lib/src/web_helpers/web_helpers.dart rename to packages/cross_file/lib/src/web_helpers/web_helpers.dart diff --git a/packages/x_file/pubspec.yaml b/packages/cross_file/pubspec.yaml similarity index 100% rename from packages/x_file/pubspec.yaml rename to packages/cross_file/pubspec.yaml diff --git a/packages/x_file/test/assets/hello.txt b/packages/cross_file/test/assets/hello.txt similarity index 100% rename from packages/x_file/test/assets/hello.txt rename to packages/cross_file/test/assets/hello.txt diff --git a/packages/x_file/test/cross_file_html_test.dart b/packages/cross_file/test/cross_file_html_test.dart similarity index 80% rename from packages/x_file/test/cross_file_html_test.dart rename to packages/cross_file/test/cross_file_html_test.dart index 118c6259d0e0..8aef9f62d3d3 100644 --- a/packages/x_file/test/cross_file_html_test.dart +++ b/packages/cross_file/test/cross_file_html_test.dart @@ -20,7 +20,7 @@ final String textFileUrl = html.Url.createObjectUrl(textFile); void main() { group('Create with an objectUrl', () { - final file = XFile(textFileUrl); + final file = CrossFile(textFileUrl); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -39,7 +39,7 @@ void main() { }); group('Create from data', () { - final file = XFile.fromData(bytes); + final file = CrossFile.fromData(bytes); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -58,25 +58,25 @@ void main() { }); group('saveTo(..)', () { - final String xFileDomElementId = '__x_file_dom_element'; + final String CrossFileDomElementId = '__x_file_dom_element'; - group('XFile saveTo(..)', () { + group('CrossFile saveTo(..)', () { test('creates a DOM container', () async { - XFile file = XFile.fromData(bytes); + CrossFile file = CrossFile.fromData(bytes); await file.saveTo(''); - final container = querySelector('#${xFileDomElementId}'); + final container = querySelector('#${CrossFileDomElementId}'); expect(container, isNotNull); }); test('create anchor element', () async { - XFile file = XFile.fromData(bytes, name: textFile.name); + CrossFile file = CrossFile.fromData(bytes, name: textFile.name); await file.saveTo('path'); - final container = querySelector('#${xFileDomElementId}'); + final container = querySelector('#${CrossFileDomElementId}'); final AnchorElement element = container?.children?.firstWhere( (element) => element.tagName == 'A', orElse: () => null); @@ -89,12 +89,12 @@ void main() { test('anchor element is clicked', () async { final mockAnchor = AnchorElement(); - XFileTestOverrides overrides = XFileTestOverrides( + CrossFileTestOverrides overrides = CrossFileTestOverrides( createAnchorElement: (_, __) => mockAnchor, ); - XFile file = - XFile.fromData(bytes, name: textFile.name, overrides: overrides); + CrossFile file = CrossFile.fromData(bytes, + name: textFile.name, overrides: overrides); bool clicked = false; mockAnchor.onClick.listen((event) => clicked = true); diff --git a/packages/x_file/test/cross_file_io_test.dart b/packages/cross_file/test/cross_file_io_test.dart similarity index 97% rename from packages/x_file/test/cross_file_io_test.dart rename to packages/cross_file/test/cross_file_io_test.dart index 65edea1ea45d..b5ff873b302c 100644 --- a/packages/x_file/test/cross_file_io_test.dart +++ b/packages/cross_file/test/cross_file_io_test.dart @@ -30,7 +30,7 @@ final String textFilePath = textFile.path; void main() { group('Create with a path', () { - final file = XFile(textFilePath); + final file = CrossFile(textFilePath); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -64,7 +64,7 @@ void main() { }); group('Create with data', () { - final file = XFile.fromData(bytes); + final file = CrossFile.fromData(bytes); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); From 8202c5be3abe9799b11db603a3e74dfca68b7c92 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 11:19:01 +0100 Subject: [PATCH 03/13] Add back x_file type to file_selector --- .../method_channel_file_selector.dart | 1 - .../file_selector_interface.dart | 1 - .../lib/src/types/types.dart | 2 + .../lib/src/types/x_file/base.dart | 82 +++++++++++ .../lib/src/types/x_file/html.dart | 132 ++++++++++++++++++ .../lib/src/types/x_file/interface.dart | 54 +++++++ .../lib/src/types/x_file/io.dart | 111 +++++++++++++++ .../lib/src/types/x_file/x_file.dart | 3 + .../pubspec.yaml | 2 - .../test/assets/hello.txt | 1 + .../test/x_file_html_test.dart | 108 ++++++++++++++ .../test/x_file_io_test.dart | 99 +++++++++++++ 12 files changed, 592 insertions(+), 4 deletions(-) create mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart create mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart create mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart create mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart create mode 100644 packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart create mode 100644 packages/file_selector/file_selector_platform_interface/test/assets/hello.txt create mode 100644 packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart create mode 100644 packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart index a09c7de92be3..8681a1dbffa6 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart @@ -6,7 +6,6 @@ import 'package:flutter/services.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:meta/meta.dart'; -import 'package:x_file/x_file.dart'; const MethodChannel _channel = MethodChannel('plugins.flutter.io/file_selector'); diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart index 87395676b76f..cf23d5f01eab 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; -import 'package:x_file/x_file.dart'; import '../method_channel/method_channel_file_selector.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart index d3a72cd2f9fa..8848c6751ba3 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/types.dart @@ -1 +1,3 @@ +export 'x_file/x_file.dart'; + export 'x_type_group/x_type_group.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart new file mode 100644 index 000000000000..7ea050ff28db --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/base.dart @@ -0,0 +1,82 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +/// The interface for a XFile. +/// +/// A XFile is a container that wraps the path of a selected +/// file by the user and (in some platforms, like web) the bytes +/// with the contents of the file. +/// +/// This class is a very limited subset of dart:io [File], so all +/// the methods should seem familiar. +abstract class XFileBase { + /// Construct a XFile + XFileBase(String path); + + /// Save the XFile at the indicated file path. + void saveTo(String path) async { + throw UnimplementedError('saveTo has not been implemented.'); + } + + /// Get the path of the picked file. + /// + /// This should only be used as a backwards-compatibility clutch + /// for mobile apps, or cosmetic reasons only (to show the user + /// the path they've picked). + /// + /// Accessing the data contained in the picked file by its path + /// is platform-dependant (and won't work on web), so use the + /// byte getters in the XFile instance instead. + String get path { + throw UnimplementedError('.path has not been implemented.'); + } + + /// The name of the file as it was selected by the user in their device. + /// + /// Use only for cosmetic reasons, do not try to use this as a path. + String get name { + throw UnimplementedError('.name has not been implemented.'); + } + + /// For web, it may be necessary for a file to know its MIME type. + String get mimeType { + throw UnimplementedError('.mimeType has not been implemented.'); + } + + /// Get the length of the file. Returns a `Future` that completes with the length in bytes. + Future length() { + throw UnimplementedError('.length() has not been implemented.'); + } + + /// Synchronously read the entire file contents as a string using the given [Encoding]. + /// + /// By default, `encoding` is [utf8]. + /// + /// Throws Exception if the operation fails. + Future readAsString({Encoding encoding = utf8}) { + throw UnimplementedError('readAsString() has not been implemented.'); + } + + /// Synchronously read the entire file contents as a list of bytes. + /// + /// Throws Exception if the operation fails. + Future readAsBytes() { + throw UnimplementedError('readAsBytes() has not been implemented.'); + } + + /// Create a new independent [Stream] for the contents of this file. + /// + /// If `start` is present, the file will be read from byte-offset `start`. Otherwise from the beginning (index 0). + /// + /// If `end` is present, only up to byte-index `end` will be read. Otherwise, until end of file. + /// + /// In order to make sure that system resources are freed, the stream must be read to completion or the subscription on the stream must be cancelled. + Stream openRead([int start, int end]) { + throw UnimplementedError('openRead() has not been implemented.'); + } + + /// Get the last-modified time for the XFile + Future lastModified() { + throw UnimplementedError('openRead() has not been implemented.'); + } +} diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart new file mode 100644 index 000000000000..fe898eb4ca62 --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/html.dart @@ -0,0 +1,132 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:http/http.dart' as http show readBytes; +import 'package:meta/meta.dart'; +import 'dart:html'; + +import '../../web_helpers/web_helpers.dart'; +import './base.dart'; + +/// A XFile that works on web. +/// +/// It wraps the bytes of a selected file. +class XFile extends XFileBase { + String path; + + final String mimeType; + final Uint8List _data; + final int _length; + final String name; + final DateTime _lastModified; + Element _target; + + final XFileTestOverrides _overrides; + + bool get _hasTestOverrides => _overrides != null; + + /// Construct a XFile object from its ObjectUrl. + /// + /// Optionally, this can be initialized with `bytes` and `length` + /// so no http requests are performed to retrieve files later. + /// + /// `name` needs to be passed from the outside, since we only have + /// access to it while we create the ObjectUrl. + XFile( + this.path, { + this.mimeType, + this.name, + int length, + Uint8List bytes, + DateTime lastModified, + @visibleForTesting XFileTestOverrides overrides, + }) : _data = bytes, + _length = length, + _overrides = overrides, + _lastModified = lastModified, + super(path); + + /// Construct an XFile from its data + XFile.fromData( + Uint8List bytes, { + this.mimeType, + this.name, + int length, + DateTime lastModified, + this.path, + @visibleForTesting XFileTestOverrides overrides, + }) : _data = bytes, + _length = length, + _overrides = overrides, + _lastModified = lastModified, + super(path) { + if (path == null) { + final blob = (mimeType == null) ? Blob([bytes]) : Blob([bytes], mimeType); + this.path = Url.createObjectUrl(blob); + } + } + + @override + Future lastModified() async { + if (_lastModified != null) { + return Future.value(_lastModified); + } + return null; + } + + Future get _bytes async { + if (_data != null) { + return Future.value(UnmodifiableUint8ListView(_data)); + } + return http.readBytes(path); + } + + @override + Future length() async { + return _length ?? (await _bytes).length; + } + + @override + Future readAsString({Encoding encoding = utf8}) async { + return encoding.decode(await _bytes); + } + + @override + Future readAsBytes() async { + return Future.value(await _bytes); + } + + @override + Stream openRead([int start, int end]) async* { + final bytes = await _bytes; + yield bytes.sublist(start ?? 0, end ?? bytes.length); + } + + /// Saves the data of this XFile at the location indicated by path. + /// For the web implementation, the path variable is ignored. + void saveTo(String path) async { + // Create a DOM container where we can host the anchor. + _target = ensureInitialized('__x_file_dom_element'); + + // Create an tag with the appropriate download attributes and click it + // May be overridden with XFileTestOverrides + final AnchorElement element = + (_hasTestOverrides && _overrides.createAnchorElement != null) + ? _overrides.createAnchorElement(this.path, this.name) + : createAnchorElement(this.path, this.name); + + // Clear the children in our container so we can add an element to click + _target.children.clear(); + addElementToContainerAndClick(_target, element); + } +} + +/// Overrides some functions to allow testing +@visibleForTesting +class XFileTestOverrides { + /// For overriding the creation of the file input element. + Element Function(String href, String suggestedName) createAnchorElement; + + /// Default constructor for overrides + XFileTestOverrides({this.createAnchorElement}); +} diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart new file mode 100644 index 000000000000..f5fe388e0899 --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/interface.dart @@ -0,0 +1,54 @@ +import 'dart:typed_data'; +import 'package:meta/meta.dart'; + +import './base.dart'; + +/// A XFile is a cross-platform, simplified File abstraction. +/// +/// It wraps the bytes of a selected file, and its (platform-dependant) path. +class XFile extends XFileBase { + /// Construct a XFile object from its path. + /// + /// Optionally, this can be initialized with `bytes` and `length` + /// so no http requests are performed to retrieve data later. + /// + /// `name` may be passed from the outside, for those cases where the effective + /// `path` of the file doesn't match what the user sees when selecting it + /// (like in web) + XFile( + String path, { + String mimeType, + String name, + int length, + Uint8List bytes, + DateTime lastModified, + @visibleForTesting XFileTestOverrides overrides, + }) : super(path) { + throw UnimplementedError( + 'XFile is not available in your current platform.'); + } + + /// Construct a XFile object from its data + XFile.fromData( + Uint8List bytes, { + String mimeType, + String name, + int length, + DateTime lastModified, + String path, + @visibleForTesting XFileTestOverrides overrides, + }) : super(path) { + throw UnimplementedError( + 'XFile is not available in your current platform.'); + } +} + +/// Overrides some functions of XFile for testing purposes +@visibleForTesting +class XFileTestOverrides { + /// For overriding the creation of the file input element. + dynamic Function(String href, String suggestedName) createAnchorElement; + + /// Default constructor for overrides + XFileTestOverrides({this.createAnchorElement}); +} diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart new file mode 100644 index 000000000000..753732df2811 --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/io.dart @@ -0,0 +1,111 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import './base.dart'; + +/// A XFile backed by a dart:io File. +class XFile extends XFileBase { + final File _file; + final String mimeType; + final DateTime _lastModified; + int _length; + + final Uint8List _bytes; + + /// Construct a XFile object backed by a dart:io File. + XFile( + String path, { + this.mimeType, + String name, + int length, + Uint8List bytes, + DateTime lastModified, + }) : _file = File(path), + _bytes = null, + _lastModified = lastModified, + super(path); + + /// Construct an XFile from its data + XFile.fromData( + Uint8List bytes, { + this.mimeType, + String path, + String name, + int length, + DateTime lastModified, + }) : _bytes = bytes, + _file = File(path ?? ''), + _length = length, + _lastModified = lastModified, + super(path) { + if (length == null) { + _length = bytes.length; + } + } + + @override + Future lastModified() { + if (_lastModified != null) { + return Future.value(_lastModified); + } + return _file.lastModified(); + } + + @override + void saveTo(String path) async { + File fileToSave = File(path); + await fileToSave.writeAsBytes(_bytes ?? (await readAsBytes())); + await fileToSave.create(); + } + + @override + String get path { + return _file.path; + } + + @override + String get name { + return _file.path.split(Platform.pathSeparator).last; + } + + @override + Future length() { + if (_length != null) { + return Future.value(_length); + } + return _file.length(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + if (_bytes != null) { + return Future.value(String.fromCharCodes(_bytes)); + } + return _file.readAsString(encoding: encoding); + } + + @override + Future readAsBytes() { + if (_bytes != null) { + return Future.value(_bytes); + } + return _file.readAsBytes(); + } + + Stream _getBytes(int start, int end) async* { + final bytes = _bytes; + yield bytes.sublist(start ?? 0, end ?? bytes.length); + } + + @override + Stream openRead([int start, int end]) { + if (_bytes != null) { + return _getBytes(start, end); + } else { + return _file + .openRead(start ?? 0, end) + .map((chunk) => Uint8List.fromList(chunk)); + } + } +} diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart new file mode 100644 index 000000000000..4545c605875a --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_file/x_file.dart @@ -0,0 +1,3 @@ +export 'interface.dart' + if (dart.library.html) 'html.dart' + if (dart.library.io) 'io.dart'; diff --git a/packages/file_selector/file_selector_platform_interface/pubspec.yaml b/packages/file_selector/file_selector_platform_interface/pubspec.yaml index 2fc60c1f178b..ca5c2bd189ae 100644 --- a/packages/file_selector/file_selector_platform_interface/pubspec.yaml +++ b/packages/file_selector/file_selector_platform_interface/pubspec.yaml @@ -11,8 +11,6 @@ dependencies: meta: ^1.0.5 http: ^0.12.0+1 plugin_platform_interface: ^1.0.1 - x_file: - path: ../../x_file dev_dependencies: test: ^1.15.0 diff --git a/packages/file_selector/file_selector_platform_interface/test/assets/hello.txt b/packages/file_selector/file_selector_platform_interface/test/assets/hello.txt new file mode 100644 index 000000000000..5dd01c177f5d --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/test/assets/hello.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart b/packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart new file mode 100644 index 000000000000..f888a0486ca7 --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/test/x_file_html_test.dart @@ -0,0 +1,108 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@TestOn('chrome') // Uses web-only Flutter SDK + +import 'dart:convert'; +import 'dart:html' as html; +import 'dart:typed_data'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; + +import 'dart:html'; + +final String expectedStringContents = 'Hello, world!'; +final Uint8List bytes = utf8.encode(expectedStringContents); +final html.File textFile = html.File([bytes], 'hello.txt'); +final String textFileUrl = html.Url.createObjectUrl(textFile); + +void main() { + group('Create with an objectUrl', () { + final file = XFile(textFileUrl); + + test('Can be read as a string', () async { + expect(await file.readAsString(), equals(expectedStringContents)); + }); + test('Can be read as bytes', () async { + expect(await file.readAsBytes(), equals(bytes)); + }); + + test('Can be read as a stream', () async { + expect(await file.openRead().first, equals(bytes)); + }); + + test('Stream can be sliced', () async { + expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); + }); + }); + + group('Create from data', () { + final file = XFile.fromData(bytes); + + test('Can be read as a string', () async { + expect(await file.readAsString(), equals(expectedStringContents)); + }); + test('Can be read as bytes', () async { + expect(await file.readAsBytes(), equals(bytes)); + }); + + test('Can be read as a stream', () async { + expect(await file.openRead().first, equals(bytes)); + }); + + test('Stream can be sliced', () async { + expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); + }); + }); + + group('saveTo(..)', () { + final String xFileDomElementId = '__x_file_dom_element'; + + group('XFile saveTo(..)', () { + test('creates a DOM container', () async { + XFile file = XFile.fromData(bytes); + + await file.saveTo(''); + + final container = querySelector('#${xFileDomElementId}'); + + expect(container, isNotNull); + }); + + test('create anchor element', () async { + XFile file = XFile.fromData(bytes, name: textFile.name); + + await file.saveTo('path'); + + final container = querySelector('#${xFileDomElementId}'); + final AnchorElement element = container?.children?.firstWhere( + (element) => element.tagName == 'A', + orElse: () => null); + + expect(element, isNotNull); + expect(element.href, file.path); + expect(element.download, file.name); + }); + + test('anchor element is clicked', () async { + final mockAnchor = AnchorElement(); + + XFileTestOverrides overrides = XFileTestOverrides( + createAnchorElement: (_, __) => mockAnchor, + ); + + XFile file = + XFile.fromData(bytes, name: textFile.name, overrides: overrides); + + bool clicked = false; + mockAnchor.onClick.listen((event) => clicked = true); + + await file.saveTo('path'); + + expect(clicked, true); + }); + }); + }); +} diff --git a/packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart b/packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart new file mode 100644 index 000000000000..b669324462b2 --- /dev/null +++ b/packages/file_selector/file_selector_platform_interface/test/x_file_io_test.dart @@ -0,0 +1,99 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@TestOn('vm') // Uses dart:io + +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; + +// Please note that executing this test with command +// `flutter test test/x_file_io_test.dart` will set the directory +// to ./file_selector_platform_interface. +// +// This will cause our hello.txt file to be not be found. Please +// execute this test with `flutter test` or change the path prefix +// to ./test/assets/ +// +// https://github.com/flutter/flutter/issues/20907 + +final pathPrefix = './assets/'; +final path = pathPrefix + 'hello.txt'; +final String expectedStringContents = 'Hello, world!'; +final Uint8List bytes = utf8.encode(expectedStringContents); +final File textFile = File(path); +final String textFilePath = textFile.path; + +void main() { + group('Create with a path', () { + final file = XFile(textFilePath); + + test('Can be read as a string', () async { + expect(await file.readAsString(), equals(expectedStringContents)); + }); + test('Can be read as bytes', () async { + expect(await file.readAsBytes(), equals(bytes)); + }); + + test('Can be read as a stream', () async { + expect(await file.openRead().first, equals(bytes)); + }); + + test('Stream can be sliced', () async { + expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); + }); + + test('saveTo(..) creates file', () async { + File removeBeforeTest = File(pathPrefix + 'newFilePath.txt'); + if (removeBeforeTest.existsSync()) { + await removeBeforeTest.delete(); + } + + await file.saveTo(pathPrefix + 'newFilePath.txt'); + File newFile = File(pathPrefix + 'newFilePath.txt'); + + expect(newFile.existsSync(), isTrue); + expect(newFile.readAsStringSync(), 'Hello, world!'); + + await newFile.delete(); + }); + }); + + group('Create with data', () { + final file = XFile.fromData(bytes); + + test('Can be read as a string', () async { + expect(await file.readAsString(), equals(expectedStringContents)); + }); + test('Can be read as bytes', () async { + expect(await file.readAsBytes(), equals(bytes)); + }); + + test('Can be read as a stream', () async { + expect(await file.openRead().first, equals(bytes)); + }); + + test('Stream can be sliced', () async { + expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); + }); + + test('Function saveTo(..) creates file', () async { + File removeBeforeTest = File(pathPrefix + 'newFileData.txt'); + if (removeBeforeTest.existsSync()) { + await removeBeforeTest.delete(); + } + + await file.saveTo(pathPrefix + 'newFileData.txt'); + File newFile = File(pathPrefix + 'newFileData.txt'); + + expect(newFile.existsSync(), isTrue); + expect(newFile.readAsStringSync(), 'Hello, world!'); + + await newFile.delete(); + }); + }); +} From c06be6b43e1a81e411a05819b7f0437b739451b3 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 11:29:50 +0100 Subject: [PATCH 04/13] Fix formatting issues --- packages/cross_file/lib/src/cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/cross_file.dart index efe379f59d01..3ebe68dbad36 100644 --- a/packages/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/lib/src/cross_file.dart @@ -1,3 +1,3 @@ export 'types/interface.dart' if (dart.library.html) 'types/html.dart' - if (dart.library.io) 'types/io.dart'; \ No newline at end of file + if (dart.library.io) 'types/io.dart'; From 0276a94052a493bd52340818edb88165d7f26524 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 11:31:16 +0100 Subject: [PATCH 05/13] Update homepage and version --- packages/cross_file/CHANGELOG.md | 2 +- packages/cross_file/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/CHANGELOG.md b/packages/cross_file/CHANGELOG.md index 07d40a432b80..3b5ae7756a98 100644 --- a/packages/cross_file/CHANGELOG.md +++ b/packages/cross_file/CHANGELOG.md @@ -1,3 +1,3 @@ -## 1.0.0 +## 0.1.0 - Initial open-source release \ No newline at end of file diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/pubspec.yaml index 1089d68b536a..40084d3d1ea0 100644 --- a/packages/cross_file/pubspec.yaml +++ b/packages/cross_file/pubspec.yaml @@ -1,8 +1,8 @@ name: cross_file description: An abstraction to allow working with files across multiple platforms. -homepage: https://github.com/flutter/plugins/tree/master/packages/x_file -version: 1.0.0 +homepage: https://github.com/flutter/plugins/tree/master/packages/cross_file +version: 0.1.0 dependencies: flutter: From ccc93381103941b31280106ec666d4805aa7d8af Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 12:05:07 +0100 Subject: [PATCH 06/13] Added README.md --- packages/cross_file/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 packages/cross_file/README.md diff --git a/packages/cross_file/README.md b/packages/cross_file/README.md new file mode 100644 index 000000000000..f1ab89bc52f1 --- /dev/null +++ b/packages/cross_file/README.md @@ -0,0 +1,34 @@ +# cross_file + +An abstraction to allow working with files across multiple platforms. + +# Usage + +Import `package:cross/cross_info.dart`, instantiate a `CrossFile` +using a path or byte array and use its methods and properties to +access the file and its metadata. + +Example: + +```dart +import 'package:cross_file/cross_file.dart'; + +final file = CrossFile('assets/hello.txt'); + +print('File information:'); +print('- Path: ${file.path}'); +print('- Name: ${file.name}'); +print('- MIME type: ${file.mimeType}'); + +final fileContent = await file.readAsString(); +print('Content of the file: ${fileContent}'); // e.g. "Moto G (4)" +``` + +You will find links to the API docs on the [pub page](https://pub.dartlang.org/packages/cross_file). + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](http://flutter.io/). + +For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code). \ No newline at end of file From 67ee328f955eb2bc455feb9e0cc15c28a958cf98 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 21:13:50 +0100 Subject: [PATCH 07/13] Added missing copyright --- packages/cross_file/lib/cross_file.dart | 4 ++++ packages/cross_file/lib/src/cross_file.dart | 4 ++++ packages/cross_file/lib/src/types/base.dart | 4 ++++ packages/cross_file/lib/src/types/html.dart | 4 ++++ packages/cross_file/lib/src/types/interface.dart | 4 ++++ packages/cross_file/lib/src/types/io.dart | 4 ++++ packages/cross_file/lib/src/web_helpers/web_helpers.dart | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/packages/cross_file/lib/cross_file.dart b/packages/cross_file/lib/cross_file.dart index e4074d629042..fbeba0bf3914 100644 --- a/packages/cross_file/lib/cross_file.dart +++ b/packages/cross_file/lib/cross_file.dart @@ -1 +1,5 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'src/cross_file.dart'; diff --git a/packages/cross_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/cross_file.dart index 3ebe68dbad36..6136bff39f36 100644 --- a/packages/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/lib/src/cross_file.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'types/interface.dart' if (dart.library.html) 'types/html.dart' if (dart.library.io) 'types/io.dart'; diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart index eb5aa8c82758..567027d316f5 100644 --- a/packages/cross_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart index 92217dc37eb4..2dece11637bc 100644 --- a/packages/cross_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart index 2b2b25e65f80..fa9036c0b7cc 100644 --- a/packages/cross_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:typed_data'; import 'package:meta/meta.dart'; diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart index 6df7562e4daf..b6554b153730 100644 --- a/packages/cross_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/lib/src/web_helpers/web_helpers.dart index 9e40e562bc9a..813f5f975561 100644 --- a/packages/cross_file/lib/src/web_helpers/web_helpers.dart +++ b/packages/cross_file/lib/src/web_helpers/web_helpers.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:html'; /// Create anchor element with download attribute From 01fe65e49f09869690155bedeb67f03c8ec22941 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 21:21:40 +0100 Subject: [PATCH 08/13] Revert "Added missing copyright" This reverts commit cf7e8d5f3810ae646669f584738502a8cc3c5ca1. --- packages/cross_file/lib/cross_file.dart | 4 ---- packages/cross_file/lib/src/cross_file.dart | 4 ---- packages/cross_file/lib/src/types/base.dart | 4 ---- packages/cross_file/lib/src/types/html.dart | 4 ---- packages/cross_file/lib/src/types/interface.dart | 4 ---- packages/cross_file/lib/src/types/io.dart | 4 ---- packages/cross_file/lib/src/web_helpers/web_helpers.dart | 4 ---- 7 files changed, 28 deletions(-) diff --git a/packages/cross_file/lib/cross_file.dart b/packages/cross_file/lib/cross_file.dart index fbeba0bf3914..e4074d629042 100644 --- a/packages/cross_file/lib/cross_file.dart +++ b/packages/cross_file/lib/cross_file.dart @@ -1,5 +1 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - export 'src/cross_file.dart'; diff --git a/packages/cross_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/cross_file.dart index 6136bff39f36..3ebe68dbad36 100644 --- a/packages/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/lib/src/cross_file.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - export 'types/interface.dart' if (dart.library.html) 'types/html.dart' if (dart.library.io) 'types/io.dart'; diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart index 567027d316f5..eb5aa8c82758 100644 --- a/packages/cross_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart index 2dece11637bc..92217dc37eb4 100644 --- a/packages/cross_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart index fa9036c0b7cc..2b2b25e65f80 100644 --- a/packages/cross_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - import 'dart:typed_data'; import 'package:meta/meta.dart'; diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart index b6554b153730..6df7562e4daf 100644 --- a/packages/cross_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/lib/src/web_helpers/web_helpers.dart index 813f5f975561..9e40e562bc9a 100644 --- a/packages/cross_file/lib/src/web_helpers/web_helpers.dart +++ b/packages/cross_file/lib/src/web_helpers/web_helpers.dart @@ -1,7 +1,3 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - import 'dart:html'; /// Create anchor element with download attribute From 6cb6b9848d7b90f0d284923cc8e0c2ccfc209094 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 10 Nov 2020 21:23:17 +0100 Subject: [PATCH 09/13] Add missing copyright Co-Authored-By: Jason Panelli <38673809+jasonpanelli@users.noreply.github.com> --- packages/cross_file/lib/cross_file.dart | 4 ++++ packages/cross_file/lib/src/cross_file.dart | 4 ++++ packages/cross_file/lib/src/types/base.dart | 4 ++++ packages/cross_file/lib/src/types/html.dart | 4 ++++ packages/cross_file/lib/src/types/interface.dart | 4 ++++ packages/cross_file/lib/src/types/io.dart | 4 ++++ packages/cross_file/lib/src/web_helpers/web_helpers.dart | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/packages/cross_file/lib/cross_file.dart b/packages/cross_file/lib/cross_file.dart index e4074d629042..fbeba0bf3914 100644 --- a/packages/cross_file/lib/cross_file.dart +++ b/packages/cross_file/lib/cross_file.dart @@ -1 +1,5 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'src/cross_file.dart'; diff --git a/packages/cross_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/cross_file.dart index 3ebe68dbad36..6136bff39f36 100644 --- a/packages/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/lib/src/cross_file.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'types/interface.dart' if (dart.library.html) 'types/html.dart' if (dart.library.io) 'types/io.dart'; diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart index eb5aa8c82758..567027d316f5 100644 --- a/packages/cross_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart index 92217dc37eb4..2dece11637bc 100644 --- a/packages/cross_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart index 2b2b25e65f80..fa9036c0b7cc 100644 --- a/packages/cross_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:typed_data'; import 'package:meta/meta.dart'; diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart index 6df7562e4daf..b6554b153730 100644 --- a/packages/cross_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; diff --git a/packages/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/lib/src/web_helpers/web_helpers.dart index 9e40e562bc9a..813f5f975561 100644 --- a/packages/cross_file/lib/src/web_helpers/web_helpers.dart +++ b/packages/cross_file/lib/src/web_helpers/web_helpers.dart @@ -1,3 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:html'; /// Create anchor element with download attribute From 02e7df19daba1b93c85a2853851eff9268118d47 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 12 Nov 2020 13:38:55 +0100 Subject: [PATCH 10/13] Renamed class implementation back to XFile --- packages/cross_file/lib/src/types/base.dart | 4 ++-- packages/cross_file/lib/src/types/html.dart | 6 +++--- packages/cross_file/lib/src/types/interface.dart | 6 +++--- packages/cross_file/lib/src/types/io.dart | 6 +++--- .../lib/src/{cross_file.dart => x_file.dart} | 0 .../cross_file/lib/{cross_file.dart => x_file.dart} | 2 +- ...oss_file_html_test.dart => x_file_html_test.dart} | 12 ++++++------ .../{cross_file_io_test.dart => x_file_io_test.dart} | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) rename packages/cross_file/lib/src/{cross_file.dart => x_file.dart} (100%) rename packages/cross_file/lib/{cross_file.dart => x_file.dart} (84%) rename packages/cross_file/test/{cross_file_html_test.dart => x_file_html_test.dart} (90%) rename packages/cross_file/test/{cross_file_io_test.dart => x_file_io_test.dart} (95%) diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart index 567027d316f5..6dc2d51b08b1 100644 --- a/packages/cross_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -13,9 +13,9 @@ import 'dart:typed_data'; /// /// This class is a very limited subset of dart:io [File], so all /// the methods should seem familiar. -abstract class CrossFileBase { +abstract class XFileBase { /// Construct a CrossFile - CrossFileBase(String path); + XFileBase(String path); /// Save the CrossFile at the indicated file path. void saveTo(String path) async { diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart index 2dece11637bc..269f2a8d9412 100644 --- a/packages/cross_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -15,7 +15,7 @@ import './base.dart'; /// A CrossFile that works on web. /// /// It wraps the bytes of a selected file. -class CrossFile extends CrossFileBase { +class XFile extends XFileBase { String path; final String mimeType; @@ -36,7 +36,7 @@ class CrossFile extends CrossFileBase { /// /// `name` needs to be passed from the outside, since we only have /// access to it while we create the ObjectUrl. - CrossFile( + XFile( this.path, { this.mimeType, this.name, @@ -51,7 +51,7 @@ class CrossFile extends CrossFileBase { super(path); /// Construct an CrossFile from its data - CrossFile.fromData( + XFile.fromData( Uint8List bytes, { this.mimeType, this.name, diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart index fa9036c0b7cc..e30bc63b4c92 100644 --- a/packages/cross_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -10,7 +10,7 @@ import './base.dart'; /// A CrossFile is a cross-platform, simplified File abstraction. /// /// It wraps the bytes of a selected file, and its (platform-dependant) path. -class CrossFile extends CrossFileBase { +class XFile extends XFileBase { /// Construct a CrossFile object from its path. /// /// Optionally, this can be initialized with `bytes` and `length` @@ -19,7 +19,7 @@ class CrossFile extends CrossFileBase { /// `name` may be passed from the outside, for those cases where the effective /// `path` of the file doesn't match what the user sees when selecting it /// (like in web) - CrossFile( + XFile( String path, { String mimeType, String name, @@ -33,7 +33,7 @@ class CrossFile extends CrossFileBase { } /// Construct a CrossFile object from its data - CrossFile.fromData( + XFile.fromData( Uint8List bytes, { String mimeType, String name, diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart index b6554b153730..81b8cdd84d67 100644 --- a/packages/cross_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -9,7 +9,7 @@ import 'dart:typed_data'; import './base.dart'; /// A CrossFile backed by a dart:io File. -class CrossFile extends CrossFileBase { +class XFile extends XFileBase { final File _file; final String mimeType; final DateTime _lastModified; @@ -18,7 +18,7 @@ class CrossFile extends CrossFileBase { final Uint8List _bytes; /// Construct a CrossFile object backed by a dart:io File. - CrossFile( + XFile( String path, { this.mimeType, String name, @@ -31,7 +31,7 @@ class CrossFile extends CrossFileBase { super(path); /// Construct an CrossFile from its data - CrossFile.fromData( + XFile.fromData( Uint8List bytes, { this.mimeType, String path, diff --git a/packages/cross_file/lib/src/cross_file.dart b/packages/cross_file/lib/src/x_file.dart similarity index 100% rename from packages/cross_file/lib/src/cross_file.dart rename to packages/cross_file/lib/src/x_file.dart diff --git a/packages/cross_file/lib/cross_file.dart b/packages/cross_file/lib/x_file.dart similarity index 84% rename from packages/cross_file/lib/cross_file.dart rename to packages/cross_file/lib/x_file.dart index fbeba0bf3914..a3e2873e670d 100644 --- a/packages/cross_file/lib/cross_file.dart +++ b/packages/cross_file/lib/x_file.dart @@ -2,4 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -export 'src/cross_file.dart'; +export 'src/x_file.dart'; diff --git a/packages/cross_file/test/cross_file_html_test.dart b/packages/cross_file/test/x_file_html_test.dart similarity index 90% rename from packages/cross_file/test/cross_file_html_test.dart rename to packages/cross_file/test/x_file_html_test.dart index 8aef9f62d3d3..bb4c77e6b851 100644 --- a/packages/cross_file/test/cross_file_html_test.dart +++ b/packages/cross_file/test/x_file_html_test.dart @@ -9,7 +9,7 @@ import 'dart:html' as html; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file/cross_file.dart'; +import 'package:cross_file/x_file.dart'; import 'dart:html'; @@ -20,7 +20,7 @@ final String textFileUrl = html.Url.createObjectUrl(textFile); void main() { group('Create with an objectUrl', () { - final file = CrossFile(textFileUrl); + final file = XFile(textFileUrl); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -39,7 +39,7 @@ void main() { }); group('Create from data', () { - final file = CrossFile.fromData(bytes); + final file = XFile.fromData(bytes); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -62,7 +62,7 @@ void main() { group('CrossFile saveTo(..)', () { test('creates a DOM container', () async { - CrossFile file = CrossFile.fromData(bytes); + XFile file = XFile.fromData(bytes); await file.saveTo(''); @@ -72,7 +72,7 @@ void main() { }); test('create anchor element', () async { - CrossFile file = CrossFile.fromData(bytes, name: textFile.name); + XFile file = XFile.fromData(bytes, name: textFile.name); await file.saveTo('path'); @@ -93,7 +93,7 @@ void main() { createAnchorElement: (_, __) => mockAnchor, ); - CrossFile file = CrossFile.fromData(bytes, + XFile file = XFile.fromData(bytes, name: textFile.name, overrides: overrides); bool clicked = false; diff --git a/packages/cross_file/test/cross_file_io_test.dart b/packages/cross_file/test/x_file_io_test.dart similarity index 95% rename from packages/cross_file/test/cross_file_io_test.dart rename to packages/cross_file/test/x_file_io_test.dart index b5ff873b302c..86ac08d24443 100644 --- a/packages/cross_file/test/cross_file_io_test.dart +++ b/packages/cross_file/test/x_file_io_test.dart @@ -9,7 +9,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file/cross_file.dart'; +import 'package:cross_file/x_file.dart'; // Please note that executing this test with command // `flutter test test/x_file_io_test.dart` will set the directory @@ -30,7 +30,7 @@ final String textFilePath = textFile.path; void main() { group('Create with a path', () { - final file = CrossFile(textFilePath); + final file = XFile(textFilePath); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); @@ -64,7 +64,7 @@ void main() { }); group('Create with data', () { - final file = CrossFile.fromData(bytes); + final file = XFile.fromData(bytes); test('Can be read as a string', () async { expect(await file.readAsString(), equals(expectedStringContents)); From f6ab8122781e2ff8754bc56fa5d4ed8ad85279df Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 12 Nov 2020 20:04:43 +0100 Subject: [PATCH 11/13] Fix formatting issues --- packages/cross_file/test/x_file_html_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/test/x_file_html_test.dart b/packages/cross_file/test/x_file_html_test.dart index bb4c77e6b851..a38d8ca8383d 100644 --- a/packages/cross_file/test/x_file_html_test.dart +++ b/packages/cross_file/test/x_file_html_test.dart @@ -93,8 +93,8 @@ void main() { createAnchorElement: (_, __) => mockAnchor, ); - XFile file = XFile.fromData(bytes, - name: textFile.name, overrides: overrides); + XFile file = + XFile.fromData(bytes, name: textFile.name, overrides: overrides); bool clicked = false; mockAnchor.onClick.listen((event) => clicked = true); From eadc0b019733de41cf1659219e0cb2a5f747908b Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 12 Nov 2020 21:22:23 +0100 Subject: [PATCH 12/13] Rename to cross_file --- packages/cross_file/lib/{x_file.dart => cross_file.dart} | 0 packages/cross_file/test/x_file_html_test.dart | 2 +- packages/cross_file/test/x_file_io_test.dart | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/cross_file/lib/{x_file.dart => cross_file.dart} (100%) diff --git a/packages/cross_file/lib/x_file.dart b/packages/cross_file/lib/cross_file.dart similarity index 100% rename from packages/cross_file/lib/x_file.dart rename to packages/cross_file/lib/cross_file.dart diff --git a/packages/cross_file/test/x_file_html_test.dart b/packages/cross_file/test/x_file_html_test.dart index a38d8ca8383d..fadba96b3c6c 100644 --- a/packages/cross_file/test/x_file_html_test.dart +++ b/packages/cross_file/test/x_file_html_test.dart @@ -9,7 +9,7 @@ import 'dart:html' as html; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file/x_file.dart'; +import 'package:cross_file/cross_file.dart'; import 'dart:html'; diff --git a/packages/cross_file/test/x_file_io_test.dart b/packages/cross_file/test/x_file_io_test.dart index 86ac08d24443..65edea1ea45d 100644 --- a/packages/cross_file/test/x_file_io_test.dart +++ b/packages/cross_file/test/x_file_io_test.dart @@ -9,7 +9,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file/x_file.dart'; +import 'package:cross_file/cross_file.dart'; // Please note that executing this test with command // `flutter test test/x_file_io_test.dart` will set the directory From 481867cb86188c6fdbf76e803f4affd083774d40 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Wed, 18 Nov 2020 07:30:58 +0100 Subject: [PATCH 13/13] Added code owners for cross_file package --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 160c0d5a3d10..5f6d83c209ac 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -9,6 +9,7 @@ packages/android_intent/** @mklim @matthew-carroll packages/battery/** @amirh @matthew-carroll packages/camera/** @bparrishMines packages/connectivity/** @cyanglaz @matthew-carroll +packages/cross_file/** @ditman @mvanbeusekom packages/device_info/** @matthew-carroll packages/espresso/** @collinjackson @adazh packages/file_selector/** @ditman