diff --git a/packages/nextcloud/generate_props.dart b/packages/nextcloud/generate_props.dart index 842278ffb8f..d01690f5c9e 100644 --- a/packages/nextcloud/generate_props.dart +++ b/packages/nextcloud/generate_props.dart @@ -6,13 +6,13 @@ void main() { final props = >{ 'dav': { // lockdiscovery and supportedlock are omitted because the server only has a dummy implementation anyway. - 'creationdate': 'DateTime', + 'creationdate': 'iso8601', 'displayname': 'String', 'getcontentlanguage': 'String', 'getcontentlength': 'int', 'getcontenttype': 'String', 'getetag': 'String', - 'getlastmodified': 'String', + 'getlastmodified': 'httpDate', 'quota-available-bytes': 'int', 'quota-used-bytes': 'int', 'resourcetype': 'WebDavResourcetype', @@ -23,7 +23,7 @@ void main() { 'acl-list': 'WebDavNcAclList', 'contained-file-count': 'int', 'contained-folder-count': 'int', - 'creation_time': 'int', + 'creation_time': 'unixEpoch', 'data-fingerprint': 'String', 'group-folder-id': 'int', 'has-preview': 'bool', @@ -36,18 +36,18 @@ void main() { 'lock-owner-displayname': 'String', 'lock-owner-editor': 'String', 'lock-owner-type': 'int', - 'lock-time': 'int', + 'lock-time': 'unixEpoch', 'lock-timeout': 'int', 'lock-token': 'String', 'metadata_etag': 'String', 'mount-type': 'String', 'note': 'String', - 'reminder-due-date': 'DateTime', + 'reminder-due-date': 'iso8601', 'rich-workspace': 'String', 'rich-workspace-file': 'int', 'share-attributes': 'String', 'sharees': 'WebDavNcShareeList', - 'upload_time': 'int', + 'upload_time': 'unixEpoch', 'version-author': 'String', 'version-label': 'String', }, @@ -80,17 +80,33 @@ void main() { final variables = []; for (final namespacePrefix in props.keys) { for (final name in props[namespacePrefix]!.keys) { - final type = props[namespacePrefix]![name]!; + var type = props[namespacePrefix]![name]!; final namespaceVariable = convertNamespace(namespacePrefix); final variable = toDartName('$namespacePrefix-$name'); - valueProps.add(''' + + final value = StringBuffer(''' @annotation.XmlElement( name: '$name', namespace: $namespaceVariable, includeIfNull: false, ) - final $type? $variable;'''); +'''); + switch (type) { + case 'httpDate': + value.writeln(' @HttpDateXMLConverter()'); + type = 'tz.TZDateTime'; + case 'iso8601': + value.writeln(' @ISO8601XMLConverter()'); + type = 'tz.TZDateTime'; + case 'unixEpoch': + value.writeln(' @UnixEpochXMLConverter()'); + type = 'tz.TZDateTime'; + } + + value.write(' final $type? $variable;'); + valueProps.add(value.toString()); + findProps.add(''' @annotation.XmlElement( name: '$name', @@ -107,7 +123,9 @@ void main() { '// ignore_for_file: public_member_api_docs', '// coverage:ignore-file', "import 'package:meta/meta.dart';", + "import 'package:nextcloud/src/utils/date_time.dart';", "import 'package:nextcloud/src/webdav/webdav.dart';", + "import 'package:timezone/timezone.dart' as tz;", "import 'package:xml/xml.dart';", "import 'package:xml_annotation/xml_annotation.dart' as annotation;", "part 'props.g.dart';", diff --git a/packages/nextcloud/lib/src/utils/date_time.dart b/packages/nextcloud/lib/src/utils/date_time.dart index a0fbf08f33c..a02d4fc1958 100644 --- a/packages/nextcloud/lib/src/utils/date_time.dart +++ b/packages/nextcloud/lib/src/utils/date_time.dart @@ -1,4 +1,9 @@ +import 'package:meta/meta.dart'; +import 'package:nextcloud/src/utils/http_date_parser.dart'; +import 'package:nextcloud/utils.dart'; import 'package:timezone/timezone.dart' as tz; +import 'package:xml/xml.dart' as xml; +import 'package:xml_annotation/xml_annotation.dart' as xml_annotation; /// Common methods to work with [DateTime] data. extension DateTimeUtils on DateTime { @@ -28,3 +33,168 @@ extension DateTimeUtils on DateTime { /// In other words: `secondsSinceEpoch.abs() <= 8640000000000`. int get secondsSinceEpoch => millisecondsSinceEpoch ~/ Duration.millisecondsPerSecond; } + +@internal +final class HttpDateXMLConverter implements xml_annotation.XmlConverter { + const HttpDateXMLConverter(); + + @override + void buildXmlChildren( + tz.TZDateTime? instance, + xml.XmlBuilder builder, { + Map namespaces = const {}, + }) { + if (instance == null) { + return; + } + + final date = formatHttpDate(instance); + builder.text(date); + } + + @override + tz.TZDateTime? fromXmlElement( + xml.XmlElement element, + ) { + final date = element.getText(); + if (date != null) { + return parseHttpDate(date); + } + + return null; + } + + @override + List toXmlAttributes( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + return const []; + } + + @override + List toXmlChildren( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + if (instance == null) { + return const []; + } + + final date = formatHttpDate(instance); + return [ + xml.XmlText(date), + ]; + } +} + +@internal +final class ISO8601XMLConverter implements xml_annotation.XmlConverter { + const ISO8601XMLConverter(); + + @override + void buildXmlChildren( + tz.TZDateTime? instance, + xml.XmlBuilder builder, { + Map namespaces = const {}, + }) { + if (instance == null) { + return; + } + + final date = instance.toIso8601String(); + builder.text(date); + } + + @override + tz.TZDateTime? fromXmlElement( + xml.XmlElement element, + ) { + final date = element.getText(); + if (date != null) { + return tz.TZDateTime.parse(tz.UTC, date); + } + + return null; + } + + @override + List toXmlAttributes( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + return const []; + } + + @override + List toXmlChildren( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + if (instance == null) { + return const []; + } + + final date = instance.toIso8601String(); + return [ + xml.XmlText(date), + ]; + } +} + +@internal +final class UnixEpochXMLConverter implements xml_annotation.XmlConverter { + const UnixEpochXMLConverter(); + + @override + void buildXmlChildren( + tz.TZDateTime? instance, + xml.XmlBuilder builder, { + Map namespaces = const {}, + }) { + if (instance == null) { + return; + } + + final date = instance.secondsSinceEpoch.toString(); + builder.text(date); + } + + @override + tz.TZDateTime? fromXmlElement( + xml.XmlElement element, + ) { + final date = element.getText(); + if (date != null) { + return DateTimeUtils.fromSecondsSinceEpoch( + tz.UTC, + int.parse(date), + ); + } + + return null; + } + + @override + List toXmlAttributes( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + return const []; + } + + @override + List toXmlChildren( + tz.TZDateTime? instance, { + Map namespaces = const {}, + }) { + if (instance == null) { + return const []; + } + + final date = instance.secondsSinceEpoch.toString(); + return [ + xml.XmlText(date), + ]; + } +} diff --git a/packages/nextcloud/lib/src/webdav/file.dart b/packages/nextcloud/lib/src/webdav/file.dart index b3037877215..fb5419a66c1 100644 --- a/packages/nextcloud/lib/src/webdav/file.dart +++ b/packages/nextcloud/lib/src/webdav/file.dart @@ -1,5 +1,3 @@ -import 'package:nextcloud/src/utils/date_time.dart'; -import 'package:nextcloud/src/utils/http_date_parser.dart'; import 'package:nextcloud/src/webdav/client.dart'; import 'package:nextcloud/src/webdav/path_uri.dart'; import 'package:nextcloud/src/webdav/props.dart'; @@ -65,28 +63,13 @@ class WebDavFile { /// Last modified date of the file. /// /// It will throw a [FormatException] if the date is invalid. - late final tz.TZDateTime? lastModified = () { - if (props.davGetlastmodified != null) { - return parseHttpDate(props.davGetlastmodified!); - } - return null; - }(); + late final tz.TZDateTime? lastModified = props.davGetlastmodified; /// Upload date of the file - late final tz.TZDateTime? uploadedDate = props.ncUploadTime != null - ? DateTimeUtils.fromSecondsSinceEpoch( - tz.UTC, - props.ncUploadTime!, - ) - : null; + late final tz.TZDateTime? uploadedDate = props.ncUploadTime; /// Creation date of the file as provided by uploader - late final tz.TZDateTime? createdDate = props.ncCreationTime != null - ? DateTimeUtils.fromSecondsSinceEpoch( - tz.UTC, - props.ncCreationTime!, - ) - : null; + late final tz.TZDateTime? createdDate = props.ncCreationTime; /// Whether this file is marked as favorite late final bool? favorite = props.ocFavorite == null ? null : props.ocFavorite == 1; diff --git a/packages/nextcloud/lib/src/webdav/props.dart b/packages/nextcloud/lib/src/webdav/props.dart index fc2016794dd..69f72d49ff8 100644 --- a/packages/nextcloud/lib/src/webdav/props.dart +++ b/packages/nextcloud/lib/src/webdav/props.dart @@ -1,7 +1,9 @@ // ignore_for_file: public_member_api_docs // coverage:ignore-file import 'package:meta/meta.dart'; +import 'package:nextcloud/src/utils/date_time.dart'; import 'package:nextcloud/src/webdav/webdav.dart'; +import 'package:timezone/timezone.dart' as tz; import 'package:xml/xml.dart'; import 'package:xml_annotation/xml_annotation.dart' as annotation; part 'props.g.dart'; @@ -729,7 +731,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceDav, includeIfNull: false, ) - final DateTime? davCreationdate; + @ISO8601XMLConverter() + final tz.TZDateTime? davCreationdate; @annotation.XmlElement( name: 'displayname', @@ -771,7 +774,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceDav, includeIfNull: false, ) - final String? davGetlastmodified; + @HttpDateXMLConverter() + final tz.TZDateTime? davGetlastmodified; @annotation.XmlElement( name: 'quota-available-bytes', @@ -834,7 +838,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncCreationTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncCreationTime; @annotation.XmlElement( name: 'data-fingerprint', @@ -925,7 +930,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncLockTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncLockTime; @annotation.XmlElement( name: 'lock-timeout', @@ -967,7 +973,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final DateTime? ncReminderDueDate; + @ISO8601XMLConverter() + final tz.TZDateTime? ncReminderDueDate; @annotation.XmlElement( name: 'rich-workspace', @@ -1002,7 +1009,8 @@ class WebDavProp with _$WebDavPropXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncUploadTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncUploadTime; @annotation.XmlElement( name: 'version-author', @@ -1203,7 +1211,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceDav, includeIfNull: false, ) - final DateTime? davCreationdate; + @ISO8601XMLConverter() + final tz.TZDateTime? davCreationdate; @annotation.XmlElement( name: 'displayname', @@ -1245,7 +1254,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceDav, includeIfNull: false, ) - final String? davGetlastmodified; + @HttpDateXMLConverter() + final tz.TZDateTime? davGetlastmodified; @annotation.XmlElement( name: 'quota-available-bytes', @@ -1308,7 +1318,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncCreationTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncCreationTime; @annotation.XmlElement( name: 'data-fingerprint', @@ -1399,7 +1410,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncLockTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncLockTime; @annotation.XmlElement( name: 'lock-timeout', @@ -1441,7 +1453,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final DateTime? ncReminderDueDate; + @ISO8601XMLConverter() + final tz.TZDateTime? ncReminderDueDate; @annotation.XmlElement( name: 'rich-workspace', @@ -1476,7 +1489,8 @@ class WebDavOcFilterRules with _$WebDavOcFilterRulesXmlSerializableMixin { namespace: namespaceNextcloud, includeIfNull: false, ) - final int? ncUploadTime; + @UnixEpochXMLConverter() + final tz.TZDateTime? ncUploadTime; @annotation.XmlElement( name: 'version-author', diff --git a/packages/nextcloud/lib/src/webdav/props.g.dart b/packages/nextcloud/lib/src/webdav/props.g.dart index 0b62d794607..2daaf8777ab 100644 --- a/packages/nextcloud/lib/src/webdav/props.g.dart +++ b/packages/nextcloud/lib/src/webdav/props.g.dart @@ -1367,10 +1367,10 @@ mixin _$WebDavPropWithoutValuesXmlSerializableMixin { void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, {Map namespaces = const {}}) { final davCreationdate = instance.davCreationdate; - final davCreationdateSerialized = davCreationdate?.toIso8601String(); + final davCreationdateSerialized = davCreationdate; if (davCreationdateSerialized != null) { builder.element('creationdate', namespace: 'DAV:', nest: () { - builder.text(davCreationdateSerialized); + const ISO8601XMLConverter().buildXmlChildren(davCreationdateSerialized, builder, namespaces: namespaces); }); } final davDisplayname = instance.davDisplayname; @@ -1412,7 +1412,7 @@ void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, final davGetlastmodifiedSerialized = davGetlastmodified; if (davGetlastmodifiedSerialized != null) { builder.element('getlastmodified', namespace: 'DAV:', nest: () { - builder.text(davGetlastmodifiedSerialized); + const HttpDateXMLConverter().buildXmlChildren(davGetlastmodifiedSerialized, builder, namespaces: namespaces); }); } final davQuotaAvailableBytes = instance.davQuotaAvailableBytes; @@ -1472,10 +1472,10 @@ void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, }); } final ncCreationTime = instance.ncCreationTime; - final ncCreationTimeSerialized = ncCreationTime?.toString(); + final ncCreationTimeSerialized = ncCreationTime; if (ncCreationTimeSerialized != null) { builder.element('creation_time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncCreationTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncCreationTimeSerialized, builder, namespaces: namespaces); }); } final ncDataFingerprint = instance.ncDataFingerprint; @@ -1575,10 +1575,10 @@ void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, }); } final ncLockTime = instance.ncLockTime; - final ncLockTimeSerialized = ncLockTime?.toString(); + final ncLockTimeSerialized = ncLockTime; if (ncLockTimeSerialized != null) { builder.element('lock-time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncLockTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncLockTimeSerialized, builder, namespaces: namespaces); }); } final ncLockTimeout = instance.ncLockTimeout; @@ -1617,10 +1617,10 @@ void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, }); } final ncReminderDueDate = instance.ncReminderDueDate; - final ncReminderDueDateSerialized = ncReminderDueDate?.toIso8601String(); + final ncReminderDueDateSerialized = ncReminderDueDate; if (ncReminderDueDateSerialized != null) { builder.element('reminder-due-date', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncReminderDueDateSerialized); + const ISO8601XMLConverter().buildXmlChildren(ncReminderDueDateSerialized, builder, namespaces: namespaces); }); } final ncRichWorkspace = instance.ncRichWorkspace; @@ -1652,10 +1652,10 @@ void _$WebDavPropBuildXmlChildren(WebDavProp instance, XmlBuilder builder, }); } final ncUploadTime = instance.ncUploadTime; - final ncUploadTimeSerialized = ncUploadTime?.toString(); + final ncUploadTimeSerialized = ncUploadTime; if (ncUploadTimeSerialized != null) { builder.element('upload_time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncUploadTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncUploadTimeSerialized, builder, namespaces: namespaces); }); } final ncVersionAuthor = instance.ncVersionAuthor; @@ -1793,13 +1793,13 @@ void _$WebDavPropBuildXmlElement(WebDavProp instance, XmlBuilder builder, {Map _$WebDavPropToXmlAttributes(WebDavProp instance, {Map _$WebDavPropToXmlChildren(WebDavProp instance, {Map namespaces = const {}}) { final children = []; final davCreationdate = instance.davCreationdate; - final davCreationdateSerialized = davCreationdate?.toIso8601String(); + final davCreationdateSerialized = davCreationdate; final davCreationdateConstructed = davCreationdateSerialized != null - ? XmlElement(XmlName('creationdate', namespaces['DAV:']), [], [XmlText(davCreationdateSerialized)]) + ? XmlElement( + XmlName('creationdate', namespaces['DAV:']), + const ISO8601XMLConverter().toXmlAttributes(davCreationdateSerialized, namespaces: namespaces), + const ISO8601XMLConverter().toXmlChildren(davCreationdateSerialized, namespaces: namespaces)) : null; if (davCreationdateConstructed != null) { children.add(davCreationdateConstructed); @@ -1994,7 +1999,10 @@ List _$WebDavPropToXmlChildren(WebDavProp instance, {Map _$WebDavPropToXmlChildren(WebDavProp instance, {Map _$WebDavPropToXmlChildren(WebDavProp instance, {Map _$WebDavPropToXmlChildren(WebDavProp instance, {Map _$WebDavPropToXmlChildren(WebDavProp instance, {Map namespaces = const {}}) { final davCreationdate = instance.davCreationdate; - final davCreationdateSerialized = davCreationdate?.toIso8601String(); + final davCreationdateSerialized = davCreationdate; if (davCreationdateSerialized != null) { builder.element('creationdate', namespace: 'DAV:', nest: () { - builder.text(davCreationdateSerialized); + const ISO8601XMLConverter().buildXmlChildren(davCreationdateSerialized, builder, namespaces: namespaces); }); } final davDisplayname = instance.davDisplayname; @@ -2541,7 +2559,7 @@ void _$WebDavOcFilterRulesBuildXmlChildren(WebDavOcFilterRules instance, XmlBuil final davGetlastmodifiedSerialized = davGetlastmodified; if (davGetlastmodifiedSerialized != null) { builder.element('getlastmodified', namespace: 'DAV:', nest: () { - builder.text(davGetlastmodifiedSerialized); + const HttpDateXMLConverter().buildXmlChildren(davGetlastmodifiedSerialized, builder, namespaces: namespaces); }); } final davQuotaAvailableBytes = instance.davQuotaAvailableBytes; @@ -2601,10 +2619,10 @@ void _$WebDavOcFilterRulesBuildXmlChildren(WebDavOcFilterRules instance, XmlBuil }); } final ncCreationTime = instance.ncCreationTime; - final ncCreationTimeSerialized = ncCreationTime?.toString(); + final ncCreationTimeSerialized = ncCreationTime; if (ncCreationTimeSerialized != null) { builder.element('creation_time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncCreationTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncCreationTimeSerialized, builder, namespaces: namespaces); }); } final ncDataFingerprint = instance.ncDataFingerprint; @@ -2704,10 +2722,10 @@ void _$WebDavOcFilterRulesBuildXmlChildren(WebDavOcFilterRules instance, XmlBuil }); } final ncLockTime = instance.ncLockTime; - final ncLockTimeSerialized = ncLockTime?.toString(); + final ncLockTimeSerialized = ncLockTime; if (ncLockTimeSerialized != null) { builder.element('lock-time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncLockTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncLockTimeSerialized, builder, namespaces: namespaces); }); } final ncLockTimeout = instance.ncLockTimeout; @@ -2746,10 +2764,10 @@ void _$WebDavOcFilterRulesBuildXmlChildren(WebDavOcFilterRules instance, XmlBuil }); } final ncReminderDueDate = instance.ncReminderDueDate; - final ncReminderDueDateSerialized = ncReminderDueDate?.toIso8601String(); + final ncReminderDueDateSerialized = ncReminderDueDate; if (ncReminderDueDateSerialized != null) { builder.element('reminder-due-date', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncReminderDueDateSerialized); + const ISO8601XMLConverter().buildXmlChildren(ncReminderDueDateSerialized, builder, namespaces: namespaces); }); } final ncRichWorkspace = instance.ncRichWorkspace; @@ -2781,10 +2799,10 @@ void _$WebDavOcFilterRulesBuildXmlChildren(WebDavOcFilterRules instance, XmlBuil }); } final ncUploadTime = instance.ncUploadTime; - final ncUploadTimeSerialized = ncUploadTime?.toString(); + final ncUploadTimeSerialized = ncUploadTime; if (ncUploadTimeSerialized != null) { builder.element('upload_time', namespace: 'http://nextcloud.org/ns', nest: () { - builder.text(ncUploadTimeSerialized); + const UnixEpochXMLConverter().buildXmlChildren(ncUploadTimeSerialized, builder, namespaces: namespaces); }); } final ncVersionAuthor = instance.ncVersionAuthor; @@ -2923,13 +2941,13 @@ void _$WebDavOcFilterRulesBuildXmlElement(WebDavOcFilterRules instance, XmlBuild } WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { - final davCreationdate = element.getElement('creationdate', namespace: 'DAV:')?.getText(); + final davCreationdate = element.getElement('creationdate', namespace: 'DAV:'); final davDisplayname = element.getElement('displayname', namespace: 'DAV:')?.getText(); final davGetcontentlanguage = element.getElement('getcontentlanguage', namespace: 'DAV:')?.getText(); final davGetcontentlength = element.getElement('getcontentlength', namespace: 'DAV:')?.getText(); final davGetcontenttype = element.getElement('getcontenttype', namespace: 'DAV:')?.getText(); final davGetetag = element.getElement('getetag', namespace: 'DAV:')?.getText(); - final davGetlastmodified = element.getElement('getlastmodified', namespace: 'DAV:')?.getText(); + final davGetlastmodified = element.getElement('getlastmodified', namespace: 'DAV:'); final davQuotaAvailableBytes = element.getElement('quota-available-bytes', namespace: 'DAV:')?.getText(); final davQuotaUsedBytes = element.getElement('quota-used-bytes', namespace: 'DAV:')?.getText(); final davResourcetype = element.getElement('resourcetype', namespace: 'DAV:'); @@ -2940,7 +2958,7 @@ WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { element.getElement('contained-file-count', namespace: 'http://nextcloud.org/ns')?.getText(); final ncContainedFolderCount = element.getElement('contained-folder-count', namespace: 'http://nextcloud.org/ns')?.getText(); - final ncCreationTime = element.getElement('creation_time', namespace: 'http://nextcloud.org/ns')?.getText(); + final ncCreationTime = element.getElement('creation_time', namespace: 'http://nextcloud.org/ns'); final ncDataFingerprint = element.getElement('data-fingerprint', namespace: 'http://nextcloud.org/ns')?.getText(); final ncGroupFolderId = element.getElement('group-folder-id', namespace: 'http://nextcloud.org/ns')?.getText(); final ncHasPreview = element.getElement('has-preview', namespace: 'http://nextcloud.org/ns')?.getText(); @@ -2954,19 +2972,19 @@ WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { element.getElement('lock-owner-displayname', namespace: 'http://nextcloud.org/ns')?.getText(); final ncLockOwnerEditor = element.getElement('lock-owner-editor', namespace: 'http://nextcloud.org/ns')?.getText(); final ncLockOwnerType = element.getElement('lock-owner-type', namespace: 'http://nextcloud.org/ns')?.getText(); - final ncLockTime = element.getElement('lock-time', namespace: 'http://nextcloud.org/ns')?.getText(); + final ncLockTime = element.getElement('lock-time', namespace: 'http://nextcloud.org/ns'); final ncLockTimeout = element.getElement('lock-timeout', namespace: 'http://nextcloud.org/ns')?.getText(); final ncLockToken = element.getElement('lock-token', namespace: 'http://nextcloud.org/ns')?.getText(); final ncMetadataEtag = element.getElement('metadata_etag', namespace: 'http://nextcloud.org/ns')?.getText(); final ncMountType = element.getElement('mount-type', namespace: 'http://nextcloud.org/ns')?.getText(); final ncNote = element.getElement('note', namespace: 'http://nextcloud.org/ns')?.getText(); - final ncReminderDueDate = element.getElement('reminder-due-date', namespace: 'http://nextcloud.org/ns')?.getText(); + final ncReminderDueDate = element.getElement('reminder-due-date', namespace: 'http://nextcloud.org/ns'); final ncRichWorkspace = element.getElement('rich-workspace', namespace: 'http://nextcloud.org/ns')?.getText(); final ncRichWorkspaceFile = element.getElement('rich-workspace-file', namespace: 'http://nextcloud.org/ns')?.getText(); final ncShareAttributes = element.getElement('share-attributes', namespace: 'http://nextcloud.org/ns')?.getText(); final ncSharees = element.getElement('sharees', namespace: 'http://nextcloud.org/ns'); - final ncUploadTime = element.getElement('upload_time', namespace: 'http://nextcloud.org/ns')?.getText(); + final ncUploadTime = element.getElement('upload_time', namespace: 'http://nextcloud.org/ns'); final ncVersionAuthor = element.getElement('version-author', namespace: 'http://nextcloud.org/ns')?.getText(); final ncVersionLabel = element.getElement('version-label', namespace: 'http://nextcloud.org/ns')?.getText(); final ocChecksums = element.getElement('checksums', namespace: 'http://owncloud.org/ns'); @@ -2988,13 +3006,14 @@ WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { final ocsSharePermissions = element.getElement('share-permissions', namespace: 'http://open-collaboration-services.org/ns')?.getText(); return WebDavOcFilterRules( - davCreationdate: davCreationdate != null ? DateTime.parse(davCreationdate) : null, + davCreationdate: davCreationdate != null ? const ISO8601XMLConverter().fromXmlElement(davCreationdate) : null, davDisplayname: davDisplayname, davGetcontentlanguage: davGetcontentlanguage, davGetcontentlength: davGetcontentlength != null ? int.parse(davGetcontentlength) : null, davGetcontenttype: davGetcontenttype, davGetetag: davGetetag, - davGetlastmodified: davGetlastmodified, + davGetlastmodified: + davGetlastmodified != null ? const HttpDateXMLConverter().fromXmlElement(davGetlastmodified) : null, davQuotaAvailableBytes: davQuotaAvailableBytes != null ? int.parse(davQuotaAvailableBytes) : null, davQuotaUsedBytes: davQuotaUsedBytes != null ? int.parse(davQuotaUsedBytes) : null, davResourcetype: davResourcetype != null ? WebDavResourcetype.fromXmlElement(davResourcetype) : null, @@ -3003,7 +3022,7 @@ WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { ncAclList: ncAclList != null ? WebDavNcAclList.fromXmlElement(ncAclList) : null, ncContainedFileCount: ncContainedFileCount != null ? int.parse(ncContainedFileCount) : null, ncContainedFolderCount: ncContainedFolderCount != null ? int.parse(ncContainedFolderCount) : null, - ncCreationTime: ncCreationTime != null ? int.parse(ncCreationTime) : null, + ncCreationTime: ncCreationTime != null ? const UnixEpochXMLConverter().fromXmlElement(ncCreationTime) : null, ncDataFingerprint: ncDataFingerprint, ncGroupFolderId: ncGroupFolderId != null ? int.parse(ncGroupFolderId) : null, ncHasPreview: ncHasPreview != null @@ -3034,18 +3053,19 @@ WebDavOcFilterRules _$WebDavOcFilterRulesFromXmlElement(XmlElement element) { ncLockOwnerDisplayname: ncLockOwnerDisplayname, ncLockOwnerEditor: ncLockOwnerEditor, ncLockOwnerType: ncLockOwnerType != null ? int.parse(ncLockOwnerType) : null, - ncLockTime: ncLockTime != null ? int.parse(ncLockTime) : null, + ncLockTime: ncLockTime != null ? const UnixEpochXMLConverter().fromXmlElement(ncLockTime) : null, ncLockTimeout: ncLockTimeout != null ? int.parse(ncLockTimeout) : null, ncLockToken: ncLockToken, ncMetadataEtag: ncMetadataEtag, ncMountType: ncMountType, ncNote: ncNote, - ncReminderDueDate: ncReminderDueDate != null ? DateTime.parse(ncReminderDueDate) : null, + ncReminderDueDate: + ncReminderDueDate != null ? const ISO8601XMLConverter().fromXmlElement(ncReminderDueDate) : null, ncRichWorkspace: ncRichWorkspace, ncRichWorkspaceFile: ncRichWorkspaceFile != null ? int.parse(ncRichWorkspaceFile) : null, ncShareAttributes: ncShareAttributes, ncSharees: ncSharees != null ? WebDavNcShareeList.fromXmlElement(ncSharees) : null, - ncUploadTime: ncUploadTime != null ? int.parse(ncUploadTime) : null, + ncUploadTime: ncUploadTime != null ? const UnixEpochXMLConverter().fromXmlElement(ncUploadTime) : null, ncVersionAuthor: ncVersionAuthor, ncVersionLabel: ncVersionLabel, ocChecksums: ocChecksums != null ? WebDavOcChecksums.fromXmlElement(ocChecksums) : null, @@ -3076,9 +3096,12 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, {Map namespaces = const {}}) { final children = []; final davCreationdate = instance.davCreationdate; - final davCreationdateSerialized = davCreationdate?.toIso8601String(); + final davCreationdateSerialized = davCreationdate; final davCreationdateConstructed = davCreationdateSerialized != null - ? XmlElement(XmlName('creationdate', namespaces['DAV:']), [], [XmlText(davCreationdateSerialized)]) + ? XmlElement( + XmlName('creationdate', namespaces['DAV:']), + const ISO8601XMLConverter().toXmlAttributes(davCreationdateSerialized, namespaces: namespaces), + const ISO8601XMLConverter().toXmlChildren(davCreationdateSerialized, namespaces: namespaces)) : null; if (davCreationdateConstructed != null) { children.add(davCreationdateConstructed); @@ -3126,7 +3149,10 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, final davGetlastmodified = instance.davGetlastmodified; final davGetlastmodifiedSerialized = davGetlastmodified; final davGetlastmodifiedConstructed = davGetlastmodifiedSerialized != null - ? XmlElement(XmlName('getlastmodified', namespaces['DAV:']), [], [XmlText(davGetlastmodifiedSerialized)]) + ? XmlElement( + XmlName('getlastmodified', namespaces['DAV:']), + const HttpDateXMLConverter().toXmlAttributes(davGetlastmodifiedSerialized, namespaces: namespaces), + const HttpDateXMLConverter().toXmlChildren(davGetlastmodifiedSerialized, namespaces: namespaces)) : null; if (davGetlastmodifiedConstructed != null) { children.add(davGetlastmodifiedConstructed); @@ -3206,10 +3232,12 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, children.add(ncContainedFolderCountConstructed); } final ncCreationTime = instance.ncCreationTime; - final ncCreationTimeSerialized = ncCreationTime?.toString(); + final ncCreationTimeSerialized = ncCreationTime; final ncCreationTimeConstructed = ncCreationTimeSerialized != null ? XmlElement( - XmlName('creation_time', namespaces['http://nextcloud.org/ns']), [], [XmlText(ncCreationTimeSerialized)]) + XmlName('creation_time', namespaces['http://nextcloud.org/ns']), + const UnixEpochXMLConverter().toXmlAttributes(ncCreationTimeSerialized, namespaces: namespaces), + const UnixEpochXMLConverter().toXmlChildren(ncCreationTimeSerialized, namespaces: namespaces)) : null; if (ncCreationTimeConstructed != null) { children.add(ncCreationTimeConstructed); @@ -3333,9 +3361,12 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, children.add(ncLockOwnerTypeConstructed); } final ncLockTime = instance.ncLockTime; - final ncLockTimeSerialized = ncLockTime?.toString(); + final ncLockTimeSerialized = ncLockTime; final ncLockTimeConstructed = ncLockTimeSerialized != null - ? XmlElement(XmlName('lock-time', namespaces['http://nextcloud.org/ns']), [], [XmlText(ncLockTimeSerialized)]) + ? XmlElement( + XmlName('lock-time', namespaces['http://nextcloud.org/ns']), + const UnixEpochXMLConverter().toXmlAttributes(ncLockTimeSerialized, namespaces: namespaces), + const UnixEpochXMLConverter().toXmlChildren(ncLockTimeSerialized, namespaces: namespaces)) : null; if (ncLockTimeConstructed != null) { children.add(ncLockTimeConstructed); @@ -3383,10 +3414,12 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, children.add(ncNoteConstructed); } final ncReminderDueDate = instance.ncReminderDueDate; - final ncReminderDueDateSerialized = ncReminderDueDate?.toIso8601String(); + final ncReminderDueDateSerialized = ncReminderDueDate; final ncReminderDueDateConstructed = ncReminderDueDateSerialized != null - ? XmlElement(XmlName('reminder-due-date', namespaces['http://nextcloud.org/ns']), [], - [XmlText(ncReminderDueDateSerialized)]) + ? XmlElement( + XmlName('reminder-due-date', namespaces['http://nextcloud.org/ns']), + const ISO8601XMLConverter().toXmlAttributes(ncReminderDueDateSerialized, namespaces: namespaces), + const ISO8601XMLConverter().toXmlChildren(ncReminderDueDateSerialized, namespaces: namespaces)) : null; if (ncReminderDueDateConstructed != null) { children.add(ncReminderDueDateConstructed); @@ -3430,9 +3463,12 @@ List _$WebDavOcFilterRulesToXmlChildren(WebDavOcFilterRules instance, children.add(ncShareesConstructed); } final ncUploadTime = instance.ncUploadTime; - final ncUploadTimeSerialized = ncUploadTime?.toString(); + final ncUploadTimeSerialized = ncUploadTime; final ncUploadTimeConstructed = ncUploadTimeSerialized != null - ? XmlElement(XmlName('upload_time', namespaces['http://nextcloud.org/ns']), [], [XmlText(ncUploadTimeSerialized)]) + ? XmlElement( + XmlName('upload_time', namespaces['http://nextcloud.org/ns']), + const UnixEpochXMLConverter().toXmlAttributes(ncUploadTimeSerialized, namespaces: namespaces), + const UnixEpochXMLConverter().toXmlChildren(ncUploadTimeSerialized, namespaces: namespaces)) : null; if (ncUploadTimeConstructed != null) { children.add(ncUploadTimeConstructed); diff --git a/packages/nextcloud/lib/utils.dart b/packages/nextcloud/lib/utils.dart index b47d93fa0a0..0779a6236ae 100644 --- a/packages/nextcloud/lib/utils.dart +++ b/packages/nextcloud/lib/utils.dart @@ -1,5 +1,5 @@ /// This library contains various utility methods for working with nextcloud APIs. library; -export 'src/utils/date_time.dart'; +export 'src/utils/date_time.dart' show DateTimeUtils; export 'src/utils/http_date_parser.dart'; diff --git a/packages/nextcloud/test/webdav_test.dart b/packages/nextcloud/test/webdav_test.dart index 4c989bbb657..13d46f6392f 100644 --- a/packages/nextcloud/test/webdav_test.dart +++ b/packages/nextcloud/test/webdav_test.dart @@ -5,7 +5,6 @@ import 'dart:typed_data'; import 'package:mocktail/mocktail.dart'; import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/src/utils/date_time.dart'; -import 'package:nextcloud/src/utils/http_date_parser.dart'; import 'package:nextcloud_test/nextcloud_test.dart'; import 'package:test/test.dart'; import 'package:test_api/src/backend/invoker.dart'; @@ -177,7 +176,7 @@ void main() { responses.singleWhere((response) => response.href!.endsWith('/Nextcloud.png')).propstats.first.prop; expect(props.ncHasPreview, isTrue); expect(props.davGetcontenttype, 'image/png'); - expect(parseHttpDate(props.davGetlastmodified!).isBefore(DateTime.timestamp()), isTrue); + expect(props.davGetlastmodified!.isBefore(DateTime.timestamp()), isTrue); expect(props.ocSize, 50598); }); @@ -191,7 +190,7 @@ void main() { }); test('Get file props', () async { - final response = (await client.webdav.propfind( + final result = await client.webdav.propfind( PathUri.parse('Nextcloud.png'), prop: const WebDavPropWithoutValues.fromBools( davCreationdate: true, @@ -253,9 +252,8 @@ void main() { ocmSharePermissions: true, ocsSharePermissions: true, ), - )) - .toWebDavFiles() - .single; + ); + final response = result.toWebDavFiles().single; expect(response.path, PathUri.parse('Nextcloud.png')); expect(response.id, isNotEmpty); @@ -281,11 +279,11 @@ void main() { expect(response.props.davGetcontentlength, 50598); expect(response.props.davGetcontenttype, 'image/png'); expect(response.props.davGetetag, isNotEmpty); - expect(parseHttpDate(response.props.davGetlastmodified!).isBefore(DateTime.timestamp()), isTrue); + expect(response.props.davGetlastmodified!.isBefore(DateTime.timestamp()), isTrue); expect(response.props.davQuotaAvailableBytes, isNull); expect(response.props.davQuotaUsedBytes, isNull); expect(response.props.davResourcetype!.collection, isNull); - expect(response.props.ncCreationTime, 0); + expect(response.props.ncCreationTime, DateTime.utc(1970)); expect(response.props.ncAclCanManage, isNull); expect(response.props.ncAclEnabled, isNull); expect(response.props.ncAclList, isNull); @@ -313,7 +311,7 @@ void main() { expect(response.props.ncRichWorkspaceFile, isNull); expect(json.decode(response.props.ncShareAttributes!), []); expect(response.props.ncSharees!.sharees, isNull); - expect(response.props.ncUploadTime, 0); + expect(response.props.ncUploadTime, DateTime.utc(1970)); expect(response.props.ncVersionAuthor, isNull); expect(response.props.ncVersionLabel, isNull); expect(response.props.ocChecksums, isNull); @@ -365,7 +363,7 @@ void main() { expect(response.props.davGetcontenttype, isNull); expect( - parseHttpDate(response.props.davGetlastmodified!).secondsSinceEpoch, + response.props.davGetlastmodified!.secondsSinceEpoch, closeTo(DateTime.timestamp().secondsSinceEpoch, 10), ); expect(response.props.davResourcetype!.collection, isNotNull); @@ -434,9 +432,9 @@ void main() { .first .prop; expect(props.ocFavorite, 1); - expect(parseHttpDate(props.davGetlastmodified!), lastModifiedDate); - expect(props.ncCreationTime, createdDate.secondsSinceEpoch); - expect(props.ncUploadTime, closeTo(uploadTime.secondsSinceEpoch, 10)); + expect(props.davGetlastmodified, lastModifiedDate); + expect(props.ncCreationTime, createdDate); + expect(props.ncUploadTime!.secondsSinceEpoch, closeTo(uploadTime.secondsSinceEpoch, 10)); }); test('Remove properties', () async {