From efc88235403fb28dd7107a146218e74665d1fff8 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Wed, 9 Oct 2024 23:19:05 +0200 Subject: [PATCH] refactor(nextcloud)!: Remove WebDavFile in favor of low-level WebDavResponse Signed-off-by: provokateurin --- .../files_app/lib/src/blocs/browser.dart | 10 ++- .../lib/src/models/file_details.dart | 30 +++---- .../files_app/lib/src/sort/files.dart | 6 +- .../lib/src/widgets/browser_view.dart | 2 +- .../lib/src/api/webdav/models/models.dart | 1 - .../src/api/webdav/models/webdav_file.dart | 88 ------------------- .../lib/src/api/webdav/utils/utils.dart | 1 + .../webdav/utils/webdav_response_helpers.dart | 26 ++++++ 8 files changed, 53 insertions(+), 111 deletions(-) delete mode 100644 packages/nextcloud/lib/src/api/webdav/models/webdav_file.dart create mode 100644 packages/nextcloud/lib/src/api/webdav/utils/webdav_response_helpers.dart diff --git a/packages/neon_framework/packages/files_app/lib/src/blocs/browser.dart b/packages/neon_framework/packages/files_app/lib/src/blocs/browser.dart index 817752bf7b4..17749811e1a 100644 --- a/packages/neon_framework/packages/files_app/lib/src/blocs/browser.dart +++ b/packages/neon_framework/packages/files_app/lib/src/blocs/browser.dart @@ -31,7 +31,7 @@ sealed class FilesBrowserBloc implements InteractiveBloc { webdav.PathUri? hideUri, }) = _FilesBrowserBloc; - BehaviorSubject>> get files; + BehaviorSubject>> get files; /// Mode to operate the `FilesBrowserView` in. FilesBrowserMode get mode; @@ -95,8 +95,12 @@ class _FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBloc { depth: webdav.WebDavDepth.one, ), converter: const webdav.WebDavResponseConverter(), - unwrap: (response) => BuiltList.build((b) { - for (final file in response.toWebDavFiles()) { + unwrap: (response) => BuiltList.build((b) { + for (final file in response.responses) { + if (file.href == null) { + continue; + } + // Do not show itself if (uri == file.path) { continue; diff --git a/packages/neon_framework/packages/files_app/lib/src/models/file_details.dart b/packages/neon_framework/packages/files_app/lib/src/models/file_details.dart index 6c80989abe7..5fdf8f7e906 100644 --- a/packages/neon_framework/packages/files_app/lib/src/models/file_details.dart +++ b/packages/neon_framework/packages/files_app/lib/src/models/file_details.dart @@ -16,14 +16,14 @@ class FileDetails { }) : task = null; FileDetails.fromWebDav({ - required webdav.WebDavFile file, + required webdav.WebDavResponse file, }) : uri = file.path, - size = file.size, - etag = file.etag, - mimeType = file.mimeType, - lastModified = file.lastModified, - isFavorite = file.favorite, - blurHash = file.blurHash, + size = file.props.ocSize, + etag = file.props.davGetetag, + mimeType = file.props.davGetcontenttype, + lastModified = file.props.davGetlastmodified, + isFavorite = file.props.ocFavorite, + blurHash = file.props.ncMetadataBlurhash, task = null; FileDetails.fromUploadTask({ @@ -38,18 +38,18 @@ class FileDetails { FileDetails.fromDownloadTask({ required FilesDownloadTask this.task, - required webdav.WebDavFile file, + required webdav.WebDavResponse file, }) : uri = task.uri, - size = file.size, - etag = file.etag, - mimeType = file.mimeType, - lastModified = file.lastModified, - isFavorite = file.favorite, - blurHash = file.blurHash; + size = file.props.ocSize, + etag = file.props.davGetetag, + mimeType = file.props.davGetcontenttype, + lastModified = file.props.davGetlastmodified, + isFavorite = file.props.ocFavorite, + blurHash = file.props.ncMetadataBlurhash; factory FileDetails.fromTask({ required FilesTask task, - required webdav.WebDavFile file, + required webdav.WebDavResponse file, }) { switch (task) { case FilesUploadTask(): diff --git a/packages/neon_framework/packages/files_app/lib/src/sort/files.dart b/packages/neon_framework/packages/files_app/lib/src/sort/files.dart index 6b3aa7e167c..39da2238082 100644 --- a/packages/neon_framework/packages/files_app/lib/src/sort/files.dart +++ b/packages/neon_framework/packages/files_app/lib/src/sort/files.dart @@ -3,11 +3,11 @@ import 'package:neon_framework/sort_box.dart'; import 'package:nextcloud/utils.dart'; import 'package:nextcloud/webdav.dart' as webdav; -final filesSortBox = SortBox( +final filesSortBox = SortBox( properties: { FilesSortProperty.name: (file) => file.name.toLowerCase(), - FilesSortProperty.modifiedDate: (file) => file.lastModified?.secondsSinceEpoch ?? 0, - FilesSortProperty.size: (file) => file.size ?? 0, + FilesSortProperty.modifiedDate: (file) => file.props.davGetlastmodified?.secondsSinceEpoch ?? 0, + FilesSortProperty.size: (file) => file.props.ocSize ?? 0, FilesSortProperty.isFolder: (file) => file.isDirectory ? 0 : 1, }, boxes: const { diff --git a/packages/neon_framework/packages/files_app/lib/src/widgets/browser_view.dart b/packages/neon_framework/packages/files_app/lib/src/widgets/browser_view.dart index fb41c934959..78cd41dbb1f 100644 --- a/packages/neon_framework/packages/files_app/lib/src/widgets/browser_view.dart +++ b/packages/neon_framework/packages/files_app/lib/src/widgets/browser_view.dart @@ -133,7 +133,7 @@ class _FilesBrowserViewState extends State { ); } - Iterable buildUploadTasks(BuiltList tasks, List files) sync* { + Iterable buildUploadTasks(BuiltList tasks, List files) sync* { for (final task in tasks) { if (task is! FilesUploadTask) { continue; diff --git a/packages/nextcloud/lib/src/api/webdav/models/models.dart b/packages/nextcloud/lib/src/api/webdav/models/models.dart index d86b8d1fae1..eee364b6765 100644 --- a/packages/nextcloud/lib/src/api/webdav/models/models.dart +++ b/packages/nextcloud/lib/src/api/webdav/models/models.dart @@ -2,5 +2,4 @@ export 'path_uri.dart'; export 'props.dart'; export 'webdav.dart'; export 'webdav_depth.dart'; -export 'webdav_file.dart'; export 'webdav_options.dart'; diff --git a/packages/nextcloud/lib/src/api/webdav/models/webdav_file.dart b/packages/nextcloud/lib/src/api/webdav/models/webdav_file.dart deleted file mode 100644 index 7b765c30fc5..00000000000 --- a/packages/nextcloud/lib/src/api/webdav/models/webdav_file.dart +++ /dev/null @@ -1,88 +0,0 @@ -import 'package:nextcloud/src/api/webdav/webdav.dart'; -import 'package:timezone/timezone.dart' as tz; - -// ignore: public_member_api_docs -extension WebDavMultistatusFile on WebDavMultistatus { - /// Convert the [WebDavMultistatus] into a [WebDavFile] for easier handling - List toWebDavFiles() => - responses.where((response) => response.href != null).map((response) => WebDavFile(response: response)).toList(); -} - -/// WebDavFile class -class WebDavFile { - /// Creates a new WebDavFile object with the given path - WebDavFile({ - required WebDavResponse response, - }) : _response = response; - - final WebDavResponse _response; - - /// Get the props of the file - late final WebDavProp props = _response.propstats.singleWhere((propstat) => propstat.status.contains('200')).prop; - - /// The path of file - late final PathUri path = () { - final href = PathUri.parse(Uri.decodeFull(_response.href!)); - return PathUri( - isAbsolute: false, - isDirectory: href.isDirectory, - pathSegments: href.pathSegments.sublist(webdavBase.pathSegments.length), - ); - }(); - - /// The fileid namespaced by the instance id, globally unique - late final String? id = props.ocId; - - /// The unique id for the file within the instance - late final int? fileId = props.ocFileid; - - /// Whether this is a collection resource type - late final bool? isCollection = props.davResourcetype != null ? props.davResourcetype!.collection != null : null; - - /// Mime-type of the file - late final String? mimeType = props.davGetcontenttype; - - /// ETag of the file - late final String? etag = props.davGetetag; - - /// File content length or folder size - late final int? size = props.ocSize ?? props.davGetcontentlength; - - /// The user id of the owner of a shared file - late final String? ownerId = props.ocOwnerId; - - /// The display name of the owner of a shared file - late final String? ownerDisplay = props.ocOwnerDisplayName; - - /// Share note - late final String? note = props.ncNote; - - /// Last modified date of the file. - /// - /// It will throw a [FormatException] if the date is invalid. - late final tz.TZDateTime? lastModified = props.davGetlastmodified; - - /// Upload date of the file - late final tz.TZDateTime? uploadedDate = props.ncUploadTime; - - /// Creation date of the file as provided by uploader - late final tz.TZDateTime? createdDate = props.ncCreationTime; - - /// Whether this file is marked as favorite - late final bool? favorite = props.ocFavorite; - - /// Whether this file has a preview image - late final bool? hasPreview = props.ncHasPreview; - - /// The compact representation of an image preview. - late final String? blurHash = props.ncMetadataBlurhash; - - /// Returns the decoded name of the file / folder without the whole path - late final String name = path.name; - - /// Whether the file is hidden. - late final bool isHidden = props.ncHidden ?? name.startsWith('.'); - - /// Whether the file is a directory - late final bool isDirectory = (isCollection ?? false) || path.isDirectory; -} diff --git a/packages/nextcloud/lib/src/api/webdav/utils/utils.dart b/packages/nextcloud/lib/src/api/webdav/utils/utils.dart index e3fe51ab46c..4f037f322dc 100644 --- a/packages/nextcloud/lib/src/api/webdav/utils/utils.dart +++ b/packages/nextcloud/lib/src/api/webdav/utils/utils.dart @@ -1,5 +1,6 @@ export 'options_parser.dart'; export 'webdav_response_converter.dart'; +export 'webdav_response_helpers.dart'; export 'webdav_uri.dart'; export 'xml_date_time_converter.dart'; export 'xml_duration_converter.dart'; diff --git a/packages/nextcloud/lib/src/api/webdav/utils/webdav_response_helpers.dart b/packages/nextcloud/lib/src/api/webdav/utils/webdav_response_helpers.dart new file mode 100644 index 00000000000..c7bb6cdda30 --- /dev/null +++ b/packages/nextcloud/lib/src/api/webdav/utils/webdav_response_helpers.dart @@ -0,0 +1,26 @@ +import 'package:nextcloud/src/api/webdav/models/models.dart'; + +/// Helpers +extension WebDavResponseHelpers on WebDavResponse { + /// All available props. + WebDavProp get props => propstats.singleWhere((propstat) => propstat.status.contains('200 OK')).prop; + + /// The path of the resource. + PathUri get path { + final href = PathUri.parse(Uri.decodeFull(this.href!)); + return PathUri( + isAbsolute: false, + isDirectory: href.isDirectory, + pathSegments: href.pathSegments.sublist(2), + ); + } + + /// The name of the resource. + String get name => path.name; + + /// Whether the file is hidden. + bool get isHidden => props.ncHidden ?? name.startsWith('.'); + + /// Whether the file is a directory + bool get isDirectory => props.davResourcetype?.collection != null || path.isDirectory; +}