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

[image_picker] Migrate image_picker_web to null-safety #3535

Merged
merged 4 commits into from
Feb 12, 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
4 changes: 4 additions & 0 deletions packages/image_picker/image_picker_for_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 2.0.0-nullsafety

* Migrate to null safety.

# 0.1.0+3

* Update Flutter SDK constraint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ final String _kAcceptVideoMimeType = 'video/3gpp,video/x-m4v,video/mp4,video/*';
///
/// This class implements the `package:image_picker` functionality for the web.
class ImagePickerPlugin extends ImagePickerPlatform {
final ImagePickerPluginTestOverrides _overrides;
final ImagePickerPluginTestOverrides? _overrides;
bool get _hasOverrides => _overrides != null;

html.Element _target;
late html.Element _target;

/// A constructor that allows tests to override the function that creates file inputs.
ImagePickerPlugin({
@visibleForTesting ImagePickerPluginTestOverrides overrides,
@visibleForTesting ImagePickerPluginTestOverrides? overrides,
}) : _overrides = overrides {
_target = _ensureInitialized(_kImagePickerInputsDomId);
}
Expand All @@ -32,23 +32,23 @@ class ImagePickerPlugin extends ImagePickerPlatform {

@override
Future<PickedFile> pickImage({
@required ImageSource source,
double maxWidth,
double maxHeight,
int imageQuality,
required ImageSource source,
double? maxWidth,
double? maxHeight,
int? imageQuality,
CameraDevice preferredCameraDevice = CameraDevice.rear,
}) {
String capture = computeCaptureAttribute(source, preferredCameraDevice);
String? capture = computeCaptureAttribute(source, preferredCameraDevice);
return pickFile(accept: _kAcceptImageMimeType, capture: capture);
}

@override
Future<PickedFile> pickVideo({
@required ImageSource source,
required ImageSource source,
CameraDevice preferredCameraDevice = CameraDevice.rear,
Duration maxDuration,
Duration? maxDuration,
}) {
String capture = computeCaptureAttribute(source, preferredCameraDevice);
String? capture = computeCaptureAttribute(source, preferredCameraDevice);
return pickFile(accept: _kAcceptVideoMimeType, capture: capture);
}

Expand All @@ -59,10 +59,11 @@ class ImagePickerPlugin extends ImagePickerPlatform {
/// See https://caniuse.com/#feat=html-media-capture
@visibleForTesting
Future<PickedFile> pickFile({
String accept,
String capture,
String? accept,
String? capture,
}) {
html.FileUploadInputElement input = createInputElement(accept, capture);
html.FileUploadInputElement input =
createInputElement(accept, capture) as html.FileUploadInputElement;
_injectAndActivate(input);
return _getSelectedFile(input);
}
Expand All @@ -73,25 +74,26 @@ class ImagePickerPlugin extends ImagePickerPlatform {
///
/// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture
@visibleForTesting
String computeCaptureAttribute(ImageSource source, CameraDevice device) {
String? computeCaptureAttribute(ImageSource source, CameraDevice device) {
if (source == ImageSource.camera) {
return (device == CameraDevice.front) ? 'user' : 'environment';
}
return null;
}

html.File _getFileFromInput(html.FileUploadInputElement input) {
html.File? _getFileFromInput(html.FileUploadInputElement input) {
if (_hasOverrides) {
return _overrides.getFileFromInput(input);
return _overrides!.getFileFromInput(input);
}
return input?.files?.first;
return input.files?.first;
}

/// Handles the OnChange event from a FileUploadInputElement object
/// Returns the objectURL of the selected file.
String _handleOnChangeEvent(html.Event event) {
final html.FileUploadInputElement input = event?.target;
final html.File file = _getFileFromInput(input);
String? _handleOnChangeEvent(html.Event event) {
final html.FileUploadInputElement input =
event.target as html.FileUploadInputElement;
final html.File? file = _getFileFromInput(input);

if (file != null) {
return html.Url.createObjectUrl(file);
Expand All @@ -105,7 +107,7 @@ class ImagePickerPlugin extends ImagePickerPlatform {
// Observe the input until we can return something
input.onChange.first.then((event) {
final objectUrl = _handleOnChangeEvent(event);
if (!_completer.isCompleted) {
if (!_completer.isCompleted && objectUrl != null) {
_completer.complete(PickedFile(objectUrl));
}
});
Expand All @@ -127,7 +129,7 @@ class ImagePickerPlugin extends ImagePickerPlatform {
final html.Element targetElement =
html.Element.tag('flt-image-picker-inputs')..id = id;

html.querySelector('body').children.add(targetElement);
html.querySelector('body')!.children.add(targetElement);
target = targetElement;
}
return target;
Expand All @@ -136,9 +138,9 @@ class ImagePickerPlugin extends ImagePickerPlatform {
/// Creates an input element that accepts certain file types, and
/// allows to `capture` from the device's cameras (where supported)
@visibleForTesting
html.Element createInputElement(String accept, String capture) {
html.Element createInputElement(String? accept, String? capture) {
if (_hasOverrides) {
return _overrides.createInputElement(accept, capture);
return _overrides!.createInputElement(accept, capture);
}

html.Element element = html.FileUploadInputElement()..accept = accept;
Expand All @@ -162,22 +164,22 @@ class ImagePickerPlugin extends ImagePickerPlatform {
/// A function that creates a file input with the passed in `accept` and `capture` attributes.
@visibleForTesting
typedef OverrideCreateInputFunction = html.Element Function(
String accept,
String capture,
String? accept,
String? capture,
);

/// A function that extracts a [html.File] from the file `input` passed in.
@visibleForTesting
typedef OverrideExtractFilesFromInputFunction = html.File Function(
html.Element input,
html.Element? input,
);

/// Overrides for some of the functionality above.
@visibleForTesting
class ImagePickerPluginTestOverrides {
/// Override the creation of the input element.
OverrideCreateInputFunction createInputElement;
late OverrideCreateInputFunction createInputElement;

/// Override the extraction of the selected file from an input element.
OverrideExtractFilesFromInputFunction getFileFromInput;
late OverrideExtractFilesFromInputFunction getFileFromInput;
}
16 changes: 7 additions & 9 deletions packages/image_picker/image_picker_for_web/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
name: image_picker_for_web
description: Web platform implementation of image_picker
homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker_for_web
# 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 0.1.0+3

version: 2.0.0-nullsafety

flutter:
plugin:
Expand All @@ -14,19 +12,19 @@ flutter:
fileName: image_picker_for_web.dart

dependencies:
image_picker_platform_interface: ^1.1.0
image_picker_platform_interface: ^2.0.0-nullsafety
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
meta: ^1.1.7
js: ^0.6.0
meta: ^1.3.0-nullsafety.6
js: ^0.6.3-nullsafety.3

dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0

environment:
sdk: ">=2.5.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.10.0"
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';

final String expectedStringContents = "Hello, world!";
final Uint8List bytes = utf8.encode(expectedStringContents);
final Uint8List bytes = utf8.encode(expectedStringContents) as Uint8List;
final html.File textFile = html.File([bytes], "hello.txt");

void main() {
// Under test...
ImagePickerPlugin plugin;
late ImagePickerPlugin plugin;

setUp(() {
plugin = ImagePickerPlugin();
Expand Down