mirror of
https://github.com/flutter/packages.git
synced 2025-07-01 23:51:55 +08:00
[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:
@ -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.
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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.');
|
||||
|
@ -11,6 +11,7 @@ dependencies:
|
||||
path: ../
|
||||
flutter:
|
||||
sdk: flutter
|
||||
web: '>=0.3.0 <0.5.0'
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -51,6 +51,7 @@
|
||||
- test_api
|
||||
- vm_service
|
||||
- wasm
|
||||
- web
|
||||
- yaml
|
||||
# Google-owned packages
|
||||
- _discoveryapis_commons
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user