Skip to content

Commit

Permalink
Merge pull request #1481 from amrgetment/master
Browse files Browse the repository at this point in the history
WASM support for Flutter web
  • Loading branch information
navaronbracke committed Apr 18, 2024
2 parents 04e32da + f63f787 commit 05af933
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 24 deletions.
8 changes: 3 additions & 5 deletions example/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@

<title>example</title>
<link rel="manifest" href="manifest.json">
<script src="flutter.js"></script>
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
{{flutter_build_config}}
_flutter.loader.load();
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
Expand Down
52 changes: 33 additions & 19 deletions lib/_internal/file_picker_web.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:html';
import 'dart:js_interop';
import 'package:web/web.dart';
import 'dart:typed_data';

import 'package:file_picker/file_picker.dart';
Expand All @@ -23,12 +24,13 @@ class FilePickerWeb extends FilePicker {

/// Initializes a DOM container where we can host input elements.
Element _ensureInitialized(String id) {
Element? target = querySelector('#$id');
Element? target = document.querySelector('#$id');
if (target == null) {
final Element targetElement = Element.tag('flt-file-picker-inputs')
..id = id;
final Element targetElement = document.createElement(
'flt-file-picker-inputs',
)..id = id;

querySelector('body')!.children.add(targetElement);
document.querySelector('body')!.children.add(targetElement);
target = targetElement;
}
return target;
Expand Down Expand Up @@ -58,7 +60,8 @@ class FilePickerWeb extends FilePicker {
Completer<List<PlatformFile>?>();

String accept = _fileType(type, allowedExtensions);
InputElement uploadInput = FileUploadInputElement() as InputElement;
HTMLInputElement uploadInput = HTMLInputElement();
uploadInput.type = 'file';
uploadInput.draggable = true;
uploadInput.multiple = allowMultiple;
uploadInput.accept = accept;
Expand All @@ -70,13 +73,13 @@ class FilePickerWeb extends FilePicker {
onFileLoading(FilePickerStatus.picking);
}

void changeEventListener(e) async {
void changeEventListener(Event e) async {
if (changeEventTriggered) {
return;
}
changeEventTriggered = true;

final List<File> files = uploadInput.files!;
final FileList files = uploadInput.files!;
final List<PlatformFile> pickedFiles = [];

void addPickedFile(
Expand All @@ -101,7 +104,12 @@ class FilePickerWeb extends FilePicker {
}
}

for (File file in files) {
for (int i = 0; i < files.length; i++) {
final File? file = files.item(i);
if (file == null) {
continue;
}

if (withReadStream) {
addPickedFile(file, null, null, _openFileReadStream(file));
continue;
Expand All @@ -110,16 +118,18 @@ class FilePickerWeb extends FilePicker {
if (!withData) {
final FileReader reader = FileReader();
reader.onLoadEnd.listen((e) {
addPickedFile(file, null, reader.result as String?, null);
String? result = (reader.result as JSString?)?.toDart;
addPickedFile(file, null, result, null);
});
reader.readAsDataUrl(file);
reader.readAsDataURL(file);
continue;
}

final syncCompleter = Completer<void>();
final FileReader reader = FileReader();
reader.onLoadEnd.listen((e) {
addPickedFile(file, reader.result as Uint8List?, null, null);
ByteBuffer? byteBuffer = (reader.result as JSArrayBuffer?)?.toDart;
addPickedFile(file, byteBuffer?.asUint8List(), null, null);
syncCompleter.complete();
});
reader.readAsArrayBuffer(file);
Expand All @@ -129,8 +139,8 @@ class FilePickerWeb extends FilePicker {
}
}

void cancelledEventListener(_) {
window.removeEventListener('focus', cancelledEventListener);
void cancelledEventListener(Event _) {
window.removeEventListener('focus', cancelledEventListener.toJS);

// This listener is called before the input changed event,
// and the `uploadInput.files` value is still null
Expand All @@ -144,14 +154,18 @@ class FilePickerWeb extends FilePicker {
}

uploadInput.onChange.listen(changeEventListener);
uploadInput.addEventListener('change', changeEventListener);
uploadInput.addEventListener('cancel', cancelledEventListener);
uploadInput.addEventListener('change', changeEventListener.toJS);
uploadInput.addEventListener('cancel', cancelledEventListener.toJS);

// Listen focus event for cancelled
window.addEventListener('focus', cancelledEventListener);
window.addEventListener('focus', cancelledEventListener.toJS);

//Add input element to the page body
_target.children.clear();
Node? firstChild = _target.firstChild;
while (firstChild != null) {
_target.removeChild(firstChild);
firstChild = _target.firstChild;
}
_target.children.add(uploadInput);
uploadInput.click();

Expand Down Expand Up @@ -193,7 +207,7 @@ class FilePickerWeb extends FilePicker {
: start + _readStreamChunkSize;
final blob = file.slice(start, end);
reader.readAsArrayBuffer(blob);
await reader.onLoad.first;
await EventStreamProviders.loadEvent.forTarget(reader).first;
yield reader.result as List<int>;
start += _readStreamChunkSize;
}
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:
path: ^1.8.2
win32: ^5.1.1
cross_file: ^0.3.3+7
web: ^0.5.1

dev_dependencies:
lints: ^3.0.0
Expand Down

0 comments on commit 05af933

Please sign in to comment.