[client][web] WIP: Upload folders

This commit is contained in:
Abhishek Shroff
2026-01-16 18:38:56 +05:30
parent ee59e2476b
commit a578037b13
6 changed files with 85 additions and 10 deletions

View File

@@ -9,6 +9,10 @@ import 'package:phylum/ui/file_viewer/file_viewer_dialog.dart';
import 'package:phylum/util/upload_utils.dart';
import 'package:provider/provider.dart';
import 'package:phylum/util/pick_directory_stub.dart'
if (dart.library.js_interop) 'package:phylum/util/pick_directory_web.dart'
if (dart.library.ffi) 'package:phylum/util/pick_directory_vm.dart';
class AppActions extends StatelessWidget {
final Widget child;

View File

@@ -1,9 +1,10 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:phylum/ui/app/shortcuts.dart';
import 'package:phylum/util/pick_directory_stub.dart'
if (dart.library.js_interop) 'package:phylum/util/pick_directory_web.dart'
if (dart.library.ffi) 'package:phylum/util/pick_directory_vm.dart';
enum CreateAction {
newFolder(descripiton: 'New Folder', icon: Icon(Icons.create_new_folder), intent: NewFolderIntent()),
uploadFiles(descripiton: 'Upload File(s)', icon: Icon(Icons.upload_file_rounded), intent: UploadFilesIntent()),
@@ -18,7 +19,7 @@ enum CreateAction {
}
List<CreateAction?> getCreateActions(BuildContext context) {
if (kIsWeb || Platform.isAndroid) {
if (!folderUploadSupported) {
return const [
CreateAction.newFolder,
CreateAction.uploadFiles,

View File

@@ -0,0 +1,5 @@
import 'package:flutter/material.dart';
bool get folderUploadSupported => throw UnimplementedError();
Future<void> pickAndUploadDirectory(BuildContext context, String parent) => throw UnimplementedError();

View File

@@ -0,0 +1,13 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:phylum/util/upload_utils.dart';
bool get folderUploadSupported => !Platform.isAndroid;
Future<void> pickAndUploadDirectory(BuildContext context, String folderId) async {
final path = await FilePicker.platform.getDirectoryPath();
if (path == null || !context.mounted) return;
return uploadPath(context, folderId, [path]);
}

View File

@@ -0,0 +1,58 @@
import 'dart:js_interop';
import 'package:flutter/material.dart';
import 'package:web/web.dart' as web;
bool get folderUploadSupported => true;
@JS()
external JSPromise<web.FileSystemDirectoryHandle> showDirectoryPicker();
Future<void> pickAndUploadDirectory(BuildContext context, String parent) async {
final dir = await showDirectoryPicker().toDart;
processDirs(dir);
}
Future<void> processDirs(web.FileSystemDirectoryHandle dir) async {
print('Processing ${dir.name}');
final it = dir.entries().asStream();
it.forEach((e) async {
final l = e.toDart;
if (l[1].isA<web.FileSystemDirectoryHandle>()) {
await processDirs(l[1] as web.FileSystemDirectoryHandle);
} else if (l[1].isA<web.FileSystemFileHandle>()) {
final file = await (l[1] as web.FileSystemFileHandle).getFile().toDart;
final reader = web.FileReader();
reader.onload = () {
// final bytes = (reader.result as JSArrayBuffer).toDart;
print('contents of ${file.name}: ${reader.result}');
}.toJS;
reader.readAsText(file);
// reader.readAsArrayBuffer(file);
}
});
}
extension on web.FileSystemDirectoryHandle {
external JsAsyncIterator<JSArray> entries();
}
extension type JsAsyncIterator<T extends JSAny>._(JSObject _) implements JSObject {
external JSPromise<JsAsyncIteratorState<T>> next();
Stream<T> asStream() async* {
while (true) {
final result = await next().toDart;
if (result.done) break;
yield result.value;
}
}
}
extension type JsAsyncIteratorState<T extends JSAny>._(JSObject _) implements JSObject {
external bool get done;
external T get value;
}

View File

@@ -108,12 +108,6 @@ Future<void> uploadFiles(BuildContext context, String folderId, Iterable<UploadF
}
}
Future<void> pickAndUploadDirectory(BuildContext context, String folderId) async {
final path = await FilePicker.platform.getDirectoryPath();
if (path == null || !context.mounted) return;
return uploadPath(context, folderId, [path]);
}
Future<void> uploadPath(BuildContext context, String folderId, Iterable<String> paths) async {
final account = context.read<PhylumAccount>();
showProgressDialog(context, message: 'Counting Files');