Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[cross_file] Migrate to null-safety. #3452

Merged
merged 9 commits into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No null-safe version of package:http yet published, so it had to go.

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);
ditman marked this conversation as resolved.
Show resolved Hide resolved
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