瀏覽代碼

Merge branch 'develop' of https://github.com/nextcloud/ios into 2460-add-other-nextcloud-apps-to-settings-as-suggestions

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

# Conflicts:
#	Nextcloud.xcodeproj/project.pbxproj
Milen Pivchev 1 年之前
父節點
當前提交
0f445ef596
共有 100 個文件被更改,包括 1497 次插入1302 次删除
  1. 2 17
      .swiftlint.yml
  2. 1 1
      Brand/Database.swift
  3. 1 1
      Cartfile
  4. 2 1
      ExternalResources/NCApplicationHandle.swift
  5. 13 13
      Nextcloud.xcodeproj/project.pbxproj
  6. 3 0
      Share/NCShareExtension+NCDelegate.swift
  7. 1 1
      Share/NCShareExtension.swift
  8. 34 1
      iOSClient/AppDelegate.swift
  9. 23 24
      iOSClient/Data/NCDataSource.swift
  10. 94 97
      iOSClient/Data/NCManageDatabase+Account.swift
  11. 65 46
      iOSClient/Data/NCManageDatabase+Activity.swift
  12. 24 24
      iOSClient/Data/NCManageDatabase+Avatar.swift
  13. 17 14
      iOSClient/Data/NCManageDatabase+Capabilities.swift
  14. 24 24
      iOSClient/Data/NCManageDatabase+DashboardWidget.swift
  15. 32 46
      iOSClient/Data/NCManageDatabase+Directory.swift
  16. 63 74
      iOSClient/Data/NCManageDatabase+E2EE.swift
  17. 1 5
      iOSClient/Data/NCManageDatabase+Groupfolders.swift
  18. 16 13
      iOSClient/Data/NCManageDatabase+LayoutForView.swift
  19. 199 174
      iOSClient/Data/NCManageDatabase+Metadata.swift
  20. 64 60
      iOSClient/Data/NCManageDatabase+Share.swift
  21. 12 17
      iOSClient/Data/NCManageDatabase+Video.swift
  22. 204 195
      iOSClient/Data/NCManageDatabase.swift
  23. 21 23
      iOSClient/EmptyView/NCEmptyDataSet.swift
  24. 21 17
      iOSClient/EmptyView/NCEmptyView.xib
  25. 6 2
      iOSClient/Extensions/UIImage+Extension.swift
  26. 0 1
      iOSClient/Favorites/NCFavorite.swift
  27. 0 1
      iOSClient/Files/NCFiles.swift
  28. 0 1
      iOSClient/Groupfolders/NCGroupfolders.swift
  29. 0 26
      iOSClient/Images.xcassets/switchGrid.imageset/Contents.json
  30. 二進制
      iOSClient/Images.xcassets/switchGrid.imageset/switchGrid.png
  31. 二進制
      iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@2x.png
  32. 二進制
      iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@3x.png
  33. 0 26
      iOSClient/Images.xcassets/switchList.imageset/Contents.json
  34. 二進制
      iOSClient/Images.xcassets/switchList.imageset/switchList.png
  35. 二進制
      iOSClient/Images.xcassets/switchList.imageset/switchList@2x.png
  36. 二進制
      iOSClient/Images.xcassets/switchList.imageset/switchList@3x.png
  37. 26 78
      iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
  38. 2 2
      iOSClient/Main/Create cloud/NCUploadAssets.swift
  39. 1 1
      iOSClient/Main/NCActionCenter.swift
  40. 12 84
      iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.swift
  41. 28 86
      iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib
  42. 1 1
      iOSClient/Media/NCMedia.swift
  43. 22 16
      iOSClient/NCGlobal.swift
  44. 5 0
      iOSClient/Networking/E2EE/NCEndToEndEncryption.h
  45. 388 36
      iOSClient/Networking/E2EE/NCEndToEndEncryption.m
  46. 8 0
      iOSClient/Networking/E2EE/NCEndToEndMetadata.swift
  47. 0 7
      iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift
  48. 2 2
      iOSClient/Networking/NCAutoUpload.swift
  49. 13 14
      iOSClient/Networking/NCNetworking.swift
  50. 7 4
      iOSClient/Networking/NCNetworkingChunkedUpload.swift
  51. 21 17
      iOSClient/Networking/NCNetworkingProcessUpload.swift
  52. 12 1
      iOSClient/Notification/NCNotification.swift
  53. 0 1
      iOSClient/Offline/NCOffline.swift
  54. 0 1
      iOSClient/Recent/NCRecent.swift
  55. 1 2
      iOSClient/Select/NCSelect.swift
  56. 3 3
      iOSClient/Settings/CCManageAutoUpload.m
  57. 0 1
      iOSClient/Shares/NCShares.swift
  58. 二進制
      iOSClient/Supporting Files/af.lproj/Localizable.strings
  59. 二進制
      iOSClient/Supporting Files/an.lproj/Localizable.strings
  60. 二進制
      iOSClient/Supporting Files/ar.lproj/Localizable.strings
  61. 二進制
      iOSClient/Supporting Files/ast.lproj/Localizable.strings
  62. 二進制
      iOSClient/Supporting Files/az.lproj/Localizable.strings
  63. 二進制
      iOSClient/Supporting Files/be.lproj/Localizable.strings
  64. 二進制
      iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
  65. 二進制
      iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
  66. 二進制
      iOSClient/Supporting Files/br.lproj/Localizable.strings
  67. 二進制
      iOSClient/Supporting Files/bs.lproj/Localizable.strings
  68. 二進制
      iOSClient/Supporting Files/ca.lproj/Localizable.strings
  69. 二進制
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  70. 二進制
      iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
  71. 二進制
      iOSClient/Supporting Files/da.lproj/Localizable.strings
  72. 二進制
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  73. 二進制
      iOSClient/Supporting Files/el.lproj/Localizable.strings
  74. 二進制
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  75. 2 0
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  76. 二進制
      iOSClient/Supporting Files/eo.lproj/Localizable.strings
  77. 二進制
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  78. 二進制
      iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
  79. 二進制
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  80. 二進制
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  81. 二進制
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  82. 二進制
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  83. 二進制
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  84. 二進制
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  85. 二進制
      iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
  86. 二進制
      iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
  87. 二進制
      iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
  88. 二進制
      iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
  89. 二進制
      iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
  90. 二進制
      iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
  91. 二進制
      iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
  92. 二進制
      iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
  93. 二進制
      iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
  94. 二進制
      iOSClient/Supporting Files/es.lproj/Localizable.strings
  95. 二進制
      iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
  96. 二進制
      iOSClient/Supporting Files/eu.lproj/Localizable.strings
  97. 二進制
      iOSClient/Supporting Files/fa.lproj/Localizable.strings
  98. 二進制
      iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
  99. 二進制
      iOSClient/Supporting Files/fo.lproj/Localizable.strings
  100. 二進制
      iOSClient/Supporting Files/fr.lproj/Localizable.strings

+ 2 - 17
.swiftlint.yml

@@ -11,7 +11,7 @@ empty_count:
 
 
 line_length:
 line_length:
   warning: 400
   warning: 400
-  error: 400
+  error: 5000
 
 
 function_body_length:
 function_body_length:
    warning: 200
    warning: 200
@@ -37,7 +37,7 @@ disabled_rules:
   - cyclomatic_complexity
   - cyclomatic_complexity
   - nesting
   - nesting
   - shorthand_operator
   - shorthand_operator
-  - force_try
+  - type_name
     
     
 excluded:
 excluded:
   - Carthage
   - Carthage
@@ -70,21 +70,6 @@ excluded:
   - iOSClient/AppDelegate.swift
   - iOSClient/AppDelegate.swift
   - iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift
   - iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift
   - iOSClient/BrowserWeb/NCBrowserWeb.swift
   - iOSClient/BrowserWeb/NCBrowserWeb.swift
-  - iOSClient/Data/NCDataSource.swift
-  - iOSClient/Data/NCDatabase.swift
-  - iOSClient/Data/NCElementsJSON.swift
-  - iOSClient/Data/NCManageDatabase+Capabilities.swift
-  - iOSClient/Data/NCManageDatabase+Account.swift
-  - iOSClient/Data/NCManageDatabase+Activity.swift
-  - iOSClient/Data/NCManageDatabase+Avatar.swift
-  - iOSClient/Data/NCManageDatabase+E2EE.swift
-  - iOSClient/Data/NCManageDatabase.swift
-  - iOSClient/Data/NCManageDatabase+Metadata.swift
-  - iOSClient/Data/NCManageDatabase+Directory.swift
-  - iOSClient/Data/NCManageDatabase+Share.swift
-  - iOSClient/Data/NCManageDatabase+Video.swift
-  - iOSClient/Data/NCManageDatabase+LayoutForView.swift
-  - iOSClient/Data/NCManageDatabase+DashboardWidget.swift
   - iOSClient/Diagnostics/NCCapabilitiesViewController.swift
   - iOSClient/Diagnostics/NCCapabilitiesViewController.swift
   - iOSClient/EmptyView/NCEmptyDataSet.swift
   - iOSClient/EmptyView/NCEmptyDataSet.swift
   - iOSClient/Extensions/UIColor+Extensions.swift
   - iOSClient/Extensions/UIColor+Extensions.swift

+ 1 - 1
Brand/Database.swift

@@ -26,4 +26,4 @@ import Foundation
 // Database Realm
 // Database Realm
 //
 //
 let databaseName                    = "nextcloud.realm"
 let databaseName                    = "nextcloud.realm"
-let databaseSchemaVersion: UInt64   = 297
+let databaseSchemaVersion: UInt64   = 299

+ 1 - 1
Cartfile

@@ -1,2 +1,2 @@
 github "https://github.com/marinofaggiana/TOPasscodeViewController" "master"
 github "https://github.com/marinofaggiana/TOPasscodeViewController" "master"
-binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" ~> 3.3.0
+binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" ~> 3.5.1

+ 2 - 1
ExternalResources/NCApplicationHandle.swift

@@ -32,7 +32,8 @@ class NCApplicationHandle: NSObject {
 
 
     // class: AppDelegate
     // class: AppDelegate
     // func nextcloudPushNotificationAction(data: [String: AnyObject])
     // func nextcloudPushNotificationAction(data: [String: AnyObject])
-    func nextcloudPushNotificationAction(data: [String: AnyObject]) {
+    func nextcloudPushNotificationAction(data: [String: AnyObject], completion: @escaping (_ detected: Bool) -> Void) {
+        completion(false)
     }
     }
 
 
     // class: AppDelegate
     // class: AppDelegate

+ 13 - 13
Nextcloud.xcodeproj/project.pbxproj

@@ -479,7 +479,7 @@
 		F78ACD4621903D010088454D /* NCGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4521903D010088454D /* NCGridCell.xib */; };
 		F78ACD4621903D010088454D /* NCGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4521903D010088454D /* NCGridCell.xib */; };
 		F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */; };
 		F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */; };
 		F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4921903F850088454D /* NCTrashListCell.xib */; };
 		F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4921903F850088454D /* NCTrashListCell.xib */; };
-		F78ACD52219046DC0088454D /* NCSectionHeaderFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */; };
+		F78ACD52219046DC0088454D /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */; };
 		F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; };
 		F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; };
 		F78ACD58219048040088454D /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */; };
 		F78ACD58219048040088454D /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */; };
 		F78C6FDE296D677300C952C3 /* NCContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78C6FDD296D677300C952C3 /* NCContextMenu.swift */; };
 		F78C6FDE296D677300C952C3 /* NCContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78C6FDD296D677300C952C3 /* NCContextMenu.swift */; };
@@ -593,6 +593,7 @@
 		F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB68992541676B0050EC94 /* NCMore.storyboard */; };
 		F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB68992541676B0050EC94 /* NCMore.storyboard */; };
 		F7CB68A0254169530050EC94 /* NCSettings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB689F254169530050EC94 /* NCSettings.storyboard */; };
 		F7CB68A0254169530050EC94 /* NCSettings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB689F254169530050EC94 /* NCSettings.storyboard */; };
 		F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */; };
 		F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */; };
+		F7CF16A32A4D7C7A000FF107 /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CF16A22A4D7C7A000FF107 /* NCMoreUserCell.xib */; };
 		F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; };
 		F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; };
 		F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F7D56B192972405500FA46C4 /* Mantis */; };
 		F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F7D56B192972405500FA46C4 /* Mantis */; };
 		F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; };
 		F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; };
@@ -621,13 +622,12 @@
 		F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; };
 		F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; };
 		F7EDE4DB262D7BA200414FE6 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; };
 		F7EDE4DB262D7BA200414FE6 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; };
 		F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD3F21903CC20088454D /* NCGridCell.swift */; };
 		F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD3F21903CC20088454D /* NCGridCell.swift */; };
-		F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */; };
+		F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */; };
 		F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */; };
 		F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */; };
 		F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */; };
 		F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */; };
 		F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */; };
 		F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */; };
 		F7EE66AD2A20B226009AE765 /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */; };
 		F7EE66AD2A20B226009AE765 /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */; };
 		F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */; };
 		F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */; };
-		F7EFC0C6256BC77700461AAD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EFC0C5256BC77700461AAD /* NCMoreUserCell.xib */; };
 		F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; };
 		F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; };
 		F7F1E54C2492369A00E42386 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */; };
 		F7F1E54C2492369A00E42386 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */; };
 		F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */; };
 		F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */; };
@@ -1108,7 +1108,7 @@
 		F78ACD4521903D010088454D /* NCGridCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCGridCell.xib; sourceTree = "<group>"; };
 		F78ACD4521903D010088454D /* NCGridCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCGridCell.xib; sourceTree = "<group>"; };
 		F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCTrashListCell+NCTrashCellProtocol.swift"; sourceTree = "<group>"; };
 		F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCTrashListCell+NCTrashCellProtocol.swift"; sourceTree = "<group>"; };
 		F78ACD4921903F850088454D /* NCTrashListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCTrashListCell.xib; sourceTree = "<group>"; };
 		F78ACD4921903F850088454D /* NCTrashListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCTrashListCell.xib; sourceTree = "<group>"; };
-		F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderFooter.swift; sourceTree = "<group>"; };
+		F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderMenu.swift; sourceTree = "<group>"; };
 		F78ACD53219047D40088454D /* NCSectionFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionFooter.xib; sourceTree = "<group>"; };
 		F78ACD53219047D40088454D /* NCSectionFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionFooter.xib; sourceTree = "<group>"; };
 		F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionHeaderMenu.xib; sourceTree = "<group>"; };
 		F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionHeaderMenu.xib; sourceTree = "<group>"; };
 		F78C6FDD296D677300C952C3 /* NCContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenu.swift; sourceTree = "<group>"; };
 		F78C6FDD296D677300C952C3 /* NCContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCContextMenu.swift; sourceTree = "<group>"; };
@@ -1283,6 +1283,7 @@
 		F7CC04E61F5AD50D00378CEF /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7CC04E61F5AD50D00378CEF /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nextcloud.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nextcloud.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Share.appex; sourceTree = BUILT_PRODUCTS_DIR; };
 		F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Share.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+		F7CF16A22A4D7C7A000FF107 /* NCMoreUserCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCMoreUserCell.xib; sourceTree = "<group>"; };
 		F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichWorkspace.storyboard; sourceTree = "<group>"; };
 		F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichWorkspace.storyboard; sourceTree = "<group>"; };
 		F7D2C772246470CA008513AE /* XLForm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XLForm.framework; path = Carthage/Build/iOS/XLForm.framework; sourceTree = "<group>"; };
 		F7D2C772246470CA008513AE /* XLForm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XLForm.framework; path = Carthage/Build/iOS/XLForm.framework; sourceTree = "<group>"; };
 		F7D532461F5D4123006568B1 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7D532461F5D4123006568B1 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1307,7 +1308,6 @@
 		F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSelectCommandViewCopyMove.xib; sourceTree = "<group>"; };
 		F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSelectCommandViewCopyMove.xib; sourceTree = "<group>"; };
 		F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = "<group>"; };
 		F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = "<group>"; };
 		F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerProviderContextMenu.swift; sourceTree = "<group>"; };
 		F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerProviderContextMenu.swift; sourceTree = "<group>"; };
-		F7EFC0C5256BC77700461AAD /* NCMoreUserCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCMoreUserCell.xib; sourceTree = "<group>"; };
 		F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserStatus.swift; sourceTree = "<group>"; };
 		F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserStatus.swift; sourceTree = "<group>"; };
 		F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = "<group>"; };
 		F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = "<group>"; };
 		F7F35B592578FB63003F5589 /* CollaboraOnlineWebViewKeyboardManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CollaboraOnlineWebViewKeyboardManager.framework; path = Carthage/Build/iOS/CollaboraOnlineWebViewKeyboardManager.framework; sourceTree = "<group>"; };
 		F7F35B592578FB63003F5589 /* CollaboraOnlineWebViewKeyboardManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CollaboraOnlineWebViewKeyboardManager.framework; path = Carthage/Build/iOS/CollaboraOnlineWebViewKeyboardManager.framework; sourceTree = "<group>"; };
@@ -1985,7 +1985,7 @@
 				F78ACD53219047D40088454D /* NCSectionFooter.xib */,
 				F78ACD53219047D40088454D /* NCSectionFooter.xib */,
 				F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */,
 				F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */,
 				F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */,
 				F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */,
-				F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */,
+				F78ACD51219046DC0088454D /* NCSectionHeaderMenu.swift */,
 			);
 			);
 			path = "Section Header Footer";
 			path = "Section Header Footer";
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -3146,7 +3146,6 @@
 				F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */,
 				F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */,
 				F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */,
 				F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */,
 				F31F69612A2F907800162F76 /* __Snapshots__ in Resources */,
 				F31F69612A2F907800162F76 /* __Snapshots__ in Resources */,
-				F7EFC0C6256BC77700461AAD /* NCMoreUserCell.xib in Resources */,
 				F702F2E725EE5C86008F8E80 /* NCAudioRecorderViewController.storyboard in Resources */,
 				F702F2E725EE5C86008F8E80 /* NCAudioRecorderViewController.storyboard in Resources */,
 				AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */,
 				AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */,
 				F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */,
 				F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */,
@@ -3188,6 +3187,7 @@
 				F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */,
 				F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */,
 				F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */,
 				F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */,
 				F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */,
 				F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */,
+				F7CF16A32A4D7C7A000FF107 /* NCMoreUserCell.xib in Resources */,
 				F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */,
 				F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */,
 				F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */,
 				F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */,
 				F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */,
 				F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */,
@@ -3378,7 +3378,7 @@
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
 				F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */,
 				F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */,
-				F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderFooter.swift in Sources */,
+				F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderMenu.swift in Sources */,
 				F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */,
 				F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */,
 				F7C30DFB291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */,
 				F7C30DFB291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */,
@@ -3598,7 +3598,7 @@
 				AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */,
 				AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */,
 				F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */,
 				F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */,
 				F758B460212C56A400515F55 /* NCScan.swift in Sources */,
 				F758B460212C56A400515F55 /* NCScan.swift in Sources */,
-				F78ACD52219046DC0088454D /* NCSectionHeaderFooter.swift in Sources */,
+				F78ACD52219046DC0088454D /* NCSectionHeaderMenu.swift in Sources */,
 				F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */,
 				F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */,
 				F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */,
 				F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */,
 				F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */,
 				F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */,
@@ -4594,7 +4594,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 1;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -4620,7 +4620,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 					"@executable_path/../../Frameworks",
 				);
 				);
-				MARKETING_VERSION = 4.8.4;
+				MARKETING_VERSION = 4.8.6;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
@@ -4659,7 +4659,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				ENABLE_TESTABILITY = YES;
@@ -4682,7 +4682,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 					"@executable_path/../../Frameworks",
 				);
 				);
-				MARKETING_VERSION = 4.8.4;
+				MARKETING_VERSION = 4.8.6;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;

+ 3 - 0
Share/NCShareExtension+NCDelegate.swift

@@ -76,6 +76,9 @@ extension NCShareExtension: NCEmptyDataSetDelegate, NCAccountRequestDelegate {
         }
         }
         self.activeAccount = activeAccount
         self.activeAccount = activeAccount
 
 
+        // CAPABILITIES
+        NCManageDatabase.shared.setCapabilities(account: account)
+
         // COLORS
         // COLORS
         NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
         NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
         NCBrandColor.shared.createUserColors()
         NCBrandColor.shared.createUserColors()

+ 1 - 1
Share/NCShareExtension.swift

@@ -83,7 +83,7 @@ class NCShareExtension: UIViewController {
         collectionView.register(UINib(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell")
         collectionView.register(UINib(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell")
         collectionView.collectionViewLayout = NCListLayout()
         collectionView.collectionViewLayout = NCListLayout()
 
 
-        collectionView.addSubview(refreshControl)
+        collectionView.refreshControl = refreshControl
         refreshControl.tintColor = NCBrandColor.shared.brandText
         refreshControl.tintColor = NCBrandColor.shared.brandText
         refreshControl.backgroundColor = .systemBackground
         refreshControl.backgroundColor = .systemBackground
         refreshControl.addTarget(self, action: #selector(reloadDatasource), for: .valueChanged)
         refreshControl.addTarget(self, action: #selector(reloadDatasource), for: .valueChanged)

+ 34 - 1
iOSClient/AppDelegate.swift

@@ -440,7 +440,40 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     }
     }
 
 
     func nextcloudPushNotificationAction(data: [String: AnyObject]) {
     func nextcloudPushNotificationAction(data: [String: AnyObject]) {
-        NCApplicationHandle().nextcloudPushNotificationAction(data: data)
+        NCApplicationHandle().nextcloudPushNotificationAction(data: data) { detected in
+            if !detected {
+
+                var findAccount: Bool = false
+
+                if let accountPush = data["account"] as? String,
+                   let app = data["app"] as? String,
+                   app == NCGlobal.shared.twofactorNotificatioName {
+                    if accountPush == self.account {
+                        findAccount = true
+                    } else {
+                        let accounts = NCManageDatabase.shared.getAllAccount()
+                        for account in accounts {
+                            if account.account == accountPush {
+                                self.changeAccount(account.account)
+                                findAccount = true
+                            }
+                        }
+                    }
+                    if findAccount, let viewController = UIStoryboard(name: "NCNotification", bundle: nil).instantiateInitialViewController() as? NCNotification {
+                        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+                            let navigationController = UINavigationController(rootViewController: viewController)
+                            navigationController.modalPresentationStyle = .fullScreen
+                            self.window?.rootViewController?.present(navigationController, animated: true)
+                        }
+                    } else if !findAccount {
+                        let message = NSLocalizedString("_the_account_", comment: "") + " " + accountPush + " " + NSLocalizedString("_does_not_exist_", comment: "")
+                        let alertController = UIAlertController(title: NSLocalizedString("_info_", comment: ""), message: message, preferredStyle: .alert)
+                        alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
+                        self.window?.rootViewController?.present(alertController, animated: true, completion: { })
+                    }
+                }
+            }
+        }
     }
     }
 
 
     // MARK: - Login & checkErrorNetworking
     // MARK: - Login & checkErrorNetworking

+ 23 - 24
iOSClient/Data/NCDataSource.swift

@@ -124,14 +124,14 @@ class NCDataSource: NSObject {
 
 
         // Unified search
         // Unified search
         if let providers = self.providers, !providers.isEmpty {
         if let providers = self.providers, !providers.isEmpty {
-            let sectionsDictionary = ThreadSafeDictionary<String,Int>()
+            let sectionsDictionary = ThreadSafeDictionary<String, Int>()
             for section in self.sectionsValue {
             for section in self.sectionsValue {
                 if let provider = providers.filter({ $0.id == section}).first {
                 if let provider = providers.filter({ $0.id == section}).first {
                     sectionsDictionary[section] = provider.order
                     sectionsDictionary[section] = provider.order
                 }
                 }
             }
             }
             self.sectionsValue.removeAll()
             self.sectionsValue.removeAll()
-            let sectionsDictionarySorted = sectionsDictionary.sorted(by: { $0.value < $1.value } )
+            let sectionsDictionarySorted = sectionsDictionary.sorted(by: {$0.value < $1.value })
             for section in sectionsDictionarySorted {
             for section in sectionsDictionarySorted {
                 if section.key == NCGlobal.shared.appName {
                 if section.key == NCGlobal.shared.appName {
                     self.sectionsValue.insert(section.key, at: 0)
                     self.sectionsValue.insert(section.key, at: 0)
@@ -173,15 +173,15 @@ class NCDataSource: NSObject {
             searchResult = searchResults.filter({ $0.id == sectionValue}).first
             searchResult = searchResults.filter({ $0.id == sectionValue}).first
         }
         }
         let metadatas = self.metadatas.filter({ getSectionValue(metadata: $0) == sectionValue})
         let metadatas = self.metadatas.filter({ getSectionValue(metadata: $0) == sectionValue})
-        let metadataForSection = NCMetadataForSection.init(sectionValue: sectionValue,
-                                                            metadatas: metadatas,
-                                                            localFiles: self.localFiles,
-                                                            lastSearchResult: searchResult,
-                                                            sort: self.sort,
-                                                            ascending: self.ascending,
-                                                            directoryOnTop: self.directoryOnTop,
-                                                            favoriteOnTop: self.favoriteOnTop,
-                                                            filterLivePhoto: self.filterLivePhoto)
+        let metadataForSection = NCMetadataForSection(sectionValue: sectionValue,
+                                                      metadatas: metadatas,
+                                                      localFiles: self.localFiles,
+                                                      lastSearchResult: searchResult,
+                                                      sort: self.sort,
+                                                      ascending: self.ascending,
+                                                      directoryOnTop: self.directoryOnTop,
+                                                      favoriteOnTop: self.favoriteOnTop,
+                                                      filterLivePhoto: self.filterLivePhoto)
         metadatasForSection.append(metadataForSection)
         metadatasForSection.append(metadataForSection)
     }
     }
 
 
@@ -200,8 +200,8 @@ class NCDataSource: NSObject {
 
 
     @discardableResult
     @discardableResult
     func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) -> [IndexPath] {
     func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NKSearchResult) -> [IndexPath] {
-        
-        guard let sectionIndex =  getSectionIndex(metadataForSection.sectionValue) else { return [] }
+
+        guard let sectionIndex = getSectionIndex(metadataForSection.sectionValue) else { return [] }
         var indexPaths: [IndexPath] = []
         var indexPaths: [IndexPath] = []
 
 
         self.metadatas.append(contentsOf: metadatas)
         self.metadatas.append(contentsOf: metadatas)
@@ -268,7 +268,7 @@ class NCDataSource: NSObject {
         let (indexPath, metadataForSection) = self.getIndexPathMetadata(ocId: ocId)
         let (indexPath, metadataForSection) = self.getIndexPathMetadata(ocId: ocId)
         if let indexPath = indexPath, let metadataForSection = metadataForSection, indexPath.row < metadataForSection.metadatas.count {
         if let indexPath = indexPath, let metadataForSection = metadataForSection, indexPath.row < metadataForSection.metadatas.count {
             metadataForSection.metadatas.remove(at: indexPath.row)
             metadataForSection.metadatas.remove(at: indexPath.row)
-            if metadataForSection.metadatas.count == 0 {
+            if metadataForSection.metadatas.isEmpty {
                 // REMOVE sectionsValue / metadatasForSection
                 // REMOVE sectionsValue / metadatasForSection
                 sectionValue = metadataForSection.sectionValue
                 sectionValue = metadataForSection.sectionValue
                 if let sectionIndex = getSectionIndex(sectionValue) {
                 if let sectionIndex = getSectionIndex(sectionValue) {
@@ -329,32 +329,32 @@ class NCDataSource: NSObject {
     }
     }
 
 
     func isSameNumbersOfSections(numberOfSections: Int) -> Bool {
     func isSameNumbersOfSections(numberOfSections: Int) -> Bool {
-        guard self.metadatasForSection.count > 0 else { return false }
+        guard !self.metadatasForSection.isEmpty else { return false }
         return numberOfSections == self.numberOfSections()
         return numberOfSections == self.numberOfSections()
     }
     }
 
 
     func numberOfSections() -> Int {
     func numberOfSections() -> Int {
-        guard self.sectionsValue.count > 0 else { return 1 }
+        guard !self.sectionsValue.isEmpty else { return 1 }
         return self.sectionsValue.count
         return self.sectionsValue.count
     }
     }
-    
+
     func numberOfItemsInSection(_ section: Int) -> Int {
     func numberOfItemsInSection(_ section: Int) -> Int {
-        guard self.sectionsValue.count > 0 && self.metadatas.count > 0, let metadataForSection = getMetadataForSection(section) else { return 0}
+        guard !self.sectionsValue.isEmpty && !self.metadatas.isEmpty, let metadataForSection = getMetadataForSection(section) else { return 0}
         return metadataForSection.metadatas.count
         return metadataForSection.metadatas.count
     }
     }
 
 
     func cellForItemAt(indexPath: IndexPath) -> tableMetadata? {
     func cellForItemAt(indexPath: IndexPath) -> tableMetadata? {
-        guard metadatasForSection.count > 0 && indexPath.section < metadatasForSection.count, let metadataForSection = getMetadataForSection(indexPath.section), indexPath.row < metadataForSection.metadatas.count else { return nil }
+        guard !metadatasForSection.isEmpty && indexPath.section < metadatasForSection.count, let metadataForSection = getMetadataForSection(indexPath.section), indexPath.row < metadataForSection.metadatas.count else { return nil }
         return metadataForSection.metadatas[indexPath.row]
         return metadataForSection.metadatas[indexPath.row]
     }
     }
 
 
     func getSectionValue(indexPath: IndexPath) -> String {
     func getSectionValue(indexPath: IndexPath) -> String {
-        guard metadatasForSection.count > 0 , let metadataForSection = self.getMetadataForSection(indexPath.section) else { return ""}
+        guard !metadatasForSection.isEmpty, let metadataForSection = self.getMetadataForSection(indexPath.section) else { return ""}
         return metadataForSection.sectionValue
         return metadataForSection.sectionValue
     }
     }
 
 
     func getSectionValueLocalization(indexPath: IndexPath) -> String {
     func getSectionValueLocalization(indexPath: IndexPath) -> String {
-        guard metadatasForSection.count > 0 , let metadataForSection = self.getMetadataForSection(indexPath.section) else { return ""}
+        guard !metadatasForSection.isEmpty, let metadataForSection = self.getMetadataForSection(indexPath.section) else { return ""}
         if let searchResults = self.searchResults, let searchResult = searchResults.filter({ $0.id == metadataForSection.sectionValue}).first {
         if let searchResults = self.searchResults, let searchResult = searchResults.filter({ $0.id == metadataForSection.sectionValue}).first {
             return searchResult.name
             return searchResult.name
         }
         }
@@ -423,7 +423,7 @@ class NCMetadataForSection: NSObject {
     var lastSearchResult: NKSearchResult?
     var lastSearchResult: NKSearchResult?
     var unifiedSearchInProgress: Bool = false
     var unifiedSearchInProgress: Bool = false
 
 
-    private var sort : String
+    private var sort: String
     private var ascending: Bool
     private var ascending: Bool
     private var directoryOnTop: Bool
     private var directoryOnTop: Bool
     private var favoriteOnTop: Bool
     private var favoriteOnTop: Bool
@@ -478,7 +478,7 @@ class NCMetadataForSection: NSObject {
 
 
         // Metadata order
         // Metadata order
         //
         //
-        if sort != "none" && sort != "" {
+        if sort != "none" && !sort.isEmpty {
             metadatasSorted = metadatas.sorted {
             metadatasSorted = metadatas.sorted {
 
 
                 switch sort {
                 switch sort {
@@ -543,7 +543,6 @@ class NCMetadataForSection: NSObject {
                 metadatasFile.append(metadata)
                 metadatasFile.append(metadata)
             }
             }
 
 
-            //Info
             if metadata.directory {
             if metadata.directory {
                 ocIds.append(metadata.ocId)
                 ocIds.append(metadata.ocId)
                 numDirectory += 1
                 numDirectory += 1

+ 94 - 97
iOSClient/Data/NCManageDatabase+Account.swift

@@ -33,7 +33,7 @@ class tableAccount: Object, NCUserBaseUrl {
     @objc dynamic var alias = ""
     @objc dynamic var alias = ""
     @objc dynamic var autoUpload: Bool = false
     @objc dynamic var autoUpload: Bool = false
     @objc dynamic var autoUploadCreateSubfolder: Bool = false
     @objc dynamic var autoUploadCreateSubfolder: Bool = false
-    @objc dynamic var autoUploadSubfolderGranularity: Int64 = 1
+    @objc dynamic var autoUploadSubfolderGranularity: Int = NCGlobal.shared.subfolderGranularityMonthly
     @objc dynamic var autoUploadDirectory = ""
     @objc dynamic var autoUploadDirectory = ""
     @objc dynamic var autoUploadFileName = ""
     @objc dynamic var autoUploadFileName = ""
     @objc dynamic var autoUploadFull: Bool = false
     @objc dynamic var autoUploadFull: Bool = false
@@ -81,19 +81,6 @@ class tableAccount: Object, NCUserBaseUrl {
     @objc dynamic var website = ""
     @objc dynamic var website = ""
     @objc dynamic var zip = ""
     @objc dynamic var zip = ""
 
 
-    // HC
-    @objc dynamic var hcIsTrial: Bool = false
-    @objc dynamic var hcTrialExpired: Bool = false
-    @objc dynamic var hcTrialRemainingSec: Int64 = 0
-    @objc dynamic var hcTrialEndTime: NSDate?
-    @objc dynamic var hcAccountRemoveExpired: Bool = false
-    @objc dynamic var hcAccountRemoveRemainingSec: Int64 = 0
-    @objc dynamic var hcAccountRemoveTime: NSDate?
-    @objc dynamic var hcNextGroupExpirationGroup = ""
-    @objc dynamic var hcNextGroupExpirationGroupExpired: Bool = false
-    @objc dynamic var hcNextGroupExpirationExpiresTime: NSDate?
-    @objc dynamic var hcNextGroupExpirationExpires = ""
-
     override static func primaryKey() -> String {
     override static func primaryKey() -> String {
         return "account"
         return "account"
     }
     }
@@ -103,9 +90,8 @@ extension NCManageDatabase {
 
 
     @objc func addAccount(_ account: String, urlBase: String, user: String, password: String) {
     @objc func addAccount(_ account: String, urlBase: String, user: String, password: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableAccount()
                 let addObject = tableAccount()
 
 
@@ -135,9 +121,8 @@ extension NCManageDatabase {
 
 
     @objc func updateAccount(_ account: tableAccount) {
     @objc func updateAccount(_ account: tableAccount) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 realm.add(account, update: .all)
                 realm.add(account, update: .all)
             }
             }
@@ -148,9 +133,8 @@ extension NCManageDatabase {
 
 
     @objc func deleteAccount(_ account: String) {
     @objc func deleteAccount(_ account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableAccount.self).filter("account == %@", account)
                 let result = realm.objects(tableAccount.self).filter("account == %@", account)
                 realm.delete(result)
                 realm.delete(result)
@@ -162,23 +146,27 @@ extension NCManageDatabase {
 
 
     @objc func getActiveAccount() -> tableAccount? {
     @objc func getActiveAccount() -> tableAccount? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableAccount.self).filter("active == true").first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return nil }
+            return tableAccount.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableAccount.init(value: result)
+        return nil
     }
     }
 
 
     @objc func getAccounts() -> [String]? {
     @objc func getAccounts() -> [String]? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableAccount.self).sorted(byKeyPath: "account", ascending: true)
-
-        if results.count > 0 {
-            return Array(results.map { $0.account })
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableAccount.self).sorted(byKeyPath: "account", ascending: true)
+            if !results.isEmpty {
+                return Array(results.map { $0.account })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return nil
         return nil
@@ -186,68 +174,82 @@ extension NCManageDatabase {
 
 
     @objc func getAccount(predicate: NSPredicate) -> tableAccount? {
     @objc func getAccount(predicate: NSPredicate) -> tableAccount? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableAccount.self).filter(predicate).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAccount.self).filter(predicate).first else { return nil }
+            return tableAccount.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableAccount.init(value: result)
+        return nil
     }
     }
 
 
     @objc func getAllAccount() -> [tableAccount] {
     @objc func getAllAccount() -> [tableAccount] {
 
 
-        let realm = try! Realm()
-
-        let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "user", ascending: true)]
-        let results = realm.objects(tableAccount.self).sorted(by: sorted)
+        do {
+            let realm = try Realm()
+            let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "user", ascending: true)]
+            let results = realm.objects(tableAccount.self).sorted(by: sorted)
+            return Array(results.map { tableAccount.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableAccount.init(value: $0) })
+        return []
     }
     }
 
 
     @objc func getAllAccountOrderAlias() -> [tableAccount] {
     @objc func getAllAccountOrderAlias() -> [tableAccount] {
 
 
-        let realm = try! Realm()
-
-        let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "alias", ascending: true), SortDescriptor(keyPath: "user", ascending: true)]
-        let results = realm.objects(tableAccount.self).sorted(by: sorted)
+        do {
+            let realm = try Realm()
+            let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "alias", ascending: true), SortDescriptor(keyPath: "user", ascending: true)]
+            let results = realm.objects(tableAccount.self).sorted(by: sorted)
+            return Array(results.map { tableAccount.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableAccount.init(value: $0) })
+        return []
     }
     }
 
 
     @objc func getAccountAutoUploadFileName() -> String {
     @objc func getAccountAutoUploadFileName() -> String {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableAccount.self).filter("active == true").first else {
-            return ""
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return "" }
+            if result.autoUploadFileName.isEmpty {
+                return NCBrandOptions.shared.folderDefaultAutoUpload
+            } else {
+                return result.autoUploadFileName
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        if result.autoUploadFileName.count > 0 {
-            return result.autoUploadFileName
-        } else {
-            return NCBrandOptions.shared.folderDefaultAutoUpload
-        }
+        return ""
     }
     }
 
 
     @objc func getAccountAutoUploadDirectory(urlBase: String, userId: String, account: String) -> String {
     @objc func getAccountAutoUploadDirectory(urlBase: String, userId: String, account: String) -> String {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableAccount.self).filter("active == true").first else {
-            return ""
-        }
-
-        if result.autoUploadDirectory.count > 0 {
-            // FIX change webdav -> /dav/files/
-            if result.autoUploadDirectory.contains("/webdav") {
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return "" }
+            if result.autoUploadDirectory.isEmpty {
                 return NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
                 return NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
             } else {
             } else {
-                return result.autoUploadDirectory
+                // FIX change webdav -> /dav/files/
+                if result.autoUploadDirectory.contains("/webdav") {
+                    return NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
+                } else {
+                    return result.autoUploadDirectory
+                }
             }
             }
-        } else {
-            return NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return ""
     }
     }
 
 
     @objc func getAccountAutoUploadPath(urlBase: String, userId: String, account: String) -> String {
     @objc func getAccountAutoUploadPath(urlBase: String, userId: String, account: String) -> String {
@@ -260,24 +262,26 @@ extension NCManageDatabase {
         return folderPhotos
         return folderPhotos
     }
     }
 
 
-    @objc func getAccountAutoUploadSubfolderGranularity() -> Int64 {
-
-        let realm = try! Realm()
+    @objc func getAccountAutoUploadSubfolderGranularity() -> Int {
 
 
-        guard let result = realm.objects(tableAccount.self).filter("active == true").first else {
-            return 1
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return NCGlobal.shared.subfolderGranularityMonthly }
+            return result.autoUploadSubfolderGranularity
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return result.autoUploadSubfolderGranularity
+        return NCGlobal.shared.subfolderGranularityMonthly
     }
     }
-    
+
     @discardableResult
     @discardableResult
     @objc func setAccountActive(_ account: String) -> tableAccount? {
     @objc func setAccountActive(_ account: String) -> tableAccount? {
 
 
-        let realm = try! Realm()
         var accountReturn = tableAccount()
         var accountReturn = tableAccount()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 let results = realm.objects(tableAccount.self)
                 let results = realm.objects(tableAccount.self)
@@ -300,9 +304,8 @@ extension NCManageDatabase {
 
 
     @objc func removePasswordAccount(_ account: String) {
     @objc func removePasswordAccount(_ account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
@@ -316,9 +319,8 @@ extension NCManageDatabase {
 
 
     @objc func setAccountAutoUploadProperty(_ property: String, state: Bool) {
     @objc func setAccountAutoUploadProperty(_ property: String, state: Bool) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                     if (tableAccount().objectSchema.properties.contains { $0.name == property }) {
                     if (tableAccount().objectSchema.properties.contains { $0.name == property }) {
@@ -331,11 +333,10 @@ extension NCManageDatabase {
         }
         }
     }
     }
 
 
-    @objc func setAccountAutoUploadGranularity(_ property: String, state: Int64) {
-
-        let realm = try! Realm()
+    @objc func setAccountAutoUploadGranularity(_ property: String, state: Int) {
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                     result.autoUploadSubfolderGranularity = state
                     result.autoUploadSubfolderGranularity = state
@@ -345,12 +346,11 @@ extension NCManageDatabase {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
     }
     }
-    
-    @objc func setAccountAutoUploadFileName(_ fileName: String?) {
 
 
-        let realm = try! Realm()
+    @objc func setAccountAutoUploadFileName(_ fileName: String?) {
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                     if let fileName = fileName {
                     if let fileName = fileName {
@@ -367,9 +367,8 @@ extension NCManageDatabase {
 
 
     @objc func setAccountAutoUploadDirectory(_ serverUrl: String?, urlBase: String, userId: String, account: String) {
     @objc func setAccountAutoUploadDirectory(_ serverUrl: String?, urlBase: String, userId: String, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                     if let serverUrl = serverUrl {
                     if let serverUrl = serverUrl {
@@ -386,9 +385,8 @@ extension NCManageDatabase {
 
 
     @objc func setAccountUserProfile(account: String, userProfile: NKUserProfile) -> tableAccount? {
     @objc func setAccountUserProfile(account: String, userProfile: NKUserProfile) -> tableAccount? {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                     result.address = userProfile.address
                     result.address = userProfile.address
@@ -416,21 +414,20 @@ extension NCManageDatabase {
                     result.website = userProfile.website
                     result.website = userProfile.website
                 }
                 }
             }
             }
+            if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
+                return tableAccount.init(value: result)
+            }
         } catch let error {
         } catch let error {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
-            return tableAccount.init(value: result)
-        } else {
-            return nil
-        }
+        return nil
     }
     }
 
 
     @objc func setAccountMediaPath(_ path: String, account: String) {
     @objc func setAccountMediaPath(_ path: String, account: String) {
 
 
-        let realm = try! Realm()
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                     result.mediaPath = path
                     result.mediaPath = path
@@ -443,8 +440,8 @@ extension NCManageDatabase {
 
 
     @objc func setAccountUserStatus(userStatusClearAt: NSDate?, userStatusIcon: String?, userStatusMessage: String?, userStatusMessageId: String?, userStatusMessageIsPredefined: Bool, userStatusStatus: String?, userStatusStatusIsUserDefined: Bool, account: String) {
     @objc func setAccountUserStatus(userStatusClearAt: NSDate?, userStatusIcon: String?, userStatusMessage: String?, userStatusMessageId: String?, userStatusMessageIsPredefined: Bool, userStatusStatus: String?, userStatusStatusIsUserDefined: Bool, account: String) {
 
 
-        let realm = try! Realm()
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                 if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
                     result.userStatusClearAt = userStatusClearAt
                     result.userStatusClearAt = userStatusClearAt
@@ -463,10 +460,10 @@ extension NCManageDatabase {
 
 
     @objc func setAccountAlias(_ alias: String?) {
     @objc func setAccountAlias(_ alias: String?) {
 
 
-        let realm = try! Realm()
         let alias = alias?.trimmingCharacters(in: .whitespacesAndNewlines)
         let alias = alias?.trimmingCharacters(in: .whitespacesAndNewlines)
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                 if let result = realm.objects(tableAccount.self).filter("active == true").first {
                     if let alias = alias {
                     if let alias = alias {

+ 65 - 46
iOSClient/Data/NCManageDatabase+Activity.swift

@@ -102,12 +102,11 @@ class tableActivitySubjectRich: Object {
 }
 }
 
 
 extension NCManageDatabase {
 extension NCManageDatabase {
-    
-    func addActivity(_ activities: [NKActivity], account: String) {
 
 
-        let realm = try! Realm()
+    func addActivity(_ activities: [NKActivity], account: String) {
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 for activity in activities {
                 for activity in activities {
@@ -195,64 +194,80 @@ extension NCManageDatabase {
 
 
     func getActivity(predicate: NSPredicate, filterFileId: String?) -> (all: [tableActivity], filter: [tableActivity]) {
     func getActivity(predicate: NSPredicate, filterFileId: String?) -> (all: [tableActivity], filter: [tableActivity]) {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableActivity.self).filter(predicate).sorted(byKeyPath: "idActivity", ascending: false)
-        let allActivity = Array(results.map(tableActivity.init))
-        guard let filterFileId = filterFileId else {
-            return (all: allActivity, filter: allActivity)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableActivity.self).filter(predicate).sorted(byKeyPath: "idActivity", ascending: false)
+            let allActivity = Array(results.map(tableActivity.init))
+            guard let filterFileId = filterFileId else {
+                return (all: allActivity, filter: allActivity)
+            }
+            // comments are loaded seperately, see NCManageDatabase.getComments
+            let filtered = allActivity.filter({ String($0.objectId) == filterFileId && $0.type != "comments" })
+            return (all: allActivity, filter: filtered)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        // comments are loaded seperately, see NCManageDatabase.getComments
-        let filtered = allActivity.filter({ String($0.objectId) == filterFileId && $0.type != "comments" })
-        return (all: allActivity, filter: filtered)
+        return([], [])
     }
     }
 
 
     func getActivitySubjectRich(account: String, idActivity: Int, key: String) -> tableActivitySubjectRich? {
     func getActivitySubjectRich(account: String, idActivity: Int, key: String) -> tableActivitySubjectRich? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && key == %@", account, idActivity, key).first
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && key == %@", account, idActivity, key).first
+            return results.map { tableActivitySubjectRich.init(value: $0) }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return results.map { tableActivitySubjectRich.init(value: $0) }
+        return nil
     }
     }
 
 
     func getActivitySubjectRich(account: String, idActivity: Int, id: String) -> tableActivitySubjectRich? {
     func getActivitySubjectRich(account: String, idActivity: Int, id: String) -> tableActivitySubjectRich? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && id == %@", account, idActivity, id)
-        var activitySubjectRich = results.first
-        if results.count == 2 {
-            for result in results {
-                if result.key == "newfile" {
-                    activitySubjectRich = result
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && id == %@", account, idActivity, id)
+            var activitySubjectRich = results.first
+            if results.count == 2 {
+                for result in results {
+                    if result.key == "newfile" {
+                        activitySubjectRich = result
+                    }
                 }
                 }
             }
             }
+            return activitySubjectRich.map { tableActivitySubjectRich.init(value: $0) }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return activitySubjectRich.map { tableActivitySubjectRich.init(value: $0) }
+        return nil
     }
     }
 
 
     func getActivityPreview(account: String, idActivity: Int, orderKeysId: [String]) -> [tableActivityPreview] {
     func getActivityPreview(account: String, idActivity: Int, orderKeysId: [String]) -> [tableActivityPreview] {
 
 
-        let realm = try! Realm()
-
         var results: [tableActivityPreview] = []
         var results: [tableActivityPreview] = []
 
 
-        for id in orderKeysId {
-            if let result = realm.objects(tableActivityPreview.self).filter("account == %@ && idActivity == %d && fileId == %d", account, idActivity, Int(id) ?? 0).first {
-                results.append(result)
+        do {
+            let realm = try Realm()
+            for id in orderKeysId {
+                if let result = realm.objects(tableActivityPreview.self).filter("account == %@ && idActivity == %d && fileId == %d", account, idActivity, Int(id) ?? 0).first {
+                    results.append(result)
+                }
             }
             }
+            return results
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return results
+        return []
     }
     }
 
 
    func updateLatestActivityId(activityFirstKnown: Int, activityLastGiven: Int, account: String) {
    func updateLatestActivityId(activityFirstKnown: Int, activityLastGiven: Int, account: String) {
-        let realm = try! Realm()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let newRecentActivity = tableActivityLatestId()
                 let newRecentActivity = tableActivityLatestId()
                 newRecentActivity.activityFirstKnown = activityFirstKnown
                 newRecentActivity.activityFirstKnown = activityFirstKnown
@@ -267,27 +282,28 @@ extension NCManageDatabase {
 
 
     func getLatestActivityId(account: String) -> tableActivityLatestId? {
     func getLatestActivityId(account: String) -> tableActivityLatestId? {
 
 
-        let realm = try! Realm()
-        return realm.objects(tableActivityLatestId.self).filter("account == %@", account).first
+        do {
+            let realm = try Realm()
+            return realm.objects(tableActivityLatestId.self).filter("account == %@", account).first
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+
+        return nil
     }
     }
-    
+
     // MARK: -
     // MARK: -
     // MARK: Table Comments
     // MARK: Table Comments
 
 
     func addComments(_ comments: [NKComments], account: String, objectId: String) {
     func addComments(_ comments: [NKComments], account: String, objectId: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let results = realm.objects(tableComments.self).filter("account == %@ AND objectId == %@", account, objectId)
                 let results = realm.objects(tableComments.self).filter("account == %@ AND objectId == %@", account, objectId)
                 realm.delete(results)
                 realm.delete(results)
-
                 for comment in comments {
                 for comment in comments {
-
                     let object = tableComments()
                     let object = tableComments()
-
                     object.account = account
                     object.account = account
                     object.actorDisplayName = comment.actorDisplayName
                     object.actorDisplayName = comment.actorDisplayName
                     object.actorId = comment.actorId
                     object.actorId = comment.actorId
@@ -300,7 +316,6 @@ extension NCManageDatabase {
                     object.objectType = comment.objectType
                     object.objectType = comment.objectType
                     object.path = comment.path
                     object.path = comment.path
                     object.verb = comment.verb
                     object.verb = comment.verb
-
                     realm.add(object, update: .all)
                     realm.add(object, update: .all)
                 }
                 }
             }
             }
@@ -311,10 +326,14 @@ extension NCManageDatabase {
 
 
     func getComments(account: String, objectId: String) -> [tableComments] {
     func getComments(account: String, objectId: String) -> [tableComments] {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableComments.self).filter("account == %@ AND objectId == %@", account, objectId).sorted(byKeyPath: "creationDateTime", ascending: false)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableComments.self).filter("account == %@ AND objectId == %@", account, objectId).sorted(byKeyPath: "creationDateTime", ascending: false)
+            return Array(results.map(tableComments.init))
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map(tableComments.init))
+        return []
     }
     }
 }
 }

+ 24 - 24
iOSClient/Data/NCManageDatabase+Avatar.swift

@@ -41,19 +41,14 @@ extension NCManageDatabase {
 
 
     func addAvatar(fileName: String, etag: String) {
     func addAvatar(fileName: String, etag: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
-                // Add new
                 let addObject = tableAvatar()
                 let addObject = tableAvatar()
-
                 addObject.date = NSDate()
                 addObject.date = NSDate()
                 addObject.etag = etag
                 addObject.etag = etag
                 addObject.fileName = fileName
                 addObject.fileName = fileName
                 addObject.loaded = true
                 addObject.loaded = true
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -63,22 +58,22 @@ extension NCManageDatabase {
 
 
     func getTableAvatar(fileName: String) -> tableAvatar? {
     func getTableAvatar(fileName: String) -> tableAvatar? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first else { return nil }
+            return tableAvatar.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableAvatar.init(value: result)
+        return nil
     }
     }
 
 
     func clearAllAvatarLoaded() {
     func clearAllAvatarLoaded() {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let results = realm.objects(tableAvatar.self)
                 let results = realm.objects(tableAvatar.self)
                 for result in results {
                 for result in results {
                     result.loaded = false
                     result.loaded = false
@@ -93,11 +88,11 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func setAvatarLoaded(fileName: String) -> UIImage? {
     func setAvatarLoaded(fileName: String) -> UIImage? {
 
 
-        let realm = try! Realm()
         let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
         let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
         var image: UIImage?
         var image: UIImage?
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first {
                 if let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first {
                     if let imageAvatar = UIImage(contentsOfFile: fileNameLocalPath) {
                     if let imageAvatar = UIImage(contentsOfFile: fileNameLocalPath) {
@@ -117,18 +112,23 @@ extension NCManageDatabase {
 
 
     func getImageAvatarLoaded(fileName: String) -> UIImage? {
     func getImageAvatarLoaded(fileName: String) -> UIImage? {
 
 
-        let realm = try! Realm()
         let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
         let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
 
 
-        let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first
-        if result == nil {
-            NCUtilityFileSystem.shared.deleteFile(filePath: fileNameLocalPath)
-            return nil
-        } else if result?.loaded == false {
-            return nil
+        do {
+            let realm = try Realm()
+            let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first
+            if result == nil {
+                NCUtilityFileSystem.shared.deleteFile(filePath: fileNameLocalPath)
+                return nil
+            } else if result?.loaded == false {
+                return nil
+            }
+            return UIImage(contentsOfFile: fileNameLocalPath)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return UIImage(contentsOfFile: fileNameLocalPath)
+        NCUtilityFileSystem.shared.deleteFile(filePath: fileNameLocalPath)
+        return nil
     }
     }
-
 }
 }

+ 17 - 14
iOSClient/Data/NCManageDatabase+Capabilities.swift

@@ -40,15 +40,12 @@ extension NCManageDatabase {
 
 
     func addCapabilitiesJSon(_ data: Data, account: String) {
     func addCapabilitiesJSon(_ data: Data, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableCapabilities()
                 let addObject = tableCapabilities()
-
                 addObject.account = account
                 addObject.account = account
                 addObject.jsondata = data
                 addObject.jsondata = data
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -58,28 +55,35 @@ extension NCManageDatabase {
 
 
     func getCapabilities(account: String) -> Data? {
     func getCapabilities(account: String) -> Data? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first else { return nil }
+            return result.jsondata
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return result.jsondata
+        return nil
     }
     }
 
 
     func setCapabilities(account: String, data: Data? = nil) {
     func setCapabilities(account: String, data: Data? = nil) {
 
 
-        let realm = try! Realm()
         let json: JSON?
         let json: JSON?
 
 
         if let data = data {
         if let data = data {
             json = JSON(data)
             json = JSON(data)
         } else {
         } else {
-            guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first,
-                  let data = result.jsondata else {
+            do {
+                let realm = try Realm()
+                guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first,
+                      let data = result.jsondata else {
+                    return
+                }
+                json = JSON(data)
+            } catch let error as NSError {
+                NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
                 return
                 return
             }
             }
-            json = JSON(data)
         }
         }
 
 
         guard let json = json else { return }
         guard let json = json else { return }
@@ -106,7 +110,6 @@ extension NCManageDatabase {
         NCGlobal.shared.capabilityE2EEEnabled = json["ocs", "data", "capabilities", "end-to-end-encryption", "enabled"].boolValue
         NCGlobal.shared.capabilityE2EEEnabled = json["ocs", "data", "capabilities", "end-to-end-encryption", "enabled"].boolValue
         NCGlobal.shared.capabilityE2EEApiVersion = json["ocs", "data", "capabilities", "end-to-end-encryption", "api-version"].stringValue
         NCGlobal.shared.capabilityE2EEApiVersion = json["ocs", "data", "capabilities", "end-to-end-encryption", "api-version"].stringValue
 
 
-
         NCGlobal.shared.capabilityRichdocumentsMimetypes.removeAll()
         NCGlobal.shared.capabilityRichdocumentsMimetypes.removeAll()
         let mimetypes = json["ocs", "data", "capabilities", "richdocuments", "mimetypes"].arrayValue
         let mimetypes = json["ocs", "data", "capabilities", "richdocuments", "mimetypes"].arrayValue
         for mimetype in mimetypes {
         for mimetype in mimetypes {

+ 24 - 24
iOSClient/Data/NCManageDatabase+DashboardWidget.swift

@@ -51,42 +51,47 @@ class tableDashboardWidgetButton: Object {
 extension NCManageDatabase {
 extension NCManageDatabase {
 
 
     func getDashboardWidget(account: String, id: String) -> (tableDashboardWidget?, [tableDashboardWidgetButton]?) {
     func getDashboardWidget(account: String, id: String) -> (tableDashboardWidget?, [tableDashboardWidgetButton]?) {
-     
-        let realm = try! Realm()
-        guard let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@ AND id == %@", account, id).first else {
-            return (nil, nil)
+
+        do {
+            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 (tableDashboardWidget.init(value: resultDashboard), Array(resultsButton.map { tableDashboardWidgetButton.init(value: $0) }))
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
-        let resultsButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@ AND id == %@", account, id).sorted(byKeyPath: "type", ascending: true)
-        
-        return (tableDashboardWidget.init(value: resultDashboard), Array(resultsButton.map { tableDashboardWidgetButton.init(value: $0) }))
+
+        return (nil, nil)
     }
     }
 
 
     func getDashboardWidgetApplications(account: String) -> [tableDashboardWidget] {
     func getDashboardWidgetApplications(account: String) -> [tableDashboardWidget] {
 
 
-        let realm = try! Realm()
-        let sortProperties = [SortDescriptor(keyPath: "order", ascending: true), SortDescriptor(keyPath: "title", ascending: true)]
-        let results = realm.objects(tableDashboardWidget.self).filter("account == %@", account).sorted(by: sortProperties)
+        do {
+            let realm = try Realm()
+            let sortProperties = [SortDescriptor(keyPath: "order", ascending: true), SortDescriptor(keyPath: "title", ascending: true)]
+            let results = realm.objects(tableDashboardWidget.self).filter("account == %@", account).sorted(by: sortProperties)
+            return Array(results.map { tableDashboardWidget.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableDashboardWidget.init(value: $0) })
+        return []
     }
     }
-    
+
     func addDashboardWidget(account: String, dashboardWidgets: [NCCDashboardWidget]) {
     func addDashboardWidget(account: String, dashboardWidgets: [NCCDashboardWidget]) {
-        
-        let realm = try! Realm()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-                
+
                 let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@", account)
                 let resultDashboard = realm.objects(tableDashboardWidget.self).filter("account == %@", account)
                 realm.delete(resultDashboard)
                 realm.delete(resultDashboard)
-                
+
                 let resultDashboardButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@", account)
                 let resultDashboardButton = realm.objects(tableDashboardWidgetButton.self).filter("account == %@", account)
                 realm.delete(resultDashboardButton)
                 realm.delete(resultDashboardButton)
-                
+
                 for widget in dashboardWidgets {
                 for widget in dashboardWidgets {
-                    
                     let addObject = tableDashboardWidget()
                     let addObject = tableDashboardWidget()
-                    
                     addObject.index = account + " " + widget.id
                     addObject.index = account + " " + widget.id
                     addObject.account = account
                     addObject.account = account
                     addObject.id = widget.id
                     addObject.id = widget.id
@@ -96,23 +101,18 @@ extension NCManageDatabase {
                     addObject.iconUrl = widget.iconUrl
                     addObject.iconUrl = widget.iconUrl
                     addObject.widgetUrl = widget.widgetUrl
                     addObject.widgetUrl = widget.widgetUrl
                     addObject.itemIconsRound = widget.itemIconsRound
                     addObject.itemIconsRound = widget.itemIconsRound
-
                     if let buttons = widget.button {
                     if let buttons = widget.button {
                         for button in buttons {
                         for button in buttons {
-                            
                             let addObject = tableDashboardWidgetButton()
                             let addObject = tableDashboardWidgetButton()
-                            
                             addObject.account = account
                             addObject.account = account
                             addObject.id = widget.id
                             addObject.id = widget.id
                             addObject.type = button.type
                             addObject.type = button.type
                             addObject.text = button.text
                             addObject.text = button.text
                             addObject.link = button.link
                             addObject.link = button.link
                             addObject.index = account + " " + widget.id + " " + button.type
                             addObject.index = account + " " + widget.id + " " + button.type
-                            
                             realm.add(addObject, update: .all)
                             realm.add(addObject, update: .all)
                         }
                         }
                     }
                     }
-                    
                     realm.add(addObject, update: .all)
                     realm.add(addObject, update: .all)
                 }
                 }
             }
             }

+ 32 - 46
iOSClient/Data/NCManageDatabase+Directory.swift

@@ -48,19 +48,16 @@ extension NCManageDatabase {
 
 
     func addDirectory(encrypted: Bool, favorite: Bool, ocId: String, fileId: String, etag: String? = nil, permissions: String? = nil, serverUrl: String, account: String) {
     func addDirectory(encrypted: Bool, favorite: Bool, ocId: String, fileId: String, etag: String? = nil, permissions: String? = nil, serverUrl: String, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 var addObject = tableDirectory()
                 var addObject = tableDirectory()
                 let result = realm.objects(tableDirectory.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableDirectory.self).filter("ocId == %@", ocId).first
-
                 if result != nil {
                 if result != nil {
                     addObject = result!
                     addObject = result!
                 } else {
                 } else {
                     addObject.ocId = ocId
                     addObject.ocId = ocId
                 }
                 }
-
                 addObject.account = account
                 addObject.account = account
                 addObject.e2eEncrypted = encrypted
                 addObject.e2eEncrypted = encrypted
                 addObject.favorite = favorite
                 addObject.favorite = favorite
@@ -72,7 +69,6 @@ extension NCManageDatabase {
                     addObject.permissions = permissions
                     addObject.permissions = permissions
                 }
                 }
                 addObject.serverUrl = serverUrl
                 addObject.serverUrl = serverUrl
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -82,19 +78,13 @@ extension NCManageDatabase {
 
 
     func deleteDirectoryAndSubDirectory(serverUrl: String, account: String) {
     func deleteDirectoryAndSubDirectory(serverUrl: String, account: String) {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl BEGINSWITH %@", account, serverUrl)
-
-        // Delete table Metadata & LocalFile
-        for result in results {
-
-            self.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", result.account, result.serverUrl))
-            self.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", result.ocId))
-        }
-
-        // Delete table Dirrectory
         do {
         do {
+            let realm = try Realm()
+            let results = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl BEGINSWITH %@", account, serverUrl)
+            for result in results {
+                self.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", result.account, result.serverUrl))
+                self.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", result.ocId))
+            }
             try realm.write {
             try realm.write {
                 realm.delete(results)
                 realm.delete(results)
             }
             }
@@ -105,19 +95,12 @@ extension NCManageDatabase {
 
 
     func setDirectory(serverUrl: String, serverUrlTo: String? = nil, etag: String? = nil, ocId: String? = nil, fileId: String? = nil, encrypted: Bool, richWorkspace: String? = nil, account: String) {
     func setDirectory(serverUrl: String, serverUrlTo: String? = nil, etag: String? = nil, ocId: String? = nil, fileId: String? = nil, encrypted: Bool, richWorkspace: String? = nil, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
-                guard let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else {
-                    return
-                }
-
+                guard let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return }
                 let directory = tableDirectory.init(value: result)
                 let directory = tableDirectory.init(value: result)
-
                 realm.delete(result)
                 realm.delete(result)
-
                 directory.e2eEncrypted = encrypted
                 directory.e2eEncrypted = encrypted
                 if let etag = etag {
                 if let etag = etag {
                     directory.etag = etag
                     directory.etag = etag
@@ -134,7 +117,6 @@ extension NCManageDatabase {
                 if let richWorkspace = richWorkspace {
                 if let richWorkspace = richWorkspace {
                     directory.richWorkspace = richWorkspace
                     directory.richWorkspace = richWorkspace
                 }
                 }
-
                 realm.add(directory, update: .all)
                 realm.add(directory, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -144,33 +126,38 @@ extension NCManageDatabase {
 
 
     func getTableDirectory(predicate: NSPredicate) -> tableDirectory? {
     func getTableDirectory(predicate: NSPredicate) -> tableDirectory? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableDirectory.self).filter(predicate).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableDirectory.self).filter(predicate).first else { return nil }
+            return tableDirectory.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableDirectory.init(value: result)
+        return nil
     }
     }
 
 
     func getTablesDirectory(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableDirectory]? {
     func getTablesDirectory(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableDirectory]? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableDirectory.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
-
-        if results.count > 0 {
-            return Array(results.map { tableDirectory.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableDirectory.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableDirectory.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     func renameDirectory(ocId: String, serverUrl: String) {
     func renameDirectory(ocId: String, serverUrl: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableDirectory.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableDirectory.self).filter("ocId == %@", ocId).first
                 result?.serverUrl = serverUrl
                 result?.serverUrl = serverUrl
@@ -182,9 +169,8 @@ extension NCManageDatabase {
 
 
     func setDirectory(serverUrl: String, offline: Bool, account: String) {
     func setDirectory(serverUrl: String, offline: Bool, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 result?.offline = offline
                 result?.offline = offline
@@ -197,10 +183,10 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func setDirectory(serverUrl: String, richWorkspace: String?, account: String) -> tableDirectory? {
     func setDirectory(serverUrl: String, richWorkspace: String?, account: String) -> tableDirectory? {
 
 
-        let realm = try! Realm()
         var result: tableDirectory?
         var result: tableDirectory?
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 result?.richWorkspace = richWorkspace
                 result?.richWorkspace = richWorkspace
@@ -219,10 +205,10 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func setDirectory(serverUrl: String, colorFolder: String?, account: String) -> tableDirectory? {
     func setDirectory(serverUrl: String, colorFolder: String?, account: String) -> tableDirectory? {
 
 
-        let realm = try! Realm()
         var result: tableDirectory?
         var result: tableDirectory?
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
                 result?.colorFolder = colorFolder
                 result?.colorFolder = colorFolder

+ 63 - 74
iOSClient/Data/NCManageDatabase+E2EE.swift

@@ -76,9 +76,8 @@ extension NCManageDatabase {
 
 
     @objc func addE2eEncryption(_ e2e: tableE2eEncryption) {
     @objc func addE2eEncryption(_ e2e: tableE2eEncryption) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 realm.add(e2e, update: .all)
                 realm.add(e2e, update: .all)
             }
             }
@@ -89,11 +88,9 @@ extension NCManageDatabase {
 
 
     @objc func deleteE2eEncryption(predicate: NSPredicate) {
     @objc func deleteE2eEncryption(predicate: NSPredicate) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let results = realm.objects(tableE2eEncryption.self).filter(predicate)
                 let results = realm.objects(tableE2eEncryption.self).filter(predicate)
                 realm.delete(results)
                 realm.delete(results)
             }
             }
@@ -104,61 +101,52 @@ extension NCManageDatabase {
 
 
     @objc func getE2eEncryption(predicate: NSPredicate) -> tableE2eEncryption? {
     @objc func getE2eEncryption(predicate: NSPredicate) -> tableE2eEncryption? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableE2eEncryption.self).filter(predicate).sorted(byKeyPath: "metadataKeyIndex", ascending: false).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableE2eEncryption.self).filter(predicate).sorted(byKeyPath: "metadataKeyIndex", ascending: false).first else { return nil }
+            return tableE2eEncryption.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableE2eEncryption.init(value: result)
+        return nil
     }
     }
 
 
     @objc func getE2eEncryptions(predicate: NSPredicate) -> [tableE2eEncryption]? {
     @objc func getE2eEncryptions(predicate: NSPredicate) -> [tableE2eEncryption]? {
 
 
-        guard self.getActiveAccount() != nil else {
-            return nil
-        }
-
-        let realm = try! Realm()
-
-        let results: Results<tableE2eEncryption>
+        guard self.getActiveAccount() != nil else { return nil }
 
 
-        results = realm.objects(tableE2eEncryption.self).filter(predicate)
-
-        if results.count > 0 {
-            return Array(results.map { tableE2eEncryption.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results: Results<tableE2eEncryption>
+            results = realm.objects(tableE2eEncryption.self).filter(predicate)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableE2eEncryption.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     @objc func renameFileE2eEncryption(serverUrl: String, fileNameIdentifier: String, newFileName: String, newFileNamePath: String) {
     @objc func renameFileE2eEncryption(serverUrl: String, fileNameIdentifier: String, newFileName: String, newFileNamePath: String) {
 
 
-        guard let activeAccount = self.getActiveAccount() else {
-            return
-        }
-
-        let realm = try! Realm()
-
-        realm.beginWrite()
-
-        guard let result = realm.objects(tableE2eEncryption.self).filter("account == %@ AND serverUrl == %@ AND fileNameIdentifier == %@", activeAccount.account, serverUrl, fileNameIdentifier).first else {
-            realm.cancelWrite()
-            return
-        }
-
-        let object = tableE2eEncryption.init(value: result)
-
-        realm.delete(result)
-
-        object.fileName = newFileName
-        object.fileNamePath = newFileNamePath
-
-        realm.add(object)
+        guard let activeAccount = self.getActiveAccount() else { return }
 
 
         do {
         do {
-            try realm.commitWrite()
-        } catch let error {
+            let realm = try Realm()
+            try realm.write {
+                guard let result = realm.objects(tableE2eEncryption.self).filter("account == %@ AND serverUrl == %@ AND fileNameIdentifier == %@", activeAccount.account, serverUrl, fileNameIdentifier).first else { return }
+                let object = tableE2eEncryption.init(value: result)
+                realm.delete(result)
+                object.fileName = newFileName
+                object.fileNamePath = newFileNamePath
+                realm.add(object)
+            }
+        } catch let error as NSError {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
     }
     }
@@ -168,41 +156,44 @@ extension NCManageDatabase {
 
 
     @objc func getE2ETokenLock(account: String, serverUrl: String) -> tableE2eEncryptionLock? {
     @objc func getE2ETokenLock(account: String, serverUrl: String) -> tableE2eEncryptionLock? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableE2eEncryptionLock.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableE2eEncryptionLock.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil }
+            return tableE2eEncryptionLock.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableE2eEncryptionLock.init(value: result)
+        return nil
     }
     }
 
 
     @objc func getE2EAllTokenLock(account: String) -> [tableE2eEncryptionLock] {
     @objc func getE2EAllTokenLock(account: String) -> [tableE2eEncryptionLock] {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableE2eEncryptionLock.self).filter("account == %@", account)
-
-        if results.count > 0 {
-            return Array(results.map { tableE2eEncryptionLock.init(value: $0) })
-        } else {
-            return []
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableE2eEncryptionLock.self).filter("account == %@", account)
+            if results.isEmpty {
+                return []
+            } else {
+                return Array(results.map { tableE2eEncryptionLock.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return []
     }
     }
 
 
     @objc func setE2ETokenLock(account: String, serverUrl: String, fileId: String, e2eToken: String) {
     @objc func setE2ETokenLock(account: String, serverUrl: String, fileId: String, e2eToken: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableE2eEncryptionLock()
                 let addObject = tableE2eEncryptionLock()
-
                 addObject.account = account
                 addObject.account = account
                 addObject.fileId = fileId
                 addObject.fileId = fileId
                 addObject.serverUrl = serverUrl
                 addObject.serverUrl = serverUrl
                 addObject.e2eToken = e2eToken
                 addObject.e2eToken = e2eToken
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -212,9 +203,8 @@ extension NCManageDatabase {
 
 
     @objc func deleteE2ETokenLock(account: String, serverUrl: String) {
     @objc func deleteE2ETokenLock(account: String, serverUrl: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableE2eEncryptionLock.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first {
                 if let result = realm.objects(tableE2eEncryptionLock.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first {
                     realm.delete(result)
                     realm.delete(result)
@@ -230,28 +220,27 @@ extension NCManageDatabase {
 
 
     func getE2eMetadata(account: String, serverUrl: String) -> tableE2eMetadata? {
     func getE2eMetadata(account: String, serverUrl: String) -> tableE2eMetadata? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableE2eMetadata.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableE2eMetadata.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil }
+            return tableE2eMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableE2eMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func setE2eMetadata(account: String, serverUrl: String, metadataKey: String, version: Double) {
     func setE2eMetadata(account: String, serverUrl: String, metadataKey: String, version: Double) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableE2eMetadata()
                 let addObject = tableE2eMetadata()
-
                 addObject.account = account
                 addObject.account = account
                 addObject.metadataKey = metadataKey
                 addObject.metadataKey = metadataKey
                 addObject.serverUrl = serverUrl
                 addObject.serverUrl = serverUrl
                 addObject.version = version
                 addObject.version = version
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {

+ 1 - 5
iOSClient/Data/NCManageDatabase+Groupfolders.swift

@@ -57,9 +57,8 @@ extension NCManageDatabase {
 
 
     func addGroupfolders(account: String, groupfolders: [NKGroupfolders]) {
     func addGroupfolders(account: String, groupfolders: [NKGroupfolders]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 let tableGroupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", account)
                 let tableGroupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", account)
@@ -69,9 +68,7 @@ extension NCManageDatabase {
                 realm.delete(tableGroupfoldersGroups)
                 realm.delete(tableGroupfoldersGroups)
 
 
                 for groupfolder in groupfolders {
                 for groupfolder in groupfolders {
-
                     let obj = TableGroupfolders()
                     let obj = TableGroupfolders()
-
                     obj.account = account
                     obj.account = account
                     obj.acl = groupfolder.acl
                     obj.acl = groupfolder.acl
                     for group in groupfolder.groups ?? [:] {
                     for group in groupfolder.groups ?? [:] {
@@ -83,7 +80,6 @@ extension NCManageDatabase {
                     obj.mountPoint = groupfolder.mountPoint
                     obj.mountPoint = groupfolder.mountPoint
                     obj.quota = groupfolder.quota
                     obj.quota = groupfolder.quota
                     obj.size = groupfolder.size
                     obj.size = groupfolder.size
-
                     realm.add(obj)
                     realm.add(obj)
                 }
                 }
             }
             }

+ 16 - 13
iOSClient/Data/NCManageDatabase+LayoutForView.swift

@@ -44,15 +44,13 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func setLayoutForView(account: String, key: String, serverUrl: String, layout: String? = nil, sort: String? = nil, ascending: Bool? = nil, groupBy: String? = nil, directoryOnTop: Bool? = nil, titleButtonHeader: String? = nil, itemForLine: Int? = nil) -> NCDBLayoutForView? {
     func setLayoutForView(account: String, key: String, serverUrl: String, layout: String? = nil, sort: String? = nil, ascending: Bool? = nil, groupBy: String? = nil, directoryOnTop: Bool? = nil, titleButtonHeader: String? = nil, itemForLine: Int? = nil) -> NCDBLayoutForView? {
 
 
-        let realm = try! Realm()
-
         var keyStore = key
         var keyStore = key
         if !serverUrl.isEmpty { keyStore = serverUrl}
         if !serverUrl.isEmpty { keyStore = serverUrl}
         let index = account + " " + keyStore
         let index = account + " " + keyStore
-
         var addObject = NCDBLayoutForView()
         var addObject = NCDBLayoutForView()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(NCDBLayoutForView.self).filter("index == %@", index).first {
                 if let result = realm.objects(NCDBLayoutForView.self).filter("index == %@", index).first {
                     addObject = result
                     addObject = result
@@ -91,16 +89,16 @@ extension NCManageDatabase {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return NCDBLayoutForView.init(value: addObject)
+        return NCDBLayoutForView(value: addObject)
     }
     }
 
 
     @discardableResult
     @discardableResult
     func setLayoutForView(layoutForView: NCDBLayoutForView) -> NCDBLayoutForView? {
     func setLayoutForView(layoutForView: NCDBLayoutForView) -> NCDBLayoutForView? {
 
 
-        let realm = try! Realm()
-        let result = NCDBLayoutForView.init(value: layoutForView)
+        let result = NCDBLayoutForView(value: layoutForView)
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 realm.add(result, update: .all)
                 realm.add(result, update: .all)
             }
             }
@@ -108,21 +106,26 @@ extension NCManageDatabase {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             return nil
             return nil
         }
         }
-        return NCDBLayoutForView.init(value: result)
+        return NCDBLayoutForView(value: result)
     }
     }
 
 
     func getLayoutForView(account: String, key: String, serverUrl: String) -> NCDBLayoutForView? {
     func getLayoutForView(account: String, key: String, serverUrl: String) -> NCDBLayoutForView? {
 
 
-        let realm = try! Realm()
-
         var keyStore = key
         var keyStore = key
         if !serverUrl.isEmpty { keyStore = serverUrl}
         if !serverUrl.isEmpty { keyStore = serverUrl}
         let index = account + " " + keyStore
         let index = account + " " + keyStore
 
 
-        if let result = realm.objects(NCDBLayoutForView.self).filter("index == %@", index).first {
-            return NCDBLayoutForView.init(value: result)
-        } else {
-            return setLayoutForView(account: account, key: key, serverUrl: serverUrl)
+        do {
+            let realm = try Realm()
+            if let result = realm.objects(NCDBLayoutForView.self).filter("index == %@", index).first {
+                return NCDBLayoutForView(value: result)
+            } else {
+                return setLayoutForView(account: account, key: key, serverUrl: serverUrl)
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return setLayoutForView(account: account, key: key, serverUrl: serverUrl)
     }
     }
 }
 }

+ 199 - 174
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -125,7 +125,7 @@ extension tableMetadata {
         }
         }
         return true
         return true
     }
     }
-    
+
     var isPrintable: Bool {
     var isPrintable: Bool {
         if isDocumentViewableOnly {
         if isDocumentViewableOnly {
             return false
             return false
@@ -144,7 +144,7 @@ extension tableMetadata {
         sharePermissionsCollaborationServices == NCGlobal.shared.permissionReadShare && classFile == NKCommon.TypeClassFile.document.rawValue
         sharePermissionsCollaborationServices == NCGlobal.shared.permissionReadShare && classFile == NKCommon.TypeClassFile.document.rawValue
     }
     }
 
 
-    var isMovie: Bool {
+    var isAudioOrVideo: Bool {
         return classFile == NKCommon.TypeClassFile.audio.rawValue || classFile == NKCommon.TypeClassFile.video.rawValue
         return classFile == NKCommon.TypeClassFile.audio.rawValue || classFile == NKCommon.TypeClassFile.video.rawValue
     }
     }
 
 
@@ -206,10 +206,8 @@ extension tableMetadata {
         if isDocumentViewableOnly {
         if isDocumentViewableOnly {
             return false
             return false
         }
         }
-
         let editors = NCUtility.shared.isDirectEditing(account: account, contentType: contentType)
         let editors = NCUtility.shared.isDirectEditing(account: account, contentType: contentType)
         let isRichDocument = NCUtility.shared.isRichDocument(self)
         let isRichDocument = NCUtility.shared.isRichDocument(self)
-
         return classFile == NKCommon.TypeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument))
         return classFile == NKCommon.TypeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument))
     }
     }
 
 
@@ -234,7 +232,7 @@ extension tableMetadata {
         return !lock || (lockOwner == user && lockOwnerType == 0)
         return !lock || (lockOwner == user && lockOwnerType == 0)
     }
     }
 
 
-    /// Return if is sharable (temp)
+    // Return if is sharable (temp)
     // TODO: modifify for E2EE 2.0
     // TODO: modifify for E2EE 2.0
     func isSharable() -> Bool {
     func isSharable() -> Bool {
         guard NCGlobal.shared.capabilityFileSharingApiEnabled else { return false }
         guard NCGlobal.shared.capabilityFileSharingApiEnabled else { return false }
@@ -309,7 +307,7 @@ extension NCManageDatabase {
         }
         }
         metadata.size = file.size
         metadata.size = file.size
         metadata.classFile = file.classFile
         metadata.classFile = file.classFile
-        //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
+        // iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
         if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue {
         if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue {
             metadata.classFile = NKCommon.TypeClassFile.document.rawValue
             metadata.classFile = NKCommon.TypeClassFile.document.rawValue
         }
         }
@@ -340,7 +338,7 @@ extension NCManageDatabase {
 
 
         var counter: Int = 0
         var counter: Int = 0
         var isDirectoryE2EE: Bool = false
         var isDirectoryE2EE: Bool = false
-        let listServerUrl = ThreadSafeDictionary<String,Bool>()
+        let listServerUrl = ThreadSafeDictionary<String, Bool>()
 
 
         var metadataFolder = tableMetadata()
         var metadataFolder = tableMetadata()
         var metadataFolders: [tableMetadata] = []
         var metadataFolders: [tableMetadata] = []
@@ -378,10 +376,10 @@ extension NCManageDatabase {
         for index in metadatas.indices {
         for index in metadatas.indices {
             let metadata = metadatas[index]
             let metadata = metadatas[index]
             if index < metadatas.count - 1,
             if index < metadatas.count - 1,
-                metadata.fileNoExtension == metadatas[index+1].fileNoExtension,
-                ((metadata.classFile == NKCommon.TypeClassFile.image.rawValue && metadatas[index+1].classFile == NKCommon.TypeClassFile.video.rawValue) || (metadata.classFile == NKCommon.TypeClassFile.video.rawValue && metadatas[index+1].classFile == NKCommon.TypeClassFile.image.rawValue)){
+                metadata.fileNoExtension == metadatas[index + 1].fileNoExtension,
+                ((metadata.classFile == NKCommon.TypeClassFile.image.rawValue && metadatas[index + 1].classFile == NKCommon.TypeClassFile.video.rawValue) || (metadata.classFile == NKCommon.TypeClassFile.video.rawValue && metadatas[index + 1].classFile == NKCommon.TypeClassFile.image.rawValue)) {
                 metadata.livePhoto = true
                 metadata.livePhoto = true
-                metadatas[index+1].livePhoto = true
+                metadatas[index + 1].livePhoto = true
             }
             }
             metadataOutput.append(metadata)
             metadataOutput.append(metadata)
         }
         }
@@ -405,7 +403,7 @@ extension NCManageDatabase {
             metadata.contentType = mimeType
             metadata.contentType = mimeType
             metadata.iconName = iconName
             metadata.iconName = iconName
             metadata.classFile = classFile
             metadata.classFile = classFile
-            //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
+            // iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
             if classFile == NKCommon.TypeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") {
             if classFile == NKCommon.TypeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") {
                 metadata.iconName = NKCommon.TypeIconFile.txt.rawValue
                 metadata.iconName = NKCommon.TypeIconFile.txt.rawValue
                 metadata.classFile = NKCommon.TypeClassFile.document.rawValue
                 metadata.classFile = NKCommon.TypeClassFile.document.rawValue
@@ -436,7 +434,7 @@ extension NCManageDatabase {
         metadata.urlBase = urlBase
         metadata.urlBase = urlBase
         metadata.user = user
         metadata.user = user
         metadata.userId = userId
         metadata.userId = userId
-        
+
         if !metadata.urlBase.isEmpty, metadata.serverUrl.hasPrefix(metadata.urlBase) {
         if !metadata.urlBase.isEmpty, metadata.serverUrl.hasPrefix(metadata.urlBase) {
             metadata.path = String(metadata.serverUrl.dropFirst(metadata.urlBase.count)) + "/"
             metadata.path = String(metadata.serverUrl.dropFirst(metadata.urlBase.count)) + "/"
         }
         }
@@ -447,10 +445,10 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func addMetadata(_ metadata: tableMetadata) -> tableMetadata? {
     func addMetadata(_ metadata: tableMetadata) -> tableMetadata? {
 
 
-        let realm = try! Realm()
         let result = tableMetadata.init(value: metadata)
         let result = tableMetadata.init(value: metadata)
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 realm.add(result, update: .all)
                 realm.add(result, update: .all)
             }
             }
@@ -463,9 +461,8 @@ extension NCManageDatabase {
 
 
     func addMetadatas(_ metadatas: [tableMetadata]) {
     func addMetadatas(_ metadatas: [tableMetadata]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 for metadata in metadatas {
                 for metadata in metadatas {
                     realm.add(metadata, update: .all)
                     realm.add(metadata, update: .all)
@@ -478,9 +475,8 @@ extension NCManageDatabase {
 
 
     func deleteMetadata(predicate: NSPredicate) {
     func deleteMetadata(predicate: NSPredicate) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableMetadata.self).filter(predicate)
                 let results = realm.objects(tableMetadata.self).filter(predicate)
                 realm.delete(results)
                 realm.delete(results)
@@ -492,9 +488,8 @@ extension NCManageDatabase {
 
 
     func moveMetadata(ocId: String, serverUrlTo: String) {
     func moveMetadata(ocId: String, serverUrlTo: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
                 if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
                     result.serverUrl = serverUrlTo
                     result.serverUrl = serverUrlTo
@@ -507,9 +502,8 @@ extension NCManageDatabase {
 
 
     func renameMetadata(fileNameTo: String, ocId: String) {
     func renameMetadata(fileNameTo: String, ocId: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
                 if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
                     let resultsType = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileNameTo, mimeType: "", directory: result.directory)
                     let resultsType = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileNameTo, mimeType: "", directory: result.directory)
@@ -528,7 +522,6 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func updateMetadatas(_ metadatas: [tableMetadata], metadatasResult: [tableMetadata], addCompareLivePhoto: Bool = true, addExistsInLocal: Bool = false, addCompareEtagLocal: Bool = false, addDirectorySynchronized: Bool = false) -> (metadatasUpdate: [tableMetadata], metadatasLocalUpdate: [tableMetadata], metadatasDelete: [tableMetadata]) {
     func updateMetadatas(_ metadatas: [tableMetadata], metadatasResult: [tableMetadata], addCompareLivePhoto: Bool = true, addExistsInLocal: Bool = false, addCompareEtagLocal: Bool = false, addDirectorySynchronized: Bool = false) -> (metadatasUpdate: [tableMetadata], metadatasLocalUpdate: [tableMetadata], metadatasDelete: [tableMetadata]) {
 
 
-        let realm = try! Realm()
         var ocIdsUdate: [String] = []
         var ocIdsUdate: [String] = []
         var ocIdsLocalUdate: [String] = []
         var ocIdsLocalUdate: [String] = []
         var metadatasDelete: [tableMetadata] = []
         var metadatasDelete: [tableMetadata] = []
@@ -536,6 +529,7 @@ extension NCManageDatabase {
         var metadatasLocalUpdate: [tableMetadata] = []
         var metadatasLocalUpdate: [tableMetadata] = []
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 // DELETE
                 // DELETE
@@ -599,30 +593,31 @@ extension NCManageDatabase {
                     }
                     }
                 }
                 }
             }
             }
-        } catch let error {
-            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
-        }
 
 
-        for ocId in ocIdsUdate {
-            if let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "ocId == %@", ocId)).first {
-                metadatasUpdate.append(tableMetadata.init(value: result))
+            for ocId in ocIdsUdate {
+                if let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "ocId == %@", ocId)).first {
+                    metadatasUpdate.append(tableMetadata.init(value: result))
+                }
             }
             }
-        }
 
 
-        for ocId in ocIdsLocalUdate {
-            if let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "ocId == %@", ocId)).first {
-                metadatasLocalUpdate.append(tableMetadata.init(value: result))
+            for ocId in ocIdsLocalUdate {
+                if let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "ocId == %@", ocId)).first {
+                    metadatasLocalUpdate.append(tableMetadata.init(value: result))
+                }
             }
             }
+
+            return (metadatasUpdate, metadatasLocalUpdate, metadatasDelete)
+        } catch let error {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return (metadatasUpdate, metadatasLocalUpdate, metadatasDelete)
+        return ([], [], [])
     }
     }
 
 
     func setMetadataSession(ocId: String, newFileName: String? = nil, session: String? = nil, sessionError: String? = nil, sessionSelector: String? = nil, sessionTaskIdentifier: Int? = nil, status: Int? = nil, etag: String? = nil) {
     func setMetadataSession(ocId: String, newFileName: String? = nil, session: String? = nil, sessionError: String? = nil, sessionSelector: String? = nil, sessionTaskIdentifier: Int? = nil, status: Int? = nil, etag: String? = nil) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 if let newFileName = newFileName {
                 if let newFileName = newFileName {
@@ -656,10 +651,10 @@ extension NCManageDatabase {
     @discardableResult
     @discardableResult
     func setMetadataStatus(ocId: String, status: Int) -> tableMetadata? {
     func setMetadataStatus(ocId: String, status: Int) -> tableMetadata? {
 
 
-        let realm = try! Realm()
         var result: tableMetadata?
         var result: tableMetadata?
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 result?.status = status
                 result?.status = status
@@ -677,13 +672,12 @@ extension NCManageDatabase {
 
 
     func setMetadataEtagResource(ocId: String, etagResource: String?) {
     func setMetadataEtagResource(ocId: String, etagResource: String?) {
 
 
-        let realm = try! Realm()
-        var result: tableMetadata?
         guard let etagResource = etagResource else { return }
         guard let etagResource = etagResource else { return }
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-                result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
+                let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 result?.etagResource = etagResource
                 result?.etagResource = etagResource
             }
             }
         } catch let error {
         } catch let error {
@@ -693,9 +687,8 @@ extension NCManageDatabase {
 
 
     func setMetadataFavorite(ocId: String, favorite: Bool) {
     func setMetadataFavorite(ocId: String, favorite: Bool) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 result?.favorite = favorite
                 result?.favorite = favorite
@@ -707,9 +700,8 @@ extension NCManageDatabase {
 
 
     func updateMetadatasFavorite(account: String, metadatas: [tableMetadata]) {
     func updateMetadatasFavorite(account: String, metadatas: [tableMetadata]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND favorite == true", account)
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND favorite == true", account)
                 for result in results {
                 for result in results {
@@ -726,9 +718,8 @@ extension NCManageDatabase {
 
 
     func setMetadataEncrypted(ocId: String, encrypted: Bool) {
     func setMetadataEncrypted(ocId: String, encrypted: Bool) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
                 result?.e2eEncrypted = encrypted
                 result?.e2eEncrypted = encrypted
@@ -740,9 +731,8 @@ extension NCManageDatabase {
 
 
     func setMetadataFileNameView(serverUrl: String, fileName: String, newFileNameView: String, account: String) {
     func setMetadataFileNameView(serverUrl: String, fileName: String, newFileNameView: String, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).first
                 let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).first
                 result?.fileNameView = newFileNameView
                 result?.fileNameView = newFileNameView
@@ -754,144 +744,159 @@ extension NCManageDatabase {
 
 
     func getMetadata(predicate: NSPredicate) -> tableMetadata? {
     func getMetadata(predicate: NSPredicate) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        guard let result = realm.objects(tableMetadata.self).filter(predicate).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableMetadata.self).filter(predicate).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadata(predicate: NSPredicate, sorted: String, ascending: Bool) -> tableMetadata? {
     func getMetadata(predicate: NSPredicate, sorted: String, ascending: Bool) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        guard let result = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadatasViewer(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableMetadata]? {
     func getMetadatasViewer(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableMetadata]? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
         let results: Results<tableMetadata>
         let results: Results<tableMetadata>
         var finals: [tableMetadata] = []
         var finals: [tableMetadata] = []
 
 
-        if (tableMetadata().objectSchema.properties.contains { $0.name == sorted }) {
-            results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
-        } else {
-            results = realm.objects(tableMetadata.self).filter(predicate)
-        }
+        do {
+            let realm = try Realm()
+            if (tableMetadata().objectSchema.properties.contains { $0.name == sorted }) {
+                results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+            } else {
+                results = realm.objects(tableMetadata.self).filter(predicate)
+            }
 
 
-        // For Live Photo
-        var fileNameImages: [String] = []
-        let filtered = results.filter { $0.classFile.contains(NKCommon.TypeClassFile.image.rawValue) }
-        filtered.forEach { print($0)
-            let fileName = ($0.fileNameView as NSString).deletingPathExtension
-            fileNameImages.append(fileName)
-        }
+            // For Live Photo
+            var fileNameImages: [String] = []
+            let filtered = results.filter { $0.classFile.contains(NKCommon.TypeClassFile.image.rawValue) }
+            filtered.forEach { print($0)
+                let fileName = ($0.fileNameView as NSString).deletingPathExtension
+                fileNameImages.append(fileName)
+            }
 
 
-        for result in results {
+            for result in results {
 
 
-            let ext = (result.fileNameView as NSString).pathExtension.uppercased()
-            let fileName = (result.fileNameView as NSString).deletingPathExtension
+                let ext = (result.fileNameView as NSString).pathExtension.uppercased()
+                let fileName = (result.fileNameView as NSString).deletingPathExtension
 
 
-            if !(ext == "MOV" && fileNameImages.contains(fileName)) {
-                finals.append(result)
+                if !(ext == "MOV" && fileNameImages.contains(fileName)) {
+                    finals.append(result)
+                }
             }
             }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        if finals.count > 0 {
-            return Array(finals.map { tableMetadata.init(value: $0) })
-        } else {
+        if finals.isEmpty {
             return nil
             return nil
+        } else {
+            return Array(finals.map { tableMetadata.init(value: $0) })
         }
         }
     }
     }
 
 
     func getMetadatas(predicate: NSPredicate) -> [tableMetadata] {
     func getMetadatas(predicate: NSPredicate) -> [tableMetadata] {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        let results = realm.objects(tableMetadata.self).filter(predicate)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter(predicate)
+            return Array(results.map { tableMetadata.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableMetadata.init(value: $0) })
+        return []
     }
     }
 
 
     func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] {
     func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] {
 
 
-        let realm = try! Realm()
-        realm.refresh()
         var metadatas: [tableMetadata] = []
         var metadatas: [tableMetadata] = []
 
 
-        let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
-
-        if results.count > 0 {
-            if page == 0 || limit == 0 {
-                return Array(results.map { tableMetadata.init(value: $0) })
-            } else {
-
-                let nFrom = (page - 1) * limit
-                let nTo = nFrom + (limit - 1)
-
-                for n in nFrom...nTo {
-                    if n == results.count {
-                        break
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+            if !results.isEmpty {
+                if page == 0 || limit == 0 {
+                    return Array(results.map { tableMetadata.init(value: $0) })
+                } else {
+                    let nFrom = (page - 1) * limit
+                    let nTo = nFrom + (limit - 1)
+                    for n in nFrom...nTo {
+                        if n == results.count {
+                            break
+                        }
+                        metadatas.append(tableMetadata.init(value: results[n]))
                     }
                     }
-                    metadatas.append(tableMetadata.init(value: results[n]))
                 }
                 }
             }
             }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
         return metadatas
         return metadatas
     }
     }
 
 
     func getMetadataAtIndex(predicate: NSPredicate, sorted: String, ascending: Bool, index: Int) -> tableMetadata? {
     func getMetadataAtIndex(predicate: NSPredicate, sorted: String, ascending: Bool, index: Int) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
-
-        if results.count > 0  && results.count > index {
-            return tableMetadata.init(value: results[index])
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+            if results.isEmpty {
+                return nil
+            } else {
+                return tableMetadata.init(value: results[index])
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     func getMetadataFromOcId(_ ocId: String?) -> tableMetadata? {
     func getMetadataFromOcId(_ ocId: String?) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        guard let ocId = ocId else { return nil }
-        guard let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first else { return nil }
+        do {
+            let realm = try Realm()
+            guard let ocId = ocId else { return nil }
+            guard let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadataFromFileId(_ fileId: String?) -> tableMetadata? {
     func getMetadataFromFileId(_ fileId: String?) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
-        guard let fileId = fileId else { return nil }
-        guard let result = realm.objects(tableMetadata.self).filter("fileId == %@", fileId).first else { return nil }
+        do {
+            let realm = try Realm()
+            guard let fileId = fileId else { return nil }
+            guard let result = realm.objects(tableMetadata.self).filter("fileId == %@", fileId).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadataFolder(account: String, urlBase: String, userId: String, serverUrl: String) -> tableMetadata? {
     func getMetadataFolder(account: String, urlBase: String, userId: String, serverUrl: String) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-        realm.refresh()
         var serverUrl = serverUrl
         var serverUrl = serverUrl
         var fileName = ""
         var fileName = ""
 
 
@@ -906,22 +911,31 @@ extension NCManageDatabase {
             }
             }
         }
         }
 
 
-        guard let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).first else { return nil }
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getTableMetadatasDirectoryFavoriteIdentifierRank(account: String) -> [String: NSNumber] {
     func getTableMetadatasDirectoryFavoriteIdentifierRank(account: String) -> [String: NSNumber] {
 
 
         var listIdentifierRank: [String: NSNumber] = [:]
         var listIdentifierRank: [String: NSNumber] = [:]
-        let realm = try! Realm()
         var counter = 10 as Int64
         var counter = 10 as Int64
 
 
-        let results = realm.objects(tableMetadata.self).filter("account == %@ AND directory == true AND favorite == true", account).sorted(byKeyPath: "fileNameView", ascending: true)
-
-        for result in results {
-            counter += 1
-            listIdentifierRank[result.ocId] = NSNumber(value: Int64(counter))
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter("account == %@ AND directory == true AND favorite == true", account).sorted(byKeyPath: "fileNameView", ascending: true)
+            for result in results {
+                counter += 1
+                listIdentifierRank[result.ocId] = NSNumber(value: Int64(counter))
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return listIdentifierRank
         return listIdentifierRank
@@ -929,12 +943,9 @@ extension NCManageDatabase {
 
 
     @objc func clearMetadatasUpload(account: String) {
     @objc func clearMetadatasUpload(account: String) {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND (status == %d OR status == %@)", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError)
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND (status == %d OR status == %@)", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError)
                 realm.delete(results)
                 realm.delete(results)
             }
             }
@@ -945,9 +956,8 @@ extension NCManageDatabase {
 
 
     func readMarkerMetadata(account: String, fileId: String) {
     func readMarkerMetadata(account: String, fileId: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND fileId == %@", account, fileId)
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND fileId == %@", account, fileId)
                 for result in results {
                 for result in results {
@@ -961,14 +971,16 @@ extension NCManageDatabase {
 
 
     func getAssetLocalIdentifiersUploaded(account: String) -> [String] {
     func getAssetLocalIdentifiersUploaded(account: String) -> [String] {
 
 
-        let realm = try! Realm()
-        realm.refresh()
-
         var assetLocalIdentifiers: [String] = []
         var assetLocalIdentifiers: [String] = []
 
 
-        let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account)
-        for result in results {
-            assetLocalIdentifiers.append(result.assetLocalIdentifier)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account)
+            for result in results {
+                assetLocalIdentifiers.append(result.assetLocalIdentifier)
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return assetLocalIdentifiers
         return assetLocalIdentifiers
@@ -976,9 +988,8 @@ extension NCManageDatabase {
 
 
     func clearAssetLocalIdentifiers(_ assetLocalIdentifiers: [String], account: String) {
     func clearAssetLocalIdentifiers(_ assetLocalIdentifiers: [String], account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier IN %@", account, assetLocalIdentifiers)
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier IN %@", account, assetLocalIdentifiers)
                 for result in results {
                 for result in results {
@@ -993,7 +1004,6 @@ extension NCManageDatabase {
 
 
     func getMetadataLivePhoto(metadata: tableMetadata) -> tableMetadata? {
     func getMetadataLivePhoto(metadata: tableMetadata) -> tableMetadata? {
 
 
-        let realm = try! Realm()
         var classFile = metadata.classFile
         var classFile = metadata.classFile
         var fileName = (metadata.fileNameView as NSString).deletingPathExtension
         var fileName = (metadata.fileNameView as NSString).deletingPathExtension
 
 
@@ -1009,31 +1019,35 @@ extension NCManageDatabase {
             fileName = fileName + ".jpg"
             fileName = fileName + ".jpg"
         }
         }
 
 
-        guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView CONTAINS[cd] %@ AND ocId != %@ AND classFile == %@", metadata.account, metadata.serverUrl, fileName, metadata.ocId, classFile)).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView CONTAINS[cd] %@ AND ocId != %@ AND classFile == %@", metadata.account, metadata.serverUrl, fileName, metadata.ocId, classFile)).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadatasMedia(predicate: NSPredicate, livePhoto: Bool) -> [tableMetadata] {
     func getMetadatasMedia(predicate: NSPredicate, livePhoto: Bool) -> [tableMetadata] {
 
 
-        let realm = try! Realm()
         var metadatas: [tableMetadata] = []
         var metadatas: [tableMetadata] = []
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-                let sortProperties = [SortDescriptor(keyPath: "serverUrl", ascending: false), SortDescriptor(keyPath:  "fileNameView", ascending: false)]
+                let sortProperties = [SortDescriptor(keyPath: "serverUrl", ascending: false), SortDescriptor(keyPath: "fileNameView", ascending: false)]
                 let results = realm.objects(tableMetadata.self).filter(predicate).sorted(by: sortProperties)
                 let results = realm.objects(tableMetadata.self).filter(predicate).sorted(by: sortProperties)
                 if livePhoto {
                 if livePhoto {
                     for index in results.indices {
                     for index in results.indices {
                         let metadata = results[index]
                         let metadata = results[index]
-                        if index < results.count - 1, metadata.fileNoExtension == results[index+1].fileNoExtension {
+                        if index < results.count - 1, metadata.fileNoExtension == results[index + 1].fileNoExtension {
                             if !metadata.livePhoto {
                             if !metadata.livePhoto {
                                 metadata.livePhoto = true
                                 metadata.livePhoto = true
                             }
                             }
-                            if !results[index+1].livePhoto {
-                                results[index+1].livePhoto = true
+                            if !results[index + 1].livePhoto {
+                                results[index + 1].livePhoto = true
                             }
                             }
                         }
                         }
                         if metadata.livePhoto {
                         if metadata.livePhoto {
@@ -1104,37 +1118,48 @@ extension NCManageDatabase {
 
 
     func getNumMetadatasInUpload() -> Int {
     func getNumMetadatasInUpload() -> Int {
 
 
-        let realm = try! Realm()
-
-        let num = realm.objects(tableMetadata.self).filter(NSPredicate(format: "status == %i || status == %i",  NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count
+        do {
+            let realm = try Realm()
+            return realm.objects(tableMetadata.self).filter(NSPredicate(format: "status == %i || status == %i", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return num
+        return 0
     }
     }
 
 
     func getMetadataFromDirectory(account: String, serverUrl: String) -> tableMetadata? {
     func getMetadataFromDirectory(account: String, serverUrl: String) -> tableMetadata? {
 
 
-        let realm = try! Realm()
-
-        guard let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil }
-        guard let result = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first else { return nil }
+        do {
+            let realm = try Realm()
+            guard let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first else { return nil }
+            guard let result = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first else { return nil }
+            return tableMetadata.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return tableMetadata.init(value: result)
+        return nil
     }
     }
 
 
     func getMetadatasFromGroupfolders(account: String, urlBase: String, userId: String) -> [tableMetadata] {
     func getMetadatasFromGroupfolders(account: String, urlBase: String, userId: String) -> [tableMetadata] {
 
 
-        let realm = try! Realm()
         var metadatas: [tableMetadata] = []
         var metadatas: [tableMetadata] = []
         let homeServerUrl = NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
         let homeServerUrl = NCUtilityFileSystem.shared.getHomeServer(urlBase: urlBase, userId: userId)
 
 
-        let groupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", account)
-        for groupfolder in groupfolders {
-            let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint
-            let serverUrlFileName = homeServerUrl + mountPoint
-            if let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrlFileName).first,
-               let metadata = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first {
-                metadatas.append(tableMetadata(value: metadata))
+        do {
+            let realm = try Realm()
+            let groupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", account)
+            for groupfolder in groupfolders {
+                let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint
+                let serverUrlFileName = homeServerUrl + mountPoint
+                if let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrlFileName).first,
+                   let metadata = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first {
+                    metadatas.append(tableMetadata(value: metadata))
+                }
             }
             }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return metadatas
         return metadatas

+ 64 - 60
iOSClient/Data/NCManageDatabase+Share.swift

@@ -77,26 +77,18 @@ extension NCManageDatabase {
 
 
     func addShare(account: String, home: String, shares: [NKShare]) {
     func addShare(account: String, home: String, shares: [NKShare]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 for share in shares {
                 for share in shares {
-
                     let serverUrlPath = home + share.path
                     let serverUrlPath = home + share.path
-                    guard let serverUrl = NCUtilityFileSystem.shared.deleteLastPath(serverUrlPath: serverUrlPath, home: home) else {
-                        continue
-                    }
-
+                    guard let serverUrl = NCUtilityFileSystem.shared.deleteLastPath(serverUrlPath: serverUrlPath, home: home) else { continue }
                     let object = tableShare()
                     let object = tableShare()
-
                     object.account = account
                     object.account = account
                     if let fileName = share.path.components(separatedBy: "/").last {
                     if let fileName = share.path.components(separatedBy: "/").last {
                         object.fileName = fileName
                         object.fileName = fileName
                     }
                     }
                     object.serverUrl = serverUrl
                     object.serverUrl = serverUrl
-
                     object.canEdit = share.canEdit
                     object.canEdit = share.canEdit
                     object.canDelete = share.canDelete
                     object.canDelete = share.canDelete
                     object.date = share.date
                     object.date = share.date
@@ -133,7 +125,6 @@ extension NCManageDatabase {
                     object.userIcon = share.userIcon
                     object.userIcon = share.userIcon
                     object.userMessage = share.userMessage
                     object.userMessage = share.userMessage
                     object.userStatus = share.userStatus
                     object.userStatus = share.userStatus
-
                     realm.add(object, update: .all)
                     realm.add(object, update: .all)
                 }
                 }
             }
             }
@@ -144,89 +135,102 @@ extension NCManageDatabase {
 
 
     func getTableShares(account: String) -> [tableShare] {
     func getTableShares(account: String) -> [tableShare] {
 
 
-        let realm = try! Realm()
-
-        let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
-        let results = realm.objects(tableShare.self).filter("account == %@", account).sorted(by: sortProperties)
+        do {
+            let realm = try Realm()
+            let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
+            let results = realm.objects(tableShare.self).filter("account == %@", account).sorted(by: sortProperties)
+            return Array(results.map { tableShare.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableShare.init(value: $0) })
+        return []
     }
     }
 
 
     func getTableShares(metadata: tableMetadata) -> (firstShareLink: tableShare?, share: [tableShare]?) {
     func getTableShares(metadata: tableMetadata) -> (firstShareLink: tableShare?, share: [tableShare]?) {
 
 
-        let realm = try! Realm()
-
-        let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
-        let firstShareLink = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND shareType == 3", metadata.account, metadata.serverUrl, metadata.fileName).first
-
-        if let firstShareLink = firstShareLink {
-            let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND idShare != %d", metadata.account, metadata.serverUrl, metadata.fileName, firstShareLink.idShare).sorted(by: sortProperties)
-            return(firstShareLink: tableShare.init(value: firstShareLink), share: Array(results.map { tableShare.init(value: $0) }))
-        } else {
-            let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, metadata.fileName).sorted(by: sortProperties)
-            return(firstShareLink: firstShareLink, share: Array(results.map { tableShare.init(value: $0) }))
+        do {
+            let realm = try Realm()
+            let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
+            let firstShareLink = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND shareType == 3", metadata.account, metadata.serverUrl, metadata.fileName).first
+            if let firstShareLink = firstShareLink {
+                let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@ AND idShare != %d", metadata.account, metadata.serverUrl, metadata.fileName, firstShareLink.idShare).sorted(by: sortProperties)
+                return(firstShareLink: tableShare.init(value: firstShareLink), share: Array(results.map { tableShare.init(value: $0) }))
+            } else {
+                let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, metadata.fileName).sorted(by: sortProperties)
+                return(firstShareLink: firstShareLink, share: Array(results.map { tableShare.init(value: $0) }))
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return (nil, nil)
     }
     }
 
 
     func getTableShare(account: String, idShare: Int) -> tableShare? {
     func getTableShare(account: String, idShare: Int) -> tableShare? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableShare.self).filter("account = %@ AND idShare = %d", account, idShare).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableShare.self).filter("account = %@ AND idShare = %d", account, idShare).first else { return nil }
+            return tableShare.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableShare.init(value: result)
+        return nil
     }
     }
 
 
     func getTableShares(account: String, serverUrl: String) -> [tableShare] {
     func getTableShares(account: String, serverUrl: String) -> [tableShare] {
 
 
-        let realm = try! Realm()
-
-        let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
-        let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).sorted(by: sortProperties)
+        do {
+            let realm = try Realm()
+            let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
+            let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).sorted(by: sortProperties)
+            return Array(results.map { tableShare.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableShare.init(value: $0) })
+        return []
     }
     }
 
 
     func getTableShares(account: String, serverUrl: String, fileName: String) -> [tableShare] {
     func getTableShares(account: String, serverUrl: String, fileName: String) -> [tableShare] {
 
 
-        let realm = try! Realm()
-
-        let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
-        let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).sorted(by: sortProperties)
+        do {
+            let realm = try Realm()
+            let sortProperties = [SortDescriptor(keyPath: "shareType", ascending: false), SortDescriptor(keyPath: "idShare", ascending: false)]
+            let results = realm.objects(tableShare.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).sorted(by: sortProperties)
+            return Array(results.map { tableShare.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableShare.init(value: $0) })
+        return []
     }
     }
 
 
     func deleteTableShare(account: String, idShare: Int) {
     func deleteTableShare(account: String, idShare: Int) {
 
 
-        let realm = try! Realm()
-
-        realm.beginWrite()
-
-        let result = realm.objects(tableShare.self).filter("account == %@ AND idShare == %d", account, idShare)
-        realm.delete(result)
-
         do {
         do {
-            try realm.commitWrite()
-        } catch let error {
+            let realm = try Realm()
+            try realm.write {
+                let result = realm.objects(tableShare.self).filter("account == %@ AND idShare == %d", account, idShare)
+                realm.delete(result)
+            }
+        } catch let error as NSError {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
     }
     }
 
 
     func deleteTableShare(account: String) {
     func deleteTableShare(account: String) {
 
 
-        let realm = try! Realm()
-
-        realm.beginWrite()
-
-        let result = realm.objects(tableShare.self).filter("account == %@", account)
-        realm.delete(result)
-
         do {
         do {
-            try realm.commitWrite()
-        } catch let error {
+            let realm = try Realm()
+
+            try realm.write {
+                let result = realm.objects(tableShare.self).filter("account == %@", account)
+                realm.delete(result)
+            }
+        } catch let error as NSError {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
     }
     }

+ 12 - 17
iOSClient/Data/NCManageDatabase+Video.swift

@@ -49,12 +49,11 @@ extension NCManageDatabase {
     func addVideo(metadata: tableMetadata, position: Float? = nil, width: Int? = nil, height: Int? = nil, length: Int? = nil, currentAudioTrackIndex: Int? = nil, currentVideoSubTitleIndex: Int? = nil) {
     func addVideo(metadata: tableMetadata, position: Float? = nil, width: Int? = nil, height: Int? = nil, length: Int? = nil, currentAudioTrackIndex: Int? = nil, currentVideoSubTitleIndex: Int? = nil) {
 
 
         if metadata.livePhoto { return }
         if metadata.livePhoto { return }
-        let realm = try! Realm()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
                 if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
-
                     if let position = position {
                     if let position = position {
                         result.position = position
                         result.position = position
                     }
                     }
@@ -73,16 +72,11 @@ extension NCManageDatabase {
                     if let currentVideoSubTitleIndex = currentVideoSubTitleIndex {
                     if let currentVideoSubTitleIndex = currentVideoSubTitleIndex {
                         result.currentVideoSubTitleIndex = currentVideoSubTitleIndex
                         result.currentVideoSubTitleIndex = currentVideoSubTitleIndex
                     }
                     }
-
                     realm.add(result, update: .all)
                     realm.add(result, update: .all)
-
                 } else {
                 } else {
-
                     let result = tableVideo()
                     let result = tableVideo()
-
                     result.account = metadata.account
                     result.account = metadata.account
                     result.ocId = metadata.ocId
                     result.ocId = metadata.ocId
-
                     if let position = position {
                     if let position = position {
                         result.position = position
                         result.position = position
                     }
                     }
@@ -101,7 +95,6 @@ extension NCManageDatabase {
                     if let currentVideoSubTitleIndex = currentVideoSubTitleIndex {
                     if let currentVideoSubTitleIndex = currentVideoSubTitleIndex {
                         result.currentVideoSubTitleIndex = currentVideoSubTitleIndex
                         result.currentVideoSubTitleIndex = currentVideoSubTitleIndex
                     }
                     }
-                    
                     realm.add(result, update: .all)
                     realm.add(result, update: .all)
                 }
                 }
             }
             }
@@ -112,9 +105,8 @@ extension NCManageDatabase {
 
 
     func addVideoCodec(metadata: tableMetadata, codecNameVideo: String?, codecNameAudio: String?, codecAudioChannelLayout: String?, codecAudioLanguage: String?, codecMaxCompatibility: Bool, codecQuality: String?) {
     func addVideoCodec(metadata: tableMetadata, codecNameVideo: String?, codecNameAudio: String?, codecAudioChannelLayout: String?, codecAudioLanguage: String?, codecMaxCompatibility: Bool, codecQuality: String?) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
                 if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
                     if let codecNameVideo = codecNameVideo { result.codecNameVideo = codecNameVideo }
                     if let codecNameVideo = codecNameVideo { result.codecNameVideo = codecNameVideo }
@@ -143,21 +135,24 @@ extension NCManageDatabase {
     }
     }
 
 
     func getVideo(metadata: tableMetadata?) -> tableVideo? {
     func getVideo(metadata: tableMetadata?) -> tableVideo? {
+
         guard let metadata = metadata else { return nil }
         guard let metadata = metadata else { return nil }
 
 
-        let realm = try! Realm()
-        guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else { return nil }
+            return tableVideo.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableVideo.init(value: result)
+        return nil
     }
     }
-    
-    func deleteVideo(metadata: tableMetadata) {
 
 
-        let realm = try! Realm()
+    func deleteVideo(metadata: tableMetadata) {
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId)
                 let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId)
                 realm.delete(result)
                 realm.delete(result)

+ 204 - 195
iOSClient/Data/NCManageDatabase.swift

@@ -149,7 +149,11 @@ class NCManageDatabase: NSObject {
         }
         }
 
 
         // Open Real
         // Open Real
-        _ = try! Realm()
+        do {
+            _ = try Realm()
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not open database: \(error)")
+        }
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -157,9 +161,8 @@ class NCManageDatabase: NSObject {
 
 
     @objc func clearTable(_ table: Object.Type, account: String? = nil) {
     @objc func clearTable(_ table: Object.Type, account: String? = nil) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 var results: Results<Object>
                 var results: Results<Object>
 
 
@@ -232,21 +235,24 @@ class NCManageDatabase: NSObject {
         }
         }
     }
     }
 
 
-    @objc func getThreadConfined(_ object: Object) -> Any {
+    func getThreadConfined(_ object: Object) -> Any {
 
 
-        // id tradeReference = [[NCManageDatabase shared] getThreadConfined:metadata];
         return ThreadSafeReference(to: object)
         return ThreadSafeReference(to: object)
     }
     }
 
 
-    @objc func putThreadConfined(_ tableRef: Any) -> Object? {
+    func putThreadConfined(_ tableRef: ThreadSafeReference<Object>) -> Object? {
 
 
-        // tableMetadata *metadataThread = (tableMetadata *)[[NCManageDatabase shared] putThreadConfined:tradeReference];
-        let realm = try! Realm()
+        do {
+            let realm = try Realm()
+            return realm.resolve(tableRef)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return realm.resolve(tableRef as! ThreadSafeReference<Object>)
+        return nil
     }
     }
 
 
-    @objc func isTableInvalidated(_ object: Object) -> Bool {
+    func isTableInvalidated(_ object: Object) -> Bool {
 
 
         return object.isInvalidated
         return object.isInvalidated
     }
     }
@@ -256,10 +262,12 @@ class NCManageDatabase: NSObject {
 
 
     func getChunkFolder(account: String, ocId: String) -> String {
     func getChunkFolder(account: String, ocId: String) -> String {
 
 
-        let realm = try! Realm()
-
-        if let result = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).first {
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).first else { return NSUUID().uuidString }
             return result.chunkFolder
             return result.chunkFolder
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return NSUUID().uuidString
         return NSUUID().uuidString
@@ -267,12 +275,17 @@ class NCManageDatabase: NSObject {
 
 
     func getChunks(account: String, ocId: String) -> [String] {
     func getChunks(account: String, ocId: String) -> [String] {
 
 
-        let realm = try! Realm()
         var filesNames: [String] = []
         var filesNames: [String] = []
 
 
-        let results = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).sorted(byKeyPath: "fileName", ascending: true)
-        for result in results {
-            filesNames.append(result.fileName)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableChunk.self).filter("account == %@ AND ocId == %@", account, ocId).sorted(byKeyPath: "fileName", ascending: true)
+            for result in results {
+                filesNames.append(result.fileName)
+            }
+            return filesNames
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return filesNames
         return filesNames
@@ -280,10 +293,10 @@ class NCManageDatabase: NSObject {
 
 
     func addChunks(account: String, ocId: String, chunkFolder: String, fileNames: [String]) {
     func addChunks(account: String, ocId: String, chunkFolder: String, fileNames: [String]) {
 
 
-        let realm = try! Realm()
         var size: Int64 = 0
         var size: Int64 = 0
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 for fileName in fileNames {
                 for fileName in fileNames {
@@ -308,22 +321,22 @@ class NCManageDatabase: NSObject {
 
 
     func getChunk(account: String, fileName: String) -> tableChunk? {
     func getChunk(account: String, fileName: String) -> tableChunk? {
 
 
-        let realm = try! Realm()
-
-        if let result = realm.objects(tableChunk.self).filter("account == %@ AND fileName == %@", account, fileName).first {
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableChunk.self).filter("account == %@ AND fileName == %@", account, fileName).first else { return nil }
             return tableChunk.init(value: result)
             return tableChunk.init(value: result)
-        } else {
-            return nil
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     func deleteChunk(account: String, ocId: String, fileName: String) {
     func deleteChunk(account: String, ocId: String, fileName: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@ AND fileName == %@", account, ocId, fileName))
                 let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@ AND fileName == %@", account, ocId, fileName))
                 realm.delete(result)
                 realm.delete(result)
             }
             }
@@ -334,9 +347,8 @@ class NCManageDatabase: NSObject {
 
 
     func deleteChunks(account: String, ocId: String) {
     func deleteChunks(account: String, ocId: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
                 let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
@@ -352,9 +364,8 @@ class NCManageDatabase: NSObject {
 
 
     func addDirectEditing(account: String, editors: [NKEditorDetailsEditors], creators: [NKEditorDetailsCreators]) {
     func addDirectEditing(account: String, editors: [NKEditorDetailsEditors], creators: [NKEditorDetailsCreators]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
 
 
                 let resultsCreators = realm.objects(tableDirectEditingCreators.self).filter("account == %@", account)
                 let resultsCreators = realm.objects(tableDirectEditingCreators.self).filter("account == %@", account)
@@ -407,39 +418,53 @@ class NCManageDatabase: NSObject {
 
 
     func getDirectEditingCreators(account: String) -> [tableDirectEditingCreators]? {
     func getDirectEditingCreators(account: String) -> [tableDirectEditingCreators]? {
 
 
-        let realm = try! Realm()
-        let results = realm.objects(tableDirectEditingCreators.self).filter("account == %@", account)
-
-        if results.count > 0 {
-            return Array(results.map { tableDirectEditingCreators.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableDirectEditingCreators.self).filter("account == %@", account)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableDirectEditingCreators.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     func getDirectEditingCreators(predicate: NSPredicate) -> [tableDirectEditingCreators]? {
     func getDirectEditingCreators(predicate: NSPredicate) -> [tableDirectEditingCreators]? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableDirectEditingCreators.self).filter(predicate)
-
-        if results.count > 0 {
-            return Array(results.map { tableDirectEditingCreators.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableDirectEditingCreators.self).filter(predicate)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableDirectEditingCreators.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     func getDirectEditingEditors(account: String) -> [tableDirectEditingEditors]? {
     func getDirectEditingEditors(account: String) -> [tableDirectEditingEditors]? {
 
 
-        let realm = try! Realm()
-        let results = realm.objects(tableDirectEditingEditors.self).filter("account == %@", account)
-
-        if results.count > 0 {
-            return Array(results.map { tableDirectEditingEditors.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableDirectEditingEditors.self).filter("account == %@", account)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableDirectEditingEditors.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -447,9 +472,8 @@ class NCManageDatabase: NSObject {
 
 
     func addExternalSites(_ externalSite: NKExternalSite, account: String) {
     func addExternalSites(_ externalSite: NKExternalSite, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableExternalSites()
                 let addObject = tableExternalSites()
 
 
@@ -470,9 +494,8 @@ class NCManageDatabase: NSObject {
 
 
     func deleteExternalSites(account: String) {
     func deleteExternalSites(account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableExternalSites.self).filter("account == %@", account)
                 let results = realm.objects(tableExternalSites.self).filter("account == %@", account)
                 realm.delete(results)
                 realm.delete(results)
@@ -484,15 +507,19 @@ class NCManageDatabase: NSObject {
 
 
     func getAllExternalSites(account: String) -> [tableExternalSites]? {
     func getAllExternalSites(account: String) -> [tableExternalSites]? {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableExternalSites.self).filter("account == %@", account).sorted(byKeyPath: "idExternalSite", ascending: true)
-
-        if results.count > 0 {
-            return Array(results.map { tableExternalSites.init(value: $0) })
-        } else {
-            return nil
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableExternalSites.self).filter("account == %@", account).sorted(byKeyPath: "idExternalSite", ascending: true)
+            if results.isEmpty {
+                return nil
+            } else {
+                return Array(results.map { tableExternalSites.init(value: $0) })
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
+
+        return nil
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -500,43 +527,37 @@ class NCManageDatabase: NSObject {
 
 
     @objc func addGeocoderLocation(_ location: String, placemarkAdministrativeArea: String, placemarkCountry: String, placemarkLocality: String, placemarkPostalCode: String, placemarkThoroughfare: String, latitude: String, longitude: String) {
     @objc func addGeocoderLocation(_ location: String, placemarkAdministrativeArea: String, placemarkCountry: String, placemarkLocality: String, placemarkPostalCode: String, placemarkThoroughfare: String, latitude: String, longitude: String) {
 
 
-        let realm = try! Realm()
-
-        realm.beginWrite()
-
-        // Verify if exists
-        guard realm.objects(tableGPS.self).filter("latitude == %@ AND longitude == %@", latitude, longitude).first == nil else {
-            realm.cancelWrite()
-            return
-        }
-
-        // Add new GPS
-        let addObject = tableGPS()
-
-        addObject.latitude = latitude
-        addObject.location = location
-        addObject.longitude = longitude
-        addObject.placemarkAdministrativeArea = placemarkAdministrativeArea
-        addObject.placemarkCountry = placemarkCountry
-        addObject.placemarkLocality = placemarkLocality
-        addObject.placemarkPostalCode = placemarkPostalCode
-        addObject.placemarkThoroughfare = placemarkThoroughfare
-
-        realm.add(addObject)
-
         do {
         do {
-            try realm.commitWrite()
-        } catch let error {
+            let realm = try Realm()
+            guard realm.objects(tableGPS.self).filter("latitude == %@ AND longitude == %@", latitude, longitude).first == nil else { return }
+            try realm.write {
+                let addObject = tableGPS()
+                addObject.latitude = latitude
+                addObject.location = location
+                addObject.longitude = longitude
+                addObject.placemarkAdministrativeArea = placemarkAdministrativeArea
+                addObject.placemarkCountry = placemarkCountry
+                addObject.placemarkLocality = placemarkLocality
+                addObject.placemarkPostalCode = placemarkPostalCode
+                addObject.placemarkThoroughfare = placemarkThoroughfare
+                realm.add(addObject)
+            }
+        } catch let error as NSError {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
     }
     }
 
 
     @objc func getLocationFromGeoLatitude(_ latitude: String, longitude: String) -> String? {
     @objc func getLocationFromGeoLatitude(_ latitude: String, longitude: String) -> String? {
 
 
-        let realm = try! Realm()
+        do {
+            let realm = try Realm()
+            let result = realm.objects(tableGPS.self).filter("latitude == %@ AND longitude == %@", latitude, longitude).first
+            return result?.location
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        let result = realm.objects(tableGPS.self).filter("latitude == %@ AND longitude == %@", latitude, longitude).first
-        return result?.location
+        return nil
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -544,13 +565,10 @@ class NCManageDatabase: NSObject {
 
 
     func addLocalFile(metadata: tableMetadata) {
     func addLocalFile(metadata: tableMetadata) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let addObject = getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) ?? tableLocalFile()
                 let addObject = getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) ?? tableLocalFile()
-
                 addObject.account = metadata.account
                 addObject.account = metadata.account
                 addObject.etag = metadata.etag
                 addObject.etag = metadata.etag
                 addObject.exifDate = NSDate()
                 addObject.exifDate = NSDate()
@@ -558,7 +576,6 @@ class NCManageDatabase: NSObject {
                 addObject.exifLongitude = "-1"
                 addObject.exifLongitude = "-1"
                 addObject.ocId = metadata.ocId
                 addObject.ocId = metadata.ocId
                 addObject.fileName = metadata.fileName
                 addObject.fileName = metadata.fileName
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -568,13 +585,10 @@ class NCManageDatabase: NSObject {
 
 
     func addLocalFile(account: String, etag: String, ocId: String, fileName: String) {
     func addLocalFile(account: String, etag: String, ocId: String, fileName: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let addObject = tableLocalFile()
                 let addObject = tableLocalFile()
-
                 addObject.account = account
                 addObject.account = account
                 addObject.etag = etag
                 addObject.etag = etag
                 addObject.exifDate = NSDate()
                 addObject.exifDate = NSDate()
@@ -582,7 +596,6 @@ class NCManageDatabase: NSObject {
                 addObject.exifLongitude = "-1"
                 addObject.exifLongitude = "-1"
                 addObject.ocId = ocId
                 addObject.ocId = ocId
                 addObject.fileName = fileName
                 addObject.fileName = fileName
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -592,9 +605,8 @@ class NCManageDatabase: NSObject {
 
 
     func deleteLocalFile(predicate: NSPredicate) {
     func deleteLocalFile(predicate: NSPredicate) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableLocalFile.self).filter(predicate)
                 let results = realm.objects(tableLocalFile.self).filter(predicate)
                 realm.delete(results)
                 realm.delete(results)
@@ -606,9 +618,8 @@ class NCManageDatabase: NSObject {
 
 
     func setLocalFile(ocId: String, fileName: String?, etag: String?) {
     func setLocalFile(ocId: String, fileName: String?, etag: String?) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first
                 if let fileName = fileName {
                 if let fileName = fileName {
@@ -625,9 +636,8 @@ class NCManageDatabase: NSObject {
 
 
     @objc func setLocalFile(ocId: String, exifDate: NSDate?, exifLatitude: String, exifLongitude: String, exifLensModel: String?) {
     @objc func setLocalFile(ocId: String, exifDate: NSDate?, exifLatitude: String, exifLongitude: String, exifLensModel: String?) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 if let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first {
                 if let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first {
                     result.exifDate = exifDate
                     result.exifDate = exifDate
@@ -645,36 +655,47 @@ class NCManageDatabase: NSObject {
 
 
     func getTableLocalFile(account: String) -> [tableLocalFile] {
     func getTableLocalFile(account: String) -> [tableLocalFile] {
 
 
-        let realm = try! Realm()
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableLocalFile.self).filter("account == %@", account)
+            return Array(results.map { tableLocalFile.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        let results = realm.objects(tableLocalFile.self).filter("account == %@", account)
-        return Array(results.map { tableLocalFile.init(value: $0) })
+        return []
     }
     }
 
 
     func getTableLocalFile(predicate: NSPredicate) -> tableLocalFile? {
     func getTableLocalFile(predicate: NSPredicate) -> tableLocalFile? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableLocalFile.self).filter(predicate).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableLocalFile.self).filter(predicate).first else { return nil }
+            return tableLocalFile.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableLocalFile.init(value: result)
+        return nil
     }
     }
 
 
     func getTableLocalFiles(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableLocalFile] {
     func getTableLocalFiles(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableLocalFile] {
 
 
-        let realm = try! Realm()
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+            return Array(results.map { tableLocalFile.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        let results = realm.objects(tableLocalFile.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
-        return Array(results.map { tableLocalFile.init(value: $0) })
+        return []
     }
     }
 
 
     func setLocalFile(ocId: String, offline: Bool) {
     func setLocalFile(ocId: String, offline: Bool) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first
                 let result = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId).first
                 result?.offline = offline
                 result?.offline = offline
@@ -690,16 +711,12 @@ class NCManageDatabase: NSObject {
     @discardableResult
     @discardableResult
     func addPhotoLibrary(_ assets: [PHAsset], account: String) -> Bool {
     func addPhotoLibrary(_ assets: [PHAsset], account: String) -> Bool {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 for asset in assets {
                 for asset in assets {
-
                     var creationDateString = ""
                     var creationDateString = ""
                     let addObject = tablePhotoLibrary()
                     let addObject = tablePhotoLibrary()
-
                     addObject.account = account
                     addObject.account = account
                     addObject.assetLocalIdentifier = asset.localIdentifier
                     addObject.assetLocalIdentifier = asset.localIdentifier
                     addObject.mediaType = asset.mediaType.rawValue
                     addObject.mediaType = asset.mediaType.rawValue
@@ -711,7 +728,6 @@ class NCManageDatabase: NSObject {
                         addObject.modificationDate = modificationDate as NSDate
                         addObject.modificationDate = modificationDate as NSDate
                     }
                     }
                     addObject.idAsset = account + asset.localIdentifier + creationDateString
                     addObject.idAsset = account + asset.localIdentifier + creationDateString
-
                     realm.add(addObject, update: .all)
                     realm.add(addObject, update: .all)
                 }
                 }
             }
             }
@@ -725,46 +741,40 @@ class NCManageDatabase: NSObject {
 
 
     func getPhotoLibraryIdAsset(image: Bool, video: Bool, account: String) -> [String]? {
     func getPhotoLibraryIdAsset(image: Bool, video: Bool, account: String) -> [String]? {
 
 
-        let realm = try! Realm()
         var predicate = NSPredicate()
         var predicate = NSPredicate()
 
 
         if image && video {
         if image && video {
-
             predicate = NSPredicate(format: "account == %@ AND (mediaType == %d OR mediaType == %d)", account, PHAssetMediaType.image.rawValue, PHAssetMediaType.video.rawValue)
             predicate = NSPredicate(format: "account == %@ AND (mediaType == %d OR mediaType == %d)", account, PHAssetMediaType.image.rawValue, PHAssetMediaType.video.rawValue)
-
         } else if image {
         } else if image {
-
             predicate = NSPredicate(format: "account == %@ AND mediaType == %d", account, PHAssetMediaType.image.rawValue)
             predicate = NSPredicate(format: "account == %@ AND mediaType == %d", account, PHAssetMediaType.image.rawValue)
-
         } else if video {
         } else if video {
-
             predicate = NSPredicate(format: "account == %@ AND mediaType == %d", account, PHAssetMediaType.video.rawValue)
             predicate = NSPredicate(format: "account == %@ AND mediaType == %d", account, PHAssetMediaType.video.rawValue)
         }
         }
 
 
-        let results = realm.objects(tablePhotoLibrary.self).filter(predicate)
-
-        let idsAsset = results.map { $0.idAsset }
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tablePhotoLibrary.self).filter(predicate)
+            let idsAsset = results.map { $0.idAsset }
+            return Array(idsAsset)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(idsAsset)
+        return nil
     }
     }
-    
+
     // MARK: -
     // MARK: -
     // MARK: Table Tag
     // MARK: Table Tag
 
 
     func addTag(_ ocId: String, tagIOS: Data?, account: String) {
     func addTag(_ ocId: String, tagIOS: Data?, account: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
-                // Add new
                 let addObject = tableTag()
                 let addObject = tableTag()
-
                 addObject.account = account
                 addObject.account = account
                 addObject.ocId = ocId
                 addObject.ocId = ocId
                 addObject.tagIOS = tagIOS
                 addObject.tagIOS = tagIOS
-
                 realm.add(addObject, update: .all)
                 realm.add(addObject, update: .all)
             }
             }
         } catch let error {
         } catch let error {
@@ -774,15 +784,12 @@ class NCManageDatabase: NSObject {
 
 
     func deleteTag(_ ocId: String) {
     func deleteTag(_ ocId: String) {
 
 
-        let realm = try! Realm()
-
-        realm.beginWrite()
-
-        let result = realm.objects(tableTag.self).filter("ocId == %@", ocId)
-        realm.delete(result)
-
         do {
         do {
-            try realm.commitWrite()
+            let realm = try Realm()
+            try realm.write {
+                let results = realm.objects(tableTag.self).filter("ocId == %@", ocId)
+                realm.delete(results)
+            }
         } catch let error {
         } catch let error {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
@@ -790,22 +797,28 @@ class NCManageDatabase: NSObject {
 
 
     func getTags(predicate: NSPredicate) -> [tableTag] {
     func getTags(predicate: NSPredicate) -> [tableTag] {
 
 
-        let realm = try! Realm()
-
-        let results = realm.objects(tableTag.self).filter(predicate)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableTag.self).filter(predicate)
+            return Array(results.map { tableTag.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableTag.init(value: $0) })
+        return []
     }
     }
 
 
     func getTag(predicate: NSPredicate) -> tableTag? {
     func getTag(predicate: NSPredicate) -> tableTag? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableTag.self).filter(predicate).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableTag.self).filter(predicate).first else { return nil }
+            return tableTag.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableTag.init(value: result)
+        return nil
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -813,12 +826,15 @@ class NCManageDatabase: NSObject {
 
 
     func tipExists(_ tipName: String) -> Bool {
     func tipExists(_ tipName: String) -> Bool {
 
 
-        let realm = try! Realm()
-
-        guard (realm.objects(tableTip.self).where {
-            $0.tipName == tipName
-        }.first) == nil else {
-            return true
+        do {
+            let realm = try Realm()
+            guard (realm.objects(tableTip.self).where {
+                $0.tipName == tipName
+            }.first) == nil else {
+                return true
+            }
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
         return false
         return false
@@ -826,9 +842,8 @@ class NCManageDatabase: NSObject {
 
 
     func addTip(_ tipName: String) {
     func addTip(_ tipName: String) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 let addObject = tableTip()
                 let addObject = tableTip()
                 addObject.tipName = tipName
                 addObject.tipName = tipName
@@ -844,13 +859,11 @@ class NCManageDatabase: NSObject {
 
 
     func addTrash(account: String, items: [NKTrash]) {
     func addTrash(account: String, items: [NKTrash]) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
                 for trash in items {
                 for trash in items {
                     let object = tableTrash()
                     let object = tableTrash()
-
                     object.account = account
                     object.account = account
                     object.contentType = trash.contentType
                     object.contentType = trash.contentType
                     object.date = trash.date
                     object.date = trash.date
@@ -865,7 +878,6 @@ class NCManageDatabase: NSObject {
                     object.trashbinFileName = trash.trashbinFileName
                     object.trashbinFileName = trash.trashbinFileName
                     object.trashbinOriginalLocation = trash.trashbinOriginalLocation
                     object.trashbinOriginalLocation = trash.trashbinOriginalLocation
                     object.classFile = trash.classFile
                     object.classFile = trash.classFile
-
                     realm.add(object, update: .all)
                     realm.add(object, update: .all)
                 }
                 }
             }
             }
@@ -876,18 +888,16 @@ class NCManageDatabase: NSObject {
 
 
     func deleteTrash(filePath: String?, account: String) {
     func deleteTrash(filePath: String?, account: String) {
 
 
-        let realm = try! Realm()
         var predicate = NSPredicate()
         var predicate = NSPredicate()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 if filePath == nil {
                 if filePath == nil {
                     predicate = NSPredicate(format: "account == %@", account)
                     predicate = NSPredicate(format: "account == %@", account)
                 } else {
                 } else {
                     predicate = NSPredicate(format: "account == %@ AND filePath == %@", account, filePath!)
                     predicate = NSPredicate(format: "account == %@ AND filePath == %@", account, filePath!)
                 }
                 }
-
                 let result = realm.objects(tableTrash.self).filter(predicate)
                 let result = realm.objects(tableTrash.self).filter(predicate)
                 realm.delete(result)
                 realm.delete(result)
             }
             }
@@ -898,18 +908,16 @@ class NCManageDatabase: NSObject {
 
 
     func deleteTrash(fileId: String?, account: String) {
     func deleteTrash(fileId: String?, account: String) {
 
 
-        let realm = try! Realm()
         var predicate = NSPredicate()
         var predicate = NSPredicate()
 
 
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 if fileId == nil {
                 if fileId == nil {
                     predicate = NSPredicate(format: "account == %@", account)
                     predicate = NSPredicate(format: "account == %@", account)
                 } else {
                 } else {
                     predicate = NSPredicate(format: "account == %@ AND fileId == %@", account, fileId!)
                     predicate = NSPredicate(format: "account == %@ AND fileId == %@", account, fileId!)
                 }
                 }
-
                 let result = realm.objects(tableTrash.self).filter(predicate)
                 let result = realm.objects(tableTrash.self).filter(predicate)
                 realm.delete(result)
                 realm.delete(result)
             }
             }
@@ -920,24 +928,31 @@ class NCManageDatabase: NSObject {
 
 
     func getTrash(filePath: String, sort: String?, ascending: Bool?, account: String) -> [tableTrash]? {
     func getTrash(filePath: String, sort: String?, ascending: Bool?, account: String) -> [tableTrash]? {
 
 
-        let realm = try! Realm()
         let sort = sort ?? "date"
         let sort = sort ?? "date"
         let ascending = ascending ?? false
         let ascending = ascending ?? false
 
 
-        let results = realm.objects(tableTrash.self).filter("account == %@ AND filePath == %@", account, filePath).sorted(byKeyPath: sort, ascending: ascending)
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableTrash.self).filter("account == %@ AND filePath == %@", account, filePath).sorted(byKeyPath: sort, ascending: ascending)
+            return Array(results.map { tableTrash.init(value: $0) })
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
 
 
-        return Array(results.map { tableTrash.init(value: $0) })
+        return nil
     }
     }
 
 
     func getTrashItem(fileId: String, account: String) -> tableTrash? {
     func getTrashItem(fileId: String, account: String) -> tableTrash? {
 
 
-        let realm = try! Realm()
-
-        guard let result = realm.objects(tableTrash.self).filter("account == %@ AND fileId == %@", account, fileId).first else {
-            return nil
+        do {
+            let realm = try Realm()
+            guard let result = realm.objects(tableTrash.self).filter("account == %@ AND fileId == %@", account, fileId).first else { return nil }
+            return tableTrash.init(value: result)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return tableTrash.init(value: result)
+        return nil
     }
     }
 
 
     // MARK: -
     // MARK: -
@@ -945,18 +960,13 @@ class NCManageDatabase: NSObject {
 
 
     func addUserStatus(_ userStatuses: [NKUserStatus], account: String, predefined: Bool) {
     func addUserStatus(_ userStatuses: [NKUserStatus], account: String, predefined: Bool) {
 
 
-        let realm = try! Realm()
-
         do {
         do {
+            let realm = try Realm()
             try realm.write {
             try realm.write {
-
                 let results = realm.objects(tableUserStatus.self).filter("account == %@ AND predefined == %@", account, predefined)
                 let results = realm.objects(tableUserStatus.self).filter("account == %@ AND predefined == %@", account, predefined)
                 realm.delete(results)
                 realm.delete(results)
-
                 for userStatus in userStatuses {
                 for userStatus in userStatuses {
-
                     let object = tableUserStatus()
                     let object = tableUserStatus()
-
                     object.account = account
                     object.account = account
                     object.clearAt = userStatus.clearAt
                     object.clearAt = userStatus.clearAt
                     object.clearAtTime = userStatus.clearAtTime
                     object.clearAtTime = userStatus.clearAtTime
@@ -967,7 +977,6 @@ class NCManageDatabase: NSObject {
                     object.predefined = userStatus.predefined
                     object.predefined = userStatus.predefined
                     object.status = userStatus.status
                     object.status = userStatus.status
                     object.userId = userStatus.userId
                     object.userId = userStatus.userId
-
                     realm.add(object)
                     realm.add(object)
                 }
                 }
             }
             }

+ 21 - 23
iOSClient/EmptyView/NCEmptyDataSet.swift

@@ -49,36 +49,30 @@ class NCEmptyDataSet: NSObject {
     init(view: UIView, offset: CGFloat = 0, delegate: NCEmptyDataSetDelegate?) {
     init(view: UIView, offset: CGFloat = 0, delegate: NCEmptyDataSetDelegate?) {
         super.init()
         super.init()
 
 
-        if let emptyView = UINib(nibName: "NCEmptyView", bundle: nil).instantiate(withOwner: self, options: nil).first as? NCEmptyView {
+        guard let emptyView = NCEmptyView.fromNib().instantiate(withOwner: self, options: nil).first as? NCEmptyView else { return }
 
 
-            self.delegate = delegate
-            self.emptyView = emptyView
+        self.delegate = delegate
+        self.emptyView = emptyView
 
 
-            emptyView.isHidden = true
-            emptyView.translatesAutoresizingMaskIntoConstraints = false
+        emptyView.isHidden = true
+        emptyView.translatesAutoresizingMaskIntoConstraints = false
 
 
-//            emptyView.backgroundColor = .red
-//            emptyView.isHidden = false
+        view.addSubview(emptyView)
 
 
-            emptyView.emptyTitle.sizeToFit()
-            emptyView.emptyDescription.sizeToFit()
+        emptyView.widthAnchor.constraint(equalToConstant: 350).isActive = true
+        emptyView.heightAnchor.constraint(equalToConstant: 250).isActive = true
 
 
-            view.addSubview(emptyView)
-
-            emptyView.widthAnchor.constraint(equalToConstant: 350).isActive = true
-            emptyView.heightAnchor.constraint(equalToConstant: 250).isActive = true
+        if let view = view.superview {
+            centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
+            centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
+        } else {
+            centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
+            centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
+        }
 
 
-            if let view = view.superview {
-                centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
-                centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
-            } else {
-                centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
-                centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
-            }
+        centerXAnchor?.isActive = true
+        centerYAnchor?.isActive = true
 
 
-            centerXAnchor?.isActive = true
-            centerYAnchor?.isActive = true
-        }
     }
     }
 
 
     func setOffset(_ offset: CGFloat) {
     func setOffset(_ offset: CGFloat) {
@@ -124,6 +118,10 @@ public class NCEmptyView: UIView {
     @IBOutlet weak var emptyTitle: UILabel!
     @IBOutlet weak var emptyTitle: UILabel!
     @IBOutlet weak var emptyDescription: UILabel!
     @IBOutlet weak var emptyDescription: UILabel!
 
 
+    static func fromNib() -> UINib {
+        return UINib(nibName: "NCEmptyView", bundle: nil)
+    }
+
     public override func awakeFromNib() {
     public override func awakeFromNib() {
         super.awakeFromNib()
         super.awakeFromNib()
 
 

+ 21 - 17
iOSClient/EmptyView/NCEmptyView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina3_5" orientation="portrait" appearance="light"/>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_72" orientation="landscape" appearance="light"/>
     <dependencies>
     <dependencies>
         <deployment identifier="iOS"/>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -12,24 +12,20 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCEmptyView" customModule="Nextcloud" customModuleProvider="target">
         <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCEmptyView" customModule="Nextcloud" customModuleProvider="target">
-            <rect key="frame" x="0.0" y="0.0" width="350" height="250"/>
+            <rect key="frame" x="0.0" y="0.0" width="422" height="475"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <subviews>
             <subviews>
                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="W3d-Us-kU4">
                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="W3d-Us-kU4">
-                    <rect key="frame" x="100" y="0.0" width="150" height="150"/>
+                    <rect key="frame" x="136" y="20" width="150" height="75"/>
                     <constraints>
                     <constraints>
-                        <constraint firstAttribute="height" constant="150" id="A8B-y7-Fre"/>
+                        <constraint firstAttribute="height" constant="150" id="A8B-y7-Fre">
+                            <variation key="heightClass=compact" constant="75"/>
+                        </constraint>
                         <constraint firstAttribute="width" constant="150" id="g0C-P6-l3d"/>
                         <constraint firstAttribute="width" constant="150" id="g0C-P6-l3d"/>
                     </constraints>
                     </constraints>
                 </imageView>
                 </imageView>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="crs-DO-owR">
-                    <rect key="frame" x="20" y="180" width="310" height="24"/>
-                    <fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
-                    <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D4p-sI-mNB">
                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D4p-sI-mNB">
-                    <rect key="frame" x="20" y="224" width="310" height="17"/>
+                    <rect key="frame" x="79" y="135" width="264" height="17"/>
                     <constraints>
                     <constraints>
                         <constraint firstAttribute="height" relation="lessThanOrEqual" constant="50" id="u7B-jW-bWI"/>
                         <constraint firstAttribute="height" relation="lessThanOrEqual" constant="50" id="u7B-jW-bWI"/>
                     </constraints>
                     </constraints>
@@ -37,18 +33,26 @@
                     <color key="textColor" systemColor="systemGrayColor"/>
                     <color key="textColor" systemColor="systemGrayColor"/>
                     <nil key="highlightedColor"/>
                     <nil key="highlightedColor"/>
                 </label>
                 </label>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="crs-DO-owR">
+                    <rect key="frame" x="79" y="103" width="264" height="24"/>
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
+                    <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <nil key="highlightedColor"/>
+                </label>
             </subviews>
             </subviews>
             <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
             <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
             <constraints>
                 <constraint firstItem="crs-DO-owR" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="CMU-Tp-bUM"/>
                 <constraint firstItem="crs-DO-owR" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="CMU-Tp-bUM"/>
-                <constraint firstItem="W3d-Us-kU4" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="Fyb-so-iAw"/>
                 <constraint firstItem="D4p-sI-mNB" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="egV-G4-wax"/>
                 <constraint firstItem="D4p-sI-mNB" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="egV-G4-wax"/>
                 <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="crs-DO-owR" secondAttribute="trailing" constant="20" id="hHl-iN-Gev"/>
                 <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="crs-DO-owR" secondAttribute="trailing" constant="20" id="hHl-iN-Gev"/>
-                <constraint firstItem="crs-DO-owR" firstAttribute="top" secondItem="W3d-Us-kU4" secondAttribute="bottom" constant="30" id="hLN-L6-0gH"/>
+                <constraint firstItem="crs-DO-owR" firstAttribute="top" secondItem="W3d-Us-kU4" secondAttribute="bottom" constant="8" id="hLN-L6-0gH"/>
                 <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="D4p-sI-mNB" secondAttribute="trailing" constant="20" id="imv-AK-mqu"/>
                 <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="D4p-sI-mNB" secondAttribute="trailing" constant="20" id="imv-AK-mqu"/>
                 <constraint firstItem="W3d-Us-kU4" firstAttribute="centerX" secondItem="vUN-kp-3ea" secondAttribute="centerX" id="kma-1Q-c3Q"/>
                 <constraint firstItem="W3d-Us-kU4" firstAttribute="centerX" secondItem="vUN-kp-3ea" secondAttribute="centerX" id="kma-1Q-c3Q"/>
-                <constraint firstItem="D4p-sI-mNB" firstAttribute="top" secondItem="crs-DO-owR" secondAttribute="bottom" constant="20" id="zbi-5P-raN"/>
+                <constraint firstItem="W3d-Us-kU4" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="uOy-F7-KNu">
+                    <variation key="heightClass=compact" constant="20"/>
+                </constraint>
+                <constraint firstItem="D4p-sI-mNB" firstAttribute="top" secondItem="crs-DO-owR" secondAttribute="bottom" constant="8" id="zbi-5P-raN"/>
             </constraints>
             </constraints>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
             <connections>
             <connections>
@@ -56,7 +60,7 @@
                 <outlet property="emptyImage" destination="W3d-Us-kU4" id="xtd-nV-OUc"/>
                 <outlet property="emptyImage" destination="W3d-Us-kU4" id="xtd-nV-OUc"/>
                 <outlet property="emptyTitle" destination="crs-DO-owR" id="IkU-6d-P64"/>
                 <outlet property="emptyTitle" destination="crs-DO-owR" id="IkU-6d-P64"/>
             </connections>
             </connections>
-            <point key="canvasLocation" x="-146.25" y="32.5"/>
+            <point key="canvasLocation" x="-86.956521739130437" y="111.49553571428571"/>
         </view>
         </view>
     </objects>
     </objects>
     <resources>
     <resources>

+ 6 - 2
iOSClient/Extensions/UIImage+Extension.swift

@@ -116,10 +116,14 @@ extension UIImage {
     }
     }
 
 
     @objc func image(color: UIColor, size: CGFloat) -> UIImage {
     @objc func image(color: UIColor, size: CGFloat) -> UIImage {
+        return image(color: color, width: size, height: size)
+    }
+
+    @objc func image(color: UIColor, width: CGFloat, height: CGFloat) -> UIImage {
 
 
-        let size = CGSize(width: size, height: size)
+        let size = CGSize(width: width, height: height)
 
 
-        UIGraphicsBeginImageContextWithOptions(size, false, self.scale)
+        UIGraphicsBeginImageContextWithOptions(.init(width: width, height: height), false, self.scale)
         color.setFill()
         color.setFill()
 
 
         let context = UIGraphicsGetCurrentContext()
         let context = UIGraphicsGetCurrentContext()

+ 0 - 1
iOSClient/Favorites/NCFavorite.swift

@@ -34,7 +34,6 @@ class NCFavorite: NCCollectionViewCommon {
         titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
         titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
         layoutKey = NCGlobal.shared.layoutViewFavorite
         layoutKey = NCGlobal.shared.layoutViewFavorite
         enableSearchBar = false
         enableSearchBar = false
-        headerMenuButtonsCommand = false
         headerMenuButtonsView = true
         headerMenuButtonsView = true
         headerRichWorkspaceDisable = true
         headerRichWorkspaceDisable = true
         emptyImage = UIImage(named: "star.fill")?.image(color: NCBrandColor.shared.yellowFavorite, size: UIScreen.main.bounds.width)
         emptyImage = UIImage(named: "star.fill")?.image(color: NCBrandColor.shared.yellowFavorite, size: UIScreen.main.bounds.width)

+ 0 - 1
iOSClient/Files/NCFiles.swift

@@ -38,7 +38,6 @@ class NCFiles: NCCollectionViewCommon {
         titleCurrentFolder = NCBrandOptions.shared.brand
         titleCurrentFolder = NCBrandOptions.shared.brand
         layoutKey = NCGlobal.shared.layoutViewFiles
         layoutKey = NCGlobal.shared.layoutViewFiles
         enableSearchBar = true
         enableSearchBar = true
-        headerMenuButtonsCommand = true
         headerMenuButtonsView = true
         headerMenuButtonsView = true
         headerRichWorkspaceDisable = false
         headerRichWorkspaceDisable = false
         emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
         emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)

+ 0 - 1
iOSClient/Groupfolders/NCGroupfolders.swift

@@ -34,7 +34,6 @@ class NCGroupfolders: NCCollectionViewCommon {
         titleCurrentFolder = NSLocalizedString("_group_folders_", comment: "")
         titleCurrentFolder = NSLocalizedString("_group_folders_", comment: "")
         layoutKey = NCGlobal.shared.layoutViewGroupfolders
         layoutKey = NCGlobal.shared.layoutViewGroupfolders
         enableSearchBar = false
         enableSearchBar = false
-        headerMenuButtonsCommand = false
         headerMenuButtonsView = true
         headerMenuButtonsView = true
         headerRichWorkspaceDisable = true
         headerRichWorkspaceDisable = true
         emptyImage = UIImage(named: "folder_group")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
         emptyImage = UIImage(named: "folder_group")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)

+ 0 - 26
iOSClient/Images.xcassets/switchGrid.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "switchGrid.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "filename" : "switchGrid@2x.png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "switchGrid@3x.png",
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}

二進制
iOSClient/Images.xcassets/switchGrid.imageset/switchGrid.png


二進制
iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@2x.png


二進制
iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@3x.png


+ 0 - 26
iOSClient/Images.xcassets/switchList.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "switchList.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "filename" : "switchList@2x.png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "switchList@3x.png",
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}

二進制
iOSClient/Images.xcassets/switchList.imageset/switchList.png


二進制
iOSClient/Images.xcassets/switchList.imageset/switchList@2x.png


二進制
iOSClient/Images.xcassets/switchList.imageset/switchList@3x.png


+ 26 - 78
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -72,7 +72,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     internal var titleCurrentFolder = ""
     internal var titleCurrentFolder = ""
     internal var titlePreviusFolder: String?
     internal var titlePreviusFolder: String?
     internal var enableSearchBar: Bool = false
     internal var enableSearchBar: Bool = false
-    internal var headerMenuButtonsCommand: Bool = true
     internal var headerMenuButtonsView: Bool = true
     internal var headerMenuButtonsView: Bool = true
     internal var headerRichWorkspaceDisable:Bool = false
     internal var headerRichWorkspaceDisable:Bool = false
     internal var emptyImage: UIImage?
     internal var emptyImage: UIImage?
@@ -434,45 +433,25 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     @objc func downloadStartFile(_ notification: NSNotification) {
     @objc func downloadStartFile(_ notification: NSNotification) {
 
 
         guard let userInfo = notification.userInfo as NSDictionary?,
         guard let userInfo = notification.userInfo as NSDictionary?,
-              let ocId = userInfo["ocId"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               serverUrl == self.serverUrl,
               serverUrl == self.serverUrl,
               let account = userInfo["account"] as? String,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
               account == appDelegate.account
         else { return }
         else { return }
 
 
-        let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId)
-        if let indexPath = indexPath {
-            if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
-                collectionView?.reloadItems(at: [indexPath])
-            } else {
-                self.collectionView?.reloadData()
-            }
-        } else {
-            reloadDataSource()
-        }
+        reloadDataSource()
     }
     }
 
 
     @objc func downloadedFile(_ notification: NSNotification) {
     @objc func downloadedFile(_ notification: NSNotification) {
 
 
         guard let userInfo = notification.userInfo as NSDictionary?,
         guard let userInfo = notification.userInfo as NSDictionary?,
-              let ocId = userInfo["ocId"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               serverUrl == self.serverUrl,
               serverUrl == self.serverUrl,
               let account = userInfo["account"] as? String,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
               account == appDelegate.account
         else { return }
         else { return }
 
 
-        let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId)
-        if let indexPath = indexPath {
-            if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
-                collectionView?.reloadItems(at: [indexPath])
-            } else {
-                self.collectionView?.reloadData()
-            }
-        } else {
-            reloadDataSource()
-        }
+        reloadDataSource()
     }
     }
 
 
     @objc func downloadCancelFile(_ notification: NSNotification) {
     @objc func downloadCancelFile(_ notification: NSNotification) {
@@ -515,34 +494,13 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     @objc func uploadedFile(_ notification: NSNotification) {
     @objc func uploadedFile(_ notification: NSNotification) {
 
 
         guard let userInfo = notification.userInfo as NSDictionary?,
         guard let userInfo = notification.userInfo as NSDictionary?,
-              let ocId = userInfo["ocId"] as? String,
-              let ocIdTemp = userInfo["ocIdTemp"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               let serverUrl = userInfo["serverUrl"] as? String,
               serverUrl == self.serverUrl,
               serverUrl == self.serverUrl,
               let account = userInfo["account"] as? String,
               let account = userInfo["account"] as? String,
               account == appDelegate.account
               account == appDelegate.account
         else { return }
         else { return }
 
 
-        // do not exists metadata ?
-        guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else {
-            reloadDataSource()
-            return
-        }
-        
-        let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: metadata.ocId, ocIdTemp: ocIdTemp)
-        if let indexPath = indexPath {
-            if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
-                collectionView?.performBatchUpdates({
-                    collectionView?.reloadItems(at: [indexPath])
-                }, completion: { _ in
-                    self.collectionView?.reloadData()
-                })
-            } else {
-                self.collectionView?.reloadData()
-            }
-        } else {
-            reloadDataSource()
-        }
+        reloadDataSource()
     }
     }
 
 
     @objc func uploadCancelFile(_ notification: NSNotification) {
     @objc func uploadCancelFile(_ notification: NSNotification) {
@@ -906,14 +864,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
     func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
 
 
         return UIContextMenuConfiguration(identifier: nil, previewProvider: {
         return UIContextMenuConfiguration(identifier: nil, previewProvider: {
-
             return nil
             return nil
-
         }, actionProvider: { _ in
         }, actionProvider: { _ in
-
-            // let share = UIAction(title: "Share Pupper", image: UIImage(systemName: "square.and.arrow.up")) { action in
-            // }
-            // return UIMenu(title: "Main Menu", children: [share])
             return nil
             return nil
         })
         })
     }
     }
@@ -1036,13 +988,12 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
 
 
     func unifiedSearchMore(metadataForSection: NCMetadataForSection?) {
     func unifiedSearchMore(metadataForSection: NCMetadataForSection?) {
 
 
-        guard let metadataForSection = metadataForSection, let searchResult = metadataForSection.lastSearchResult, let cursor = searchResult.cursor, let term = literalSearch else { return }
+        guard let metadataForSection = metadataForSection, let lastSearchResult = metadataForSection.lastSearchResult, let cursor = lastSearchResult.cursor, let term = literalSearch else { return }
 
 
         metadataForSection.unifiedSearchInProgress = true
         metadataForSection.unifiedSearchInProgress = true
         self.collectionView?.reloadData()
         self.collectionView?.reloadData()
 
 
-        NCNetworking.shared.unifiedSearchFilesProvider(userBaseUrl: appDelegate, id: searchResult.id, term: term, limit: 5, cursor: cursor) { account, searchResult, metadatas, error in
-
+        NCNetworking.shared.unifiedSearchFilesProvider(userBaseUrl: appDelegate, id: lastSearchResult.id, term: term, limit: 5, cursor: cursor) { account, searchResult, metadatas, error in
             if error != .success {
             if error != .success {
                 NCContentPresenter.shared.showError(error: error)
                 NCContentPresenter.shared.showError(error: error)
             }
             }
@@ -1304,10 +1255,10 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
             
             
             let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
             let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
 
 
-            if metadata.isImage || metadata.isMovie {
+            if !metadata.isDirectoryE2EE && (metadata.isImage || metadata.isAudioOrVideo) {
                 var metadatas: [tableMetadata] = []
                 var metadatas: [tableMetadata] = []
                 for metadata in metadataSourceForAllSections {
                 for metadata in metadataSourceForAllSections {
-                    if metadata.isImage || metadata.isMovie {
+                    if metadata.isImage || metadata.isAudioOrVideo {
                         metadatas.append(metadata)
                         metadatas.append(metadata)
                     }
                     }
                 }
                 }
@@ -1409,14 +1360,6 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
                         NCOperationQueue.shared.downloadAvatar(user: ownerId, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView)
                         NCOperationQueue.shared.downloadAvatar(user: ownerId, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView)
                     }
                     }
                 }
                 }
-
-//                if metadata.iconName.contains("contacts"), let subline = metadata.subline, !subline.isEmpty, let cell = cell as? NCCellProtocol {
-//                    let components = subline.components(separatedBy: "@")
-//                    if let user = components.first {
-//                        let fileName = metadata.userBaseUrl + "-" + user + ".png"
-//                        NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView)
-//                    }
-//                }
             }
             }
         }
         }
 
 
@@ -1494,7 +1437,6 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
                 cell.fileInfoLabel?.text = NSLocalizedString("_in_", comment: "") + " " + NCUtilityFileSystem.shared.getPath(path: metadata.path, user: metadata.user)
                 cell.fileInfoLabel?.text = NSLocalizedString("_in_", comment: "") + " " + NCUtilityFileSystem.shared.getPath(path: metadata.path, user: metadata.user)
             } else {
             } else {
                 cell.fileInfoLabel?.text = metadata.subline
                 cell.fileInfoLabel?.text = metadata.subline
-                cell.titleInfoTrailingFull()
             }
             }
         } else {
         } else {
             cell.fileTitleLabel?.text = metadata.fileNameView
             cell.fileTitleLabel?.text = metadata.fileNameView
@@ -1668,6 +1610,13 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
         // Add TAGS
         // Add TAGS
         cell.setTags(tags: Array(metadata.tags))
         cell.setTags(tags: Array(metadata.tags))
 
 
+        // Hide buttons
+        if metadata.name != NCGlobal.shared.appName {
+            cell.titleInfoTrailingFull()
+            cell.hideButtonShare(true)
+            cell.hideButtonMore(true)
+        }
+
         // ** IMPORT MUST BE AT THE END **
         // ** IMPORT MUST BE AT THE END **
         //
         //
 
 
@@ -1698,19 +1647,13 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
                 }
                 }
 
 
                 header.delegate = self
                 header.delegate = self
-                if headerMenuButtonsCommand && !isSearchingMode {
-                    let imageButton2 = isDirectoryE2EE ? UIImage(named: "folderEncrypted") : UIImage(named: "folder")
-                    let titleButton2 = isDirectoryE2EE ? NSLocalizedString("_create_folder_e2ee_", comment: "") : NSLocalizedString("_create_folder_", comment: "")
-                    header.setButtonsCommand(heigt: NCGlobal.shared.heightButtonsCommand, imageButton1: UIImage(named: "addImage"), titleButton1: NSLocalizedString("_upload_", comment: ""), imageButton2: imageButton2, titleButton2: titleButton2, imageButton3: UIImage(systemName: "doc.text.viewfinder"), titleButton3: NSLocalizedString("_scan_", comment: ""))
-                } else {
-                    header.setButtonsCommand(heigt: 0)
-                }
+
                 if headerMenuButtonsView {
                 if headerMenuButtonsView {
                     header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
                     header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
-                    header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
+                    header.setButtonsView(height: NCGlobal.shared.heightButtonsView)
                     header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
                     header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
                 } else {
                 } else {
-                    header.setButtonsView(heigt: 0)
+                    header.setButtonsView(height: 0)
                 }
                 }
 
 
                 header.setRichWorkspaceHeight(heightHeaderRichWorkspace)
                 header.setRichWorkspaceHeight(heightHeaderRichWorkspace)
@@ -1755,13 +1698,21 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
             footer.buttonIsHidden(true)
             footer.buttonIsHidden(true)
             footer.hideActivityIndicatorSection()
             footer.hideActivityIndicatorSection()
 
 
+
             if isSearchingMode {
             if isSearchingMode {
                 if sections > 1 && section != sections - 1 {
                 if sections > 1 && section != sections - 1 {
                     footer.separatorIsHidden(false)
                     footer.separatorIsHidden(false)
                 }
                 }
-                if isSearchingMode && isPaginated && metadatasCount > 0 {
+
+                // If the number of entries(metadatas) is lower than the cursor, then there are no more entries.
+                // The blind spot in this is when the number of entries is the same as the cursor. If so, we don't have a way of knowing if there are no more entries.
+                // This is as good as it gets for determining last page without server-side flag.
+                let isLastPage = (metadatasCount < metadataForSection?.lastSearchResult?.cursor ?? 0) || metadataForSection?.lastSearchResult?.entries.isEmpty == true
+
+                if isSearchingMode && isPaginated && metadatasCount > 0 && !isLastPage {
                     footer.buttonIsHidden(false)
                     footer.buttonIsHidden(false)
                 }
                 }
+
                 if unifiedSearchInProgress {
                 if unifiedSearchInProgress {
                     footer.showActivityIndicatorSection()
                     footer.showActivityIndicatorSection()
                 }
                 }
@@ -1785,9 +1736,6 @@ extension NCCollectionViewCommon: UICollectionViewDelegateFlowLayout {
 
 
         var size: CGFloat = 0
         var size: CGFloat = 0
 
 
-        if headerMenuButtonsCommand && !isSearchingMode {
-            size += NCGlobal.shared.heightButtonsCommand
-        }
         if headerMenuButtonsView {
         if headerMenuButtonsView {
             size += NCGlobal.shared.heightButtonsView
             size += NCGlobal.shared.heightButtonsView
         }
         }

+ 2 - 2
iOSClient/Main/Create cloud/NCUploadAssets.swift

@@ -243,9 +243,9 @@ struct UploadAssetsView: View {
                 let monthString = dateFormatter.string(from: creationDate)
                 let monthString = dateFormatter.string(from: creationDate)
                 dateFormatter.dateFormat = "dd"
                 dateFormatter.dateFormat = "dd"
                 let dayString = dateFormatter.string(from: creationDate)
                 let dayString = dateFormatter.string(from: creationDate)
-                if autoUploadSubfolderGranularity == 0 {
+                if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityYearly {
                     serverUrl = autoUploadPath + "/" + yearString
                     serverUrl = autoUploadPath + "/" + yearString
-                } else if autoUploadSubfolderGranularity == 2 {
+                } else if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily {
                     serverUrl = autoUploadPath + "/" + yearString + "/" + monthString + "/" + dayString
                     serverUrl = autoUploadPath + "/" + yearString + "/" + monthString + "/" + dayString
                 } else {  // Month Granularity is default
                 } else {  // Month Granularity is default
                     serverUrl = autoUploadPath + "/" + yearString + "/" + monthString
                     serverUrl = autoUploadPath + "/" + yearString + "/" + monthString

+ 1 - 1
iOSClient/Main/NCActionCenter.swift

@@ -217,7 +217,7 @@ class NCActionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelec
                 let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
                 let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
                 let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
                 let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
 
 
-                if metadata.isMovie {
+                if metadata.isAudioOrVideo {
                     NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
                     NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
                 } else {
                 } else {
                     hud.show(in: hudView)
                     hud.show(in: hudView)

+ 12 - 84
iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift → iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.swift

@@ -30,17 +30,11 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
     @IBOutlet weak var buttonOrder: UIButton!
     @IBOutlet weak var buttonOrder: UIButton!
     @IBOutlet weak var buttonMore: UIButton!
     @IBOutlet weak var buttonMore: UIButton!
 
 
-    @IBOutlet weak var button1: UIButton!
-    @IBOutlet weak var button2: UIButton!
-    @IBOutlet weak var button3: UIButton!
-
-    @IBOutlet weak var viewButtonsCommand: UIView!
     @IBOutlet weak var viewButtonsView: UIView!
     @IBOutlet weak var viewButtonsView: UIView!
     @IBOutlet weak var viewSeparator: UIView!
     @IBOutlet weak var viewSeparator: UIView!
     @IBOutlet weak var viewRichWorkspace: UIView!
     @IBOutlet weak var viewRichWorkspace: UIView!
     @IBOutlet weak var viewSection: UIView!
     @IBOutlet weak var viewSection: UIView!
 
 
-    @IBOutlet weak var viewButtonsCommandHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewButtonsViewHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewButtonsViewHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewSeparatorHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewSeparatorHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewRichWorkspaceHeightConstraint: NSLayoutConstraint!
     @IBOutlet weak var viewRichWorkspaceHeightConstraint: NSLayoutConstraint!
@@ -61,36 +55,12 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
 
 
         backgroundColor = .clear
         backgroundColor = .clear
 
 
-        buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: .systemGray, size: 25), for: .normal)
+        buttonSwitch.setImage(UIImage(systemName: "list.bullet")!.image(color: .systemGray, size: 25), for: .normal)
 
 
         buttonOrder.setTitle("", for: .normal)
         buttonOrder.setTitle("", for: .normal)
         buttonOrder.setTitleColor(.systemBlue, for: .normal)
         buttonOrder.setTitleColor(.systemBlue, for: .normal)
         buttonMore.setImage(UIImage(named: "more")!.image(color: .systemGray, size: 25), for: .normal)
         buttonMore.setImage(UIImage(named: "more")!.image(color: .systemGray, size: 25), for: .normal)
 
 
-        button1.setImage(nil, for: .normal)
-        button1.isHidden = true
-        button1.backgroundColor = .clear
-        button1.setTitleColor(.systemBlue, for: .normal)
-        button1.layer.borderColor = UIColor.systemGray.cgColor
-        button1.layer.borderWidth = 0.4
-        button1.layer.cornerRadius = 3
-
-        button2.setImage(nil, for: .normal)
-        button2.isHidden = true
-        button2.backgroundColor = .clear
-        button2.setTitleColor(.systemBlue, for: .normal)
-        button2.layer.borderColor = UIColor.systemGray.cgColor
-        button2.layer.borderWidth = 0.4
-        button2.layer.cornerRadius = 3
-
-        button3.setImage(nil, for: .normal)
-        button3.isHidden = true
-        button3.backgroundColor = .clear
-        button3.setTitleColor(.systemBlue, for: .normal)
-        button3.layer.borderColor = UIColor.systemGray.cgColor
-        button3.layer.borderWidth = 0.4
-        button3.layer.cornerRadius = 3
-
         // Gradient
         // Gradient
         gradient.startPoint = CGPoint(x: 0, y: 0.50)
         gradient.startPoint = CGPoint(x: 0, y: 0.50)
         gradient.endPoint = CGPoint(x: 0, y: 1)
         gradient.endPoint = CGPoint(x: 0, y: 1)
@@ -127,47 +97,7 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
         setInterfaceColor()
         setInterfaceColor()
     }
     }
 
 
-    //MARK: - Command
-
-    func setStatusButtonsCommand(enable: Bool) {
-
-        button1.isEnabled = enable
-        button2.isEnabled = enable
-        button3.isEnabled = enable
-    }
-
-    func setButtonsCommand(heigt :CGFloat, imageButton1: UIImage? = nil, titleButton1: String? = nil, imageButton2: UIImage? = nil, titleButton2: String? = nil, imageButton3: UIImage? = nil, titleButton3: String? = nil) {
-
-        viewButtonsCommandHeightConstraint.constant = heigt
-        if heigt == 0 {
-            viewButtonsView.isHidden = true
-            button1.isHidden = true
-            button2.isHidden = true
-            button3.isHidden = true
-        } else {
-            viewButtonsView.isHidden = false
-            if var image = imageButton1, let title = titleButton1 {
-                image = image.image(color: .systemGray, size: 25)
-                button1.setImage(image, for: .normal)
-                button1.isHidden = false
-                button1.setTitle(title.firstUppercased, for: .normal)
-            }
-            if var image = imageButton2, let title = titleButton2 {
-                image = image.image(color: .systemGray, size: 25)
-                button2.setImage(image, for: .normal)
-                button2.isHidden = false
-                button2.setTitle(title.firstUppercased, for: .normal)
-            }
-            if var image = imageButton3, let title = titleButton3 {
-                image = image.image(color: .systemGray, size: 25)
-                button3.setImage(image, for: .normal)
-                button3.isHidden = false
-                button3.setTitle(title.firstUppercased, for: .normal)
-            }
-        }
-    }
-
-    //MARK: - View
+    // MARK: - View
 
 
     func setStatusButtonsView(enable: Bool) {
     func setStatusButtonsView(enable: Bool) {
 
 
@@ -183,18 +113,18 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
 
 
     func setImageSwitchList() {
     func setImageSwitchList() {
 
 
-        buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: .systemGray, size: 50), for: .normal)
+        buttonSwitch.setImage(UIImage(systemName: "list.bullet")!.image(color: .systemGray, width: 20, height: 15), for: .normal)
     }
     }
 
 
     func setImageSwitchGrid() {
     func setImageSwitchGrid() {
 
 
-        buttonSwitch.setImage(UIImage(named: "switchGrid")!.image(color: .systemGray, size: 50), for: .normal)
+        buttonSwitch.setImage(UIImage(systemName: "square.grid.2x2")!.image(color: .systemGray, size: 20), for: .normal)
     }
     }
 
 
-    func setButtonsView(heigt :CGFloat) {
+    func setButtonsView(height: CGFloat) {
 
 
-        viewButtonsViewHeightConstraint.constant = heigt
-        if heigt == 0 {
+        viewButtonsViewHeightConstraint.constant = height
+        if height == 0 {
             viewButtonsView.isHidden = true
             viewButtonsView.isHidden = true
         } else {
         } else {
             viewButtonsView.isHidden = false
             viewButtonsView.isHidden = false
@@ -204,12 +134,10 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
     func setSortedTitle(_ title: String) {
     func setSortedTitle(_ title: String) {
 
 
         let title = NSLocalizedString(title, comment: "")
         let title = NSLocalizedString(title, comment: "")
-        //let size = title.size(withAttributes: [.font: buttonOrder.titleLabel?.font as Any])
-
         buttonOrder.setTitle(title, for: .normal)
         buttonOrder.setTitle(title, for: .normal)
     }
     }
 
 
-    //MARK: - RichWorkspace
+    // MARK: - RichWorkspace
 
 
     func setRichWorkspaceHeight(_ size: CGFloat) {
     func setRichWorkspaceHeight(_ size: CGFloat) {
 
 
@@ -239,9 +167,9 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
         }
         }
     }
     }
 
 
-    //MARK: - Section
+    // MARK: - Section
 
 
-    func setSectionHeight(_ size:CGFloat) {
+    func setSectionHeight(_ size: CGFloat) {
 
 
         viewSectionHeightConstraint.constant = size
         viewSectionHeightConstraint.constant = size
         if size == 0 {
         if size == 0 {
@@ -359,9 +287,9 @@ class NCSectionFooter: UICollectionReusableView, NCSectionFooterDelegate {
             filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
             filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
         }
         }
 
 
-        if foldersText == "" {
+        if foldersText.isEmpty {
             labelSection.text = filesText
             labelSection.text = filesText
-        } else if filesText == "" {
+        } else if filesText.isEmpty {
             labelSection.text = foldersText
             labelSection.text = foldersText
         } else {
         } else {
             labelSection.text = foldersText + ", " + filesText
             labelSection.text = foldersText + ", " + filesText

+ 28 - 86
iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
     <dependencies>
         <deployment identifier="iOS"/>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -15,55 +15,8 @@
             <rect key="frame" x="0.0" y="0.0" width="574" height="211"/>
             <rect key="frame" x="0.0" y="0.0" width="574" height="211"/>
             <autoresizingMask key="autoresizingMask"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
             <subviews>
-                <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="bottom" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="5Lz-Ux-j8Z">
-                    <rect key="frame" x="10" y="0.0" width="554" height="50"/>
-                    <subviews>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hie-dN-B9L">
-                            <rect key="frame" x="0.0" y="10" width="178" height="40"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="40" id="luF-yL-wde"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                            <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
-                            <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                            <state key="normal" title="Button 1"/>
-                            <connections>
-                                <action selector="touchUpInsideButton1:" destination="tys-A2-nDX" eventType="touchUpInside" id="n7r-8n-gT3"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cjh-je-E6h">
-                            <rect key="frame" x="188" y="10" width="178" height="40"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="40" id="Qbm-WY-vBX"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                            <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
-                            <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                            <state key="normal" title="Button 2"/>
-                            <connections>
-                                <action selector="touchUpInsideButton2:" destination="tys-A2-nDX" eventType="touchUpInside" id="hek-Xq-Lh2"/>
-                            </connections>
-                        </button>
-                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zta-tv-COt">
-                            <rect key="frame" x="376" y="10" width="178" height="40"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="40" id="DG7-Fz-W9H"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                            <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
-                            <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                            <state key="normal" title="Button 3"/>
-                            <connections>
-                                <action selector="touchUpInsideButton3:" destination="tys-A2-nDX" eventType="touchUpInside" id="Krk-cP-Iq5"/>
-                            </connections>
-                        </button>
-                    </subviews>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="50" id="d8V-tN-fUz"/>
-                    </constraints>
-                </stackView>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s4I-Jo-yCE">
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s4I-Jo-yCE">
-                    <rect key="frame" x="0.0" y="50" width="574" height="50"/>
+                    <rect key="frame" x="0.0" y="20" width="574" height="50"/>
                     <subviews>
                     <subviews>
                         <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LD-cd-zhc">
                         <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LD-cd-zhc">
                             <rect key="frame" x="10" y="12.5" width="25" height="25"/>
                             <rect key="frame" x="10" y="12.5" width="25" height="25"/>
@@ -71,7 +24,8 @@
                                 <constraint firstAttribute="width" constant="25" id="D76-X9-Tw9"/>
                                 <constraint firstAttribute="width" constant="25" id="D76-X9-Tw9"/>
                                 <constraint firstAttribute="height" constant="25" id="izT-Ru-XYG"/>
                                 <constraint firstAttribute="height" constant="25" id="izT-Ru-XYG"/>
                             </constraints>
                             </constraints>
-                            <state key="normal" image="switchList"/>
+                            <color key="tintColor" systemColor="systemGrayColor"/>
+                            <state key="normal" image="list.bullet" catalog="system"/>
                             <connections>
                             <connections>
                                 <action selector="touchUpInsideSwitch:" destination="tys-A2-nDX" eventType="touchUpInside" id="iT8-1j-fib"/>
                                 <action selector="touchUpInsideSwitch:" destination="tys-A2-nDX" eventType="touchUpInside" id="iT8-1j-fib"/>
                             </connections>
                             </connections>
@@ -79,9 +33,7 @@
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bo-yl-t5k">
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bo-yl-t5k">
                             <rect key="frame" x="45" y="11" width="163" height="28"/>
                             <rect key="frame" x="45" y="11" width="163" height="28"/>
                             <fontDescription key="fontDescription" type="system" pointSize="13"/>
                             <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                            <state key="normal" title="Sort by name (from A to Z)">
-                                <color key="titleColor" systemColor="darkTextColor"/>
-                            </state>
+                            <state key="normal" title="Sort by name (from A to Z)"/>
                             <connections>
                             <connections>
                                 <action selector="touchUpInsideOrder:" destination="tys-A2-nDX" eventType="touchUpInside" id="oiL-3O-hMQ"/>
                                 <action selector="touchUpInsideOrder:" destination="tys-A2-nDX" eventType="touchUpInside" id="oiL-3O-hMQ"/>
                             </connections>
                             </connections>
@@ -109,13 +61,25 @@
                     </constraints>
                     </constraints>
                 </view>
                 </view>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LZu-Te-clJ">
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LZu-Te-clJ">
-                    <rect key="frame" x="0.0" y="99" width="574" height="1"/>
+                    <rect key="frame" x="0.0" y="69" width="574" height="1"/>
                     <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
                     <constraints>
                         <constraint firstAttribute="height" constant="1" id="VuP-sT-hUI"/>
                         <constraint firstAttribute="height" constant="1" id="VuP-sT-hUI"/>
                     </constraints>
                     </constraints>
                 </view>
                 </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="f9U-NY-4OS">
+                    <rect key="frame" x="0.0" y="191" width="574" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="ZcL-Wd-xhN"/>
+                    </constraints>
+                </view>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mB5-5n-AL9">
+                    <rect key="frame" x="10" y="193" width="554" height="18"/>
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+                    <nil key="textColor"/>
+                    <nil key="highlightedColor"/>
+                </label>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NC1-5C-E5z" userLabel="View RichWorkspace">
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NC1-5C-E5z" userLabel="View RichWorkspace">
                     <rect key="frame" x="0.0" y="141" width="574" height="50"/>
                     <rect key="frame" x="0.0" y="141" width="574" height="50"/>
                     <subviews>
                     <subviews>
@@ -135,53 +99,31 @@
                         <constraint firstAttribute="bottom" secondItem="pYo-pF-MGv" secondAttribute="bottom" id="t4r-dA-VyW"/>
                         <constraint firstAttribute="bottom" secondItem="pYo-pF-MGv" secondAttribute="bottom" id="t4r-dA-VyW"/>
                     </constraints>
                     </constraints>
                 </view>
                 </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="f9U-NY-4OS">
-                    <rect key="frame" x="0.0" y="191" width="574" height="20"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mB5-5n-AL9">
-                            <rect key="frame" x="10" y="2" width="554" height="18"/>
-                            <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
-                            <nil key="textColor"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                    </subviews>
-                    <constraints>
-                        <constraint firstAttribute="trailing" secondItem="mB5-5n-AL9" secondAttribute="trailing" constant="10" id="Cct-8N-ghQ"/>
-                        <constraint firstAttribute="height" constant="20" id="ZcL-Wd-xhN"/>
-                        <constraint firstItem="mB5-5n-AL9" firstAttribute="leading" secondItem="f9U-NY-4OS" secondAttribute="leading" constant="10" id="xQp-zk-G00"/>
-                        <constraint firstAttribute="bottom" secondItem="mB5-5n-AL9" secondAttribute="bottom" id="ySZ-Z1-BQ1"/>
-                    </constraints>
-                </view>
             </subviews>
             </subviews>
             <viewLayoutGuide key="safeArea" id="pm7-uW-mZE"/>
             <viewLayoutGuide key="safeArea" id="pm7-uW-mZE"/>
             <constraints>
             <constraints>
                 <constraint firstItem="f9U-NY-4OS" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="7kv-IL-kwZ"/>
                 <constraint firstItem="f9U-NY-4OS" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="7kv-IL-kwZ"/>
-                <constraint firstItem="s4I-Jo-yCE" firstAttribute="top" secondItem="5Lz-Ux-j8Z" secondAttribute="bottom" id="Bsp-bF-E1f"/>
                 <constraint firstItem="s4I-Jo-yCE" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CaM-Eb-nHq"/>
                 <constraint firstItem="s4I-Jo-yCE" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CaM-Eb-nHq"/>
                 <constraint firstItem="LZu-Te-clJ" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CyS-jg-0vc"/>
                 <constraint firstItem="LZu-Te-clJ" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CyS-jg-0vc"/>
+                <constraint firstAttribute="bottom" secondItem="mB5-5n-AL9" secondAttribute="bottom" id="EFG-nD-yUb"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="f9U-NY-4OS" secondAttribute="trailing" id="GbG-un-mCe"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="f9U-NY-4OS" secondAttribute="trailing" id="GbG-un-mCe"/>
-                <constraint firstItem="5Lz-Ux-j8Z" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" constant="10" id="Mlm-5i-CrU"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="LZu-Te-clJ" secondAttribute="trailing" id="NiW-2m-3HS"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="LZu-Te-clJ" secondAttribute="trailing" id="NiW-2m-3HS"/>
+                <constraint firstAttribute="trailing" secondItem="mB5-5n-AL9" secondAttribute="trailing" constant="10" id="OO6-Qd-6hP"/>
                 <constraint firstItem="NC1-5C-E5z" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="QpF-nE-s7J"/>
                 <constraint firstItem="NC1-5C-E5z" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="QpF-nE-s7J"/>
-                <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="5Lz-Ux-j8Z" secondAttribute="trailing" constant="10" id="Rsh-4o-ndc"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="NC1-5C-E5z" secondAttribute="trailing" id="UH6-8N-JUD"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="NC1-5C-E5z" secondAttribute="trailing" id="UH6-8N-JUD"/>
+                <constraint firstItem="mB5-5n-AL9" firstAttribute="leading" secondItem="tys-A2-nDX" secondAttribute="leading" constant="10" id="bDt-8i-Gxr"/>
                 <constraint firstItem="LZu-Te-clJ" firstAttribute="top" secondItem="s4I-Jo-yCE" secondAttribute="bottom" constant="-1" id="ede-24-v8F"/>
                 <constraint firstItem="LZu-Te-clJ" firstAttribute="top" secondItem="s4I-Jo-yCE" secondAttribute="bottom" constant="-1" id="ede-24-v8F"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="bottom" id="eyu-CE-rTX"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="bottom" id="eyu-CE-rTX"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="s4I-Jo-yCE" secondAttribute="trailing" id="oCg-UW-8TQ"/>
                 <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="s4I-Jo-yCE" secondAttribute="trailing" id="oCg-UW-8TQ"/>
-                <constraint firstItem="5Lz-Ux-j8Z" firstAttribute="top" secondItem="pm7-uW-mZE" secondAttribute="top" id="os0-Gk-1V7"/>
                 <constraint firstItem="NC1-5C-E5z" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="top" id="pmY-5s-Pv2"/>
                 <constraint firstItem="NC1-5C-E5z" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="top" id="pmY-5s-Pv2"/>
+                <constraint firstItem="s4I-Jo-yCE" firstAttribute="top" secondItem="pm7-uW-mZE" secondAttribute="top" id="pzr-LC-JPk"/>
             </constraints>
             </constraints>
             <connections>
             <connections>
-                <outlet property="button1" destination="Hie-dN-B9L" id="kzL-vK-FCu"/>
-                <outlet property="button2" destination="cjh-je-E6h" id="jUf-rf-F2d"/>
-                <outlet property="button3" destination="Zta-tv-COt" id="jk9-MY-ylh"/>
                 <outlet property="buttonMore" destination="D0O-wK-14O" id="eEx-3R-zCS"/>
                 <outlet property="buttonMore" destination="D0O-wK-14O" id="eEx-3R-zCS"/>
                 <outlet property="buttonOrder" destination="0bo-yl-t5k" id="Kbw-BG-73C"/>
                 <outlet property="buttonOrder" destination="0bo-yl-t5k" id="Kbw-BG-73C"/>
                 <outlet property="buttonSwitch" destination="1LD-cd-zhc" id="Ec2-cM-CoY"/>
                 <outlet property="buttonSwitch" destination="1LD-cd-zhc" id="Ec2-cM-CoY"/>
                 <outlet property="labelSection" destination="mB5-5n-AL9" id="uxf-bN-nZA"/>
                 <outlet property="labelSection" destination="mB5-5n-AL9" id="uxf-bN-nZA"/>
                 <outlet property="textViewRichWorkspace" destination="pYo-pF-MGv" id="2h4-LP-T1z"/>
                 <outlet property="textViewRichWorkspace" destination="pYo-pF-MGv" id="2h4-LP-T1z"/>
-                <outlet property="viewButtonsCommand" destination="5Lz-Ux-j8Z" id="USK-Qe-J1d"/>
-                <outlet property="viewButtonsCommandHeightConstraint" destination="d8V-tN-fUz" id="sFt-OL-Fei"/>
                 <outlet property="viewButtonsView" destination="s4I-Jo-yCE" id="FOI-ZK-1oj"/>
                 <outlet property="viewButtonsView" destination="s4I-Jo-yCE" id="FOI-ZK-1oj"/>
                 <outlet property="viewButtonsViewHeightConstraint" destination="vvG-dH-6c1" id="SEQ-Tn-EE0"/>
                 <outlet property="viewButtonsViewHeightConstraint" destination="vvG-dH-6c1" id="SEQ-Tn-EE0"/>
                 <outlet property="viewRichWorkspace" destination="NC1-5C-E5z" id="NyN-tr-sJl"/>
                 <outlet property="viewRichWorkspace" destination="NC1-5C-E5z" id="NyN-tr-sJl"/>
@@ -195,13 +137,13 @@
         </collectionReusableView>
         </collectionReusableView>
     </objects>
     </objects>
     <resources>
     <resources>
+        <image name="list.bullet" catalog="system" width="128" height="87"/>
         <image name="moreBig" width="50" height="50"/>
         <image name="moreBig" width="50" height="50"/>
-        <image name="switchList" width="25" height="25"/>
-        <systemColor name="darkTextColor">
-            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
         <systemColor name="labelColor">
         <systemColor name="labelColor">
-            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </systemColor>
+        <systemColor name="systemGrayColor">
+            <color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
         </systemColor>
     </resources>
     </resources>
 </document>
 </document>

+ 1 - 1
iOSClient/Media/NCMedia.swift

@@ -402,7 +402,7 @@ extension NCMedia: UICollectionViewDataSource {
             cell.fileObjectId = metadata.ocId
             cell.fileObjectId = metadata.ocId
             cell.fileUser = metadata.ownerId
             cell.fileUser = metadata.ownerId
 
 
-            if metadata.isMovie {
+            if metadata.isAudioOrVideo {
                 cell.imageStatus.image = cacheImages.cellPlayImage
                 cell.imageStatus.image = cacheImages.cellPlayImage
             } else if metadata.livePhoto && livePhoto {
             } else if metadata.livePhoto && livePhoto {
                 cell.imageStatus.image = cacheImages.cellLivePhotoImage
                 cell.imageStatus.image = cacheImages.cellLivePhotoImage

+ 22 - 16
iOSClient/NCGlobal.swift

@@ -86,24 +86,26 @@ class NCGlobal: NSObject {
     let refreshTask                                 = "com.nextcloud.refreshTask"
     let refreshTask                                 = "com.nextcloud.refreshTask"
     let processingTask                              = "com.nextcloud.processingTask"
     let processingTask                              = "com.nextcloud.processingTask"
 
 
-    // Name
+    // App
     //
     //
-    @objc let appName                               = "files"
-    @objc let talkName                              = "talk-message"
-    @objc let appScheme                             = "nextcloud"
+    let appName                                     = "files"
+    let appScheme                                   = "nextcloud"
+    let talkName                                    = "talk-message"
+    let spreedName                                  = "spreed"
+    let twofactorNotificatioName                    = "twofactor_nextcloud_notification"
 
 
     // Nextcloud version
     // Nextcloud version
     //
     //
-    let nextcloudVersion12: Int                     =  12
-    let nextcloudVersion15: Int                     =  15
-    let nextcloudVersion17: Int                     =  17
-    let nextcloudVersion18: Int                     =  18
-    let nextcloudVersion20: Int                     =  20
-    let nextcloudVersion23: Int                     =  23
-    let nextcloudVersion24: Int                     =  24
-    let nextcloudVersion25: Int                     =  25
-    let nextcloudVersion26: Int                     =  26
-    let nextcloudVersion27: Int                     =  27
+    let nextcloudVersion12: Int                     = 12
+    let nextcloudVersion15: Int                     = 15
+    let nextcloudVersion17: Int                     = 17
+    let nextcloudVersion18: Int                     = 18
+    let nextcloudVersion20: Int                     = 20
+    let nextcloudVersion23: Int                     = 23
+    let nextcloudVersion24: Int                     = 24
+    let nextcloudVersion25: Int                     = 25
+    let nextcloudVersion26: Int                     = 26
+    let nextcloudVersion27: Int                     = 27
 
 
     // Nextcloud unsupported
     // Nextcloud unsupported
     //
     //
@@ -127,7 +129,6 @@ class NCGlobal: NSObject {
 
 
     // E2EE
     // E2EE
     //
     //
-    let e2eeMaxFileSize: UInt64                     = 500000000     // 500 MB
     let e2eePassphraseTest                          = "more over television factory tendency independence international intellectual impress interest sentence pony"
     let e2eePassphraseTest                          = "more over television factory tendency independence international intellectual impress interest sentence pony"
     @objc let e2eeReadVersions                      = ["1.1", "1.2"]
     @objc let e2eeReadVersions                      = ["1.1", "1.2"]
 
 
@@ -166,7 +167,6 @@ class NCGlobal: NSObject {
 
 
     // Standard height sections header/footer
     // Standard height sections header/footer
     //
     //
-    let heightButtonsCommand: CGFloat               = 50
     let heightButtonsView: CGFloat                  = 50
     let heightButtonsView: CGFloat                  = 50
     let heightSection: CGFloat                      = 30
     let heightSection: CGFloat                      = 30
     let heightFooter: CGFloat                       = 1
     let heightFooter: CGFloat                       = 1
@@ -312,6 +312,12 @@ class NCGlobal: NSObject {
     //
     //
     let includeHiddenFiles: [String]                = [".LivePhoto"]
     let includeHiddenFiles: [String]                = [".LivePhoto"]
 
 
+    // Auto upload subfolder granularity
+    //
+    @objc let subfolderGranularityDaily             = 2
+    @objc let subfolderGranularityMonthly           = 1
+    @objc let subfolderGranularityYearly            = 0
+
     // Notification Center
     // Notification Center
     //
     //
     @objc let notificationCenterApplicationDidEnterBackground   = "applicationDidEnterBackground"
     @objc let notificationCenterApplicationDidEnterBackground   = "applicationDidEnterBackground"

+ 5 - 0
iOSClient/Networking/E2EE/NCEndToEndEncryption.h

@@ -56,6 +56,11 @@
 - (BOOL)encryptFile:(NSString *)fileName fileNameIdentifier:(NSString *)fileNameIdentifier directory:(NSString *)directory key:(NSString **)key initializationVector:(NSString **)initializationVector authenticationTag:(NSString **)authenticationTag;
 - (BOOL)encryptFile:(NSString *)fileName fileNameIdentifier:(NSString *)fileNameIdentifier directory:(NSString *)directory key:(NSString **)key initializationVector:(NSString **)initializationVector authenticationTag:(NSString **)authenticationTag;
 - (BOOL)decryptFile:(NSString *)fileName fileNameView:(NSString *)fileNameView ocId:(NSString *)ocId key:(NSString *)key initializationVector:(NSString *)initializationVector authenticationTag:(NSString *)authenticationTag;
 - (BOOL)decryptFile:(NSString *)fileName fileNameView:(NSString *)fileNameView ocId:(NSString *)ocId key:(NSString *)key initializationVector:(NSString *)initializationVector authenticationTag:(NSString *)authenticationTag;
 
 
+// Signature CMS
+
+- (NSData *)generateSignatureCMS:(NSData *)data certificate:(NSString *)certificate privateKey:(NSString *)privateKey publicKey:(NSString *)publicKey userId:(NSString *)userId;
+- (BOOL)verifySignatureCMS:(NSData *)cmsContent data:(NSData *)data publicKey:(NSString *)publicKey userId:(NSString *)userId;
+
 // Utility
 // Utility
 
 
 - (void)Encodedkey:(NSString **)key initializationVector:(NSString **)initializationVector;
 - (void)Encodedkey:(NSString **)key initializationVector:(NSString **)initializationVector;

+ 388 - 36
iOSClient/Networking/E2EE/NCEndToEndEncryption.m

@@ -44,6 +44,8 @@
 #define fileNamePrivateKey          @"privateKey.pem"
 #define fileNamePrivateKey          @"privateKey.pem"
 #define fileNamePubliceKey          @"publicKey.pem"
 #define fileNamePubliceKey          @"publicKey.pem"
 
 
+#define streamBuffer                1024
+
 #define AES_KEY_128_LENGTH          16
 #define AES_KEY_128_LENGTH          16
 #define AES_KEY_256_LENGTH          32
 #define AES_KEY_256_LENGTH          32
 #define AES_IVEC_LENGTH             16
 #define AES_IVEC_LENGTH             16
@@ -536,7 +538,6 @@
 
 
 - (BOOL)encryptFile:(NSString *)fileName fileNameIdentifier:(NSString *)fileNameIdentifier directory:(NSString *)directory key:(NSString **)key initializationVector:(NSString **)initializationVector authenticationTag:(NSString **)authenticationTag
 - (BOOL)encryptFile:(NSString *)fileName fileNameIdentifier:(NSString *)fileNameIdentifier directory:(NSString *)directory key:(NSString **)key initializationVector:(NSString **)initializationVector authenticationTag:(NSString **)authenticationTag
 {
 {
-    NSMutableData *cipherData;
     NSData *authenticationTagData;
     NSData *authenticationTagData;
    
    
     NSData *plainData = [[NSFileManager defaultManager] contentsAtPath:[NSString stringWithFormat:@"%@/%@", directory, fileName]];
     NSData *plainData = [[NSFileManager defaultManager] contentsAtPath:[NSString stringWithFormat:@"%@/%@", directory, fileName]];
@@ -545,13 +546,11 @@
     
     
     NSData *keyData = [self generateKey:AES_KEY_128_LENGTH];
     NSData *keyData = [self generateKey:AES_KEY_128_LENGTH];
     NSData *initializationVectorData = [self generateIV:AES_IVEC_LENGTH];
     NSData *initializationVectorData = [self generateIV:AES_IVEC_LENGTH];
-    
-    BOOL result = [self encryptData:plainData cipher:&cipherData key:keyData keyLen:AES_KEY_128_LENGTH initializationVector:initializationVectorData authenticationTag:&authenticationTagData];
-    
-    if (cipherData != nil && result) {
-        
-        [cipherData writeToFile:[NSString stringWithFormat:@"%@/%@", directory, fileNameIdentifier] atomically:YES];
-        
+
+    BOOL result = [self encryptFile:[NSString stringWithFormat:@"%@/%@", directory, fileName] fileNameCipher:[NSString stringWithFormat:@"%@/%@", directory, fileNameIdentifier] key:keyData keyLen:AES_KEY_128_LENGTH initializationVector:initializationVectorData authenticationTag:&authenticationTagData];
+
+    if (result) {
+
         *key = [keyData base64EncodedStringWithOptions:0];
         *key = [keyData base64EncodedStringWithOptions:0];
         *initializationVector = [initializationVectorData base64EncodedStringWithOptions:0];
         *initializationVector = [initializationVectorData base64EncodedStringWithOptions:0];
         *authenticationTag = [authenticationTagData base64EncodedStringWithOptions:0];
         *authenticationTag = [authenticationTagData base64EncodedStringWithOptions:0];
@@ -568,23 +567,11 @@
 
 
 - (BOOL)decryptFile:(NSString *)fileName fileNameView:(NSString *)fileNameView ocId:(NSString *)ocId key:(NSString *)key initializationVector:(NSString *)initializationVector authenticationTag:(NSString *)authenticationTag
 - (BOOL)decryptFile:(NSString *)fileName fileNameView:(NSString *)fileNameView ocId:(NSString *)ocId key:(NSString *)key initializationVector:(NSString *)initializationVector authenticationTag:(NSString *)authenticationTag
 {
 {
-    NSMutableData *plainData;
-
-    NSData *cipherData = [[NSFileManager defaultManager] contentsAtPath:[CCUtility getDirectoryProviderStorageOcId:ocId fileNameView:fileName]];
-    if (cipherData == nil)
-        return false;
-    
     NSData *keyData = [[NSData alloc] initWithBase64EncodedString:key options:0];
     NSData *keyData = [[NSData alloc] initWithBase64EncodedString:key options:0];
     NSData *initializationVectorData = [[NSData alloc] initWithBase64EncodedString:initializationVector options:0];
     NSData *initializationVectorData = [[NSData alloc] initWithBase64EncodedString:initializationVector options:0];
     NSData *authenticationTagData = [[NSData alloc] initWithBase64EncodedString:authenticationTag options:0];
     NSData *authenticationTagData = [[NSData alloc] initWithBase64EncodedString:authenticationTag options:0];
 
 
-    BOOL result = [self decryptData:cipherData plain:&plainData key:keyData keyLen:AES_KEY_128_LENGTH initializationVector:initializationVectorData authenticationTag:authenticationTagData];
-    if (plainData != nil && result) {
-        [plainData writeToFile:[CCUtility getDirectoryProviderStorageOcId:ocId fileNameView:fileNameView] atomically:YES];
-        return true;
-    }
-    
-    return false;
+   return [self decryptFile:[CCUtility getDirectoryProviderStorageOcId:ocId fileNameView:fileName] fileNamePlain:[CCUtility getDirectoryProviderStorageOcId:ocId fileNameView:fileNameView] key:keyData keyLen:AES_KEY_128_LENGTH initializationVector:initializationVectorData authenticationTag:authenticationTagData];
 }
 }
 
 
 // -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -729,7 +716,7 @@
 #pragma mark - AES/GCM/NoPadding
 #pragma mark - AES/GCM/NoPadding
 #
 #
 
 
-// Encryption using GCM mode
+// Encryption data using GCM mode
 - (BOOL)encryptData:(NSData *)plain cipher:(NSMutableData **)cipher key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData **)authenticationTag
 - (BOOL)encryptData:(NSData *)plain cipher:(NSMutableData **)cipher key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData **)authenticationTag
 {
 {
     int status = 0;
     int status = 0;
@@ -763,32 +750,41 @@
     else if (keyLen == AES_KEY_256_LENGTH)
     else if (keyLen == AES_KEY_256_LENGTH)
         status = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
         status = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
     
     
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Set IV length. Not necessary if this is 12 bytes (96 bits)
     // Set IV length. Not necessary if this is 12 bytes (96 bits)
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Initialise key and IV
     // Initialise key and IV
     status = EVP_EncryptInit_ex (ctx, NULL, NULL, cKey, cIV);
     status = EVP_EncryptInit_ex (ctx, NULL, NULL, cKey, cIV);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Provide the message to be encrypted, and obtain the encrypted output
     // Provide the message to be encrypted, and obtain the encrypted output
     *cipher = [NSMutableData dataWithLength:[plain length]];
     *cipher = [NSMutableData dataWithLength:[plain length]];
     unsigned char * cCipher = [*cipher mutableBytes];
     unsigned char * cCipher = [*cipher mutableBytes];
     int cCipherLen = 0;
     int cCipherLen = 0;
     status = EVP_EncryptUpdate(ctx, cCipher, &cCipherLen, [plain bytes], (int)[plain length]);
     status = EVP_EncryptUpdate(ctx, cCipher, &cCipherLen, [plain bytes], (int)[plain length]);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Finalise the encryption
     // Finalise the encryption
-    len = cCipherLen;
-    status = EVP_EncryptFinal_ex(ctx, cCipher+cCipherLen, &len);
-    if (status <= 0)
+    status = EVP_EncryptFinal_ex(ctx, cCipher, &cCipherLen);
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Get the tag
     // Get the tag
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)sizeof(cTag), cTag);
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)sizeof(cTag), cTag);
@@ -797,13 +793,139 @@
     // Append TAG
     // Append TAG
     [*cipher appendData:*authenticationTag];
     [*cipher appendData:*authenticationTag];
 
 
-    // Free
     EVP_CIPHER_CTX_free(ctx);
     EVP_CIPHER_CTX_free(ctx);
     
     
     return status; // OpenSSL uses 1 for success
     return status; // OpenSSL uses 1 for success
 }
 }
 
 
-// Decryption using GCM mode
+// Encryption file using GCM mode
+- (BOOL)encryptFile:(NSString *)fileName fileNameCipher:(NSString *)fileNameCipher key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData **)authenticationTag
+{
+    int status = 0;
+    int len = 0;
+
+    // set up key
+    len = keyLen;
+    unsigned char cKey[len];
+    bzero(cKey, sizeof(cKey));
+    [key getBytes:cKey length:len];
+
+    // set up ivec
+    len = AES_IVEC_LENGTH;
+    unsigned char cIV[len];
+    bzero(cIV, sizeof(cIV));
+    [initializationVector getBytes:cIV length:len];
+
+    // set up tag
+    len = AES_GCM_TAG_LENGTH;
+    unsigned char cTag[len];
+    bzero(cTag, sizeof(cTag));
+
+    // Create and initialise the context
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+    if (!ctx) {
+        return NO;
+    }
+
+    // Initialise the encryption operation
+    if (keyLen == AES_KEY_128_LENGTH)
+        status = EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+    else if (keyLen == AES_KEY_256_LENGTH)
+        status = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
+
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    // Set IV length. Not necessary if this is 12 bytes (96 bits)
+    status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    // Initialise key and IV
+    status = EVP_EncryptInit_ex (ctx, NULL, NULL, cKey, cIV);
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    NSInputStream *inStream = [NSInputStream inputStreamWithFileAtPath:fileName];
+    [inStream open];
+    NSOutputStream *outStream = [NSOutputStream outputStreamToFileAtPath:fileNameCipher append:false];
+    [outStream open];
+
+    Byte buffer[streamBuffer];
+    NSInteger totalNumberOfBytesWritten = 0;
+
+    int cCipherLen = 0;
+    unsigned char *cCipher;
+
+    while ([inStream hasBytesAvailable]) {
+
+        NSInteger bytesRead = [inStream read:buffer maxLength:streamBuffer];
+
+        if (bytesRead > 0) {
+
+            cCipher = [[NSMutableData dataWithLength:bytesRead] mutableBytes];
+            status = EVP_EncryptUpdate(ctx, cCipher, &cCipherLen, [[NSData dataWithBytes:buffer length:bytesRead] bytes], (int)bytesRead);
+            if (status <= 0) {
+                [inStream close];
+                [outStream close];
+                EVP_CIPHER_CTX_free(ctx);
+                return NO;
+            }
+
+            if ([outStream hasSpaceAvailable]) {
+                totalNumberOfBytesWritten = [outStream write:cCipher maxLength:cCipherLen];
+                if (totalNumberOfBytesWritten != cCipherLen) {
+                    [inStream close];
+                    [outStream close];
+                    EVP_CIPHER_CTX_free(ctx);
+                    return NO;
+                }
+            }
+        }
+    }
+
+    [inStream close];
+
+    status = EVP_EncryptFinal_ex(ctx, cCipher, &cCipherLen);
+    if (status <= 0) {
+        [outStream close];
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    // Get the tag
+    status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)sizeof(cTag), cTag);
+    if (status <= 0) {
+        [outStream close];
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+    *authenticationTag = [NSData dataWithBytes:cTag length:sizeof(cTag)];
+
+    // Append TAG
+    if ([outStream hasSpaceAvailable]) {
+        totalNumberOfBytesWritten = [outStream write:cTag maxLength:sizeof(cTag)];
+        if (totalNumberOfBytesWritten != sizeof(cTag)) {
+            status = NO;
+        }
+    } else {
+        status = NO;
+    }
+
+    [outStream close];
+
+    EVP_CIPHER_CTX_free(ctx);
+
+    return status; // OpenSSL uses 1 for success
+}
+
+// Decryption data using GCM mode
 - (BOOL)decryptData:(NSData *)cipher plain:(NSMutableData **)plain key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData *)authenticationTag
 - (BOOL)decryptData:(NSData *)cipher plain:(NSMutableData **)plain key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData *)authenticationTag
 {    
 {    
     int status = 0;
     int status = 0;
@@ -838,31 +960,41 @@
     else if (keyLen == AES_KEY_256_LENGTH)
     else if (keyLen == AES_KEY_256_LENGTH)
         status = EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
         status = EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
     
     
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Set IV length. Not necessary if this is 12 bytes (96 bits)
     // Set IV length. Not necessary if this is 12 bytes (96 bits)
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Initialise key and IV
     // Initialise key and IV
     status = EVP_DecryptInit_ex(ctx, NULL, NULL, cKey, cIV);
     status = EVP_DecryptInit_ex(ctx, NULL, NULL, cKey, cIV);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Provide the message to be decrypted, and obtain the plaintext output
     // Provide the message to be decrypted, and obtain the plaintext output
     *plain = [NSMutableData dataWithLength:([cipher length])];
     *plain = [NSMutableData dataWithLength:([cipher length])];
     int cPlainLen = 0;
     int cPlainLen = 0;
     unsigned char * cPlain = [*plain mutableBytes];
     unsigned char * cPlain = [*plain mutableBytes];
     status = EVP_DecryptUpdate(ctx, cPlain, &cPlainLen, [cipher bytes], (int)([cipher length]));
     status = EVP_DecryptUpdate(ctx, cPlain, &cPlainLen, [cipher bytes], (int)([cipher length]));
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Tag is the last 16 bytes
     // Tag is the last 16 bytes
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)sizeof(cTag), cTag);
     status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)sizeof(cTag), cTag);
-    if (status <= 0)
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
         return NO;
         return NO;
+    }
     
     
     // Finalise the encryption
     // Finalise the encryption
     EVP_DecryptFinal_ex(ctx,NULL, &cPlainLen);
     EVP_DecryptFinal_ex(ctx,NULL, &cPlainLen);
@@ -873,6 +1005,226 @@
     return status; // OpenSSL uses 1 for success
     return status; // OpenSSL uses 1 for success
 }
 }
 
 
+// Decryption file using GCM mode
+- (BOOL)decryptFile:(NSString *)fileName fileNamePlain:(NSString *)fileNamePlain key:(NSData *)key keyLen:(int)keyLen initializationVector:(NSData *)initializationVector authenticationTag:(NSData *)authenticationTag
+{
+    int status = 0;
+    int len = 0;
+
+    // set up key
+    len = keyLen;
+    unsigned char cKey[len];
+    bzero(cKey, sizeof(cKey));
+    [key getBytes:cKey length:len];
+
+    // set up ivec
+    len = (int)[initializationVector length];
+    unsigned char cIV[len];
+    bzero(cIV, sizeof(cIV));
+    [initializationVector getBytes:cIV length:len];
+
+    // set up tag
+    len = (int)[authenticationTag length];;
+    unsigned char cTag[len];
+    bzero(cTag, sizeof(cTag));
+    [authenticationTag getBytes:cTag length:len];
+
+    // Create and initialise the context
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+    if (!ctx)
+        return NO;
+
+    // Initialise the decryption operation
+    if (keyLen == AES_KEY_128_LENGTH)
+        status = EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+    else if (keyLen == AES_KEY_256_LENGTH)
+        status = EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
+
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    // Set IV length. Not necessary if this is 12 bytes (96 bits)
+    status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)sizeof(cIV), NULL);
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    // Initialise key and IV
+    status = EVP_DecryptInit_ex(ctx, NULL, NULL, cKey, cIV);
+    if (status <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return NO;
+    }
+
+    NSInputStream *inStream = [NSInputStream inputStreamWithFileAtPath:fileName];
+    [inStream open];
+    NSOutputStream *outStream = [NSOutputStream outputStreamToFileAtPath:fileNamePlain append:false];
+    [outStream open];
+
+    Byte buffer[streamBuffer];
+    NSInteger totalNumberOfBytesWritten = 0;
+
+    int cPlainLen = 0;
+    unsigned char *cPlain;
+
+    while ([inStream hasBytesAvailable]) {
+
+        NSInteger bytesRead = [inStream read:buffer maxLength:streamBuffer];
+
+        if (bytesRead > 0) {
+
+            cPlain = [[NSMutableData dataWithLength:bytesRead] mutableBytes];
+            status = EVP_DecryptUpdate(ctx, cPlain, &cPlainLen, [[NSData dataWithBytes:buffer length:bytesRead] bytes], (int)bytesRead);
+            if (status <= 0) {
+                [inStream close];
+                [outStream close];
+                EVP_CIPHER_CTX_free(ctx);
+                return NO;
+            }
+
+            if ([outStream hasSpaceAvailable]) {
+                totalNumberOfBytesWritten = [outStream write:cPlain maxLength:cPlainLen];
+                if (totalNumberOfBytesWritten != cPlainLen) {
+                    [inStream close];
+                    [outStream close];
+                    EVP_CIPHER_CTX_free(ctx);
+                    return NO;
+                }
+            }
+        }
+    }
+
+    [inStream close];
+    [outStream close];
+
+    // Tag is the last 16 bytes
+    status = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)sizeof(cTag), cTag);
+    if (status <= 0)
+        return NO;
+
+    // Finalise the encryption
+    EVP_DecryptFinal_ex(ctx,NULL, &cPlainLen);
+
+    // Free
+    EVP_CIPHER_CTX_free(ctx);
+
+    return status; // OpenSSL uses 1 for success
+}
+
+#
+#pragma mark - CMS
+#
+
+- (NSData *)generateSignatureCMS:(NSData *)data certificate:(NSString *)certificate privateKey:(NSString *)privateKey publicKey:(NSString *)publicKey userId:(NSString *)userId
+{
+    unsigned char *pKey = (unsigned char *)[privateKey UTF8String];
+    unsigned char *certKey = (unsigned char *)[certificate UTF8String];
+    BIO *printBIO = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+    BIO *certKeyBIO = BIO_new_mem_buf(certKey, -1);
+    if (!certKeyBIO)
+        return nil;
+
+    X509 *x509 = PEM_read_bio_X509(certKeyBIO, NULL, 0, NULL);
+    if (!x509)
+        return nil;
+
+    BIO *pkeyBIO = BIO_new_mem_buf(pKey, -1);
+    EVP_PKEY *key = PEM_read_bio_PrivateKey(pkeyBIO, NULL, NULL, NULL);
+    if (!key)
+        return nil;
+
+    BIO *dataBIO = BIO_new_mem_buf((void*)data.bytes, (int)data.length);
+
+    CMS_ContentInfo *contentInfo = CMS_sign(x509, key, NULL, dataBIO, CMS_DETACHED);
+    if (contentInfo == nil)
+        return nil;
+
+    CMS_ContentInfo_print_ctx(printBIO, contentInfo, 0, NULL);
+    PEM_write_bio_CMS(printBIO, contentInfo);
+
+    BIO *i2dCmsBioOut = BIO_new(BIO_s_mem());
+    if (i2d_CMS_bio(i2dCmsBioOut, contentInfo) != 1)
+        return nil;
+
+    int len = BIO_pending(i2dCmsBioOut);
+    char *keyBytes = malloc(len);
+    BIO_read(i2dCmsBioOut, keyBytes, len);
+
+    NSData *i2dCmsData = [NSData dataWithBytes:keyBytes length:len];
+
+    // TEST
+    [self verifySignatureCMS:i2dCmsData data:data publicKey:publicKey userId:userId];
+
+    BIO_free(printBIO);
+    BIO_free(certKeyBIO);
+    BIO_free(pkeyBIO);
+    BIO_free(dataBIO);
+    BIO_free(i2dCmsBioOut);
+
+    return i2dCmsData;
+}
+
+- (BOOL)verifySignatureCMS:(NSData *)cmsContent data:(NSData *)data publicKey:(NSString *)publicKey userId:(NSString *)userId
+{
+    BIO *dataBIO = BIO_new_mem_buf((void*)data.bytes, (int)data.length);
+    BIO *printBIO = BIO_new_fp(stdout, BIO_NOCLOSE);
+    BIO *cmsBIO = BIO_new_mem_buf(cmsContent.bytes, (int)cmsContent.length);
+
+    CMS_ContentInfo *contentInfo = d2i_CMS_bio(cmsBIO, NULL);
+
+    unsigned char *publicKeyUTF8 = (unsigned char *)[publicKey UTF8String];
+    BIO *publicKeyBIO = BIO_new_mem_buf(publicKeyUTF8, -1);
+    EVP_PKEY *pkey = PEM_read_bio_PUBKEY(publicKeyBIO, NULL, NULL, NULL);
+
+    CMS_ContentInfo_print_ctx(printBIO, contentInfo, 0, NULL);
+
+    BOOL verifyResult = CMS_verify(contentInfo, NULL, NULL, dataBIO, NULL, CMS_DETACHED | CMS_NO_SIGNER_CERT_VERIFY);
+
+    if (verifyResult) {
+
+        STACK_OF(X509) *signers = CMS_get0_signers(contentInfo);
+        int numSigners = sk_X509_num(signers);
+
+        for (int i = 0; i < numSigners; ++i) {
+
+            X509 *signer = sk_X509_value(signers, i);
+            int result = X509_verify(signer, pkey);
+            if (result <= 0) {
+                verifyResult = false;
+                break;
+            }
+
+            int cnDataLength = X509_NAME_get_text_by_NID(X509_get_subject_name(signer), NID_commonName, 0, 0);
+            cnDataLength += 1;
+            NSMutableData* cnData = [NSMutableData dataWithLength:cnDataLength];
+            X509_NAME_get_text_by_NID(X509_get_subject_name(signer), NID_commonName, [cnData mutableBytes], cnDataLength);
+            NSString *cn = [[NSString alloc] initWithCString:[cnData mutableBytes] encoding:NSUTF8StringEncoding];
+            if ([userId isEqualToString:cn]) {
+                verifyResult = true;
+                break;
+            } else {
+                verifyResult = false;
+            }
+        }
+
+        if (signers) {
+            sk_X509_free(signers);
+        }
+        signers = NULL;
+    }
+
+    BIO_free(dataBIO);
+    BIO_free(printBIO);
+    BIO_free(cmsBIO);
+    BIO_free(publicKeyBIO);
+
+    return verifyResult;
+}
+
 #
 #
 #pragma mark - Utility
 #pragma mark - Utility
 #
 #

File diff suppressed because it is too large
+ 8 - 0
iOSClient/Networking/E2EE/NCEndToEndMetadata.swift


+ 0 - 7
iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift

@@ -54,13 +54,6 @@ class NCNetworkingE2EEUpload: NSObject {
         let ocIdTemp = metadata.ocId
         let ocIdTemp = metadata.ocId
         let errorCreateEncrypted = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_e2e_error_create_encrypted_")
         let errorCreateEncrypted = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_e2e_error_create_encrypted_")
 
 
-        // Verify max size
-        if metadata.size > NCGlobal.shared.e2eeMaxFileSize {
-            NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": metadata.ocId, "error": NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "E2E Error file too big")])
-            return NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "E2E Error file too big")
-        }
-
         // Create metadata for upload
         // Create metadata for upload
         if let result = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "serverUrl == %@ AND fileNameView == %@ AND ocId != %@", metadata.serverUrl, metadata.fileNameView, metadata.ocId)) {
         if let result = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "serverUrl == %@ AND fileNameView == %@ AND ocId != %@", metadata.serverUrl, metadata.fileNameView, metadata.ocId)) {
             metadata.fileName = result.fileName
             metadata.fileName = result.fileName

+ 2 - 2
iOSClient/Networking/NCAutoUpload.swift

@@ -139,10 +139,10 @@ class NCAutoUpload: NSObject {
                 }
                 }
 
 
                 if account.autoUploadCreateSubfolder {
                 if account.autoUploadCreateSubfolder {
-                    if (autoUploadSubfolderGranularity == 0) {
+                    if (autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityYearly) {
                         serverUrl = autoUploadPath + "/" + year
                         serverUrl = autoUploadPath + "/" + year
                     }
                     }
-                    else if (autoUploadSubfolderGranularity == 2) {
+                    else if (autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily) {
                         serverUrl = autoUploadPath + "/" + year + "/" + month + "/" + day
                         serverUrl = autoUploadPath + "/" + year + "/" + month + "/" + day
                     }
                     }
                     else {  // Month Granularity is default
                     else {  // Month Granularity is default

+ 13 - 14
iOSClient/Networking/NCNetworking.swift

@@ -1120,9 +1120,9 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 let month = dateFormatter.string(from: date)
                 let month = dateFormatter.string(from: date)
                 dateFormatter.dateFormat = "dd"
                 dateFormatter.dateFormat = "dd"
                 let day = dateFormatter.string(from: date)
                 let day = dateFormatter.string(from: date)
-                if autoUploadSubfolderGranularity == 0 {
+                if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityYearly {
                     datesSubFolder.append("\(year)")
                     datesSubFolder.append("\(year)")
-                } else if autoUploadSubfolderGranularity == 2 {
+                } else if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily {
                     datesSubFolder.append("\(year)/\(month)/\(day)")
                     datesSubFolder.append("\(year)/\(month)/\(day)")
                 } else {  // Month Granularity is default
                 } else {  // Month Granularity is default
                     datesSubFolder.append("\(year)/\(month)")
                     datesSubFolder.append("\(year)/\(month)")
@@ -1140,11 +1140,11 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 let year = subfolderArray[0]
                 let year = subfolderArray[0]
                 let serverUrlYear = autoUploadPath
                 let serverUrlYear = autoUploadPath
                 result = createFolder(fileName: String(year), serverUrl: serverUrlYear)  // Year always present independently of preference value
                 result = createFolder(fileName: String(year), serverUrl: serverUrlYear)  // Year always present independently of preference value
-                if result && autoUploadSubfolderGranularity >= 1 {
+                if result && autoUploadSubfolderGranularity >= NCGlobal.shared.subfolderGranularityMonthly {
                     let month = subfolderArray[1]
                     let month = subfolderArray[1]
                     let serverUrlMonth = autoUploadPath + "/" + year
                     let serverUrlMonth = autoUploadPath + "/" + year
                     result = createFolder(fileName: String(month), serverUrl: serverUrlMonth)
                     result = createFolder(fileName: String(month), serverUrl: serverUrlMonth)
-                    if result && autoUploadSubfolderGranularity == 2 {
+                    if result && autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily {
                         let day = subfolderArray[2]
                         let day = subfolderArray[2]
                         let serverUrlDay = autoUploadPath + "/" + year + "/" + month
                         let serverUrlDay = autoUploadPath + "/" + year + "/" + month
                         result = createFolder(fileName: String(day), serverUrl: serverUrlDay)
                         result = createFolder(fileName: String(day), serverUrl: serverUrlDay)
@@ -1188,18 +1188,18 @@ class NCNetworking: NSObject, NKCommonDelegate {
 
 
         if metadata.isDirectoryE2EE {
         if metadata.isDirectoryE2EE {
 #if !EXTENSION
 #if !EXTENSION
-            Task {
-                if let metadataLive = metadataLive {
-                    let error = await NCNetworkingE2EEDelete.shared.delete(metadata: metadataLive)
-                    if error == .success {
-                        return await NCNetworkingE2EEDelete.shared.delete(metadata: metadata)
-                    } else {
-                        return error
-                    }
-                } else {
+            if let metadataLive = metadataLive {
+                let error = await NCNetworkingE2EEDelete.shared.delete(metadata: metadataLive)
+                if error == .success {
                     return await NCNetworkingE2EEDelete.shared.delete(metadata: metadata)
                     return await NCNetworkingE2EEDelete.shared.delete(metadata: metadata)
+                } else {
+                    return error
                 }
                 }
+            } else {
+                return await NCNetworkingE2EEDelete.shared.delete(metadata: metadata)
             }
             }
+#else
+            return NKError()
 #endif
 #endif
         } else {
         } else {
             if let metadataLive = metadataLive {
             if let metadataLive = metadataLive {
@@ -1213,7 +1213,6 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 return await deleteMetadataPlain(metadata)
                 return await deleteMetadataPlain(metadata)
             }
             }
         }
         }
-        return NKError()
     }
     }
 
 
     func deleteMetadataPlain(_ metadata: tableMetadata, customHeader: [String: String]? = nil) async -> (NKError) {
     func deleteMetadataPlain(_ metadata: tableMetadata, customHeader: [String: String]? = nil) async -> (NKError) {

+ 7 - 4
iOSClient/Networking/NCNetworkingChunkedUpload.swift

@@ -144,11 +144,14 @@ extension NCNetworking {
             let serverUrlFileNameDestination = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
             let serverUrlFileNameDestination = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
 
 
             var customHeader: [String: String] = [:]
             var customHeader: [String: String] = [:]
-            let creationDate = "\(metadata.creationDate.timeIntervalSince1970)"
-            let modificationDate = "\(metadata.date.timeIntervalSince1970)"
 
 
-            customHeader["X-OC-CTime"] = creationDate
-            customHeader["X-OC-MTime"] = modificationDate
+            if metadata.creationDate.timeIntervalSince1970 > 0 {
+                customHeader["X-OC-CTime"] = "\(metadata.creationDate.timeIntervalSince1970)"
+            }
+
+            if metadata.date.timeIntervalSince1970 > 0 {
+                customHeader["X-OC-MTime"] = "\(metadata.date.timeIntervalSince1970)"
+            }
 
 
             // Calculate Assemble Timeout
             // Calculate Assemble Timeout
             let ASSEMBLE_TIME_PER_GB: Double    = 3 * 60            // 3  min
             let ASSEMBLE_TIME_PER_GB: Double    = 3 * 60            // 3  min

+ 21 - 17
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -39,25 +39,29 @@ class NCNetworkingProcessUpload: NSObject {
     private var pauseProcess: Bool = false
     private var pauseProcess: Bool = false
 
 
     func observeTableMetadata() {
     func observeTableMetadata() {
-        let realm = try! Realm()
-        let results = realm.objects(tableMetadata.self).filter("session != '' || sessionError != ''")
-        notificationToken = results.observe { [weak self] (changes: RealmCollectionChange) in
-            switch changes {
-            case .initial:
-                print("Initial")
-            case .update(_, let deletions, let insertions, let modifications):
-                if (deletions.count > 0 || insertions.count > 0 || modifications.count > 0) {
-                    self?.invalidateObserveTableMetadata()
-                    self?.start(completition: { items in
-                        print("[LOG] PROCESS-UPLOAD-OBSERVE \(items)")
-                        DispatchQueue.main.async {
-                            self?.observeTableMetadata()
-                        }
-                    })
+        do {
+            let realm = try Realm()
+            let results = realm.objects(tableMetadata.self).filter("session != '' || sessionError != ''")
+            notificationToken = results.observe { [weak self] (changes: RealmCollectionChange) in
+                switch changes {
+                case .initial:
+                    print("Initial")
+                case .update(_, let deletions, let insertions, let modifications):
+                    if (deletions.count > 0 || insertions.count > 0 || modifications.count > 0) {
+                        self?.invalidateObserveTableMetadata()
+                        self?.start(completition: { items in
+                            print("[LOG] PROCESS-UPLOAD-OBSERVE \(items)")
+                            DispatchQueue.main.async {
+                                self?.observeTableMetadata()
+                            }
+                        })
+                    }
+                case .error(let error):
+                    NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to TableMetadata: \(error)")
                 }
                 }
-            case .error(let error):
-                NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to TableMetadata: \(error)")
             }
             }
+        } catch let error as NSError {
+            NSLog("Could not access database: ", error)
         }
         }
     }
     }
 
 

+ 12 - 1
iOSClient/Notification/NCNotification.swift

@@ -49,6 +49,13 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
 
 
         refreshControl?.addTarget(self, action: #selector(getNetwokingNotification), for: .valueChanged)
         refreshControl?.addTarget(self, action: #selector(getNetwokingNotification), for: .valueChanged)
 
 
+        // Navigation controller is being presented modally
+        if navigationController?.presentingViewController != nil {
+            navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .plain, action: { [weak self] in
+                self?.dismiss(animated: true)
+            })
+        }
+
         // Empty
         // Empty
         let offset = (self.navigationController?.navigationBar.bounds.height ?? 0) - 20
         let offset = (self.navigationController?.navigationBar.bounds.height ?? 0) - 20
         emptyDataSet = NCEmptyDataSet(view: tableView, offset: -offset, delegate: self)
         emptyDataSet = NCEmptyDataSet(view: tableView, offset: -offset, delegate: self)
@@ -258,7 +265,7 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
     }
     }
 
 
     func tapAction(with notification: NKNotifications, label: String) {
     func tapAction(with notification: NKNotifications, label: String) {
-        if notification.app == "spreed",
+        if notification.app == NCGlobal.shared.spreedName,
            let roomToken = notification.objectId.split(separator: "/").first,
            let roomToken = notification.objectId.split(separator: "/").first,
            let talkUrl = URL(string: "nextcloudtalk://open-conversation?server=\(appDelegate.urlBase)&user=\(appDelegate.userId)&withRoomToken=\(roomToken)"),
            let talkUrl = URL(string: "nextcloudtalk://open-conversation?server=\(appDelegate.urlBase)&user=\(appDelegate.userId)&withRoomToken=\(roomToken)"),
            UIApplication.shared.canOpenURL(talkUrl) {
            UIApplication.shared.canOpenURL(talkUrl) {
@@ -280,11 +287,15 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
                         self.notifications.remove(at: index)
                         self.notifications.remove(at: index)
                     }
                     }
                     self.tableView.reloadData()
                     self.tableView.reloadData()
+                    if self.navigationController?.presentingViewController != nil, notification.app == NCGlobal.shared.twofactorNotificatioName {
+                        self.dismiss(animated: true)
+                    }
                 } else if error != .success {
                 } else if error != .success {
                     NCContentPresenter.shared.showError(error: error)
                     NCContentPresenter.shared.showError(error: error)
                 } else {
                 } else {
                     print("[Error] The user has been changed during networking process.")
                     print("[Error] The user has been changed during networking process.")
                 }
                 }
+
             }
             }
         } // else: Action not found
         } // else: Action not found
     }
     }

+ 0 - 1
iOSClient/Offline/NCOffline.swift

@@ -34,7 +34,6 @@ class NCOffline: NCCollectionViewCommon {
         titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
         titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
         layoutKey = NCGlobal.shared.layoutViewOffline
         layoutKey = NCGlobal.shared.layoutViewOffline
         enableSearchBar = false
         enableSearchBar = false
-        headerMenuButtonsCommand = false
         headerMenuButtonsView = true
         headerMenuButtonsView = true
         headerRichWorkspaceDisable = true
         headerRichWorkspaceDisable = true
         emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
         emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)

+ 0 - 1
iOSClient/Recent/NCRecent.swift

@@ -34,7 +34,6 @@ class NCRecent: NCCollectionViewCommon {
         titleCurrentFolder = NSLocalizedString("_recent_", comment: "")
         titleCurrentFolder = NSLocalizedString("_recent_", comment: "")
         layoutKey = NCGlobal.shared.layoutViewRecent
         layoutKey = NCGlobal.shared.layoutViewRecent
         enableSearchBar = false
         enableSearchBar = false
-        headerMenuButtonsCommand = false
         headerMenuButtonsView = false
         headerMenuButtonsView = false
         headerRichWorkspaceDisable = true
         headerRichWorkspaceDisable = true
         emptyImage = NCUtility.shared.loadImage(named: "clock.arrow.circlepath", color: .gray, size: UIScreen.main.bounds.width)
         emptyImage = NCUtility.shared.loadImage(named: "clock.arrow.circlepath", color: .gray, size: UIScreen.main.bounds.width)

+ 1 - 2
iOSClient/Select/NCSelect.swift

@@ -599,8 +599,7 @@ extension NCSelect: UICollectionViewDataSource {
 
 
                 header.delegate = self
                 header.delegate = self
 
 
-                header.setButtonsCommand(heigt: 0)
-                header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
+                header.setButtonsView(height: NCGlobal.shared.heightButtonsView)
                 header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
                 header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
                 header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
                 header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
 
 

+ 3 - 3
iOSClient/Settings/CCManageAutoUpload.m

@@ -151,9 +151,9 @@
     row.cellConfigAtConfigure[@"backgroundColor"] = UIColor.secondarySystemGroupedBackgroundColor;
     row.cellConfigAtConfigure[@"backgroundColor"] = UIColor.secondarySystemGroupedBackgroundColor;
     row.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
     row.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
     row.selectorOptions = @[
     row.selectorOptions = @[
-        [XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:NSLocalizedString(@"_yearly_", nil)],
-        [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:NSLocalizedString(@"_monthly_", nil)],
-        [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:NSLocalizedString(@"_daily_", nil)]
+        [XLFormOptionsObject formOptionsObjectWithValue:@(NCGlobal.shared.subfolderGranularityYearly) displayText:NSLocalizedString(@"_yearly_", nil)],
+        [XLFormOptionsObject formOptionsObjectWithValue:@(NCGlobal.shared.subfolderGranularityMonthly) displayText:NSLocalizedString(@"_monthly_", nil)],
+        [XLFormOptionsObject formOptionsObjectWithValue:@(NCGlobal.shared.subfolderGranularityDaily) displayText:NSLocalizedString(@"_daily_", nil)]
         ];
         ];
     row.value = row.selectorOptions[activeAccount.autoUploadSubfolderGranularity];
     row.value = row.selectorOptions[activeAccount.autoUploadSubfolderGranularity];
     row.required = true;
     row.required = true;

+ 0 - 1
iOSClient/Shares/NCShares.swift

@@ -34,7 +34,6 @@ class NCShares: NCCollectionViewCommon {
         titleCurrentFolder = NSLocalizedString("_list_shares_", comment: "")
         titleCurrentFolder = NSLocalizedString("_list_shares_", comment: "")
         layoutKey = NCGlobal.shared.layoutViewShares
         layoutKey = NCGlobal.shared.layoutViewShares
         enableSearchBar = false
         enableSearchBar = false
-        headerMenuButtonsCommand = false
         headerMenuButtonsView = true
         headerMenuButtonsView = true
         headerRichWorkspaceDisable = true
         headerRichWorkspaceDisable = true
         emptyImage = UIImage(named: "share")?.image(color: .gray, size: UIScreen.main.bounds.width)
         emptyImage = UIImage(named: "share")?.image(color: .gray, size: UIScreen.main.bounds.width)

二進制
iOSClient/Supporting Files/af.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/an.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ar.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ast.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/az.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/be.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/br.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bs.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ca.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/da.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/de.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/el.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/en-GB.lproj/Localizable.strings


+ 2 - 0
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -113,6 +113,8 @@
 "_purchase_"                = "Purchase";
 "_purchase_"                = "Purchase";
 "_account_not_available_"   = "The account %@ of %@ does not exist, please add it to be able to read the file %@";
 "_account_not_available_"   = "The account %@ of %@ does not exist, please add it to be able to read the file %@";
 "_account_not_exists_"      = "The account %@ of %@ does not exist";
 "_account_not_exists_"      = "The account %@ of %@ does not exist";
+"_the_account_"             = "The account";
+"_does_not_exist_"          = "does not exist";
 "_error_parameter_schema_"  = "Wrong parameters, impossible to continue";
 "_error_parameter_schema_"  = "Wrong parameters, impossible to continue";
 "_comments_"                = "Comments";
 "_comments_"                = "Comments";
 "_sharing_"                 = "Sharing";
 "_sharing_"                 = "Sharing";

二進制
iOSClient/Supporting Files/eo.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-419.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-AR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CL.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-DO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-EC.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-GT.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-HN.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-MX.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-NI.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PA.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PE.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PY.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-SV.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-UY.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/et_EE.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/eu.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fa.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fo.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fr.lproj/Localizable.strings


Some files were not shown because too many files changed in this diff