pickFiles method

Future<FilePickerResult?> pickFiles({
  1. String? dialogTitle,
  2. String? initialDirectory,
  3. FileType type = FileType.any,
  4. List<String>? allowedExtensions,
  5. bool allowMultiple = false,
  6. dynamic onFileLoading(
    1. FilePickerStatus
    )?,
  7. bool allowCompression = true,
  8. bool withData = true,
  9. bool withReadStream = false,
  10. bool lockParentWindow = false,
})

Implementation

Future<FilePickerResult?> pickFiles({
  String? dialogTitle,
  String? initialDirectory,
  FileType type = FileType.any,
  List<String>? allowedExtensions,
  bool allowMultiple = false,
  Function(FilePickerStatus)? onFileLoading,
  bool allowCompression = true,
  bool withData = true,
  bool withReadStream = false,
  bool lockParentWindow = false,
}) async {
  if (type != FileType.custom && (allowedExtensions?.isNotEmpty ?? false)) {
    throw Exception(
        'You are setting a type [$type]. Custom extension filters are only allowed with FileType.custom, please change it or remove filters.');
  }

  final Completer<List<PlatformFile>?> filesCompleter =
      Completer<List<PlatformFile>?>();
  final Completer<List<File>?> filesCompleter2 = Completer<List<File>?>();

  String accept = _fileType(type, allowedExtensions);
  InputElement uploadInput = FileUploadInputElement() as InputElement;
  uploadInput.draggable = true;
  uploadInput.multiple = allowMultiple;
  uploadInput.accept = accept;

  bool changeEventTriggered = false;

  if (onFileLoading != null) {
    onFileLoading(FilePickerStatus.picking);
  }

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

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

    void addPickedFile(
      File file,
      Uint8List? bytes,
      String? path,
      Stream<List<int>>? readStream,
    ) {
      pickedFiles.add(PlatformFile(
        name: file.name,
        path: path,
        size: bytes != null ? bytes.length : file.size,
        bytes: bytes,
        readStream: readStream,
      ));

      if (pickedFiles.length >= files.length) {
        if (onFileLoading != null) {
          onFileLoading(FilePickerStatus.done);
        }
        filesCompleter.complete(pickedFiles);
        filesCompleter2.complete(files);
      }
    }

    for (File file in files) {
      if (withReadStream) {
        addPickedFile(file, null, null, _openFileReadStream(file));
        continue;
      }

      if (!withData) {
        final FileReader reader = FileReader();
        reader.onLoadEnd.listen((e) {
          addPickedFile(file, null, '', null);
        });
        reader.readAsDataUrl(file);
        continue;
      }

      final FileReader reader = FileReader();
      reader.onLoadEnd.listen((e) {
        addPickedFile(file, reader.result as Uint8List?, null, null);
      });
      reader.readAsArrayBuffer(file);
    }
  }

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

    // This listener is called before the input changed event,
    // and the `uploadInput.files` value is still null
    // Wait for results from js to dart
    Future.delayed(const Duration(milliseconds: 500)).then((value) {
      if (!changeEventTriggered) {
        changeEventTriggered = true;
        filesCompleter.complete(null);
        filesCompleter2.complete(null);
      }
    });
  }

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

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

  //Add input element to the page body
  _target.children.clear();
  _target.children.add(uploadInput);
  uploadInput.click();

  final List<PlatformFile>? files = await filesCompleter.future;
  final List<File>? files2 = await filesCompleter2.future;

  return files == null || files2 == null
      ? null
      : FilePickerResult(files, files2);
}