useFile function

FileHandler<PlatformFile> useFile(
  1. {required FileType fileType,
  2. List<String>? allowedExtensions}
)

Uses file_picker to pick a file and returns that file as PlatformFile. Loading, error and data states are handled through the AsyncSnapshot type.

Implementation

FileHandler<PlatformFile> useFile({
  required FileType fileType,
  List<String>? allowedExtensions,
}) {
  final filePickerResult = useState<FilePickerResult?>(null);
  final isLoading = useState<bool>(false);
  final error = useState<Object?>(null);
  final stackTrace = useState<StackTrace?>(null);
  final isMounted = useIsMounted();

  void clearError() {
    error.value = null;
    stackTrace.value = null;
  }

  final _error = error.value;
  final _stackTrace = stackTrace.value;

  Future<PlatformFile?> select() async {
    clearError();
    isLoading.value = true;

    try {
      final result = await FilePicker.platform.pickFiles(
        type: fileType,
        allowedExtensions: allowedExtensions,
        allowMultiple: false,
      );

      if (result != null && result.files.isNotEmpty && isMounted()) {
        filePickerResult.value = result;
        return result.files.single;
      } else {
        return null;
      }
    } catch (_error, _stackTrace) {
      error.value = _error;
      stackTrace.value = _stackTrace;
      rethrow;
    } finally {
      if (isMounted()) {
        isLoading.value = false;
      }
    }
  }

  final filePickerValue = filePickerResult.value;
  final AsyncSnapshot<PlatformFile> snapshot;

  if (isLoading.value) {
    snapshot = const AsyncSnapshot<PlatformFile>.waiting();
  } else if (filePickerValue != null) {
    snapshot = AsyncSnapshot<PlatformFile>.withData(
      ConnectionState.done,
      filePickerValue.files.single,
    );
  } else if (_error != null && _stackTrace != null) {
    snapshot = AsyncSnapshot<PlatformFile>.withError(
      ConnectionState.done,
      _error,
      _stackTrace,
    );
  } else {
    assert(_error == null && _stackTrace == null);
    snapshot = const AsyncSnapshot<PlatformFile>.nothing();
  }

  return FileHandler(
    select: select,
    snapshot: snapshot,
  );
}