Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[file_selector_web] migrate to pkg:web #5413

Merged
merged 25 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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/file_selector/file_selector_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.3

* Updates minimum supported SDK version to Dart 3.2.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Updates minimum supported SDK version to Dart 3.2.
* Migrates web implementation to `package:web` from `dart:html`.
* Updates minimum supported SDK version to Dart 3.2.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤷 – for the most part, this is not a user visible change so I omitted that bit.


## 0.9.2+1

* Adds pub topics to package metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand All @@ -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);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// 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';
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', () {
Expand Down Expand Up @@ -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.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies:
path: ../
flutter:
sdk: flutter
web: '>=0.3.0 <0.5.0'

dev_dependencies:
flutter_test:
Expand Down
42 changes: 26 additions & 16 deletions packages/file_selector/file_selector_web/lib/src/dom_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Copy link
Member

Choose a reason for hiding this comment

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

It'd be nice if this asserted that input.type == 'file', to retain some of the old type safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not worried about this, since it's text only

_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);
});
Expand All @@ -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();
Expand All @@ -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),
);
}
7 changes: 4 additions & 3 deletions packages/file_selector/file_selector_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -22,6 +22,7 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
web: '>=0.3.0 <0.5.0'

dev_dependencies:
flutter_test:
Expand Down
1 change: 1 addition & 0 deletions script/configs/allowed_unpinned_deps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
- test_api
- vm_service
- wasm
- web
- yaml
# Google-owned packages
- _discoveryapis_commons
Expand Down
1 change: 1 addition & 0 deletions script/tool/lib/src/common/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down