diff --git a/packages/neon/neon_files/lib/models/file_details.dart b/packages/neon/neon_files/lib/models/file_details.dart index 19e8620b..221cfa29 100644 --- a/packages/neon/neon_files/lib/models/file_details.dart +++ b/packages/neon/neon_files/lib/models/file_details.dart @@ -11,7 +11,9 @@ class FileDetails { required this.lastModified, required this.hasPreview, required this.isFavorite, - }); + }) : progress = null, + isUploading = false, + isDownloading = false; FileDetails.fromWebDav({ required final WebDavFile file, @@ -23,19 +25,40 @@ class FileDetails { mimeType = file.mimeType, lastModified = file.lastModified, hasPreview = file.hasPreview, - isFavorite = file.favorite; + isFavorite = file.favorite, + progress = null, + isUploading = false, + isDownloading = false; FileDetails.fromUploadTask({ required final UploadTask task, }) : path = task.path, size = task.size, lastModified = task.lastModified, + progress = task.progress, + isUploading = true, + isDownloading = false, isDirectory = false, etag = null, mimeType = null, hasPreview = null, isFavorite = null; + FileDetails.fromDownloadTask({ + required final DownloadTask task, + required final WebDavFile file, + }) : path = task.path, + isDirectory = file.isDirectory, + size = file.size, + etag = file.etag, + mimeType = file.mimeType, + lastModified = file.lastModified, + hasPreview = file.hasPreview, + isFavorite = file.favorite, + progress = task.progress, + isUploading = false, + isDownloading = true; + String get name => path.last; final List path; @@ -53,4 +76,10 @@ class FileDetails { final bool? hasPreview; final bool? isFavorite; + + final Stream? progress; + final bool isUploading; + final bool isDownloading; + + bool get isLoading => isUploading || isDownloading; } diff --git a/packages/neon/neon_files/lib/widgets/browser_view.dart b/packages/neon/neon_files/lib/widgets/browser_view.dart index 56973863..34fe1f61 100644 --- a/packages/neon/neon_files/lib/widgets/browser_view.dart +++ b/packages/neon/neon_files/lib/widgets/browser_view.dart @@ -68,21 +68,13 @@ class _FilesBrowserViewState extends State { (final task) => sorted.where((final file) => _pathMatchesFile(task.path, file.name)).isEmpty, )) ...[ - StreamBuilder( - stream: uploadTask.progress, - builder: (final context, final uploadTaskProgressSnapshot) => - !uploadTaskProgressSnapshot.hasData - ? const SizedBox() - : FileListTile( - context: context, - details: FileDetails.fromUploadTask( - task: uploadTask, - ), - uploadProgress: uploadTaskProgressSnapshot.data, - downloadProgress: null, - enableFileActions: widget.enableFileActions, - onPickFile: widget.onPickFile, - ), + FileListTile( + context: context, + details: FileDetails.fromUploadTask( + task: uploadTask, + ), + enableFileActions: widget.enableFileActions, + onPickFile: widget.onPickFile, ), ], if (sorted != null) ...[ @@ -91,39 +83,32 @@ class _FilesBrowserViewState extends State { Builder( builder: (final context) { final matchingUploadTasks = uploadTasksSnapshot.requireData - .where((final task) => _pathMatchesFile(task.path, file.name)); + .firstWhereOrNull((final task) => _pathMatchesFile(task.path, file.name)); final matchingDownloadTasks = downloadTasksSnapshot.requireData - .where((final task) => _pathMatchesFile(task.path, file.name)); + .firstWhereOrNull((final task) => _pathMatchesFile(task.path, file.name)); - return StreamBuilder( - stream: - matchingUploadTasks.isNotEmpty ? matchingUploadTasks.first.progress : null, - builder: (final context, final uploadTaskProgressSnapshot) => - StreamBuilder( - stream: matchingDownloadTasks.isNotEmpty - ? matchingDownloadTasks.first.progress - : null, - builder: (final context, final downloadTaskProgressSnapshot) { - final path = widget.bloc.path.value; - final details = matchingUploadTasks.isEmpty - ? FileDetails.fromWebDav( - file: file, - path: path, - ) - : FileDetails.fromUploadTask( - task: matchingUploadTasks.first, - ); + final FileDetails details; + if (matchingDownloadTasks != null) { + details = FileDetails.fromDownloadTask( + task: matchingDownloadTasks, + file: file, + ); + } else if (matchingUploadTasks != null) { + details = FileDetails.fromUploadTask( + task: matchingUploadTasks, + ); + } else { + details = FileDetails.fromWebDav( + file: file, + path: widget.bloc.path.value, + ); + } - return FileListTile( - context: context, - details: details, - uploadProgress: uploadTaskProgressSnapshot.data, - downloadProgress: downloadTaskProgressSnapshot.data, - enableFileActions: widget.enableFileActions, - onPickFile: widget.onPickFile, - ); - }, - ), + return FileListTile( + context: context, + details: details, + enableFileActions: widget.enableFileActions, + onPickFile: widget.onPickFile, ); }, ), diff --git a/packages/neon/neon_files/lib/widgets/file_list_tile.dart b/packages/neon/neon_files/lib/widgets/file_list_tile.dart index c29dea8e..33455c5e 100644 --- a/packages/neon/neon_files/lib/widgets/file_list_tile.dart +++ b/packages/neon/neon_files/lib/widgets/file_list_tile.dart @@ -10,8 +10,6 @@ class FileListTile extends StatelessWidget { const FileListTile({ required this.context, required this.details, - required this.uploadProgress, - required this.downloadProgress, this.enableFileActions = true, this.onPickFile, super.key, @@ -19,23 +17,9 @@ class FileListTile extends StatelessWidget { final BuildContext context; final FileDetails details; - final double? uploadProgress; - final double? downloadProgress; final bool enableFileActions; final Function(FileDetails)? onPickFile; - bool get _isUploading => uploadProgress != null; - - bool get _hasProgress => uploadProgress != null || downloadProgress != null; - - double? get _progress { - if (!_hasProgress) { - return null; - } - - return (uploadProgress ?? downloadProgress)!; - } - @override Widget build(final BuildContext context) { final bloc = Provider.of(context); @@ -79,12 +63,9 @@ class FileListTile extends StatelessWidget { ], ), leading: _FileIcon( - hasProgress: _hasProgress, - isUploading: _isUploading, - progress: _progress, details: details, ), - trailing: !_hasProgress && enableFileActions + trailing: !details.isLoading && enableFileActions ? FileActions(details: details) : const SizedBox.square( dimension: 48, @@ -96,14 +77,8 @@ class FileListTile extends StatelessWidget { class _FileIcon extends StatelessWidget { const _FileIcon({ required this.details, - required this.hasProgress, - required this.isUploading, - this.progress, }); - final bool hasProgress; - final bool isUploading; - final double? progress; final FileDetails details; @override @@ -111,17 +86,20 @@ class _FileIcon extends StatelessWidget { final bloc = Provider.of(context); Widget icon = Center( - child: hasProgress - ? Column( - children: [ - Icon( - isUploading ? MdiIcons.upload : MdiIcons.download, - color: Theme.of(context).colorScheme.primary, - ), - LinearProgressIndicator( - value: progress, - ), - ], + child: details.isLoading + ? StreamBuilder( + stream: details.progress, + builder: (final context, final progress) => Column( + children: [ + Icon( + details.isUploading ? MdiIcons.upload : MdiIcons.download, + color: Theme.of(context).colorScheme.primary, + ), + LinearProgressIndicator( + value: progress.data, + ), + ], + ), ) : FilePreview( bloc: bloc,