blob: c19748b92443714bfc7277ed31c529b2a64bf07f [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
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/web.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 = document.querySelector('body')!;
body.appendChild(_container);
}
final Element _container = document.createElement('file-selector');
/// Sets the <input /> attributes and waits for a file to be selected.
Future<List<XFile>> getFiles({
String accept = '',
bool multiple = false,
@visibleForTesting HTMLInputElement? input,
}) {
final Completer<List<XFile>> completer = Completer<List<XFile>>();
final HTMLInputElement inputElement =
input ?? (document.createElement('input') as HTMLInputElement)
..type = 'file';
_container.appendChild(
inputElement
..accept = accept
..multiple = multiple,
);
inputElement.onChange.first.then((_) {
final List<XFile> files = Iterable<File>.generate(
inputElement.files!.length,
(int i) => inputElement.files!.item(i)!)
.map(_convertFileToXFile)
.toList();
inputElement.remove();
completer.complete(files);
});
inputElement.onError.first.then((Event event) {
final ErrorEvent error = event as ErrorEvent;
final PlatformException platformException = PlatformException(
code: error.type,
message: error.message,
);
inputElement.remove();
completer.completeError(platformException);
});
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();
return completer.future;
}
XFile _convertFileToXFile(File file) => XFile(
URL.createObjectURL(file),
name: file.name,
length: file.size,
lastModified: DateTime.fromMillisecondsSinceEpoch(file.lastModified),
);
}