From 4aacf970f3891c9cf23c768ca1c8bec04c42b35a Mon Sep 17 00:00:00 2001 From: David Iglesias Date: Tue, 26 Jan 2021 17:33:26 -0800 Subject: [PATCH] Revert "[cross_file] Migrate to null-safety. (#3452)" (#3468) This reverts commit ca9921196a7ae96edad91a9cd7b7d8fe9f5689ff. --- packages/cross_file/CHANGELOG.md | 12 +-- packages/cross_file/lib/src/types/base.dart | 10 +-- packages/cross_file/lib/src/types/html.dart | 79 ++++++++++--------- .../cross_file/lib/src/types/interface.dart | 26 +++--- packages/cross_file/lib/src/types/io.dart | 32 ++++---- .../lib/src/web_helpers/web_helpers.dart | 2 +- packages/cross_file/pubspec.yaml | 9 ++- .../cross_file/test/x_file_html_test.dart | 18 +++-- packages/cross_file/test/x_file_io_test.dart | 2 +- script/build_all_plugins_app.sh | 3 +- script/nnbd_plugins.sh | 1 - 11 files changed, 95 insertions(+), 99 deletions(-) diff --git a/packages/cross_file/CHANGELOG.md b/packages/cross_file/CHANGELOG.md index c9b3d1ab2522..45f516ad334d 100644 --- a/packages/cross_file/CHANGELOG.md +++ b/packages/cross_file/CHANGELOG.md @@ -1,12 +1,6 @@ -## 0.3.0-nullsafety - -* Migrated package to null-safety. -* **breaking change** According to our unit tests, the API should be backwards-compatible. Some relevant changes were made, however: - * Web: `lastModified` returns the epoch time as a default value, to maintain the `Future` return type (and not `null`) - ## 0.2.1 -* Prepare for breaking `package:http` change. +* Prepare for breaking `package:http` change. ## 0.2.0 @@ -18,8 +12,8 @@ ## 0.1.0+1 -* Update Flutter SDK constraint. +- Update Flutter SDK constraint. ## 0.1.0 -* Initial open-source release. +- Initial open-source release diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/lib/src/types/base.dart index 2a59c1c2b246..1a1b5694d58f 100644 --- a/packages/cross_file/lib/src/types/base.dart +++ b/packages/cross_file/lib/src/types/base.dart @@ -15,7 +15,7 @@ import 'dart:typed_data'; /// the methods should seem familiar. abstract class XFileBase { /// Construct a CrossFile - XFileBase(String? path); + XFileBase(String path); /// Save the CrossFile at the indicated file path. Future saveTo(String path) { @@ -31,19 +31,19 @@ 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 CrossFile instance instead. - String? get path { + 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 { + 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 { + String get mimeType { throw UnimplementedError('.mimeType has not been implemented.'); } @@ -75,7 +75,7 @@ abstract class XFileBase { /// 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]) { + Stream openRead([int start, int end]) { throw UnimplementedError('openRead() has not been implemented.'); } diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart index 203ab5d82e12..527d5e6911f6 100644 --- a/packages/cross_file/lib/src/types/html.dart +++ b/packages/cross_file/lib/src/types/html.dart @@ -6,6 +6,7 @@ import 'dart:convert'; import 'dart:html'; import 'dart:typed_data'; +import 'package:http/http.dart' as http show readBytes; import 'package:meta/meta.dart'; import './base.dart'; @@ -15,17 +16,16 @@ import '../web_helpers/web_helpers.dart'; /// /// It wraps the bytes of a selected file. class XFile extends XFileBase { - late String path; + String path; - final String? mimeType; - final Uint8List? _data; - final int? _length; + final String mimeType; + final Uint8List _data; + final int _length; final String name; - final DateTime? _lastModified; + final DateTime _lastModified; + Element _target; - late Element _target; - - final CrossFileTestOverrides? _overrides; + final CrossFileTestOverrides _overrides; bool get _hasTestOverrides => _overrides != null; @@ -39,58 +39,56 @@ class XFile extends XFileBase { XFile( this.path, { this.mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - @visibleForTesting CrossFileTestOverrides? overrides, + this.name, + int length, + Uint8List bytes, + DateTime lastModified, + @visibleForTesting CrossFileTestOverrides overrides, }) : _data = bytes, _length = length, _overrides = overrides, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - name = name ?? '', + _lastModified = lastModified, super(path); /// Construct an CrossFile from its data XFile.fromData( Uint8List bytes, { this.mimeType, - String? name, - int? length, - DateTime? lastModified, - String? path, - @visibleForTesting CrossFileTestOverrides? overrides, + this.name, + int length, + DateTime lastModified, + this.path, + @visibleForTesting CrossFileTestOverrides overrides, }) : _data = bytes, _length = length, _overrides = overrides, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - name = name ?? '', + _lastModified = lastModified, super(path) { if (path == null) { final blob = (mimeType == null) ? Blob([bytes]) : Blob([bytes], mimeType); this.path = Url.createObjectUrl(blob); - } else { - this.path = path; } } @override - Future lastModified() async => Future.value(_lastModified); + 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 Future.value(UnmodifiableUint8ListView(_data)); } - - // We can force 'response' to be a byte buffer by passing responseType: - ByteBuffer? response = - (await HttpRequest.request(path, responseType: 'arraybuffer')).response; - - return response?.asUint8List() ?? Uint8List(0); + return http.readBytes(Uri.parse(path)); } @override - Future length() async => _length ?? (await _bytes).length; + Future length() async { + return _length ?? (await _bytes).length; + } @override Future readAsString({Encoding encoding = utf8}) async { @@ -98,10 +96,12 @@ class XFile extends XFileBase { } @override - Future readAsBytes() async => Future.value(await _bytes); + Future readAsBytes() async { + return Future.value(await _bytes); + } @override - Stream openRead([int? start, int? end]) async* { + Stream openRead([int start, int end]) async* { final bytes = await _bytes; yield bytes.sublist(start ?? 0, end ?? bytes.length); } @@ -114,9 +114,10 @@ class XFile extends XFileBase { // Create an tag with the appropriate download attributes and click it // May be overridden with CrossFileTestOverrides - final AnchorElement element = _hasTestOverrides - ? _overrides!.createAnchorElement(this.path, this.name) as AnchorElement - : createAnchorElement(this.path, this.name); + 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(); @@ -131,5 +132,5 @@ class CrossFileTestOverrides { Element Function(String href, String suggestedName) createAnchorElement; /// Default constructor for overrides - CrossFileTestOverrides({required this.createAnchorElement}); + CrossFileTestOverrides({this.createAnchorElement}); } diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/lib/src/types/interface.dart index 122f3d1d9364..e30bc63b4c92 100644 --- a/packages/cross_file/lib/src/types/interface.dart +++ b/packages/cross_file/lib/src/types/interface.dart @@ -21,12 +21,12 @@ class XFile extends XFileBase { /// (like in web) XFile( String path, { - String? mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - @visibleForTesting CrossFileTestOverrides? overrides, + String mimeType, + String name, + int length, + Uint8List bytes, + DateTime lastModified, + @visibleForTesting CrossFileTestOverrides overrides, }) : super(path) { throw UnimplementedError( 'CrossFile is not available in your current platform.'); @@ -35,12 +35,12 @@ class XFile extends XFileBase { /// Construct a CrossFile object from its data XFile.fromData( Uint8List bytes, { - String? mimeType, - String? name, - int? length, - DateTime? lastModified, - String? path, - @visibleForTesting CrossFileTestOverrides? overrides, + String mimeType, + String name, + int length, + DateTime lastModified, + String path, + @visibleForTesting CrossFileTestOverrides overrides, }) : super(path) { throw UnimplementedError( 'CrossFile is not available in your current platform.'); @@ -54,5 +54,5 @@ class CrossFileTestOverrides { dynamic Function(String href, String suggestedName) createAnchorElement; /// Default constructor for overrides - CrossFileTestOverrides({required this.createAnchorElement}); + CrossFileTestOverrides({this.createAnchorElement}); } diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/lib/src/types/io.dart index 6eafaf0ce0cc..d9a93559b507 100644 --- a/packages/cross_file/lib/src/types/io.dart +++ b/packages/cross_file/lib/src/types/io.dart @@ -11,20 +11,20 @@ import './base.dart'; /// A CrossFile backed by a dart:io File. class XFile extends XFileBase { final File _file; - final String? mimeType; - final DateTime? _lastModified; - int? _length; + final String mimeType; + final DateTime _lastModified; + int _length; - final Uint8List? _bytes; + final Uint8List _bytes; /// Construct a CrossFile object backed by a dart:io File. XFile( String path, { this.mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, + String name, + int length, + Uint8List bytes, + DateTime lastModified, }) : _file = File(path), _bytes = null, _lastModified = lastModified, @@ -34,10 +34,10 @@ class XFile extends XFileBase { XFile.fromData( Uint8List bytes, { this.mimeType, - String? path, - String? name, - int? length, - DateTime? lastModified, + String path, + String name, + int length, + DateTime lastModified, }) : _bytes = bytes, _file = File(path ?? ''), _length = length, @@ -84,7 +84,7 @@ class XFile extends XFileBase { @override Future readAsString({Encoding encoding = utf8}) { if (_bytes != null) { - return Future.value(String.fromCharCodes(_bytes!)); + return Future.value(String.fromCharCodes(_bytes)); } return _file.readAsString(encoding: encoding); } @@ -97,13 +97,13 @@ class XFile extends XFileBase { return _file.readAsBytes(); } - Stream _getBytes(int? start, int? end) async* { - final bytes = _bytes!; + 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]) { + Stream openRead([int start, int end]) { if (_bytes != null) { return _getBytes(start, end); } else { 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 a963e9933f99..813f5f975561 100644 --- a/packages/cross_file/lib/src/web_helpers/web_helpers.dart +++ b/packages/cross_file/lib/src/web_helpers/web_helpers.dart @@ -31,7 +31,7 @@ Element ensureInitialized(String id) { if (target == null) { final Element targetElement = Element.tag('flt-x-file')..id = id; - querySelector('body')!.children.add(targetElement); + querySelector('body').children.add(targetElement); target = targetElement; } return target; diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/pubspec.yaml index af1b7e7d4c0f..2228674baf40 100644 --- a/packages/cross_file/pubspec.yaml +++ b/packages/cross_file/pubspec.yaml @@ -1,18 +1,19 @@ name: cross_file description: An abstraction to allow working with files across multiple platforms. homepage: https://github.com/flutter/plugins/tree/master/packages/cross_file -version: 0.3.0-nullsafety +version: 0.2.1 dependencies: flutter: sdk: flutter - meta: ^1.3.0-nullsafety.3 + http: ^0.12.0+1 + meta: ^1.0.5 dev_dependencies: flutter_test: sdk: flutter - pedantic: ^1.10.0-nullsafety.3 + pedantic: ^1.8.0 environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.1.0 <3.0.0" flutter: ">=1.22.0" diff --git a/packages/cross_file/test/x_file_html_test.dart b/packages/cross_file/test/x_file_html_test.dart index a271aa1f1525..fadba96b3c6c 100644 --- a/packages/cross_file/test/x_file_html_test.dart +++ b/packages/cross_file/test/x_file_html_test.dart @@ -11,8 +11,10 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:cross_file/cross_file.dart'; +import 'dart:html'; + final String expectedStringContents = 'Hello, world!'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); +final Uint8List bytes = utf8.encode(expectedStringContents); final html.File textFile = html.File([bytes], 'hello.txt'); final String textFileUrl = html.Url.createObjectUrl(textFile); @@ -64,7 +66,7 @@ void main() { await file.saveTo(''); - final container = html.querySelector('#${CrossFileDomElementId}'); + final container = querySelector('#${CrossFileDomElementId}'); expect(container, isNotNull); }); @@ -74,18 +76,18 @@ void main() { await file.saveTo('path'); - final container = html.querySelector('#${CrossFileDomElementId}'); - final html.AnchorElement element = - container?.children.firstWhere((element) => element.tagName == 'A') - as html.AnchorElement; + final container = querySelector('#${CrossFileDomElementId}'); + final AnchorElement element = container?.children?.firstWhere( + (element) => element.tagName == 'A', + orElse: () => null); - // if element is not found, the `firstWhere` call will throw StateError. + expect(element, isNotNull); expect(element.href, file.path); expect(element.download, file.name); }); test('anchor element is clicked', () async { - final mockAnchor = html.AnchorElement(); + final mockAnchor = AnchorElement(); CrossFileTestOverrides overrides = CrossFileTestOverrides( createAnchorElement: (_, __) => mockAnchor, diff --git a/packages/cross_file/test/x_file_io_test.dart b/packages/cross_file/test/x_file_io_test.dart index 94ac81c4cac4..d45ff599fec1 100644 --- a/packages/cross_file/test/x_file_io_test.dart +++ b/packages/cross_file/test/x_file_io_test.dart @@ -15,7 +15,7 @@ final pathPrefix = Directory.current.path.endsWith('test') ? './assets/' : './test/assets/'; final path = pathPrefix + 'hello.txt'; final String expectedStringContents = 'Hello, world!'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); +final Uint8List bytes = utf8.encode(expectedStringContents); final File textFile = File(path); final String textFilePath = textFile.path; diff --git a/script/build_all_plugins_app.sh b/script/build_all_plugins_app.sh index 3e08b914ff86..72390c213da9 100755 --- a/script/build_all_plugins_app.sh +++ b/script/build_all_plugins_app.sh @@ -23,15 +23,14 @@ readonly EXCLUDED_PLUGINS_LIST=( "connectivity_platform_interface" "connectivity_web" "extension_google_sign_in_as_googleapis_auth" - "file_selector" # currently out of sync with camera "flutter_plugin_android_lifecycle" "google_maps_flutter_platform_interface" "google_maps_flutter_web" "google_sign_in_platform_interface" "google_sign_in_web" "image_picker_platform_interface" - "instrumentation_adapter" "local_auth" # flutter_plugin_android_lifecycle conflict + "instrumentation_adapter" "path_provider_linux" "path_provider_macos" "path_provider_platform_interface" diff --git a/script/nnbd_plugins.sh b/script/nnbd_plugins.sh index 44e5df9e95ef..b2ca25bf6836 100644 --- a/script/nnbd_plugins.sh +++ b/script/nnbd_plugins.sh @@ -8,7 +8,6 @@ readonly NNBD_PLUGINS_LIST=( "android_intent" "battery" "connectivity" - "cross_file" "device_info" "flutter_plugin_android_lifecycle" "flutter_webview"