浏览代码

Merge pull request #2154 from nextcloud/feature/widget

Feature/widget
Marino Faggiana 2 年之前
父节点
当前提交
a29241318a
共有 80 个文件被更改,包括 904 次插入545 次删除
  1. 4 2
      .swiftlint.yml
  2. 33 29
      Nextcloud.xcodeproj/project.pbxproj
  3. 二进制
      Widget/Assets.xcassets/nextcloud.imageset/nextcloud-icon29@1x.png
  4. 1 1
      Widget/Assets.xcassets/widget.imageset/Contents.json
  5. 二进制
      Widget/Assets.xcassets/widget.imageset/icons8-widgetsmith-250.png
  6. 200 0
      Widget/Dashboard.intentdefinition
  7. 105 44
      Widget/Dashboard/DashboardData.swift
  8. 11 7
      Widget/Dashboard/DashboardWidgetProvider.swift
  9. 117 31
      Widget/Dashboard/DashboardWidgetView.swift
  10. 32 28
      Widget/Files/FilesData.swift
  11. 8 8
      Widget/Files/FilesWidgetProvider.swift
  12. 18 22
      Widget/Files/FilesWidgetView.swift
  13. 1 1
      Widget/Toolbar/ToolbarData.swift
  14. 14 7
      Widget/Toolbar/ToolbarWidgetView.swift
  15. 0 59
      Widget/Widget.intentdefinition
  16. 10 10
      Widget/Widget.swift
  17. 3 3
      iOSClient/Activity/NCActivity.swift
  18. 1 0
      iOSClient/AppDelegate.swift
  19. 8 0
      iOSClient/Brand/iOSClient.plist
  20. 23 0
      iOSClient/Data/NCDatabase.swift
  21. 91 0
      iOSClient/Data/NCManageDatabase+DashboardWidget.swift
  22. 3 1
      iOSClient/Data/NCManageDatabase.swift
  23. 1 1
      iOSClient/Diagnostics/NCCapabilitiesViewController.swift
  24. 4 9
      iOSClient/Extensions/UIImage+Extensions.swift
  25. 2 13
      iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json
  26. 二进制
      iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).png
  27. 二进制
      iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).png
  28. 二进制
      iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).png
  29. 4 0
      iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image.svg
  30. 2 13
      iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json
  31. 二进制
      iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).png
  32. 二进制
      iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).png
  33. 二进制
      iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).png
  34. 4 0
      iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan.svg
  35. 5 5
      iOSClient/Images.xcassets/microphone.imageset/Contents.json
  36. 二进制
      iOSClient/Images.xcassets/microphone.imageset/Microphone.png
  37. 4 0
      iOSClient/Images.xcassets/microphone.imageset/icons8-microfono-400.svg
  38. 0 15
      iOSClient/Images.xcassets/microphone_off.imageset/Contents.json
  39. 二进制
      iOSClient/Images.xcassets/microphone_off.imageset/microphone_off.pdf
  40. 0 15
      iOSClient/Images.xcassets/modifyPhoto.imageset/Contents.json
  41. 二进制
      iOSClient/Images.xcassets/modifyPhoto.imageset/modifyPhoto.pdf
  42. 0 15
      iOSClient/Images.xcassets/moon.circle.imageset/Contents.json
  43. 二进制
      iOSClient/Images.xcassets/moon.circle.imageset/darkModeDetect.pdf
  44. 0 23
      iOSClient/Images.xcassets/navigationControllerMenu.imageset/Contents.json
  45. 二进制
      iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu.png
  46. 二进制
      iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu@2x.png
  47. 二进制
      iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu@3x.png
  48. 1 1
      iOSClient/Login/NCAppConfigView.swift
  49. 2 2
      iOSClient/Login/NCLogin.swift
  50. 1 1
      iOSClient/Login/NCLoginWeb.swift
  51. 2 2
      iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
  52. 4 4
      iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
  53. 2 2
      iOSClient/Media/NCMedia.swift
  54. 1 1
      iOSClient/Menu/AppDelegate+Menu.swift
  55. 1 1
      iOSClient/Menu/UIViewController+Menu.swift
  56. 1 1
      iOSClient/More/NCMore.swift
  57. 3 1
      iOSClient/NCGlobal.swift
  58. 19 35
      iOSClient/Networking/NCNetworking.swift
  59. 2 1
      iOSClient/Networking/NCNetworkingCheckRemoteUser.swift
  60. 11 11
      iOSClient/Networking/NCNetworkingE2EE.swift
  61. 44 27
      iOSClient/Networking/NCService.swift
  62. 1 1
      iOSClient/Notification/NCNotification.swift
  63. 1 1
      iOSClient/PushNotification/NCPushNotification.m
  64. 1 1
      iOSClient/Recent/NCRecent.swift
  65. 2 2
      iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
  66. 2 2
      iOSClient/ScanDocument/NCScan+CollectionView.swift
  67. 6 6
      iOSClient/Settings/NCEndToEndInitialize.swift
  68. 4 4
      iOSClient/Share/NCShareNetworking.swift
  69. 1 1
      iOSClient/Shares/NCShares.swift
  70. 5 4
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  71. 1 1
      iOSClient/Transfers/NCTransfers.swift
  72. 1 1
      iOSClient/Trash/NCTrash.swift
  73. 3 3
      iOSClient/UserStatus/NCUserStatus.swift
  74. 66 2
      iOSClient/Utility/NCUtility.swift
  75. 0 57
      iOSClient/Utility/NCUtilityGUI.swift
  76. 2 2
      iOSClient/Viewer/NCViewer.swift
  77. 2 1
      iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
  78. 0 1
      iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
  79. 1 1
      iOSClient/Viewer/NCViewerProviderContextMenu.swift
  80. 2 2
      iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift

+ 4 - 2
.swiftlint.yml

@@ -42,8 +42,9 @@ excluded:
   - File Provider Extension/FileProviderUtility.swift
   - Notification Service Extension/NotificationService.swift
   - Widget/Dashboard/DashboardData.swift
-  - Widget/Nextcloud/NextcloudData.swift
-  - Widget/Nextcloud/NextcloudWidgetView.swift
+  - Widget/Dashboard/DashboardWidgetView.swift
+  - Widget/Files/FilesData.swift
+  - Widget/Files/FilesWidgetView.swift
   - iOSClient/Activity/NCActivity.swift
   - iOSClient/Activity/NCActivityTableViewCell.swift
   - iOSClient/AppDelegate.swift
@@ -59,6 +60,7 @@ excluded:
   - iOSClient/Data/NCManageDatabase.swift
   - iOSClient/Data/NCManageDatabase+Metadata.swift
   - iOSClient/Data/NCManageDatabase+Video.swift
+  - iOSClient/Data/NCManageDatabase+DashboardWidget.swift
   - iOSClient/Diagnostics/NCCapabilitiesViewController.swift
   - iOSClient/EmptyView/NCEmptyDataSet.swift
   - iOSClient/Extensions/UIColor+Extensions.swift

+ 33 - 29
Nextcloud.xcodeproj/project.pbxproj

@@ -144,7 +144,7 @@
 		F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */; };
 		F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */; };
 		F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; };
-		F71EB73728CA81D1007FAB9D /* Widget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */; };
+		F71EB73728CA81D1007FAB9D /* Dashboard.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F71EB73628CA81D1007FAB9D /* Dashboard.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; };
 		F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7226EDB1EE4089300EBECB1 /* Main.storyboard */; };
 		F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */; };
 		F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; };
@@ -156,6 +156,7 @@
 		F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
 		F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F72685E927C78E490019EF5E /* InfoPlist.strings */; };
 		F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */; };
+		F729027128CF503E00180CF4 /* Dashboard.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F71EB73628CA81D1007FAB9D /* Dashboard.intentdefinition */; };
 		F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F729289F253B0937009CA4FD /* NCMainNavigationController.swift */; };
 		F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */; };
 		F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */; };
@@ -170,9 +171,9 @@
 		F72D7EB7263B1207000B3DFC /* MarkdownKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72D7EB6263B1207000B3DFC /* MarkdownKit */; };
 		F72DA9B425F53E4E00B87DB1 /* SwiftRichString in Frameworks */ = {isa = PBXBuildFile; productRef = F72DA9B325F53E4E00B87DB1 /* SwiftRichString */; };
 		F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95128B7BA2A00C88F0C /* DashboardWidgetProvider.swift */; };
-		F72EA95428B7BABA00C88F0C /* NextcloudWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */; };
-		F72EA95828B7BC4F00C88F0C /* NextcloudData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */; };
-		F72EA95A28B7BD0D00C88F0C /* NextcloudWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */; };
+		F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95328B7BABA00C88F0C /* FilesWidgetProvider.swift */; };
+		F72EA95828B7BC4F00C88F0C /* FilesData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95728B7BC4F00C88F0C /* FilesData.swift */; };
+		F72EA95A28B7BD0D00C88F0C /* FilesWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EA95928B7BD0D00C88F0C /* FilesWidgetView.swift */; };
 		F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */; };
 		F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733598025C1C188002ABA72 /* NCAskAuthorization.swift */; };
 		F7346E1228B0EF5B006CE2D2 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7346E1128B0EF5B006CE2D2 /* WidgetKit.framework */; };
@@ -422,14 +423,15 @@
 		F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; };
 		F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; };
 		F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; };
+		F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
+		F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
+		F7D68FCE28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
+		F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
+		F7D68FD028CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
 		F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */; };
 		F7DBC37C23325E02001A85BA /* NCAppConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */; };
 		F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
 		F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */; };
-		F7E03DBC28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
-		F7E03DBD28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
-		F7E03DBE28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
-		F7E03DBF28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */; };
 		F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E0710028B13BB00001B882 /* DashboardData.swift */; };
 		F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; };
 		F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */; };
@@ -708,7 +710,7 @@
 		F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerMediaDetailView.swift; sourceTree = "<group>"; };
 		F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCColorPicker.storyboard; sourceTree = "<group>"; };
 		F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = "<group>"; };
-		F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.intentdefinition; path = Widget.intentdefinition; sourceTree = "<group>"; };
+		F71EB73628CA81D1007FAB9D /* Dashboard.intentdefinition */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.intentdefinition; path = Dashboard.intentdefinition; sourceTree = "<group>"; };
 		F7226EDB1EE4089300EBECB1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
 		F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = "<group>"; };
 		F7239870253D86B600257F49 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = "<group>"; };
@@ -729,9 +731,9 @@
 		F72D404823D2082500A97FD0 /* NCViewerNextcloudText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerNextcloudText.swift; sourceTree = "<group>"; };
 		F72E0B9C21AD60BC00898D7B /* WeScan.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WeScan.framework; path = Carthage/Build/iOS/WeScan.framework; sourceTree = "<group>"; };
 		F72EA95128B7BA2A00C88F0C /* DashboardWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardWidgetProvider.swift; sourceTree = "<group>"; };
-		F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudWidgetProvider.swift; sourceTree = "<group>"; };
-		F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudData.swift; sourceTree = "<group>"; };
-		F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudWidgetView.swift; sourceTree = "<group>"; };
+		F72EA95328B7BABA00C88F0C /* FilesWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesWidgetProvider.swift; sourceTree = "<group>"; };
+		F72EA95728B7BC4F00C88F0C /* FilesData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesData.swift; sourceTree = "<group>"; };
+		F72EA95928B7BD0D00C88F0C /* FilesWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesWidgetView.swift; sourceTree = "<group>"; };
 		F7320934201B812F008A0888 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F732093B201B81E4008A0888 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCPlayerToolBar.xib; sourceTree = "<group>"; };
@@ -1004,13 +1006,13 @@
 		F7D532541F5D4155006568B1 /* sk-SK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sk-SK"; path = "sk-SK.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7D5328F1F5D443B006568B1 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7D532A41F5D4461006568B1 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+DashboardWidget.swift"; sourceTree = "<group>"; };
 		F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCNetworkingCheckRemoteUser.swift; sourceTree = "<group>"; };
 		F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCAppConfigView.swift; sourceTree = "<group>"; };
 		F7DBD82B23E46A4700ECB7C6 /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = "<group>"; };
 		F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadAssets.swift; sourceTree = "<group>"; };
 		F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = "<group>"; };
-		F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUtilityGUI.swift; sourceTree = "<group>"; };
 		F7E0710028B13BB00001B882 /* DashboardData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardData.swift; sourceTree = "<group>"; };
 		F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = "<group>"; };
 		F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -1371,14 +1373,14 @@
 			path = Dashboard;
 			sourceTree = "<group>";
 		};
-		F72EA95628B7BAE700C88F0C /* Nextcloud */ = {
+		F72EA95628B7BAE700C88F0C /* Files */ = {
 			isa = PBXGroup;
 			children = (
-				F72EA95728B7BC4F00C88F0C /* NextcloudData.swift */,
-				F72EA95328B7BABA00C88F0C /* NextcloudWidgetProvider.swift */,
-				F72EA95928B7BD0D00C88F0C /* NextcloudWidgetView.swift */,
+				F72EA95728B7BC4F00C88F0C /* FilesData.swift */,
+				F72EA95328B7BABA00C88F0C /* FilesWidgetProvider.swift */,
+				F72EA95928B7BD0D00C88F0C /* FilesWidgetView.swift */,
 			);
-			path = Nextcloud;
+			path = Files;
 			sourceTree = "<group>";
 		};
 		F7346E1428B0EF5B006CE2D2 /* Widget */ = {
@@ -1386,10 +1388,10 @@
 			children = (
 				F7346E2228B0FEBA006CE2D2 /* Assets.xcassets */,
 				F72EA95528B7BAD100C88F0C /* Dashboard */,
-				F72EA95628B7BAE700C88F0C /* Nextcloud */,
+				F72EA95628B7BAE700C88F0C /* Files */,
 				F77ED59628C9CEEE00E24ED0 /* Toolbar */,
 				F7346E2028B0FA3A006CE2D2 /* Widget-Brinding-header.h */,
-				F71EB73628CA81D1007FAB9D /* Widget.intentdefinition */,
+				F71EB73628CA81D1007FAB9D /* Dashboard.intentdefinition */,
 				F7346E1528B0EF5C006CE2D2 /* Widget.swift */,
 			);
 			path = Widget;
@@ -1688,6 +1690,7 @@
 				F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */,
 				AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */,
 				AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */,
+				F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */,
 				AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */,
 				F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */,
 				F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */,
@@ -1719,7 +1722,6 @@
 				F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */,
 				F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
 				F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
-				F7E03DBB28BB48E4009AFDA1 /* NCUtilityGUI.swift */,
 				F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */,
 				AF93474B27E34120002537EE /* NCUtility+Image.swift */,
 				AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */,
@@ -2604,6 +2606,7 @@
 				2C1D5D7523E2DE3300334ABB /* NCDatabase.swift in Sources */,
 				F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
 				2C1D5D7623E2DE3300334ABB /* NCManageDatabase.swift in Sources */,
+				F7D68FD028CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */,
 				2C33C48223E2C475005F963B /* NotificationService.swift in Sources */,
 				AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
@@ -2669,10 +2672,10 @@
 				AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */,
 				F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */,
 				F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */,
-				F7E03DBE28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
+				F7D68FCE28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				AF22B217277D196700DAB0CC /* NCShareExtension+DataSource.swift in Sources */,
 				F76D364728A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
 				F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
@@ -2694,15 +2697,14 @@
 				F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */,
 				F783030328B4C4DD00B84583 /* ThreadSafeDictionary.swift in Sources */,
 				F77ED59128C9CE9D00E24ED0 /* ToolbarData.swift in Sources */,
-				F7E03DBD28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F78302F728B4C3C900B84583 /* NCManageDatabase.swift in Sources */,
 				F7346E1628B0EF5C006CE2D2 /* Widget.swift in Sources */,
 				F78302F828B4C3E100B84583 /* NCManageDatabase+Activity.swift in Sources */,
 				F783030228B4C4B800B84583 /* NCUtility.swift in Sources */,
-				F72EA95A28B7BD0D00C88F0C /* NextcloudWidgetView.swift in Sources */,
+				F72EA95A28B7BD0D00C88F0C /* FilesWidgetView.swift in Sources */,
 				F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */,
 				F793E5A028B7651B005E4B02 /* NCViewCertificateDetails.swift in Sources */,
-				F71EB73728CA81D1007FAB9D /* Widget.intentdefinition in Sources */,
+				F71EB73728CA81D1007FAB9D /* Dashboard.intentdefinition in Sources */,
 				F793E59F28B764F6005E4B02 /* NCContentPresenter.swift in Sources */,
 				F78302FA28B4C3EA00B84583 /* NCManageDatabase+Metadata.swift in Sources */,
 				F783030728B4C52800B84583 /* UIColor+Extensions.swift in Sources */,
@@ -2719,12 +2721,13 @@
 				F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */,
 				F793E5A228B76580005E4B02 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F783031228B4C8EC00B84583 /* CCUtility.m in Sources */,
-				F72EA95828B7BC4F00C88F0C /* NextcloudData.swift in Sources */,
+				F72EA95828B7BC4F00C88F0C /* FilesData.swift in Sources */,
 				F793E59E28B763C2005E4B02 /* NCAskAuthorization.swift in Sources */,
 				F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */,
 				F78302F628B4C3C500B84583 /* NCDatabase.swift in Sources */,
+				F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				F783030128B4C49700B84583 /* UIImage+Extensions.swift in Sources */,
-				F72EA95428B7BABA00C88F0C /* NextcloudWidgetProvider.swift in Sources */,
+				F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2747,6 +2750,7 @@
 				AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */,
 				F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */,
+				F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
 				F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
@@ -2755,7 +2759,6 @@
 				AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F771E3F320E239A600AFB62D /* FileProviderData.swift in Sources */,
 				F7B8CD9B261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
-				F7E03DBF28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
 				F7A0D1372591FBC5008F8A13 /* String+Extensions.swift in Sources */,
 				F771E3D720E2392D00AFB62D /* FileProviderEnumerator.swift in Sources */,
 				F74AF3A6247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
@@ -2918,6 +2921,7 @@
 				F7725A60251F33BB00D125E0 /* NCFiles.swift in Sources */,
 				F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
 				F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,
+				F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */,
 				F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */,
 				F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */,
@@ -2927,7 +2931,7 @@
 				F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */,
 				F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */,
 				F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */,
-				F7E03DBC28BB48E4009AFDA1 /* NCUtilityGUI.swift in Sources */,
+				F729027128CF503E00180CF4 /* Dashboard.intentdefinition in Sources */,
 				F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */,
 				F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */,
 				F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */,

二进制
Widget/Assets.xcassets/nextcloud.imageset/nextcloud-icon29@1x.png


+ 1 - 1
Widget/Assets.xcassets/nextcloud.imageset/Contents.json → Widget/Assets.xcassets/widget.imageset/Contents.json

@@ -1,7 +1,7 @@
 {
   "images" : [
     {
-      "filename" : "nextcloud-icon29@1x.png",
+      "filename" : "icons8-widgetsmith-250.png",
       "idiom" : "universal"
     }
   ],

二进制
Widget/Assets.xcassets/widget.imageset/icons8-widgetsmith-250.png


+ 200 - 0
Widget/Dashboard.intentdefinition

@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>INEnums</key>
+	<array>
+		<dict>
+			<key>INEnumDisplayName</key>
+			<string>Applications</string>
+			<key>INEnumDisplayNameID</key>
+			<string>9yMkyI</string>
+			<key>INEnumGeneratesHeader</key>
+			<true/>
+			<key>INEnumName</key>
+			<string>Applications</string>
+			<key>INEnumType</key>
+			<string>Regular</string>
+			<key>INEnumValues</key>
+			<array>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>unknown</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>EVRbMg</string>
+					<key>INEnumValueName</key>
+					<string>unknown</string>
+				</dict>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>Notes</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>jHprBS</string>
+					<key>INEnumValueIndex</key>
+					<integer>1</integer>
+					<key>INEnumValueName</key>
+					<string>notes</string>
+				</dict>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>Deck</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>zqY55O</string>
+					<key>INEnumValueIndex</key>
+					<integer>2</integer>
+					<key>INEnumValueName</key>
+					<string>deck</string>
+				</dict>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>Recommendations</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>maQPuV</string>
+					<key>INEnumValueIndex</key>
+					<integer>3</integer>
+					<key>INEnumValueName</key>
+					<string>recommendations</string>
+				</dict>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>User status</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>oMvXKY</string>
+					<key>INEnumValueIndex</key>
+					<integer>4</integer>
+					<key>INEnumValueName</key>
+					<string>user_status</string>
+				</dict>
+				<dict>
+					<key>INEnumValueDisplayName</key>
+					<string>Activity</string>
+					<key>INEnumValueDisplayNameID</key>
+					<string>roy1t6</string>
+					<key>INEnumValueIndex</key>
+					<integer>5</integer>
+					<key>INEnumValueName</key>
+					<string>activity</string>
+				</dict>
+			</array>
+		</dict>
+	</array>
+	<key>INIntentDefinitionModelVersion</key>
+	<string>1.2</string>
+	<key>INIntentDefinitionNamespace</key>
+	<string>88xZPY</string>
+	<key>INIntentDefinitionSystemVersion</key>
+	<string>21G83</string>
+	<key>INIntentDefinitionToolsBuildVersion</key>
+	<string>13F100</string>
+	<key>INIntentDefinitionToolsVersion</key>
+	<string>13.4.1</string>
+	<key>INIntents</key>
+	<array>
+		<dict>
+			<key>INIntentCategory</key>
+			<string>information</string>
+			<key>INIntentDescriptionID</key>
+			<string>tVvJ9c</string>
+			<key>INIntentEligibleForWidgets</key>
+			<true/>
+			<key>INIntentIneligibleForSuggestions</key>
+			<true/>
+			<key>INIntentLastParameterTag</key>
+			<integer>6</integer>
+			<key>INIntentName</key>
+			<string>Dashboard</string>
+			<key>INIntentParameters</key>
+			<array>
+				<dict>
+					<key>INIntentParameterConfigurable</key>
+					<true/>
+					<key>INIntentParameterDisplayName</key>
+					<string>Application</string>
+					<key>INIntentParameterDisplayNameID</key>
+					<string>TRaTZg</string>
+					<key>INIntentParameterDisplayPriority</key>
+					<integer>1</integer>
+					<key>INIntentParameterEnumType</key>
+					<string>Applications</string>
+					<key>INIntentParameterEnumTypeNamespace</key>
+					<string>88xZPY</string>
+					<key>INIntentParameterMetadata</key>
+					<dict>
+						<key>INIntentParameterMetadataDefaultValue</key>
+						<string>recommendations</string>
+					</dict>
+					<key>INIntentParameterName</key>
+					<string>Applications</string>
+					<key>INIntentParameterPromptDialogs</key>
+					<array>
+						<dict>
+							<key>INIntentParameterPromptDialogCustom</key>
+							<true/>
+							<key>INIntentParameterPromptDialogType</key>
+							<string>Configuration</string>
+						</dict>
+						<dict>
+							<key>INIntentParameterPromptDialogCustom</key>
+							<true/>
+							<key>INIntentParameterPromptDialogType</key>
+							<string>Primary</string>
+						</dict>
+						<dict>
+							<key>INIntentParameterPromptDialogCustom</key>
+							<true/>
+							<key>INIntentParameterPromptDialogFormatString</key>
+							<string>There are ${count} options matching ‘${Applications}’.</string>
+							<key>INIntentParameterPromptDialogFormatStringID</key>
+							<string>qZKu0p</string>
+							<key>INIntentParameterPromptDialogType</key>
+							<string>DisambiguationIntroduction</string>
+						</dict>
+						<dict>
+							<key>INIntentParameterPromptDialogCustom</key>
+							<true/>
+							<key>INIntentParameterPromptDialogFormatString</key>
+							<string>Just to confirm, you wanted ‘${Applications}’?</string>
+							<key>INIntentParameterPromptDialogFormatStringID</key>
+							<string>XKkeMc</string>
+							<key>INIntentParameterPromptDialogType</key>
+							<string>Confirmation</string>
+						</dict>
+					</array>
+					<key>INIntentParameterTag</key>
+					<integer>6</integer>
+					<key>INIntentParameterType</key>
+					<string>Integer</string>
+				</dict>
+			</array>
+			<key>INIntentResponse</key>
+			<dict>
+				<key>INIntentResponseCodes</key>
+				<array>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>success</string>
+						<key>INIntentResponseCodeSuccess</key>
+						<true/>
+					</dict>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>failure</string>
+					</dict>
+				</array>
+				<key>INIntentResponseLastParameterTag</key>
+				<integer>1</integer>
+			</dict>
+			<key>INIntentTitle</key>
+			<string>titolo</string>
+			<key>INIntentTitleID</key>
+			<string>gpCwrM</string>
+			<key>INIntentType</key>
+			<string>Custom</string>
+			<key>INIntentVerb</key>
+			<string>View</string>
+		</dict>
+	</array>
+	<key>INTypes</key>
+	<array/>
+</dict>
+</plist>

+ 105 - 44
Widget/Dashboard/DashboardData.swift

@@ -23,67 +23,83 @@
 
 import WidgetKit
 import NextcloudKit
+import Queuer
+import RealmSwift
 
-let dashboaardItems = 4
+let dashboaardItems = 5
 
 struct DashboardDataEntry: TimelineEntry {
     let date: Date
     let datas: [DashboardData]
+    let tableDashboard: tableDashboardWidget?
+    let tableButton: Results<tableDashboardWidgetButton>?
     let isPlaceholder: Bool
+    let titleImage: UIImage
     let title: String
     let footerImage: String
     let footerText: String
 }
 
 struct DashboardData: Identifiable, Hashable {
-    var id: String
-    var image: UIImage
-    var title: String
-    var subTitle: String
-    var url: URL
+    let id: Int
+    let title: String
+    let subTitle: String
+    let link: URL
+    let icon: UIImage
+}
+
+struct DashboardDataButton: Hashable {
+    let type: String
+    let Text: String
+    let link: String
 }
 
 let dashboardDatasTest: [DashboardData] = [
-    .init(id: "1", image: UIImage(named: "nextcloud")!, title: "title1", subTitle: "subTitle-description1", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "2", image: UIImage(named: "nextcloud")!, title: "title2", subTitle: "subTitle-description2", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "3", image: UIImage(named: "nextcloud")!, title: "title3", subTitle: "subTitle-description3", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "4", image: UIImage(named: "nextcloud")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "5", image: UIImage(named: "nextcloud")!, title: "title5", subTitle: "subTitle-description5", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "6", image: UIImage(named: "nextcloud")!, title: "title6", subTitle: "subTitle-description6", url: URL(string: "https://nextcloud.com/")!)
+    .init(id: 0, title: "title0", subTitle: "subTitle-description0", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 1, title: "title1", subTitle: "subTitle-description1", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 2, title: "title2", subTitle: "subTitle-description2", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 3, title: "title3", subTitle: "subTitle-description3", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 4, title: "title4", subTitle: "subTitle-description4", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 5, title: "title5", subTitle: "subTitle-description5", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 6, title: "title6", subTitle: "subTitle-description6", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 7, title: "title7", subTitle: "subTitle-description7", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 8, title: "title8", subTitle: "subTitle-description8", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!),
+    .init(id: 9, title: "title9", subTitle: "subTitle-description9", link: URL(string: "https://nextcloud.com/")!, icon: UIImage(named: "widget")!)
 ]
 
-func getTitleDashboard() -> String {
-
-    let hour = Calendar.current.component(.hour, from: Date())
-    var good = ""
-
-    switch hour {
-    case 6..<12: good = NSLocalizedString("_good_morning_", value: "Good morning", comment: "")
-    case 12: good = NSLocalizedString("_good_noon_", value: "Good noon", comment: "")
-    case 13..<17: good = NSLocalizedString("_good_afternoon_", value: "Good afternoon", comment: "")
-    case 17..<22: good = NSLocalizedString("_good_evening_", value: "Good evening", comment: "")
-    default: good = NSLocalizedString("_good_night_", value: "Good night", comment: "")
-    }
-
-    if let account = NCManageDatabase.shared.getActiveAccount() {
-        return good + ", " + account.displayName
-    } else {
-        return good
-    }
-}
-
-func getDashboardDataEntry(isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: DashboardDataEntry) -> Void) {
+func getDashboardDataEntry(intent: Applications, isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: DashboardDataEntry) -> Void) {
 
     let datasPlaceholder = Array(dashboardDatasTest[0...dashboaardItems - 1])
+    var id = "recommendations"
+    switch intent {
+    case .unknown:
+        id = "recommendations"
+    case .notes:
+        id = "notes"
+    case .deck:
+        id = "deck"
+    case .recommendations:
+        id = "recommendations"
+    case .activity:
+        id = "activity"
+    case .user_status:
+        id = "user_status"
+    }
     
     if isPreview {
-        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, tableDashboard: nil, tableButton: nil, isPlaceholder: true, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
     }
 
     guard let account = NCManageDatabase.shared.getActiveAccount() else {
-        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
+        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, tableDashboard: nil, tableButton: nil, isPlaceholder: true, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", comment: "")))
     }
     
+    let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+
+    guard serverVersionMajor >= NCGlobal.shared.nextcloudVersion25 else {
+        return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, tableDashboard: nil, tableButton: nil, isPlaceholder: true, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_widget_available_nc25_", comment: "")))
+    }
+        
     // NETWORKING
     let password = CCUtility.getPassword(account.account)!
     NKCommon.shared.setup(
@@ -111,27 +127,72 @@ func getDashboardDataEntry(isPreview: Bool, displaySize: CGSize, completion: @es
         NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) dashboard widget session with level \(levelLog) " + versionNextcloudiOS)
     }
     
-    NextcloudKit.shared.getDashboard { account, dashboardResults, json, error in
+    let (tableDashboard, tableButton) = NCManageDatabase.shared.getDashboardWidget(account: account.account, id: id)
+    let existsButton: Int = tableButton == nil ? 0 : 1
+    let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+    let title = tableDashboard?.title ?? id
+    var titleImage = UIImage(named: "widget")!
+
+    if let fileName = tableDashboard?.iconClass {
+        let fileNamePath: String = CCUtility.getDirectoryUserData() + "/" + fileName + ".png"
+        if let image = UIImage(contentsOfFile: fileNamePath) {
+            titleImage = image.imageColor(NCBrandColor.shared.label)
+        }
+    }
+        
+    NextcloudKit.shared.getDashboardWidgetsApplication(id, options: options) { account, results, data, error in
         
         var datas = [DashboardData]()
         
-        if let dashboardResults = dashboardResults {
-            for dashboardResult in dashboardResults {
-                let application = dashboardResult.application
-                if let entries = dashboardResult.dashboardEntries {
-                    for entry in entries {
+        if let results = results {
+            for result in results {
+                if let items = result.items {
+                    var counter: Int = 0
+                    let maxCounter = dashboaardItems - existsButton
+                    for item in items {
+                        counter += 1
+                        let title = item.title ?? ""
+                        let subtitle = item.subtitle ?? ""
+                        var link = URL(string: "https://")!
+                        if let entryLink = item.link, let url = URL(string: entryLink){ link = url }
+                        var icon = UIImage(named: "file")!
+                        var iconFileName: String?
+
+                        if let iconUrl = item.iconUrl, let url = URL(string: iconUrl) {
+                            if let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {
+                                let queryItems = urlComponents.queryItems
+                                if let item = CCUtility.value(forKey: "fileId", fromQueryItems: queryItems) {
+                                    iconFileName = item
+                                } else {
+                                    let path = (urlComponents.path as NSString)
+                                    iconFileName = ((path.lastPathComponent) as NSString).deletingPathExtension
+                                }
+                            }
+                            let semaphore = Semaphore()
+                            NCUtility.shared.getImageUserData(url: url, fileName: iconFileName , size: 128) { image in
+                                if let image = image {
+                                    icon = image
+                                }
+                                semaphore.continue()
+                            }
+                            semaphore.wait()
+                        }
+                        
+                        let data = DashboardData(id: counter, title: title, subTitle: subtitle, link: link, icon: icon)
+                        datas.append(data)
                         
+                        if datas.count == maxCounter { break }
                     }
                 }
             }
         }
         
         if error != .success {
-            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "xmark.icloud", footerText: error.errorDescription))
+            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, tableDashboard: tableDashboard, tableButton: tableButton, isPlaceholder: true, titleImage: titleImage, title: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
         } else if datas.isEmpty {
-            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+            completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, tableDashboard: tableDashboard, tableButton: tableButton, isPlaceholder: true, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: NSLocalizedString("_no_data_available_", comment: "")))
         } else {
-            completion(DashboardDataEntry(date: Date(), datas: datas, isPlaceholder: false, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
+            completion(DashboardDataEntry(date: Date(), datas: datas, tableDashboard: tableDashboard, tableButton: tableButton, isPlaceholder: false, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
         }
     }
 }

+ 11 - 7
Widget/Dashboard/DashboardWidgetProvider.swift

@@ -23,24 +23,28 @@
 
 import WidgetKit
 import SwiftUI
+import Intents
 
-struct DashboardWidgetProvider: TimelineProvider {
+struct DashboardWidgetProvider: IntentTimelineProvider {
 
+    typealias Intent = DashboardIntent
     typealias Entry = DashboardDataEntry
 
     func placeholder(in context: Context) -> Entry {
-        let datasPlaceholder = Array(dashboardDatasTest[0...nextcloudItems - 1])
-        return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, title: getTitleDashboard(), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
+        let datasPlaceholder = Array(dashboardDatasTest[0...dashboaardItems - 1])
+        let title = "Dashboard"
+        let titleImage = UIImage(named: "widget")!
+        return Entry(date: Date(), datas: datasPlaceholder, tableDashboard: nil, tableButton: nil, isPlaceholder: true, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
     }
 
-    func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
-        getDashboardDataEntry(isPreview: false, displaySize: context.displaySize) { entry in
+    func getSnapshot(for configuration: DashboardIntent, in context: Context, completion: @escaping (DashboardDataEntry) -> Void) {
+        getDashboardDataEntry(intent: configuration.Applications, isPreview: false, displaySize: context.displaySize) { entry in
             completion(entry)
         }
     }
 
-    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
-        getDashboardDataEntry(isPreview: context.isPreview, displaySize: context.displaySize) { entry in
+    func getTimeline(for configuration: DashboardIntent, in context: Context, completion: @escaping (Timeline<DashboardDataEntry>) -> Void) {
+        getDashboardDataEntry(intent: configuration.Applications, isPreview: context.isPreview, displaySize: context.displaySize) { entry in
             let timeLine = Timeline(entries: [entry], policy: .atEnd)
             completion(timeLine)
         }

+ 117 - 31
Widget/Dashboard/DashboardWidgetView.swift

@@ -25,51 +25,137 @@ import SwiftUI
 import WidgetKit
 
 struct DashboardWidgetView: View {
+
     var entry: DashboardDataEntry
+    let brandColor = Color(NCBrandColor.shared.brand)
+    let brandTextColor = Color(NCBrandColor.shared.brandText)
+    
     var body: some View {
-        ZStack(alignment: .top) {
-            VStack {
-                Text(entry.title)
-                    .font(.title3)
-                    .bold()
-                    .fixedSize(horizontal: false, vertical: true)
-                VStack(spacing: 5) {
-                    ForEach(entry.datas, id: \.id) { element in
-                        Link(destination: element.url) {
-                            HStack {
-                                Image(uiImage: element.image)
-                                    .resizable()
-                                    .aspectRatio(contentMode: .fit)
-                                    .frame(width: 40, height: 40)
-                                    .clipShape(Circle())
-                                VStack(alignment: .leading) {
-                                    Text(element.title)
-                                        .font(.headline)
-                                    Text(element.subTitle)
-                                        .font(.subheadline)
-                                        .foregroundColor(Color(white: 0.4745))
+        
+        GeometryReader { geo in
+
+            ZStack(alignment: .topLeading) {
+
+                HStack() {
+                    
+                    Image(uiImage: entry.titleImage)
+                        .resizable()
+                        .scaledToFill()
+                        .frame(width: 20, height: 20)
+                    
+                    Text(entry.title)
+                        .font(.system(size: 15))
+                        .fontWeight(.bold)
+                        .multilineTextAlignment(.center)
+                        .textCase(.uppercase)
+                        .lineLimit(1)
+                }
+                .frame(width: geo.size.width - 20)
+                .padding([.top, .leading, .trailing], 10)
+                
+                VStack(alignment: .leading) {
+                    
+                    VStack(spacing: 0) {
+                                                
+                        ForEach(entry.datas, id: \.id) { element in
+                            
+                            Link(destination: element.link) {
+                                
+                                HStack {
+                                    
+                                    let subTitleColor = Color(white: 0.5)
+                                    let imageSize:CGFloat = 35
+                                    
+                                    if entry.tableDashboard?.itemIconsRound ?? false {
+                                        Image(uiImage: element.icon)
+                                            .resizable()
+                                            .scaledToFill()
+                                            .frame(width: imageSize, height: imageSize)
+                                            .clipShape(Circle())
+                                            .overlay(Circle().stroke(Color.white, lineWidth: 1))
+                                    } else {
+                                        Image(uiImage: element.icon)
+                                            .resizable()
+                                            .scaledToFill()
+                                            .frame(width: imageSize, height: imageSize)
+                                            .clipped()
+                                            .cornerRadius(5)
+                                    }
+
+                                    VStack(alignment: .leading, spacing: 2) {
+
+                                        Text(element.title)
+                                            .font(.system(size: 12))
+                                            .fontWeight(.regular)
+
+                                        Text(element.subTitle)
+                                            .font(.system(size: CGFloat(10)))
+                                            .foregroundColor(subTitleColor)
+                                    }
+                                    Spacer()
                                 }
-                                Spacer()
+                                .padding(.leading, 10)
+                                .frame(height: 45)
                             }
-                            .padding(5)
+                            Divider()
+                                .padding(.leading, 54)
                         }
                     }
                 }
-            }.padding(5)
+                .padding(.top, 40)
                 .redacted(reason: entry.isPlaceholder ? .placeholder : [])
-            Text(entry.footerText)
-                    .font(.caption2)
-                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
-                    .padding(.trailing, 10.0)
-                    .padding(.bottom, 5.0)
+
+                if let tableButton = entry.tableButton, !tableButton.isEmpty {
+                    
+                    HStack(spacing: 10) {
+
+                        let brandColor = Color(NCBrandColor.shared.brand)
+                        let brandTextColor = Color(NCBrandColor.shared.brandText)
+
+                        ForEach(tableButton, id: \.index) { element in
+                            Link(destination: URL(string: element.link)! , label: {
+                                
+                                Text(element.text)
+                                    .font(.system(size: 18))
+                                    .padding(7)
+                                    .background(brandColor)
+                                    .foregroundColor(brandTextColor)
+                                    .border(brandColor, width: 1)
+                                    .cornerRadius(17)
+                            })
+                        }
+                    }
+                    .frame(width: geo.size.width - 10, height: geo.size.height - 28, alignment: .bottomTrailing)
+                }
+                
+                HStack {
+
+                    let placeholderColor = Color(white: 0.2)
+                    let brandColor = Color(NCBrandColor.shared.brand)
+                    
+                    Image(systemName: entry.footerImage)
+                        .resizable()
+                        .scaledToFit()
+                        .frame(width: 15, height: 15)
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
+
+                    Text(entry.footerText)
+                        .font(.caption2)
+                        .padding(.trailing, 13.0)
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
+                }
+                .frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
+            }
         }
     }
 }
 
 struct DashboardWidget_Previews: PreviewProvider {
     static var previews: some View {
-        let datas = Array(dashboardDatasTest[0...3])
-        let entry = DashboardDataEntry(date: Date(), datas: datas, isPlaceholder: false, title: "Dashboard", footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
+        let datas = Array(dashboardDatasTest[0...dashboaardItems - 1])
+        let title = "Dashboard"
+        let titleImage = UIImage(named: "widget")!
+        let entry = DashboardDataEntry(date: Date(), datas: datas, tableDashboard: nil, tableButton: nil, isPlaceholder: false, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
         DashboardWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
     }
 }

+ 32 - 28
Widget/Nextcloud/NextcloudData.swift → Widget/Files/FilesData.swift

@@ -1,5 +1,5 @@
 //
-//  NextcloudData.swift
+//  FilesData.swift
 //  Widget
 //
 //  Created by Marino Faggiana on 25/08/22.
@@ -24,18 +24,18 @@
 import WidgetKit
 import NextcloudKit
 
-let nextcloudItems = 4
+let filesItems = 4
 
-struct NextcloudDataEntry: TimelineEntry {
+struct FilesDataEntry: TimelineEntry {
     let date: Date
-    let datas: [NextcloudRecentData]
+    let datas: [FilesData]
     let isPlaceholder: Bool
     let tile: String
     let footerImage: String
     let footerText: String
 }
 
-struct NextcloudRecentData: Identifiable, Hashable {
+struct FilesData: Identifiable, Hashable {
     var id: String
     var image: UIImage
     var title: String
@@ -43,23 +43,22 @@ struct NextcloudRecentData: Identifiable, Hashable {
     var url: URL
 }
 
-let recentDatasTest: [NextcloudRecentData] = [
-    .init(id: "1", image: UIImage(named: "nextcloud")!, title: "title1", subTitle: "subTitle-description1", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "2", image: UIImage(named: "nextcloud")!, title: "title2", subTitle: "subTitle-description2", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "3", image: UIImage(named: "nextcloud")!, title: "title3", subTitle: "subTitle-description3", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "4", image: UIImage(named: "nextcloud")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "5", image: UIImage(named: "nextcloud")!, title: "title5", subTitle: "subTitle-description5", url: URL(string: "https://nextcloud.com/")!),
-    .init(id: "6", image: UIImage(named: "nextcloud")!, title: "title6", subTitle: "subTitle-description6", url: URL(string: "https://nextcloud.com/")!)
+let filesDatasTest: [FilesData] = [
+    .init(id: "0", image: UIImage(named: "widget")!, title: "title1", subTitle: "subTitle-description1", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "1", image: UIImage(named: "widget")!, title: "title2", subTitle: "subTitle-description2", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "2", image: UIImage(named: "widget")!, title: "title3", subTitle: "subTitle-description3", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "3", image: UIImage(named: "widget")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!),
+    .init(id: "4", image: UIImage(named: "widget")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!)
 ]
 
-func getTitleNextcloudWidget() -> String {
+func getTitleFilesWidget() -> String {
 
     let hour = Calendar.current.component(.hour, from: Date())
     var good = ""
 
     switch hour {
     case 6..<12: good = NSLocalizedString("_good_morning_", value: "Good morning", comment: "")
-    case 12: good = NSLocalizedString("_good_noon_", value: "Good noon", comment: "")
+    case 12: good = NSLocalizedString("_good_day_", value: "Good day", comment: "")
     case 13..<17: good = NSLocalizedString("_good_afternoon_", value: "Good afternoon", comment: "")
     case 17..<22: good = NSLocalizedString("_good_evening_", value: "Good evening", comment: "")
     default: good = NSLocalizedString("_good_night_", value: "Good night", comment: "")
@@ -72,17 +71,17 @@ func getTitleNextcloudWidget() -> String {
     }
 }
 
-func getNextcloudDataEntry(isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: NextcloudDataEntry) -> Void) {
+func getFilesDataEntry(isPreview: Bool, displaySize: CGSize, completion: @escaping (_ entry: FilesDataEntry) -> Void) {
 
-    let datasPlaceholder = Array(recentDatasTest[0...nextcloudItems - 1])
-    let title = getTitleNextcloudWidget()
+    let datasPlaceholder = Array(filesDatasTest[0...filesItems - 1])
+    let title = getTitleFilesWidget()
     
     if isPreview {
-        return completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+        return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files"))
     }
 
     guard let account = NCManageDatabase.shared.getActiveAccount() else {
-        return completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
+        return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
     }
 
     func isLive(file: NKFile, files: [NKFile]) -> Bool {
@@ -189,9 +188,9 @@ func getNextcloudDataEntry(isPreview: Bool, displaySize: CGSize, completion: @es
         NKCommon.shared.writeLog("Start \(NCBrandOptions.shared.brand) widget session with level \(levelLog) " + versionNextcloudiOS)
     }
     
-    NextcloudKit.shared.searchBodyRequest(serverUrl: account.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles()) { _, files, error in
+    NextcloudKit.shared.searchBodyRequest(serverUrl: account.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles()) { _, files, data, error in
 
-        var datas: [NextcloudRecentData] = []
+        var datas: [FilesData] = []
         
         for file in files {
             guard !file.directory else { continue }
@@ -206,24 +205,29 @@ func getNextcloudDataEntry(isPreview: Bool, displaySize: CGSize, completion: @es
             guard let url = URL(string: urlString) else { continue }
             // Build Recent Data
             var imageRecent = UIImage()
-            if let image = NCUtilityGUI().createFilePreviewImage(ocId: file.ocId, etag: file.etag, fileNameView: file.fileName, classFile: file.classFile, status: 0, createPreviewMedia: false) {
+            if let image = NCUtility.shared.createFilePreviewImage(ocId: file.ocId, etag: file.etag, fileNameView: file.fileName, classFile: file.classFile, status: 0, createPreviewMedia: false) {
                 imageRecent = image
             } else if !file.iconName.isEmpty {
                 imageRecent = UIImage(named: file.iconName)!
             } else {
                 imageRecent = UIImage(named: "file")!
             }
-            let recentData = NextcloudRecentData.init(id: file.ocId, image: imageRecent, title: file.fileName, subTitle: subTitle, url: url)
-            datas.append(recentData)
-            if datas.count == nextcloudItems { break}
+            let data = FilesData.init(id: file.ocId, image: imageRecent, title: file.fileName, subTitle: subTitle, url: url)
+            datas.append(data)
+            if datas.count == filesItems { break}
         }
 
         if error != .success {
-            completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
+            completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
         } else if datas.isEmpty {
-            completion(NextcloudDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+            var footerText = NSLocalizedString("_no_data_available_", comment: "")
+            let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+            if serverVersionMajor < NCGlobal.shared.nextcloudVersion25 {
+                footerText = NSLocalizedString("_widget_available_nc25_", comment: "")
+            }
+            completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: footerText))
         } else {
-            completion(NextcloudDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget"))
+            completion(FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files"))
         }
     }
 }

+ 8 - 8
Widget/Nextcloud/NextcloudWidgetProvider.swift → Widget/Files/FilesWidgetProvider.swift

@@ -1,5 +1,5 @@
 //
-//  NextcloudWidgetProvider.swift
+//  FilesWidgetProvider.swift
 //  Widget
 //
 //  Created by Marino Faggiana on 25/08/22.
@@ -24,24 +24,24 @@
 import WidgetKit
 import SwiftUI
 
-struct NextcloudWidgetProvider: TimelineProvider {
+struct FilesWidgetProvider: TimelineProvider {
 
-    typealias Entry = NextcloudDataEntry
+    typealias Entry = FilesDataEntry
 
     func placeholder(in context: Context) -> Entry {
-        let datasPlaceholder = Array(recentDatasTest[0...nextcloudItems - 1])
-        let title = getTitleNextcloudWidget()
-        return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
+        let datasPlaceholder = Array(filesDatasTest[0...filesItems - 1])
+        let title = getTitleFilesWidget()
+        return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files")
     }
 
     func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {
-        getNextcloudDataEntry(isPreview: false, displaySize: context.displaySize) { entry in
+        getFilesDataEntry(isPreview: false, displaySize: context.displaySize) { entry in
             completion(entry)
         }
     }
 
     func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
-        getNextcloudDataEntry(isPreview: context.isPreview, displaySize: context.displaySize) { entry in
+        getFilesDataEntry(isPreview: context.isPreview, displaySize: context.displaySize) { entry in
             let timeLine = Timeline(entries: [entry], policy: .atEnd)
             completion(timeLine)
         }

+ 18 - 22
Widget/Nextcloud/NextcloudWidgetView.swift → Widget/Files/FilesWidgetView.swift

@@ -1,5 +1,5 @@
 //
-//  NextcloudWidgetView.swift
+//  FilesWidgetView.swift
 //  Widget
 //
 //  Created by Marino Faggiana on 25/08/22.
@@ -24,9 +24,9 @@
 import SwiftUI
 import WidgetKit
 
-struct NextcloudWidgetView: View {
+struct FilesWidgetView: View {
     
-    var entry: NextcloudDataEntry
+    var entry: FilesDataEntry
     
     var body: some View {
         
@@ -50,11 +50,6 @@ struct NextcloudWidgetView: View {
                     
                     VStack(spacing: 0) {
                         
-                        let datasCount = CGFloat(entry.datas.count)
-                        let heightFrame = (geo.size.height - 120) / datasCount
-                        let addSizeIcon = heightFrame / datasCount
-                        let spacing = (addSizeIcon - datasCount) / 2
-                        
                         ForEach(entry.datas, id: \.id) { element in
                             
                             Link(destination: element.url) {
@@ -62,16 +57,16 @@ struct NextcloudWidgetView: View {
                                 HStack {
                                     
                                     let subTitleColor = Color(white: 0.5)
-                                    let imageSize:CGFloat = 30
+                                    let imageSize:CGFloat = 35
                                     
                                     Image(uiImage: element.image)
                                         .resizable()
                                         .scaledToFill()
-                                        .frame(width: imageSize+addSizeIcon, height: imageSize+addSizeIcon)
+                                        .frame(width: imageSize, height: imageSize)
                                         .clipped()
                                         .cornerRadius(5)
                                     
-                                    VStack(alignment: .leading, spacing: spacing) {
+                                    VStack(alignment: .leading, spacing: 2) {
                                         
                                         Text(element.title)
                                             .font(.system(size: 12))
@@ -84,10 +79,10 @@ struct NextcloudWidgetView: View {
                                     Spacer()
                                 }
                                 .padding(.leading, 10)
-                                .frame(height: heightFrame)
+                                .frame(height: 50)
                             }
                             Divider()
-                                .padding(.leading, 48 + addSizeIcon)
+                                .padding(.leading, 54)
                         }
                     }
                 }
@@ -106,7 +101,7 @@ struct NextcloudWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding(11)
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -118,7 +113,7 @@ struct NextcloudWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding(11)
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -130,7 +125,7 @@ struct NextcloudWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding(11)
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -142,7 +137,7 @@ struct NextcloudWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding(11)
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -162,10 +157,11 @@ struct NextcloudWidgetView: View {
                         .scaledToFit()
                         .frame(width: 15, height: 15)
                         .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
-                    
+                
                     Text(entry.footerText)
                         .font(.caption2)
                         .padding(.trailing, 13.0)
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
                 }
                 .frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
             }
@@ -173,10 +169,10 @@ struct NextcloudWidgetView: View {
     }
 }
 
-struct NextcloudWidget_Previews: PreviewProvider {
+struct FilesWidget_Previews: PreviewProvider {
     static var previews: some View {
-        let datas = Array(recentDatasTest[0...3])
-        let entry = NextcloudDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: "Good afternoon, Marino Faggiana", footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
-        NextcloudWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
+        let datas = Array(filesDatasTest[0...filesItems-1])
+        let entry = FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, tile: "Good afternoon, Marino Faggiana", footerImage: "checkmark.icloud", footerText: "Nextcloud files")
+        FilesWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
     }
 }

+ 1 - 1
Widget/Toolbar/ToolbarData.swift

@@ -35,7 +35,7 @@ func getToolbarDataEntry(isPreview: Bool, completion: @escaping (_ entry: Toolba
     if isPreview {
         return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
     }
-    
+
     if NCManageDatabase.shared.getActiveAccount() == nil {
         return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
     }

+ 14 - 7
Widget/Toolbar/ToolbarWidgetView.swift

@@ -34,6 +34,10 @@ struct ToolbarWidgetView: View {
 
             ZStack(alignment: .topLeading) {
 
+                // Color.init(.sRGB, red: 0.89, green: 0.89, blue: 0.89, opacity: 0.75)
+                Color(.black)
+                    .ignoresSafeArea()
+
                 HStack(spacing: 0) {
 
                     let sizeButton: CGFloat = 65
@@ -46,7 +50,7 @@ struct ToolbarWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding(14)
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -58,7 +62,7 @@ struct ToolbarWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding()
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -70,7 +74,7 @@ struct ToolbarWidgetView: View {
                             .resizable()
                             .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding()
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -80,9 +84,8 @@ struct ToolbarWidgetView: View {
                     Link(destination: entry.isPlaceholder ? NCGlobal.shared.widgetActionNoAction : NCGlobal.shared.widgetActionVoiceMemo, label: {
                         Image("microphone")
                             .resizable()
-                            .renderingMode(.template)
                             .foregroundColor(entry.isPlaceholder ? placeholderColor : brandTextColor)
-                            .padding(10)
+                            .padding()
                             .background(entry.isPlaceholder ? placeholderColor : brandColor)
                             .clipShape(Circle())
                             .scaledToFit()
@@ -94,18 +97,22 @@ struct ToolbarWidgetView: View {
 
                 HStack {
 
+                    let placeholderColor = Color(white: 0.2)
+                    let brandColor = Color(NCBrandColor.shared.brand)
+
                     Image(systemName: entry.footerImage)
                         .resizable()
                         .scaledToFit()
                         .frame(width: 15, height: 15)
-                        .foregroundColor(entry.isPlaceholder ? Color(white: 0.2) : Color(NCBrandColor.shared.brand))
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
 
                     Text(entry.footerText)
                         .font(.caption2)
                         .padding(.trailing, 13.0)
+                        .foregroundColor(entry.isPlaceholder ? placeholderColor : brandColor)
                 }
                 .frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
-            }.background(ContainerRelativeShape().fill(Color(.sRGB, red: 0.89, green: 0.89, blue: 0.89, opacity: 0.75)))
+            }
         }
     }
 }

+ 0 - 59
Widget/Widget.intentdefinition

@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>INEnums</key>
-	<array/>
-	<key>INIntentDefinitionModelVersion</key>
-	<string>1.2</string>
-	<key>INIntentDefinitionNamespace</key>
-	<string>88xZPY</string>
-	<key>INIntentDefinitionSystemVersion</key>
-	<string>20A294</string>
-	<key>INIntentDefinitionToolsBuildVersion</key>
-	<string>12A6144</string>
-	<key>INIntentDefinitionToolsVersion</key>
-	<string>12.0</string>
-	<key>INIntents</key>
-	<array>
-		<dict>
-			<key>INIntentCategory</key>
-			<string>information</string>
-			<key>INIntentDescriptionID</key>
-			<string>tVvJ9c</string>
-			<key>INIntentEligibleForWidgets</key>
-			<true/>
-			<key>INIntentIneligibleForSuggestions</key>
-			<true/>
-			<key>INIntentName</key>
-			<string>Configuration</string>
-			<key>INIntentResponse</key>
-			<dict>
-				<key>INIntentResponseCodes</key>
-				<array>
-					<dict>
-						<key>INIntentResponseCodeName</key>
-						<string>success</string>
-						<key>INIntentResponseCodeSuccess</key>
-						<true/>
-					</dict>
-					<dict>
-						<key>INIntentResponseCodeName</key>
-						<string>failure</string>
-					</dict>
-				</array>
-			</dict>
-			<key>INIntentTitle</key>
-			<string>Configuration</string>
-			<key>INIntentTitleID</key>
-			<string>gpCwrM</string>
-			<key>INIntentType</key>
-			<string>Custom</string>
-			<key>INIntentVerb</key>
-			<string>View</string>
-		</dict>
-	</array>
-	<key>INTypes</key>
-	<array/>
-</dict>
-</plist>

+ 10 - 10
Widget/Widget.swift

@@ -30,7 +30,7 @@ struct NextcloudWidgetBundle: WidgetBundle {
     @WidgetBundleBuilder
     var body: some Widget {
         DashboardWidget()
-        NextcloudWidget()
+        FilesWidget()
         ToolbarWidget()
     }
 }
@@ -39,25 +39,25 @@ struct DashboardWidget: Widget {
     let kind: String = "DashboardWidget"
 
     var body: some WidgetConfiguration {
-        StaticConfiguration(kind: kind, provider: DashboardWidgetProvider()) { entry in
+        IntentConfiguration(kind: kind, intent: DashboardIntent.self, provider: DashboardWidgetProvider()) { entry in
             DashboardWidgetView(entry: entry)
         }
         .supportedFamilies([.systemLarge])
-        .configurationDisplayName(NCBrandOptions.shared.brand + " Dashboard")
+        .configurationDisplayName("Dashboard")
         .description(NSLocalizedString("_description_dashboardwidget_", comment: ""))
     }
 }
 
-struct NextcloudWidget: Widget {
-    let kind: String = "NextcloudWidget"
+struct FilesWidget: Widget {
+    let kind: String = "FilesWidget"
 
     var body: some WidgetConfiguration {
-        StaticConfiguration(kind: kind, provider: NextcloudWidgetProvider()) { entry in
-            NextcloudWidgetView(entry: entry)
+        StaticConfiguration(kind: kind, provider: FilesWidgetProvider()) { entry in
+            FilesWidgetView(entry: entry)
         }
         .supportedFamilies([.systemLarge])
-        .configurationDisplayName(NCBrandOptions.shared.brand + " Widget")
-        .description(NSLocalizedString("_description_nextcloudwidget_", comment: ""))
+        .configurationDisplayName("Files")
+        .description(NSLocalizedString("_description_fileswidget_", comment: ""))
     }
 }
 
@@ -69,7 +69,7 @@ struct ToolbarWidget: Widget {
             ToolbarWidgetView(entry: entry)
         }
         .supportedFamilies([.systemMedium])
-        .configurationDisplayName(NCBrandOptions.shared.brand + " Toolbar")
+        .configurationDisplayName("Toolbar")
         .description(NSLocalizedString("_description_toolbarwidget_", comment: ""))
     }
 }

+ 3 - 3
iOSClient/Activity/NCActivity.swift

@@ -403,7 +403,7 @@ extension NCActivity {
         guard showComments, let metadata = metadata else { return }
         disptachGroup?.enter()
 
-        NextcloudKit.shared.getComments(fileId: metadata.fileId) { account, comments, error in
+        NextcloudKit.shared.getComments(fileId: metadata.fileId) { account, comments, data, error in
             if error == .success, let comments = comments {
                 NCManageDatabase.shared.addComments(comments, account: metadata.account, objectId: metadata.fileId)
             } else if error.errorCode != NCGlobal.shared.errorResourceNotFound {
@@ -432,7 +432,7 @@ extension NCActivity {
             limit: 1,
             objectId: nil,
             objectType: objectType,
-            previews: true) { account, _, activityFirstKnown, activityLastGiven, error in
+            previews: true) { account, _, activityFirstKnown, activityLastGiven, data, error in
                 defer { disptachGroup.leave() }
 
                 let largestActivityId = max(activityFirstKnown, activityLastGiven)
@@ -459,7 +459,7 @@ extension NCActivity {
             limit: min(limit, 200),
             objectId: metadata?.fileId,
             objectType: objectType,
-            previews: true) { account, activities, activityFirstKnown, activityLastGiven, error in
+            previews: true) { account, activities, activityFirstKnown, activityLastGiven, data, error in
                 defer { disptachGroup.leave() }
                 guard error == .success,
                       account == self.appDelegate.account,

+ 1 - 0
iOSClient/AppDelegate.swift

@@ -276,6 +276,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         // Reload Widget
         if #available(iOS 14.0, *) {
             WidgetCenter.shared.reloadAllTimelines()
+            //WidgetCenter.shared.reloadTimelines(ofKind: "DashboardWidget")
         }
 
         // Clear operation queue

+ 8 - 0
iOSClient/Brand/iOSClient.plist

@@ -42,6 +42,10 @@
 	</array>
 	<key>CFBundleVersion</key>
 	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>INIntentsSupported</key>
+	<array>
+		<string>Dashboard</string>
+	</array>
 	<key>ITSAppUsesNonExemptEncryption</key>
 	<true/>
 	<key>ITSEncryptionExportComplianceCode</key>
@@ -75,6 +79,10 @@
 	<string>Photo library access is required to upload your photos and videos to your cloud.</string>
 	<key>NSPhotoLibraryUsageDescription</key>
 	<string>Photo library access is required to upload your photos and videos to your cloud.</string>
+	<key>NSUserActivityTypes</key>
+	<array>
+		<string>DashboardIntent</string>
+	</array>
 	<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
 	<true/>
 	<key>UIAppFonts</key>

+ 23 - 0
iOSClient/Data/NCDatabase.swift

@@ -244,6 +244,29 @@ class tableDirectEditingCreators: Object {
     @objc dynamic var templates: Int = 0
 }
 
+class tableDashboardWidget: Object {
+    
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var account = ""
+    @Persisted var id = ""
+    @Persisted var title = ""
+    @Persisted var order: Int = 0
+    @Persisted var iconClass: String?
+    @Persisted var iconUrl: String?
+    @Persisted var widgetUrl: String?
+    @Persisted var itemIconsRound: Bool = false
+}
+
+class tableDashboardWidgetButton: Object {
+
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var account = ""
+    @Persisted var id = ""
+    @Persisted var type = ""
+    @Persisted var text = ""
+    @Persisted var link = ""
+}
+
 class tableDirectEditingEditors: Object {
 
     @objc dynamic var account = ""

+ 91 - 0
iOSClient/Data/NCManageDatabase+DashboardWidget.swift

@@ -0,0 +1,91 @@
+//
+//  NCManageDatabase+DashboardWidget.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 09/09/22.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+import RealmSwift
+import NextcloudKit
+
+extension NCManageDatabase {
+
+    func getDashboardWidget(account: String, id: String) -> (tableDashboardWidget?, Results<tableDashboardWidgetButton>?) {
+     
+        let realm = try! Realm()
+        guard let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@ AND id == %@", account, id).first else {
+            return (nil, nil)
+        }
+        let resultsButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@ AND id == %@", account, id).sorted(byKeyPath: "type", ascending: true)
+        
+        return (resultDashboard, resultsButton)
+    }
+    
+    func addDashboardWidget(account: String, dashboardWidgets: [NCCDashboardWidget]) {
+        
+        let realm = try! Realm()
+
+        do {
+            try realm.safeWrite {
+                
+                let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@", account)
+                realm.delete(resultDashboard)
+                
+                let resultDashboardButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@", account)
+                realm.delete(resultDashboardButton)
+                
+                for widget in dashboardWidgets {
+                    
+                    let addObject = tableDashboardWidget()
+                    
+                    addObject.index = account + " " + widget.id
+                    addObject.account = account
+                    addObject.id = widget.id
+                    addObject.title = widget.title
+                    addObject.order = widget.order
+                    addObject.iconClass = widget.iconClass
+                    addObject.iconUrl = widget.iconUrl
+                    addObject.widgetUrl = widget.widgetUrl
+                    addObject.itemIconsRound = widget.itemIconsRound
+
+                    if let buttons = widget.button {
+                        for button in buttons {
+                            
+                            let addObject = tableDashboardWidgetButton()
+                            
+                            addObject.account = account
+                            addObject.id = widget.id
+                            addObject.type = button.type
+                            addObject.text = button.text
+                            addObject.link = button.link
+                            addObject.index = account + " " + widget.id + " " + button.type
+                            
+                            realm.add(addObject, update: .all)
+                        }
+                    }
+                    
+                    realm.add(addObject, update: .all)
+                }
+            }
+        } catch let error {
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
+        }
+    }
+}

+ 3 - 1
iOSClient/Data/NCManageDatabase.swift

@@ -70,7 +70,7 @@ class NCManageDatabase: NSObject {
             let config = Realm.Configuration(
                 fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + NCGlobal.shared.databaseDefault),
                 schemaVersion: NCGlobal.shared.databaseSchemaVersion,
-                objectTypes: [tableMetadata.self, tableLocalFile.self, tableDirectory.self, tableTag.self, tableAccount.self, tableCapabilities.self, tablePhotoLibrary.self, tableE2eEncryption.self, tableE2eEncryptionLock.self, tableShare.self, tableChunk.self, tableAvatar.self]
+                objectTypes: [tableMetadata.self, tableLocalFile.self, tableDirectory.self, tableTag.self, tableAccount.self, tableCapabilities.self, tablePhotoLibrary.self, tableE2eEncryption.self, tableE2eEncryptionLock.self, tableShare.self, tableChunk.self, tableAvatar.self, tableDashboardWidget.self, tableDashboardWidgetButton.self]
             )
 
             Realm.Configuration.defaultConfiguration = config
@@ -259,6 +259,8 @@ class NCManageDatabase: NSObject {
         self.clearTable(tableCapabilities.self, account: account)
         self.clearTable(tableChunk.self, account: account)
         self.clearTable(tableComments.self, account: account)
+        self.clearTable(tableDashboardWidget.self, account: account)
+        self.clearTable(tableDashboardWidgetButton.self, account: account)
         self.clearTable(tableDirectEditingCreators.self, account: account)
         self.clearTable(tableDirectEditingEditors.self, account: account)
         self.clearTable(tableDirectory.self, account: account)

+ 1 - 1
iOSClient/Diagnostics/NCCapabilitiesViewController.swift

@@ -201,7 +201,7 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
                 // EDITORS
                 let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
                 if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
-                    NextcloudKit.shared.NCTextObtainEditorDetails { account, editors, creators, error in
+                    NextcloudKit.shared.NCTextObtainEditorDetails { account, editors, creators, data, error in
                         if error == .success && account == self.appDelegate.account {
                             NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
                             self.readCapabilities()

+ 4 - 9
iOSClient/Extensions/UIImage+Extensions.swift

@@ -27,7 +27,7 @@ import Accelerate
 
 extension UIImage {
 
-    @objc func resizeImage(size: CGSize, isAspectRation: Bool) -> UIImage? {
+    @objc func resizeImage(size: CGSize, isAspectRation: Bool = true) -> UIImage? {
 
         let originRatio = self.size.width / self.size.height
         let newRatio = size.width / size.height
@@ -139,14 +139,9 @@ extension UIImage {
     }
 
     func imageColor(_ color: UIColor) -> UIImage {
-
-        if #available(iOS 13.0, *) {
-            return self.withTintColor(color, renderingMode: .alwaysOriginal)
-        } else {
-            return UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { _ in
-                color.set()
-                withRenderingMode(.alwaysTemplate).draw(at: .zero)
-            }
+        return UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { _ in
+            color.set()
+            withRenderingMode(.alwaysTemplate).draw(at: .zero)
         }
     }
 

+ 2 - 13
iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json

@@ -1,19 +1,8 @@
 {
   "images" : [
     {
-      "filename" : "icons8-image-upload-24(@1x).png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "filename" : "icons8-image-upload-48(@2x).png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "icons8-image-upload-72(@3x).png",
-      "idiom" : "universal",
-      "scale" : "3x"
+      "filename" : "icons8-image.svg",
+      "idiom" : "universal"
     }
   ],
   "info" : {

二进制
iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).png


二进制
iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).png


二进制
iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).png


+ 4 - 0
iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg fill="#000000" viewBox="0 0 512 512" width="512px" height="512px" xmlns="http://www.w3.org/2000/svg">
+  <path d="M 40 30 A 40.045 40.045 0 0 0 0 70 L 0 334.91211 A 40.121 40.121 0 0 0 40 375 L 240.32617 375 C 254.22017 436 309.08489 482.04492 374.46289 482.04492 C 450.30189 482.04492 512.16211 420.32337 512.16211 344.48438 C 512.16111 304.09238 494 267.69281 467 242.50781 L 467 70 C 467 47.944 448.73373 30 426.67773 30 L 40 30 z M 40 50 L 426.67773 50 A 20.3 20.3 0 0 1 447 70 L 447 227.45703 A 137.255 137.255 0 0 0 374.62305 206.92383 A 138.761 138.761 0 0 0 351.53906 208.85742 A 61.651 61.651 0 0 0 280.14453 213.59961 L 209.92383 272.19922 A 41.068 41.068 0 0 1 163.57227 276.37695 L 20 195.92383 L 20 70 A 20.024 20.024 0 0 1 40 50 z M 166.64648 80.462891 C 130.66548 80.462891 101.39258 108.64516 101.39258 143.28516 C 101.39258 177.92516 130.66548 206.10742 166.64648 206.10742 C 202.62748 206.10742 231.90039 177.92516 231.90039 143.28516 C 231.90039 108.64516 202.62748 80.462891 166.64648 80.462891 z M 166.64648 100.46289 C 191.59948 100.46289 211.90039 119.67316 211.90039 143.28516 C 211.90039 166.89716 191.60048 186.10742 166.64648 186.10742 C 141.69248 186.10742 121.39258 166.89716 121.39258 143.28516 C 121.39258 119.67316 141.69348 100.46289 166.64648 100.46289 z M 20 218.84961 L 153.80078 293.83203 A 60.969 60.969 0 0 0 222.66211 287.59961 L 292.86133 228.99805 A 41.216 41.216 0 0 1 316.54883 219.72852 A 137.781 137.781 0 0 0 236.91992 344.50586 C 236.91992 348.02086 237.05431 351 237.32031 355 L 40 355 A 20.1 20.1 0 0 1 20 334.91211 L 20 218.84961 z M 369.57227 227.02344 A 117.539 117.539 0 0 1 492 344.46289 A 117.672 117.672 0 0 1 374.46289 462 A 117.539 117.539 0 0 1 369.57227 227.02344 z M 374.69727 288.78516 A 10 10 0 0 0 368.03906 291.59961 L 329.89062 328.57617 A 10.000059 10.000059 0 1 0 343.81055 342.9375 L 365 322.40039 L 365 391.2207 A 10 10 0 0 0 385 391.2207 L 385 322.40039 L 406.18945 342.9375 A 10.000059 10.000059 0 0 0 420.10938 328.57617 L 381.96094 291.59961 A 10 10 0 0 0 374.69727 288.78516 z" style="fill: rgb(255, 255, 255);"/>
+</svg>

+ 2 - 13
iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json

@@ -1,19 +1,8 @@
 {
   "images" : [
     {
-      "filename" : "icons8-scan-24(@1x).png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "filename" : "icons8-scan-48(@2x).png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "icons8-scan-72(@3x).png",
-      "idiom" : "universal",
-      "scale" : "3x"
+      "filename" : "icons8-scan.svg",
+      "idiom" : "universal"
     }
   ],
   "info" : {

二进制
iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).png


二进制
iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).png


二进制
iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).png


+ 4 - 0
iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg fill="#000000" viewBox="0 0 24 24" width="384px" height="384px" xmlns="http://www.w3.org/2000/svg">
+  <path d="M 4 1.25 C 2.481 1.25 1.25 2.481 1.25 4 L 1.25 8 C 1.25 8.414 1.586 8.75 2 8.75 C 2.414 8.75 2.75 8.414 2.75 8 L 2.75 4 C 2.75 3.31 3.31 2.75 4 2.75 L 8 2.75 C 8.414 2.75 8.75 2.414 8.75 2 C 8.75 1.586 8.414 1.25 8 1.25 L 4 1.25 z M 16 1.25 C 15.586 1.25 15.25 1.586 15.25 2 C 15.25 2.414 15.586 2.75 16 2.75 L 20 2.75 C 20.69 2.75 21.25 3.31 21.25 4 L 21.25 8 C 21.25 8.414 21.586 8.75 22 8.75 C 22.414 8.75 22.75 8.414 22.75 8 L 22.75 4 C 22.75 2.481 21.519 1.25 20 1.25 L 16 1.25 z M 8 5.25 C 7.536 5.25 7.0916719 5.4346719 6.7636719 5.7636719 C 6.4346719 6.0916719 6.25 6.536 6.25 7 L 6.25 17 C 6.25 17.966 7.033 18.75 8 18.75 L 16 18.75 C 16.967 18.75 17.75 17.966 17.75 17 L 17.75 10.414062 C 17.75 9.9500625 17.565328 9.5057344 17.236328 9.1777344 C 16.497328 8.4377344 14.562266 6.5026719 13.822266 5.7636719 C 13.494266 5.4346719 13.049938 5.25 12.585938 5.25 L 8 5.25 z M 8 6.75 L 12.25 6.75 L 12.25 9 C 12.25 9.464 12.434672 9.9083281 12.763672 10.236328 C 13.091672 10.565328 13.536 10.75 14 10.75 L 16.25 10.75 L 16.25 17 C 16.25 17.138 16.138 17.25 16 17.25 L 8 17.25 C 7.862 17.25 7.75 17.138 7.75 17 L 7.75 7 C 7.75 6.934 7.7752656 6.8692656 7.8222656 6.8222656 C 7.8692656 6.7752656 7.934 6.75 8 6.75 z M 13.75 7.8085938 L 15.191406 9.25 L 14 9.25 C 13.934 9.25 13.869266 9.2247344 13.822266 9.1777344 C 13.775266 9.1307344 13.75 9.066 13.75 9 L 13.75 7.8085938 z M 2 15.25 C 1.586 15.25 1.25 15.586 1.25 16 L 1.25 20 C 1.25 21.519 2.481 22.75 4 22.75 L 8 22.75 C 8.414 22.75 8.75 22.414 8.75 22 C 8.75 21.586 8.414 21.25 8 21.25 L 4 21.25 C 3.31 21.25 2.75 20.69 2.75 20 L 2.75 16 C 2.75 15.586 2.414 15.25 2 15.25 z M 22 15.25 C 21.586 15.25 21.25 15.586 21.25 16 L 21.25 20 C 21.25 20.69 20.69 21.25 20 21.25 L 16 21.25 C 15.586 21.25 15.25 21.586 15.25 22 C 15.25 22.414 15.586 22.75 16 22.75 L 20 22.75 C 21.519 22.75 22.75 21.519 22.75 20 L 22.75 16 C 22.75 15.586 22.414 15.25 22 15.25 z" style="fill: rgb(255, 255, 255);"/>
+</svg>

+ 5 - 5
iOSClient/Images.xcassets/microphone.imageset/Contents.json

@@ -1,15 +1,15 @@
 {
   "images" : [
     {
-      "idiom" : "universal",
-      "filename" : "Microphone.png"
+      "filename" : "icons8-microfono-400.svg",
+      "idiom" : "universal"
     }
   ],
   "info" : {
-    "version" : 1,
-    "author" : "xcode"
+    "author" : "xcode",
+    "version" : 1
   },
   "properties" : {
     "preserves-vector-representation" : true
   }
-}
+}

二进制
iOSClient/Images.xcassets/microphone.imageset/Microphone.png


+ 4 - 0
iOSClient/Images.xcassets/microphone.imageset/icons8-microfono-400.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg fill="#000000" viewBox="0 0 48 48" width="400px" height="400px" xmlns="http://www.w3.org/2000/svg">
+  <path d="M 24 2 C 19.047281 2 15 6.0472805 15 11 L 15 26 C 15 30.952719 19.047281 35 24 35 C 28.952719 35 33 30.952719 33 26 L 33 11 C 33 6.0472805 28.952719 2 24 2 z M 10.476562 20.978516 A 1.50015 1.50015 0 0 0 9 22.5 L 9 26 C 9 33.760508 14.934038 40.16812 22.5 40.923828 L 22.5 45.5 A 1.50015 1.50015 0 1 0 25.5 45.5 L 25.5 40.923828 C 33.065962 40.16812 39 33.760508 39 26 L 39 22.5 A 1.50015 1.50015 0 1 0 36 22.5 L 36 26 C 36 32.585372 30.739679 37.894735 24.177734 37.990234 A 1.50015 1.50015 0 0 0 23.976562 37.978516 A 1.50015 1.50015 0 0 0 23.8125 37.990234 C 17.255134 37.889572 12 32.582085 12 26 L 12 22.5 A 1.50015 1.50015 0 0 0 10.476562 20.978516 z" style="fill: rgb(255, 255, 255);"/>
+</svg>

+ 0 - 15
iOSClient/Images.xcassets/microphone_off.imageset/Contents.json

@@ -1,15 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "microphone_off.pdf"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}

二进制
iOSClient/Images.xcassets/microphone_off.imageset/microphone_off.pdf


+ 0 - 15
iOSClient/Images.xcassets/modifyPhoto.imageset/Contents.json

@@ -1,15 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "modifyPhoto.pdf"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}

二进制
iOSClient/Images.xcassets/modifyPhoto.imageset/modifyPhoto.pdf


+ 0 - 15
iOSClient/Images.xcassets/moon.circle.imageset/Contents.json

@@ -1,15 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "darkModeDetect.pdf"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}

二进制
iOSClient/Images.xcassets/moon.circle.imageset/darkModeDetect.pdf


+ 0 - 23
iOSClient/Images.xcassets/navigationControllerMenu.imageset/Contents.json

@@ -1,23 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "navigationControllerMenu.png",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "universal",
-      "filename" : "navigationControllerMenu@2x.png",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "universal",
-      "filename" : "navigationControllerMenu@3x.png",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}

二进制
iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu.png


二进制
iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu@2x.png


二进制
iOSClient/Images.xcassets/navigationControllerMenu.imageset/navigationControllerMenu@3x.png


+ 1 - 1
iOSClient/Login/NCAppConfigView.swift

@@ -78,7 +78,7 @@ class NCAppConfigView: UIViewController {
             return
         }
 
-        NextcloudKit.shared.getAppPassword(serverUrl: serverUrl, username: username, password: password, userAgent: nil) { token, error in
+        NextcloudKit.shared.getAppPassword(serverUrl: serverUrl, username: username, password: password, userAgent: nil) { token, data, error in
             DispatchQueue.main.async {
                 if error == .success && token != nil {
                     let account: String = "\(username) \(serverUrl)"

+ 2 - 2
iOSClient/Login/NCLogin.swift

@@ -215,7 +215,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
 
         loginButton.isEnabled = false
 
-        NextcloudKit.shared.getServerStatus(serverUrl: url) { _, _, versionMajor, _, _, _, error in
+        NextcloudKit.shared.getServerStatus(serverUrl: url) { _, _, versionMajor, _, _, _, _, error in
 
             if error == .success {
 
@@ -223,7 +223,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
                     NCNetworking.shared.writeCertificate(host: host)
                 }
 
-                NextcloudKit.shared.getLoginFlowV2(serverUrl: url) { token, endpoint, login, error in
+                NextcloudKit.shared.getLoginFlowV2(serverUrl: url) { token, endpoint, login, data, error in
 
                     self.loginButton.isEnabled = true
 

+ 1 - 1
iOSClient/Login/NCLoginWeb.swift

@@ -273,7 +273,7 @@ extension NCLoginWeb: WKNavigationDelegate {
 
         if loginFlowV2Available {
             DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, error in
+                NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, data, error in
                     if error == .success && server != nil && loginName != nil && appPassword != nil {
                         self.createAccount(server: server!, username: loginName!, password: appPassword!)
                     }

+ 2 - 2
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -1101,7 +1101,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     self.metadataFolder = metadataFolder
                     // E2EE
                     if let metadataFolder = metadataFolder, metadataFolder.e2eEncrypted, CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
-                        NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, error in
+                        NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, data, error in
                             if error == .success, let e2eMetadata = e2eMetadata {
                                 if NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
                                     self.reloadDataSource()
@@ -1360,7 +1360,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
         // Thumbnail
         if !metadata.directory {
             if metadata.name == NCGlobal.shared.appName {
-                    if let image = NCUtilityGUI().createFilePreviewImage(ocId: metadata.ocId, etag: metadata.etag, fileNameView: metadata.fileNameView, classFile: metadata.classFile, status: metadata.status, createPreviewMedia: !metadata.hasPreview) {
+                    if let image = NCUtility.shared.createFilePreviewImage(ocId: metadata.ocId, etag: metadata.etag, fileNameView: metadata.fileNameView, classFile: metadata.classFile, status: metadata.status, createPreviewMedia: !metadata.hasPreview) {
                     (cell as! NCCellProtocol).filePreviewImageView?.image = image
                 } else {
                     NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: true, cell: cell, view: collectionView)

+ 4 - 4
iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift

@@ -319,7 +319,7 @@ import XLForm
                 options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentNCText())
             }
             
-            NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, options: options) { account, url, error in
+            NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, options: options) { account, url, data, error in
                 guard error == .success, account == self.appDelegate.account, let url = url else {
                     self.navigationItem.rightBarButtonItem?.isEnabled = true
                     NCContentPresenter.shared.showError(error: error)
@@ -343,7 +343,7 @@ import XLForm
 
         if self.editorId == NCGlobal.shared.editorCollabora {
 
-            NextcloudKit.shared.createRichdocuments(path: fileNamePath, templateId: templateIdentifier) { account, url, error in
+            NextcloudKit.shared.createRichdocuments(path: fileNamePath, templateId: templateIdentifier) { account, url, data, error in
                 guard error == .success, account == self.appDelegate.account, let url = url else {
                     self.navigationItem.rightBarButtonItem?.isEnabled = true
                     NCContentPresenter.shared.showError(error: error)
@@ -382,7 +382,7 @@ import XLForm
                 options = NKRequestOptions(customUserAgent: NCUtility.shared.getCustomUserAgentNCText())
             }
 
-            NextcloudKit.shared.NCTextGetListOfTemplates(options: options) { account, templates, error in
+            NextcloudKit.shared.NCTextGetListOfTemplates(options: options) { account, templates, data, error in
 
                 self.indicator.stopAnimating()
 
@@ -439,7 +439,7 @@ import XLForm
 
         if self.editorId == NCGlobal.shared.editorCollabora {
 
-            NextcloudKit.shared.getTemplatesRichdocuments(typeTemplate: typeTemplate) { account, templates, error in
+            NextcloudKit.shared.getTemplatesRichdocuments(typeTemplate: typeTemplate) { account, templates, data, error in
 
                 self.indicator.stopAnimating()
 

+ 2 - 2
iOSClient/Media/NCMedia.swift

@@ -532,7 +532,7 @@ extension NCMedia {
 
         let options = NKRequestOptions(timeout: 300)
         
-        NextcloudKit.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
+        NextcloudKit.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, data, error in
 
             self.oldInProgress = false
             NCActivityIndicator.shared.stop()
@@ -613,7 +613,7 @@ extension NCMedia {
 
             let options = NKRequestOptions(timeout: 300)
             
-            NextcloudKit.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
+            NextcloudKit.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, data, error in
 
                 self.newInProgress = false
                 self.mediaCommandView?.activityIndicator.stopAnimating()

+ 1 - 1
iOSClient/Menu/AppDelegate+Menu.swift

@@ -85,7 +85,7 @@ extension AppDelegate {
         if #available(iOS 13.0, *) {
             actions.append(
                 NCMenuAction(
-                    title: NSLocalizedString("_scans_document_", comment: ""), icon: NCUtility.shared.loadImage(named: "doc.text.viewfinder"), action: { _ in
+                    title: NSLocalizedString("_scans_document_", comment: ""), icon: NCUtility.shared.loadImage(named: "buttonAddScan"), action: { _ in
                         if let viewController = appDelegate.window?.rootViewController {
                             NCCreateScanDocument.shared.openScannerDocument(viewController: viewController)
                         }

+ 1 - 1
iOSClient/Menu/UIViewController+Menu.swift

@@ -65,7 +65,7 @@ extension UIViewController {
         let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
         guard serverVersionMajor >= NCGlobal.shared.nextcloudVersion23 else { return }
 
-        NextcloudKit.shared.getHovercard(for: userId) { account, card, _ in
+        NextcloudKit.shared.getHovercard(for: userId) { account, card, data, _ in
             guard let card = card, account == appDelegate.account else { return }
 
             let personHeader = NCMenuAction(

+ 1 - 1
iOSClient/More/NCMore.swift

@@ -144,7 +144,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         if #available(iOS 13.0, *) {
             item = NKExternalSite()
             item.name = "_scanned_images_"
-            item.icon = "doc.text.viewfinder"
+            item.icon = "buttonAddScan"
             item.url = "openStoryboardNCScan"
             functionMenu.append(item)
         }

+ 3 - 1
iOSClient/NCGlobal.swift

@@ -109,11 +109,13 @@ class NCGlobal: NSObject {
     let nextcloudVersion18: Int                     =  18
     let nextcloudVersion20: Int                     =  20
     let nextcloudVersion23: Int                     =  23
+    let nextcloudVersion24: Int                     =  24
+    let nextcloudVersion25: Int                     =  25
 
     // Database Realm
     //
     let databaseDefault                             = "nextcloud.realm"
-    let databaseSchemaVersion: UInt64               = 237
+    let databaseSchemaVersion: UInt64               = 246
 
     // Intro selector
     //

+ 19 - 35
iOSClient/Networking/NCNetworking.swift

@@ -773,7 +773,7 @@ import Photos
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.searchLiteral(serverUrl: urlBase.urlBase, depth: "infinity", literal: literal, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { (account, files, error) in
+        NextcloudKit.shared.searchLiteral(serverUrl: urlBase.urlBase, depth: "infinity", literal: literal, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { (account, files, data, error) in
             guard error == .success else {
                 return completion(nil, error)
             }
@@ -861,7 +861,7 @@ import Photos
                 })
             }
             update(account, provider.id, partialResult, metadatas)
-        } completion: { account, error in
+        } completion: { account, data, error in
             self.requestsUnifiedSearch.removeAll()
             dispatchGroup.leave()
         }
@@ -871,7 +871,7 @@ import Photos
 
         var metadatas: [tableMetadata] = []
 
-        let request = NextcloudKit.shared.searchProvider(id, account: userBaseUrl.account, term: term, limit: limit, cursor: cursor, timeout: 60) { account, searchResult, error in
+        let request = NextcloudKit.shared.searchProvider(id, account: userBaseUrl.account, term: term, limit: limit, cursor: cursor, timeout: 60) { account, searchResult, data, error in
             guard let searchResult = searchResult else {
                 completion(account, nil, metadatas, error)
                 return
@@ -1165,7 +1165,7 @@ import Photos
         
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.listingFavorites(showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
+        NextcloudKit.shared.listingFavorites(showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, data, error in
             guard error == .success else {
                 completion(account, nil, error)
                 return
@@ -1391,7 +1391,7 @@ import Photos
         if CCUtility.fileProviderStorageExists(metadata) {
             completition(URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)))
         } else {
-            NextcloudKit.shared.getDirectDownload(fileId: metadata.fileId) { _, url, error in
+            NextcloudKit.shared.getDirectDownload(fileId: metadata.fileId) { account, url, data, error in
                 if error == .success && url != nil {
                     if let url = URL(string: url!) {
                         completition(url)
@@ -1407,41 +1407,25 @@ import Photos
 
     // MARK: - TEST API
 
-    /*
-    @objc public func getDashboardWidget(urlBase: String, username: String, password: String, customUserAgent: String? = nil, completionHandler: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
-                
-        let endpoint = "/ocs/v2.php/apps/dashboard/api/v1/widget-items"
-        
-        let url:URLConvertible = try! (urlBase + endpoint).asURL() as URLConvertible
-        var headers: HTTPHeaders = [.authorization(username: username, password: password)]
-        if customUserAgent != nil {
-            headers.update(.userAgent(customUserAgent!))
-        }
-        //headers.update(.contentType("application/json"))
-        headers.update(name: "OCS-APIRequest", value: "true")
-               
-        let method = HTTPMethod(rawValue: "GET")
-
-//        let parameters = [
-//            "fileId": fileId,
-//        ]
-        
-        AF.request(url, method: method, parameters: nil, headers: headers).validate(statusCode: 200..<300).response { (response) in
-            debugPrint(response)
+    @available(iOS 13.0, *)
+    func getPreview(url: URL, options: NKRequestOptions = NKRequestOptions()) async throws -> Data? {
+
+        try await withUnsafeThrowingContinuation { continuation in
             
-            switch response.result {
-            case .failure(let error):
-                completionHandler(0, "")
-            case .success(let data):
-                if let data = data {
-                    completionHandler(0, "")
-                } else {
-                    completionHandler(NSURLErrorBadServerResponse, NSLocalizedString("_error_decode_xml_", value: "Invalid response, error decode XML", comment: ""))
+            let headers = NKCommon.shared.getStandardHeaders(options: options)
+            
+            AF.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers, interceptor: nil).validate(statusCode: 200..<300).response(queue: NKCommon.shared.backgroundQueue) { (response) in
+                debugPrint(response)
+                
+                switch response.result {
+                case .failure(let error):
+                    continuation.resume(throwing: error)
+                case .success(let data):
+                    continuation.resume(returning: data)
                 }
             }
         }
     }
-    */
 }
 
 extension Array where Element == URLQueryItem {

+ 2 - 1
iOSClient/Networking/NCNetworkingCheckRemoteUser.swift

@@ -47,7 +47,7 @@ class NCNetworkingCheckRemoteUser {
                 return
             }
 
-            NextcloudKit.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, error in
+            NextcloudKit.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, data, error in
 
                 let appDelegate = UIApplication.shared.delegate as! AppDelegate
                 if wipe {
@@ -64,6 +64,7 @@ class NCNetworkingCheckRemoteUser {
                         let error = NKError(errorCode: error.errorCode, errorDescription: description)
                         NCContentPresenter.shared.showError(error: error, priority: .max)
                         CCUtility.setPassword(account, password: nil)
+                        NKCommon.shared.writeLog("Password removed.")
                         appDelegate.deletePasswordSession = true
                     }
                 }

+ 11 - 11
iOSClient/Networking/NCNetworkingE2EE.swift

@@ -58,7 +58,7 @@ import Alamofire
                         guard let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) else {
                             // unlock
                             if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                             }
                             return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "Error convert ocId"))
                         }
@@ -93,7 +93,7 @@ import Alamofire
                                 self.sendE2EMetadata(account: account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: urlBase) { e2eToken, error in
                                     // unlock
                                     if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                        NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                                        NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                                     }
                                     if error == .success {
                                         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: nil)
@@ -104,7 +104,7 @@ import Alamofire
                             } else {
                                 // unlock
                                 if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                                 }
                                 completion(error)
                             }
@@ -113,7 +113,7 @@ import Alamofire
                     } else {
                         // unlock
                         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: serverUrl) {
-                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                         }
                         completion(error)
                     }
@@ -139,14 +139,14 @@ import Alamofire
                         self.sendE2EMetadata(account: metadata.account, serverUrl: metadata.serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: deleteE2eEncryption, urlBase: metadata.urlBase) { e2eToken, error in
                             // unlock
                             if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                                NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                             }
                             completion(error)
                         }
                     } else {
                         // unlock
                         if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                            NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                         }
                         completion(error)
                     }
@@ -185,7 +185,7 @@ import Alamofire
 
                 // unlock
                 if let tableLock = NCManageDatabase.shared.getE2ETokenLock(account: metadata.account, serverUrl: metadata.serverUrl) {
-                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _ in }
+                    NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, method: "DELETE") { _, _, _, _ in }
                 }
 
                 completion(error)
@@ -356,7 +356,7 @@ import Alamofire
             e2eToken = tableLock.e2eToken
         }
 
-        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "POST") { account, e2eToken, error in
+        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "POST") { account, e2eToken, data, error in
             if error == .success && e2eToken != nil {
                 NCManageDatabase.shared.setE2ETokenLock(account: account, serverUrl: serverUrl, fileId: directory.fileId, e2eToken: e2eToken!)
             }
@@ -376,7 +376,7 @@ import Alamofire
             e2eToken = tableLock.e2eToken
         }
 
-        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "DELETE") { account, e2eToken, error in
+        NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, method: "DELETE") { account, e2eToken, data, error in
             if error == .success {
                 NCManageDatabase.shared.deteleE2ETokenLock(account: account, serverUrl: serverUrl)
             }
@@ -389,7 +389,7 @@ import Alamofire
         self.lock(account: account, serverUrl: serverUrl) { directory, e2eToken, error in
             if error == .success && e2eToken != nil && directory != nil {
 
-                NextcloudKit.shared.getE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken) { account, e2eMetadata, error in
+                NextcloudKit.shared.getE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken) { account, e2eMetadata, data, error in
                     var method = "POST"
                     var e2eMetadataNew: String?
 
@@ -418,7 +418,7 @@ import Alamofire
                         method = "DELETE"
                     }
 
-                    NextcloudKit.shared.putE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken!, e2eMetadata: e2eMetadataNew, method: method) { account, _, error in
+                    NextcloudKit.shared.putE2EEMetadata(fileId: directory!.fileId, e2eToken: e2eToken!, e2eMetadata: e2eMetadataNew, method: method) { account, _, _, error in
 
                         if upload {
                             completion(e2eToken, error)

+ 44 - 27
iOSClient/Networking/NCService.swift

@@ -44,7 +44,7 @@ class NCService: NSObject {
 
         addInternalTypeIdentifier()
         requestServerStatus()
-        requestUserProfile()
+        requestUserProfile()        
     }
 
     // MARK: -
@@ -80,11 +80,13 @@ class NCService: NSObject {
         NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.keynote.key", classFile: NKCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NKCommon.typeIconFile.ppt.rawValue, name: "keynote")
     }
 
+    // MARK: -
+
     private func requestServerStatus() {
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.getServerStatus(serverUrl: appDelegate.urlBase, options: options) { serverProductName, _, versionMajor, _, _, extendedSupport, error in
+        NextcloudKit.shared.getServerStatus(serverUrl: appDelegate.urlBase, options: options) { serverProductName, _, versionMajor, _, _, extendedSupport, data, error in
             guard error == .success, extendedSupport == false else {
                 return
             }
@@ -99,16 +101,27 @@ class NCService: NSObject {
         }
     }
 
+    // MARK: -
+
     private func requestUserProfile() {
         guard !appDelegate.account.isEmpty else { return }
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.getUserProfile(options: options) { account, userProfile, error in
+        NextcloudKit.shared.getUserProfile(options: options) { account, userProfile, data, error in
             guard error == .success, account == self.appDelegate.account else {
-                NCBrandColor.shared.settingThemingColor(account: account)
-                if error.errorCode == NCGlobal.shared.errorNCUnauthorized || error.errorCode == NCGlobal.shared.errorUnauthorized || error.errorCode == NCGlobal.shared.errorForbidden {
-                    NCNetworkingCheckRemoteUser().checkRemoteUser(account: account, error: error)
+                
+                // Ops the server has Unauthorized
+                NKCommon.shared.writeLog("The server has response with Unauthorized \(error.errorCode)")
+
+                DispatchQueue.main.async {
+                    if  (UIApplication.shared.applicationState == .active) &&
+                        (NCNetworking.shared.networkReachability != NKCommon.typeReachability.notReachable) &&
+                        (error.errorCode == NCGlobal.shared.errorNCUnauthorized || error.errorCode == NCGlobal.shared.errorUnauthorized || error.errorCode == NCGlobal.shared.errorForbidden) {
+                        
+                        NCBrandColor.shared.settingThemingColor(account: account)
+                        NCNetworkingCheckRemoteUser().checkRemoteUser(account: account, error: error)
+                    }
                 }
                 return
             }
@@ -146,9 +159,12 @@ class NCService: NSObject {
             }
 
             self.requestServerCapabilities()
+            self.requestDashboardWidget()
         }
     }
 
+    // MARK: -
+
     private func requestServerCapabilities() {
         guard !appDelegate.account.isEmpty else { return }
 
@@ -179,7 +195,7 @@ class NCService: NSObject {
             // File Sharing
             let isFilesSharingEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
             if isFilesSharingEnabled {
-                NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { account, shares, error in
+                NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { account, shares, data, error in
                     if error == .success {
                         NCManageDatabase.shared.deleteTableShare(account: account)
                         if let shares = shares, !shares.isEmpty {
@@ -202,7 +218,7 @@ class NCService: NSObject {
             // Text direct editor detail
             if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
                 let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
-                NextcloudKit.shared.NCTextObtainEditorDetails(options: options) { account, editors, creators, error in
+                NextcloudKit.shared.NCTextObtainEditorDetails(options: options) { account, editors, creators, data, error in
                     if error == .success && account == self.appDelegate.account {
                         NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
                     }
@@ -212,7 +228,7 @@ class NCService: NSObject {
             // External file Server
             let isExternalSitesServerEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesExternalSitesExists, exists: true)
             if isExternalSitesServerEnabled {
-                NextcloudKit.shared.getExternalSite(options: options) { account, externalSites, error in
+                NextcloudKit.shared.getExternalSite(options: options) { account, externalSites, data, error in
                     if error == .success && account == self.appDelegate.account {
                         NCManageDatabase.shared.deleteExternalSites(account: account)
                         for externalSite in externalSites {
@@ -227,7 +243,7 @@ class NCService: NSObject {
             // User Status
             let userStatus = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesUserStatusEnabled, exists: false)
             if userStatus {
-                NextcloudKit.shared.getUserStatus(options: options) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, error in
+                NextcloudKit.shared.getUserStatus(options: options) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, data, error in
                     if error == .success && account == self.appDelegate.account && userId == self.appDelegate.userId {
                         NCManageDatabase.shared.setAccountUserStatus(userStatusClearAt: clearAt, userStatusIcon: icon, userStatusMessage: message, userStatusMessageId: messageId, userStatusMessageIsPredefined: messageIsPredefined, userStatusStatus: status, userStatusStatusIsUserDefined: statusIsUserDefined, account: account)
                     }
@@ -247,29 +263,32 @@ class NCService: NSObject {
                     NKCommon.shared.addInternalTypeIdentifier(typeIdentifier: directEditing.mimetype, classFile: NKCommon.typeClassFile.document.rawValue, editor: directEditing.editor, iconName: NKCommon.typeIconFile.document.rawValue, name: "document")
                 }
             }
+        }
+    }
+    
+    // MARK: -
+
+    private func requestDashboardWidget() {
+        
+        let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-            //TODO: Test DASHBOARD
-            /*
-            if #available(iOS 15.0, *) {
-                NextcloudKit.shared.getDashboard { request in
-                } completion: { dashboardResults, json, errorCode, errorDescription in
-                    if let dashboardResults = dashboardResults {
-                        for result in dashboardResults {
-                            for entry in result.dashboardEntries ?? [] {
-                                if let url = URL(string: entry.iconUrl) {
-                                    NextcloudKit.shared.getPreview(url: url) { account, data, errorCode, errorDescription in
-
-                                    }
-                                }
-                            }
+        if serverVersionMajor >= NCGlobal.shared.nextcloudVersion25 {
+            NextcloudKit.shared.getDashboardWidget(options: options) { account, dashboardWidgets, data, error in
+                if error == .success, let dashboardWidgets = dashboardWidgets  {
+                    NCManageDatabase.shared.addDashboardWidget(account: account, dashboardWidgets: dashboardWidgets)
+                    for widget in dashboardWidgets {
+                        if let url = URL(string: widget.iconUrl), let fileName = widget.iconClass {
+                            NCUtility.shared.getImageUserData(url: url, fileName: fileName, size: 128)
                         }
                     }
                 }
             }
-            */
         }
     }
 
+    // MARK: -
+
     @objc func synchronizeOffline(account: String) {
 
         // Synchronize Offline Directory
@@ -291,6 +310,4 @@ class NCService: NSObject {
             NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorDownloadFile)
         }
     }
-
-    // MARK: - Thirt Part
 }

+ 1 - 1
iOSClient/Notification/NCNotification.swift

@@ -289,7 +289,7 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
 
     func getNetwokingNotification() {
 
-        NextcloudKit.shared.getNotifications { account, notifications, error in
+        NextcloudKit.shared.getNotifications { account, notifications, data, error in
 
             if error == .success && account == self.appDelegate.account {
 

+ 1 - 1
iOSClient/PushNotification/NCPushNotification.m

@@ -106,7 +106,7 @@
     NSString *pushDevicePublicKey = [[NSString alloc] initWithData:pushPublicKey encoding:NSUTF8StringEncoding];
     NSString *proxyServerPath = [NCBrandOptions shared].pushNotificationServerProxy;
     
-    [[NextcloudKit shared] subscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] pushTokenHash:pushTokenHash devicePublicKey:pushDevicePublicKey proxyServerUrl:proxyServerPath customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completion:^(NSString *account, NSString *deviceIdentifier, NSString *signature, NSString *publicKey, NKError *error) {
+    [[NextcloudKit shared] subscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] pushTokenHash:pushTokenHash devicePublicKey:pushDevicePublicKey proxyServerUrl:proxyServerPath customUserAgent:nil addCustomHeaders:nil queue:dispatch_get_main_queue() completion:^(NSString *account, NSString *deviceIdentifier, NSString *signature, NSString *publicKey, NSData *data, NKError *error) {
         if (error == NKError.success) {
             NSString *userAgent = [NSString stringWithFormat:@"%@  (Strict VoIP)", [CCUtility getUserAgent]];
             [[NextcloudKit shared] subscribingPushProxyWithProxyServerUrl:proxyServerPath pushToken:self.pushKitToken deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent queue:dispatch_get_main_queue() completion:^(NKError *error) {

+ 1 - 1
iOSClient/Recent/NCRecent.swift

@@ -140,7 +140,7 @@ class NCRecent: NCCollectionViewCommon {
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.searchBodyRequest(serverUrl: appDelegate.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, error in
+        NextcloudKit.shared.searchBodyRequest(serverUrl: appDelegate.urlBase, requestBody: requestBody, showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { account, files, data, error in
 
             if error == .success {
                 NCManageDatabase.shared.convertNKFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, metadatasFolder, metadatas in

+ 2 - 2
iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift

@@ -41,7 +41,7 @@ import NextcloudKit
         NCActivityIndicator.shared.start(backgroundView: viewController.view)
 
         let fileNamePath = CCUtility.returnFileNamePath(fromFileName: NCGlobal.shared.fileNameRichWorkspace, serverUrl: serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
-        NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: directEditingCreator.editor, creatorId: directEditingCreator.identifier, templateId: "") { account, url, error in
+        NextcloudKit.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: directEditingCreator.editor, creatorId: directEditingCreator.identifier, templateId: "") { account, url, data, error in
 
             NCActivityIndicator.shared.stop()
 
@@ -76,7 +76,7 @@ import NextcloudKit
                 NCActivityIndicator.shared.start(backgroundView: viewController.view)
 
                 let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
-                NextcloudKit.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: "text") { account, url, error in
+                NextcloudKit.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: "text") { account, url, data, error in
 
                     NCActivityIndicator.shared.stop()
 

+ 2 - 2
iOSClient/ScanDocument/NCScan+CollectionView.swift

@@ -46,7 +46,7 @@ extension NCScan: UICollectionViewDataSource {
 
             // 72 DPI
             if imageWidthInPixels > 595 || imageHeightInPixels > 842 {
-                image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image
+                image = image.resizeImage(size: CGSize(width: 595, height: 842)) ?? image
             }
 
             cell.customImageView?.image = image
@@ -78,7 +78,7 @@ extension NCScan: UICollectionViewDataSource {
 
             // 72 DPI
             if imageWidthInPixels > 595 || imageHeightInPixels > 842 {
-                image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image
+                image = image.resizeImage(size: CGSize(width: 595, height: 842)) ?? image
             }
 
             cell.customImageView?.image = filter(image: image)

+ 6 - 6
iOSClient/Settings/NCEndToEndInitialize.swift

@@ -53,7 +53,7 @@ class NCEndToEndInitialize: NSObject {
 
     func getPublicKey() {
 
-        NextcloudKit.shared.getE2EECertificate { account, certificate, error in
+        NextcloudKit.shared.getE2EECertificate { account, certificate, data, error in
 
             if error == .success && account == self.appDelegate.account {
 
@@ -80,7 +80,7 @@ class NCEndToEndInitialize: NSObject {
                         return
                     }
 
-                    NextcloudKit.shared.signE2EECertificate(certificate: csr) { account, certificate, error in
+                    NextcloudKit.shared.signE2EECertificate(certificate: csr) { account, certificate, data, error in
 
                         if error == .success && account == self.appDelegate.account {
 
@@ -130,7 +130,7 @@ class NCEndToEndInitialize: NSObject {
     func getPrivateKeyCipher() {
 
         // Request PrivateKey chiper to Server
-        NextcloudKit.shared.getE2EEPrivateKey { account, privateKeyChiper, error in
+        NextcloudKit.shared.getE2EEPrivateKey { account, privateKeyChiper, data, error in
 
             if error == .success && account == self.appDelegate.account {
 
@@ -161,7 +161,7 @@ class NCEndToEndInitialize: NSObject {
                     CCUtility.setEndToEndPassphrase(self.appDelegate.account, passphrase: passphrase)
 
                     // request server publicKey
-                    NextcloudKit.shared.getE2EEPublicKey { account, publicKey, error in
+                    NextcloudKit.shared.getE2EEPublicKey { account, publicKey, data, error in
 
                         if error == .success && account == self.appDelegate.account {
 
@@ -236,7 +236,7 @@ class NCEndToEndInitialize: NSObject {
                         // privateKeyChiper
                         print(privateKeyChiper)
 
-                        NextcloudKit.shared.storeE2EEPrivateKey(privateKey: privateKeyChiper) { account, privateKey, error in
+                        NextcloudKit.shared.storeE2EEPrivateKey(privateKey: privateKeyChiper) { account, privateKey, data, error in
 
                             if error == .success && account == self.appDelegate.account {
 
@@ -244,7 +244,7 @@ class NCEndToEndInitialize: NSObject {
                                 CCUtility.setEndToEndPassphrase(account, passphrase: e2ePassphrase)
 
                                 // request server publicKey
-                                NextcloudKit.shared.getE2EEPublicKey { account, publicKey, error in
+                                NextcloudKit.shared.getE2EEPublicKey { account, publicKey, data, error in
 
                                     if error == .success && account == self.appDelegate.account {
 

+ 4 - 4
iOSClient/Share/NCShareNetworking.swift

@@ -48,7 +48,7 @@ class NCShareNetworking: NSObject {
 
         let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
         let parameter = NKShareParameter(path: filenamePath)
-        NextcloudKit.shared.readShares(parameters: parameter) { account, shares, error in
+        NextcloudKit.shared.readShares(parameters: parameter) { account, shares, data, error in
             if showLoadingIndicator {
                 NCActivityIndicator.shared.stop()
             }
@@ -74,7 +74,7 @@ class NCShareNetworking: NSObject {
         NCActivityIndicator.shared.start(backgroundView: view)
         let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
 
-        NextcloudKit.shared.createShare(path: filenamePath, shareType: option.shareType, shareWith: option.shareWith, password: option.password, permissions: option.permissions) { (account, share, error) in
+        NextcloudKit.shared.createShare(path: filenamePath, shareType: option.shareType, shareWith: option.shareWith, password: option.password, permissions: option.permissions) { (account, share, data, error) in
             NCActivityIndicator.shared.stop()
             if error == .success, let share = share {
                 option.idShare = share.idShare
@@ -105,7 +105,7 @@ class NCShareNetworking: NSObject {
 
     func updateShare(option: NCTableShareable) {
         NCActivityIndicator.shared.start(backgroundView: view)
-        NextcloudKit.shared.updateShare(idShare: option.idShare, password: option.password, expireDate: option.expDateString, permissions: option.permissions, note: option.note, label: option.label, hideDownload: option.hideDownload) { account, share, error in
+        NextcloudKit.shared.updateShare(idShare: option.idShare, password: option.password, expireDate: option.expDateString, permissions: option.permissions, note: option.note, label: option.label, hideDownload: option.hideDownload) { account, share, data, error in
             NCActivityIndicator.shared.stop()
             if error == .success, let share = share {
                 NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share])
@@ -120,7 +120,7 @@ class NCShareNetworking: NSObject {
 
     func getSharees(searchString: String) {
         NCActivityIndicator.shared.start(backgroundView: view)
-        NextcloudKit.shared.searchSharees(search: searchString) { _, sharees, error in
+        NextcloudKit.shared.searchSharees(search: searchString) { _, sharees, data, error in
             NCActivityIndicator.shared.stop()
             if error == .success {
                 self.delegate?.getSharees(sharees: sharees)

+ 1 - 1
iOSClient/Shares/NCShares.swift

@@ -84,7 +84,7 @@ class NCShares: NCCollectionViewCommon {
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { account, shares, error in
+        NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { account, shares, data, error in
 
             DispatchQueue.main.async {
                 self.refreshControl.endRefreshing()

+ 5 - 4
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -588,7 +588,7 @@
 "_password_pdf_error_"          = "Wrong password";
 "_error_download_photobrowser_" = "Error: Unable to download photo";
 "_good_morning_"                = "Good morning";
-"_good_noon_"                   = "Good noon";
+"_good_day_"                    = "Good day";
 "_good_afternoon_"              = "Good afternoon";
 "_good_evening_"                = "Good evening";
 "_good_night_"                  = "Good night";
@@ -884,10 +884,11 @@
 "_copy_passphrase_"         = "Copy passphrase";
 "_select_color_"            = "Select the color";
 "_change_color_"            = "Change color";
-
 "_description_dashboardwidget_" = "Having the Dashboard always at your fingertips has never been easier.";
-"_description_nextcloudwidget_" = "View your recent files and use the toolbar to speed up your operations.";
-"_description_toolbarwidget_"   = "A the toolbar to speed up your operations.";
+"_description_fileswidget_" = "View your recent files and use the toolbar to speed up your operations.";
+"_description_toolbarwidget_"   = "A toolbar to speed up your operations.";
+"_no_data_available_"       = "no data available";
+"_widget_available_nc25_"   = "Widget only available starting with Nextcloud 25";
 
 // Video
 "_select_trace_"            = "Select the trace";

+ 1 - 1
iOSClient/Transfers/NCTransfers.swift

@@ -184,7 +184,7 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
         cell.labelPath.text = pathText
         cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
         cell.progressView.progress = 0.0
-        if let image = NCUtilityGUI().createFilePreviewImage(ocId: metadata.ocId, etag: metadata.etag, fileNameView: metadata.fileNameView, classFile: metadata.classFile, status: metadata.status, createPreviewMedia: true) {
+        if let image = NCUtility.shared.createFilePreviewImage(ocId: metadata.ocId, etag: metadata.etag, fileNameView: metadata.fileNameView, classFile: metadata.classFile, status: metadata.status, createPreviewMedia: true) {
             cell.imageItem.image = image
         } else if !metadata.iconName.isEmpty {
             cell.imageItem.image = UIImage(named: metadata.iconName)

+ 1 - 1
iOSClient/Trash/NCTrash.swift

@@ -277,7 +277,7 @@ extension NCTrash {
 
         let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
 
-        NextcloudKit.shared.listingTrash(showHiddenFiles: false, options: options) { account, items, error in
+        NextcloudKit.shared.listingTrash(showHiddenFiles: false, options: options) { account, items, data, error in
 
             DispatchQueue.main.async { self.refreshControl.endRefreshing() }
 

+ 3 - 3
iOSClient/UserStatus/NCUserStatus.swift

@@ -171,7 +171,7 @@ class NCUserStatus: UIViewController {
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
 
-        NextcloudKit.shared.getUserStatus { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, _, error in
+        NextcloudKit.shared.getUserStatus { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, _, data, error in
 
             if error == .success {
 
@@ -336,7 +336,7 @@ class NCUserStatus: UIViewController {
 
     func getStatus() {
 
-        NextcloudKit.shared.getUserStatus { _, clearAt, icon, message, _, _, status, _, _, error in
+        NextcloudKit.shared.getUserStatus { _, clearAt, icon, message, _, _, status, _, _, data, error in
 
             if error == .success || error.errorCode == NCGlobal.shared.errorResourceNotFound {
 
@@ -369,7 +369,7 @@ class NCUserStatus: UIViewController {
                     print("No status")
                 }
 
-                NextcloudKit.shared.getUserStatusPredefinedStatuses { _, userStatuses, error in
+                NextcloudKit.shared.getUserStatusPredefinedStatuses { _, userStatuses, data, error in
 
                     if error == .success {
 

+ 66 - 2
iOSClient/Utility/NCUtility.swift

@@ -633,8 +633,8 @@ class NCUtility: NSObject {
 
             originalImage = UIImage(contentsOfFile: fileNamePath)
 
-            scaleImagePreview = originalImage?.resizeImage(size: CGSize(width: NCGlobal.shared.sizePreview, height: NCGlobal.shared.sizePreview), isAspectRation: false)
-            scaleImageIcon = originalImage?.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: false)
+            scaleImagePreview = originalImage?.resizeImage(size: CGSize(width: NCGlobal.shared.sizePreview, height: NCGlobal.shared.sizePreview))
+            scaleImageIcon = originalImage?.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon))
 
             try? scaleImagePreview?.jpegData(compressionQuality: 0.7)?.write(to: URL(fileURLWithPath: fileNamePathPreview))
             try? scaleImageIcon?.jpegData(compressionQuality: 0.7)?.write(to: URL(fileURLWithPath: fileNamePathIcon))
@@ -993,4 +993,68 @@ class NCUtility: NSObject {
         let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
         return emailPred.evaluate(with: email)
     }
+    
+    func createFilePreviewImage(ocId: String, etag: String, fileNameView: String, classFile: String, status: Int, createPreviewMedia: Bool) -> UIImage? {
+
+        var imagePreview: UIImage?
+        let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView)!
+        let iconImagePath = CCUtility.getDirectoryProviderStorageIconOcId(ocId, etag: etag)!
+
+        if FileManager().fileExists(atPath: iconImagePath) {
+            imagePreview = UIImage(contentsOfFile: iconImagePath)
+        } else if !createPreviewMedia {
+            return nil
+        } else if createPreviewMedia && status >= NCGlobal.shared.metadataStatusNormal && classFile == NKCommon.typeClassFile.image.rawValue && FileManager().fileExists(atPath: filePath) {
+            if let image = UIImage(contentsOfFile: filePath), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon)), let data = image.jpegData(compressionQuality: 0.5) {
+                do {
+                    try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+                    imagePreview = image
+                } catch { }
+            }
+        } else if createPreviewMedia && status >= NCGlobal.shared.metadataStatusNormal && classFile == NKCommon.typeClassFile.video.rawValue && FileManager().fileExists(atPath: filePath) {
+            if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: filePath), at: 0), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon)), let data = image.jpegData(compressionQuality: 0.5) {
+                do {
+                    try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+                    imagePreview = image
+                } catch { }
+            }
+        }
+
+        return imagePreview
+    }
+    
+    func getImageUserData(url: URL, fileName: String?, size: CGFloat, completition: @escaping (_ image: UIImage?) -> () = { _ in }) {
+        
+        let size = CGSize(width: size, height: size)
+        let options = NKRequestOptions(queue: NKCommon.shared.backgroundQueue)
+
+        if let fileName = fileName {
+            let fileNamePath: String = CCUtility.getDirectoryUserData() + "/" + fileName + ".png"
+            if FileManager().fileExists(atPath: fileNamePath) {
+                return completition(UIImage(contentsOfFile: fileNamePath))
+            }
+        }
+        
+        NextcloudKit.shared.getPreview(url: url, options: options) { account, data, error in
+            var image: UIImage?
+            if error == .success {
+                guard let data = data else { return completition(nil) }
+                if let uiImage = UIImage(data: data) {
+                    image = uiImage.resizeImage(size: size)
+                } else if let svgImage = SVGKImage(data: data) {
+                    svgImage.size = size
+                    image = svgImage.uiImage
+                } else {
+                    print("error")
+                }
+                if let image = image, let fileName = fileName {
+                    do {
+                        let fileNamePath: String = CCUtility.getDirectoryUserData() + "/" + fileName + ".png"
+                        try image.pngData()?.write(to: URL(fileURLWithPath: fileNamePath), options: .atomic)
+                    } catch { }
+                }
+            }
+            completition(image)
+        }
+    }
 }

+ 0 - 57
iOSClient/Utility/NCUtilityGUI.swift

@@ -1,57 +0,0 @@
-//
-//  NCUtilityGUI.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 28/08/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NextcloudKit
-
-class NCUtilityGUI{
-
-    func createFilePreviewImage(ocId: String, etag: String, fileNameView: String, classFile: String, status: Int, createPreviewMedia: Bool) -> UIImage? {
-
-        var imagePreview: UIImage?
-        let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView)!
-        let iconImagePath = CCUtility.getDirectoryProviderStorageIconOcId(ocId, etag: etag)!
-
-        if FileManager().fileExists(atPath: iconImagePath) {
-            imagePreview = UIImage(contentsOfFile: iconImagePath)
-        } else if !createPreviewMedia {
-            return nil
-        } else if createPreviewMedia && status >= NCGlobal.shared.metadataStatusNormal && classFile == NKCommon.typeClassFile.image.rawValue && FileManager().fileExists(atPath: filePath) {
-            if let image = UIImage(contentsOfFile: filePath), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
-                do {
-                    try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
-                    imagePreview = image
-                } catch { }
-            }
-        } else if createPreviewMedia && status >= NCGlobal.shared.metadataStatusNormal && classFile == NKCommon.typeClassFile.video.rawValue && FileManager().fileExists(atPath: filePath) {
-            if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: filePath), at: 0), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
-                do {
-                    try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
-                    imagePreview = image
-                } catch { }
-            }
-        }
-
-        return imagePreview
-    }
-}

+ 2 - 2
iOSClient/Viewer/NCViewer.swift

@@ -102,7 +102,7 @@ class NCViewer: NSObject {
                 if metadata.url == "" {
 
                     NCActivityIndicator.shared.start(backgroundView: viewController.view)
-                    NextcloudKit.shared.createUrlRichdocuments(fileID: metadata.fileId) { account, url, error in
+                    NextcloudKit.shared.createUrlRichdocuments(fileID: metadata.fileId) { account, url, data, error in
 
                         NCActivityIndicator.shared.stop()
 
@@ -167,7 +167,7 @@ class NCViewer: NSObject {
                         }
 
                         NCActivityIndicator.shared.start(backgroundView: viewController.view)
-                        NextcloudKit.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: editor, options: options) { account, url, error in
+                        NextcloudKit.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: editor, options: options) { account, url, data, error in
 
                             NCActivityIndicator.shared.stop()
 

+ 2 - 1
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift

@@ -135,7 +135,8 @@ class NCPlayer: NSObject {
             if let player = self.player,
                let playerItem = player.currentItem,
                let object = player.currentItem,
-               playerItem === object {
+               playerItem === object,
+               self.viewController != nil {
 
                 if self.isStartPlayer {
                     return

+ 0 - 1
iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift

@@ -77,7 +77,6 @@ class NCViewerMedia: UIViewController {
         print("deinit NCViewerMedia")
 
         self.tipView?.dismiss()
-        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterPauseMedia, userInfo: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
     }
 

+ 1 - 1
iOSClient/Viewer/NCViewerProviderContextMenu.swift

@@ -64,7 +64,7 @@ class NCViewerProviderContextMenu: UIViewController {
         } else {
 
             // ICON
-            if let image = UIImage(named: metadata.iconName)?.resizeImage(size: CGSize(width: sizeIcon*2, height: sizeIcon*2), isAspectRation: true) {
+            if let image = UIImage(named: metadata.iconName)?.resizeImage(size: CGSize(width: sizeIcon*2, height: sizeIcon*2)) {
 
                 imageView.image = image
                 imageView.frame = resize(CGSize(width: sizeIcon, height: sizeIcon))

+ 2 - 2
iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift

@@ -284,7 +284,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
 
             let path = CCUtility.returnFileNamePath(fromFileName: metadata!.fileName, serverUrl: serverUrl!, urlBase: appDelegate.urlBase, account: metadata!.account)!
 
-            NextcloudKit.shared.createAssetRichdocuments(path: path) { account, url, error in
+            NextcloudKit.shared.createAssetRichdocuments(path: path) { account, url, data, error in
                 if error == .success && account == self.appDelegate.account {
                     let functionJS = "OCA.RichDocuments.documentsMain.postAsset('\(metadata!.fileNameView)', '\(url!)')"
                     self.webView.evaluateJavaScript(functionJS, completionHandler: { _, _ in })
@@ -301,7 +301,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
 
         let path = CCUtility.returnFileNamePath(fromFileName: metadata!.fileName, serverUrl: serverUrl!, urlBase: appDelegate.urlBase, account: metadata!.account)!
 
-        NextcloudKit.shared.createAssetRichdocuments(path: path) { account, url, error in
+        NextcloudKit.shared.createAssetRichdocuments(path: path) { account, url, data, error in
             if error == .success && account == self.appDelegate.account {
                 let functionJS = "OCA.RichDocuments.documentsMain.postAsset('\(metadata.fileNameView)', '\(url!)')"
                 self.webView.evaluateJavaScript(functionJS, completionHandler: { _, _ in })