Browse Source

fix(neon_files): Fix uploading files for web

Signed-off-by: jld3103 <jld3103yt@gmail.com>
pull/372/head
jld3103 2 years ago
parent
commit
7391081019
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 22
      packages/neon/neon_files/lib/blocs/files.dart
  2. 25
      packages/neon/neon_files/lib/dialogs/choose_create.dart
  3. 4
      packages/neon/neon_files/lib/models/file_details.dart
  4. 1
      packages/neon/neon_files/lib/neon_files.dart
  5. 65
      packages/neon/neon_files/lib/utils/task.dart

22
packages/neon/neon_files/lib/blocs/files.dart

@ -3,6 +3,8 @@ part of '../neon_files.dart';
abstract interface class FilesBlocEvents {
void uploadFile(final List<String> path, final String localPath);
void uploadBytes(final List<String> path, final Uint8List bytes);
void syncFile(final List<String> path);
void openFile(final List<String> path, final String etag, final String? mimeType);
@ -159,7 +161,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
void uploadFile(final List<String> path, final String localPath) {
wrapAction(
() async {
final task = FilesUploadTask(
final task = FilesUploadFileTask(
path: path,
file: File(localPath),
);
@ -171,6 +173,22 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
);
}
@override
void uploadBytes(final List<String> path, final Uint8List bytes) {
wrapAction(
() async {
final task = FilesUploadBytesTask(
path: path,
bytes: bytes,
);
tasks.add(tasks.value..add(task));
await _uploadQueue.add(() => task.execute(account.client));
tasks.add(tasks.value..removeWhere((final t) => t == task));
},
disableTimeout: true,
);
}
Future<File> _cacheFile(final List<String> path, final String etag) async {
final cacheDir = await getApplicationCacheDirectory();
final file = File(p.join(cacheDir.path, 'files', etag.replaceAll('"', ''), path.last));
@ -190,7 +208,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
final List<String> path,
final File file,
) async {
final task = FilesDownloadTask(
final task = FilesDownloadFileTask(
path: path,
file: file,
);

25
packages/neon/neon_files/lib/dialogs/choose_create.dart

@ -22,14 +22,24 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
);
if (result != null) {
for (final file in result.files) {
await upload(File(file.path!));
await upload(
file.name,
path: kIsWeb ? null : file.path,
bytes: file.bytes,
);
}
}
}
Future<void> upload(final File file) async {
Future<void> upload(
final String name, {
final String? path,
final Uint8List? bytes,
}) async {
assert((path == null) != (bytes == null), 'Provide either path or bytes');
final sizeWarning = widget.bloc.options.uploadSizeWarning.value;
if (sizeWarning != null) {
if (path != null && sizeWarning != null) {
final file = File(path);
final stat = file.statSync();
if (stat.size > sizeWarning) {
if (!(await showConfirmationDialog(
@ -43,7 +53,12 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
}
}
}
widget.bloc.uploadFile([...widget.basePath, p.basename(file.path)], file.path);
if (path != null) {
widget.bloc.uploadFile([...widget.basePath, name], path);
} else {
widget.bloc.uploadBytes([...widget.basePath, name], bytes!);
}
}
@override
@ -90,7 +105,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
final picker = ImagePicker();
final result = await picker.pickImage(source: ImageSource.camera);
if (result != null) {
await upload(File(result.path));
await upload(result.name, path: result.path);
}
},
),

4
packages/neon/neon_files/lib/models/file_details.dart

@ -29,8 +29,8 @@ class FileDetails {
FileDetails.fromUploadTask({
required FilesUploadTask this.task,
}) : path = task.path,
size = task.stat.size,
lastModified = task.stat.modified,
size = task.size,
lastModified = task.modified,
isDirectory = false,
etag = null,
mimeType = null,

1
packages/neon/neon_files/lib/neon_files.dart

@ -6,6 +6,7 @@ import 'package:collection/collection.dart';
import 'package:file_icons/file_icons.dart';
import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:go_router/go_router.dart';

65
packages/neon/neon_files/lib/utils/task.dart

@ -3,13 +3,10 @@ part of '../neon_files.dart';
sealed class FilesTask {
FilesTask({
required this.path,
required this.file,
});
final List<String> path;
final File file;
@protected
final streamController = StreamController<double>();
@ -17,12 +14,18 @@ sealed class FilesTask {
late final progress = streamController.stream.asBroadcastStream();
}
class FilesDownloadTask extends FilesTask {
FilesDownloadTask({
abstract class FilesDownloadTask extends FilesTask {
FilesDownloadTask({required super.path});
}
class FilesDownloadFileTask extends FilesDownloadTask {
FilesDownloadFileTask({
required super.path,
required super.file,
required this.file,
});
final File file;
Future<void> execute(final NextcloudClient client) async {
await client.webdav.getFile(
Uri(pathSegments: path),
@ -33,15 +36,31 @@ class FilesDownloadTask extends FilesTask {
}
}
class FilesUploadTask extends FilesTask {
FilesUploadTask({
abstract class FilesUploadTask extends FilesTask {
FilesUploadTask({required super.path});
int get size;
DateTime? get modified;
}
class FilesUploadFileTask extends FilesUploadTask {
FilesUploadFileTask({
required super.path,
required super.file,
required this.file,
});
final File file;
FileStat? _stat;
FileStat get stat => _stat ??= file.statSync();
@override
int get size => stat.size;
@override
DateTime? get modified => stat.modified;
Future<void> execute(final NextcloudClient client) async {
await client.webdav.putFile(
file,
@ -53,3 +72,31 @@ class FilesUploadTask extends FilesTask {
await streamController.close();
}
}
class FilesUploadBytesTask extends FilesUploadTask {
FilesUploadBytesTask({
required super.path,
required this.bytes,
this.modified,
});
final Uint8List bytes;
@override
int get size => bytes.lengthInBytes;
@override
DateTime? modified;
Future<void> execute(final NextcloudClient client) async {
await client.webdav.putStream(
Stream.value(bytes),
Uri(pathSegments: path),
lastModified: modified,
contentLength: bytes.lengthInBytes,
onProgress: (final progress) {
streamController.add(progress);
},
);
}
}

Loading…
Cancel
Save