[file_selector_web] migrate to pkg:web (#5413)

This allows this package to be used in a web app compiled to Wasm.

Helps unblock https://github.com/flutter/devtools/issues/6606
This commit is contained in:
Kevin Moore
2023-11-16 16:40:15 -08:00
committed by GitHub
parent 25574f996e
commit 42dbb7573a
8 changed files with 55 additions and 30 deletions

View File

@ -1,3 +1,7 @@
## 0.9.3
* Updates minimum supported SDK version to Dart 3.2.
## 0.9.2+1
* Adds pub topics to package metadata.

View File

@ -2,23 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:html';
import 'dart:js_interop';
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:file_selector_web/src/dom_helper.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:web/helpers.dart';
void main() {
group('dom_helper', () {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
late DomHelper domHelper;
late FileUploadInputElement input;
late HTMLInputElement input;
FileList? createFileList(List<File> files) {
final DataTransfer dataTransfer = DataTransfer();
files.forEach(dataTransfer.items!.add);
return dataTransfer.files as FileList?;
for (final File e in files) {
// TODO(srujzs): This is necessary in order to support package:web 0.4.0.
// This was not needed with 0.3.0, hence the lint.
// ignore: unnecessary_cast
dataTransfer.items.add(e as JSAny);
}
return dataTransfer.files;
}
void setFilesAndTriggerEvent(List<File> files, Event event) {
@ -36,12 +42,13 @@ void main() {
setUp(() {
domHelper = DomHelper();
input = FileUploadInputElement();
input = (createElementTag('input') as HTMLInputElement)..type = 'file';
});
group('getFiles', () {
final File mockFile1 = File(<Object>['123456'], 'file1.txt');
final File mockFile2 = File(<Object>[], 'file2.txt');
final File mockFile1 =
File(<Object>['123456'].jsify as JSArray, 'file1.txt');
final File mockFile2 = File(<Object>[].jsify as JSArray, 'file2.txt');
testWidgets('works', (_) async {
final Future<List<XFile>> futureFiles = domHelper.getFiles(
@ -114,7 +121,7 @@ void main() {
input: input,
);
expect(input.matchesWithAncestors('body'), true);
expect(input.matches('body'), true);
expect(input.accept, accept);
expect(input.multiple, multiple);
expect(
@ -128,7 +135,7 @@ void main() {
await futureFile;
// It should be already removed from the DOM after the file is resolved.
expect(input.parent, isNull);
expect(input.parentElement, isNull);
});
});
});

View File

@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:html';
import 'dart:typed_data';
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
@ -10,6 +9,7 @@ import 'package:file_selector_web/file_selector_web.dart';
import 'package:file_selector_web/src/dom_helper.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:web/helpers.dart';
void main() {
group('FileSelectorWeb', () {
@ -121,7 +121,7 @@ class MockDomHelper implements DomHelper {
Future<List<XFile>> getFiles({
String accept = '',
bool multiple = false,
FileUploadInputElement? input,
HTMLInputElement? input,
}) {
expect(accept, _expectedAccept,
reason: 'Expected "accept" value does not match.');

View File

@ -11,6 +11,7 @@ dependencies:
path: ../
flutter:
sdk: flutter
web: '>=0.3.0 <0.5.0'
dev_dependencies:
flutter_test:

View File

@ -3,41 +3,46 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:html';
import 'dart:js_interop';
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';
import 'package:web/helpers.dart';
/// Class to manipulate the DOM with the intention of reading files from it.
class DomHelper {
/// Default constructor, initializes the container DOM element.
DomHelper() {
final Element body = querySelector('body')!;
body.children.add(_container);
body.appendChild(_container);
}
final Element _container = Element.tag('file-selector');
final Element _container = createElementTag('file-selector');
/// Sets the <input /> attributes and waits for a file to be selected.
Future<List<XFile>> getFiles({
String accept = '',
bool multiple = false,
@visibleForTesting FileUploadInputElement? input,
@visibleForTesting HTMLInputElement? input,
}) {
final Completer<List<XFile>> completer = Completer<List<XFile>>();
final FileUploadInputElement inputElement =
input ?? FileUploadInputElement();
final HTMLInputElement inputElement =
input ?? (createElementTag('input') as HTMLInputElement)
..type = 'file';
_container.children.add(
_container.appendChild(
inputElement
..accept = accept
..multiple = multiple,
);
inputElement.onChange.first.then((_) {
final List<XFile> files =
inputElement.files!.map(_convertFileToXFile).toList();
final List<XFile> files = Iterable<File>.generate(
inputElement.files!.length,
(int i) => inputElement.files!.item(i)!)
.map(_convertFileToXFile)
.toList();
inputElement.remove();
completer.complete(files);
});
@ -52,10 +57,13 @@ class DomHelper {
completer.completeError(platformException);
});
inputElement.addEventListener('cancel', (Event event) {
inputElement.remove();
completer.complete(<XFile>[]);
});
inputElement.addEventListener(
'cancel',
(Event event) {
inputElement.remove();
completer.complete(<XFile>[]);
}.toJS,
);
// TODO(dit): Reimplement this with the showPicker() API, https://github.com/flutter/flutter/issues/130365
inputElement.click();
@ -64,10 +72,12 @@ class DomHelper {
}
XFile _convertFileToXFile(File file) => XFile(
Url.createObjectUrl(file),
// TODO(srujzs): This is necessary in order to support package:web 0.4.0.
// This was not needed with 0.3.0, hence the lint.
// ignore: unnecessary_cast
URL.createObjectURL(file as JSObject),
name: file.name,
length: file.size,
lastModified: DateTime.fromMillisecondsSinceEpoch(
file.lastModified ?? DateTime.now().millisecondsSinceEpoch),
lastModified: DateTime.fromMillisecondsSinceEpoch(file.lastModified),
);
}

View File

@ -2,11 +2,11 @@ name: file_selector_web
description: Web platform implementation of file_selector
repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector_web
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22
version: 0.9.2+1
version: 0.9.3
environment:
sdk: ">=2.19.0 <4.0.0"
flutter: ">=3.7.0"
sdk: ^3.2.0
flutter: ">=3.16.0"
flutter:
plugin:
@ -22,6 +22,7 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
web: '>=0.3.0 <0.5.0'
dev_dependencies:
flutter_test:

View File

@ -51,6 +51,7 @@
- test_api
- vm_service
- wasm
- web
- yaml
# Google-owned packages
- _discoveryapis_commons

View File

@ -68,6 +68,7 @@ final Map<Version, Version> _dartSdkForFlutterSdk = <Version, Version>{
Version(3, 10, 0): Version(3, 0, 0),
Version(3, 10, 6): Version(3, 0, 6),
Version(3, 13, 0): Version(3, 1, 0),
Version(3, 16, 0): Version(3, 2, 0),
};
/// Returns the version of the Dart SDK that shipped with the given Flutter