Skip to content

Commit

Permalink
[cross_file] Migrate to null-safety. (flutter#3452)
Browse files Browse the repository at this point in the history
Also: skip some packages from the all_plugins app so CI passes.
  • Loading branch information
ditman authored Jan 26, 2021
1 parent ced7fd6 commit ca99211
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 95 deletions.
12 changes: 9 additions & 3 deletions packages/cross_file/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
## 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<DateTime>` return type (and not `null`)

## 0.2.1

* Prepare for breaking `package:http` change.
* Prepare for breaking `package:http` change.

## 0.2.0

Expand All @@ -12,8 +18,8 @@

## 0.1.0+1

- Update Flutter SDK constraint.
* Update Flutter SDK constraint.

## 0.1.0

- Initial open-source release
* Initial open-source release.
10 changes: 5 additions & 5 deletions packages/cross_file/lib/src/types/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> saveTo(String path) {
Expand All @@ -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.');
}

Expand Down Expand Up @@ -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<Uint8List> openRead([int start, int end]) {
Stream<Uint8List> openRead([int? start, int? end]) {
throw UnimplementedError('openRead() has not been implemented.');
}

Expand Down
79 changes: 39 additions & 40 deletions packages/cross_file/lib/src/types/html.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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';
Expand All @@ -16,16 +15,17 @@ import '../web_helpers/web_helpers.dart';
///
/// It wraps the bytes of a selected file.
class XFile extends XFileBase {
String path;
late 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;
Element _target;
final DateTime? _lastModified;

final CrossFileTestOverrides _overrides;
late Element _target;

final CrossFileTestOverrides? _overrides;

bool get _hasTestOverrides => _overrides != null;

Expand All @@ -39,69 +39,69 @@ class XFile extends XFileBase {
XFile(
this.path, {
this.mimeType,
this.name,
int length,
Uint8List bytes,
DateTime lastModified,
@visibleForTesting CrossFileTestOverrides overrides,
String? name,
int? length,
Uint8List? bytes,
DateTime? lastModified,
@visibleForTesting CrossFileTestOverrides? overrides,
}) : _data = bytes,
_length = length,
_overrides = overrides,
_lastModified = lastModified,
_lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0),
name = name ?? '',
super(path);

/// Construct an CrossFile from its data
XFile.fromData(
Uint8List bytes, {
this.mimeType,
this.name,
int length,
DateTime lastModified,
this.path,
@visibleForTesting CrossFileTestOverrides overrides,
String? name,
int? length,
DateTime? lastModified,
String? path,
@visibleForTesting CrossFileTestOverrides? overrides,
}) : _data = bytes,
_length = length,
_overrides = overrides,
_lastModified = lastModified,
_lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0),
name = name ?? '',
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<DateTime> lastModified() async {
if (_lastModified != null) {
return Future.value(_lastModified);
}
return null;
}
Future<DateTime> lastModified() async => Future.value(_lastModified);

Future<Uint8List> get _bytes async {
if (_data != null) {
return Future.value(UnmodifiableUint8ListView(_data));
return Future.value(UnmodifiableUint8ListView(_data!));
}
return http.readBytes(Uri.parse(path));

// 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);
}

@override
Future<int> length() async {
return _length ?? (await _bytes).length;
}
Future<int> length() async => _length ?? (await _bytes).length;

@override
Future<String> readAsString({Encoding encoding = utf8}) async {
return encoding.decode(await _bytes);
}

@override
Future<Uint8List> readAsBytes() async {
return Future.value(await _bytes);
}
Future<Uint8List> readAsBytes() async => Future.value(await _bytes);

@override
Stream<Uint8List> openRead([int start, int end]) async* {
Stream<Uint8List> openRead([int? start, int? end]) async* {
final bytes = await _bytes;
yield bytes.sublist(start ?? 0, end ?? bytes.length);
}
Expand All @@ -114,10 +114,9 @@ class XFile extends XFileBase {

// Create an <a> tag with the appropriate download attributes and click it
// May be overridden with CrossFileTestOverrides
final AnchorElement element =
(_hasTestOverrides && _overrides.createAnchorElement != null)
? _overrides.createAnchorElement(this.path, this.name)
: createAnchorElement(this.path, this.name);
final AnchorElement element = _hasTestOverrides
? _overrides!.createAnchorElement(this.path, this.name) as AnchorElement
: createAnchorElement(this.path, this.name);

// Clear the children in our container so we can add an element to click
_target.children.clear();
Expand All @@ -132,5 +131,5 @@ class CrossFileTestOverrides {
Element Function(String href, String suggestedName) createAnchorElement;

/// Default constructor for overrides
CrossFileTestOverrides({this.createAnchorElement});
CrossFileTestOverrides({required this.createAnchorElement});
}
26 changes: 13 additions & 13 deletions packages/cross_file/lib/src/types/interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
Expand All @@ -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.');
Expand All @@ -54,5 +54,5 @@ class CrossFileTestOverrides {
dynamic Function(String href, String suggestedName) createAnchorElement;

/// Default constructor for overrides
CrossFileTestOverrides({this.createAnchorElement});
CrossFileTestOverrides({required this.createAnchorElement});
}
32 changes: 16 additions & 16 deletions packages/cross_file/lib/src/types/io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -84,7 +84,7 @@ class XFile extends XFileBase {
@override
Future<String> readAsString({Encoding encoding = utf8}) {
if (_bytes != null) {
return Future.value(String.fromCharCodes(_bytes));
return Future.value(String.fromCharCodes(_bytes!));
}
return _file.readAsString(encoding: encoding);
}
Expand All @@ -97,13 +97,13 @@ class XFile extends XFileBase {
return _file.readAsBytes();
}

Stream<Uint8List> _getBytes(int start, int end) async* {
final bytes = _bytes;
Stream<Uint8List> _getBytes(int? start, int? end) async* {
final bytes = _bytes!;
yield bytes.sublist(start ?? 0, end ?? bytes.length);
}

@override
Stream<Uint8List> openRead([int start, int end]) {
Stream<Uint8List> openRead([int? start, int? end]) {
if (_bytes != null) {
return _getBytes(start, end);
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/cross_file/lib/src/web_helpers/web_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 4 additions & 5 deletions packages/cross_file/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
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.2.1
version: 0.3.0-nullsafety

dependencies:
flutter:
sdk: flutter
http: ^0.12.0+1
meta: ^1.0.5
meta: ^1.3.0-nullsafety.3

dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.3

environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.22.0"
Loading

0 comments on commit ca99211

Please sign in to comment.