瀏覽代碼

Merge pull request #2274 from nextcloud/layoutForViewDB

Layout for view db
Marino Faggiana 2 年之前
父節點
當前提交
fa298a39ae

+ 1 - 0
.swiftlint.yml

@@ -65,6 +65,7 @@ excluded:
   - iOSClient/Data/NCManageDatabase+Metadata.swift
   - iOSClient/Data/NCManageDatabase+Directory.swift
   - iOSClient/Data/NCManageDatabase+Video.swift
+  - iOSClient/Data/NCManageDatabase+LayoutForView.swift
   - iOSClient/Data/NCManageDatabase+DashboardWidget.swift
   - iOSClient/Diagnostics/NCCapabilitiesViewController.swift
   - iOSClient/EmptyView/NCEmptyDataSet.swift

+ 14 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -448,6 +448,12 @@
 		F7BC287E26663F6C004D46C5 /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; };
 		F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; };
 		F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */; };
+		F7BF9D822934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
+		F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
+		F7BF9D842934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
+		F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
+		F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
+		F7BF9D872934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */; };
 		F7C1EEA525053A9C00866ACC /* NCDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C1EEA425053A9C00866ACC /* NCDataSource.swift */; };
 		F7C30DF6291BC0CA0017149B /* NCNetworkingE2EEUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DF5291BC0CA0017149B /* NCNetworkingE2EEUpload.swift */; };
 		F7C30DF7291BC0D30017149B /* NCNetworkingE2EEUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DF5291BC0CA0017149B /* NCNetworkingE2EEUpload.swift */; };
@@ -1078,6 +1084,7 @@
 		F7BE7C77290ADF15002ABB61 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Intent.strings; sourceTree = "<group>"; };
 		F7BE7C79290ADF16002ABB61 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Intent.strings"; sourceTree = "<group>"; };
 		F7BE7C7B290ADF16002ABB61 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Intent.strings"; sourceTree = "<group>"; };
+		F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+LayoutForView.swift"; sourceTree = "<group>"; };
 		F7C1EEA425053A9C00866ACC /* NCDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCDataSource.swift; sourceTree = "<group>"; };
 		F7C30DF5291BC0CA0017149B /* NCNetworkingE2EEUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EEUpload.swift; sourceTree = "<group>"; };
 		F7C30DF9291BCF790017149B /* NCNetworkingE2EECreateFolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EECreateFolder.swift; sourceTree = "<group>"; };
@@ -1835,6 +1842,7 @@
 				AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */,
 				F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */,
 				F78A10BE29322E8A008499B8 /* NCManageDatabase+Directory.swift */,
+				F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */,
 				AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */,
 				F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */,
 				F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */,
@@ -2803,6 +2811,7 @@
 				F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */,
 				2C33C48223E2C475005F963B /* NotificationService.swift in Sources */,
 				AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
+				F7BF9D872934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */,
 				F73D5E4A246DE09200DF6467 /* NCElementsJSON.swift in Sources */,
 				F79B646326CA661600838ACA /* UIControl+Extensions.swift in Sources */,
@@ -2835,6 +2844,7 @@
 				F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */,
 				F73D5E48246DE09200DF6467 /* NCElementsJSON.swift in Sources */,
 				F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderFooter.swift in Sources */,
+				F7BF9D852934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */,
 				F7C30DFB291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */,
 				AF4BF61F27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
@@ -2914,6 +2924,7 @@
 				F783030028B4C45800B84583 /* NCGlobal.swift in Sources */,
 				F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */,
 				F78302FC28B4C3F300B84583 /* NCElementsJSON.swift in Sources */,
+				F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F783030628B4C51E00B84583 /* String+Extensions.swift in Sources */,
 				F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */,
 				F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */,
@@ -2956,6 +2967,7 @@
 				AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
 				F78A10C329322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
+				F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
 				F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */,
 				F79B646226CA661600838ACA /* UIControl+Extensions.swift in Sources */,
@@ -3026,6 +3038,7 @@
 				F749C10C23C4A5340027D966 /* NCIntroViewController.swift in Sources */,
 				F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */,
 				F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */,
+				F7BF9D822934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */,
 				F78A10BF29322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
 				F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
@@ -3167,6 +3180,7 @@
 				F7A8D74328F1826F008BBE1C /* String+Extensions.swift in Sources */,
 				F7A8D73728F17E1E008BBE1C /* NCManageDatabase+Account.swift in Sources */,
 				F7A8D73B28F17E2C008BBE1C /* NCElementsJSON.swift in Sources */,
+				F7BF9D842934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F7A8D73C28F181BC008BBE1C /* NCBrand.swift in Sources */,
 				F7A8D74228F18261008BBE1C /* NCUtility.swift in Sources */,
 				F7A8D73A28F17E28008BBE1C /* NCManageDatabase+Video.swift in Sources */,

+ 1 - 1
Share/NCShareExtension+Files.swift

@@ -29,7 +29,7 @@ extension NCShareExtension {
 
         var groupByField = "name"
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: keyLayout, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.setLayoutForView(account: activeAccount.account, key: keyLayout, serverUrl: serverUrl)
 
         // set GroupField for Grid
         if layoutForView?.layout == NCGlobal.shared.layoutGrid {

+ 1 - 1
Share/NCShareExtension+NCDelegate.swift

@@ -97,7 +97,7 @@ extension NCShareExtension: NCEmptyDataSetDelegate, NCAccountRequestDelegate {
 
         serverUrl = NCUtilityFileSystem.shared.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId)
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: keyLayout, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: activeAccount.account, key: keyLayout, serverUrl: serverUrl)
 
         reloadDatasource(withLoadFolder: true)
         setNavigationBar(navigationTitle: NCBrandOptions.shared.brand)

+ 1 - 1
Share/NCShareExtension.swift

@@ -58,7 +58,7 @@ class NCShareExtension: UIViewController {
     var metadataFolder: tableMetadata?
     var networkInProgress = false
     var dataSource = NCDataSource()
-    var layoutForView: NCGlobal.layoutForViewType?
+    var layoutForView: NCDBLayoutForView?
     let heightRowTableView: CGFloat = 50
     let heightCommandView: CGFloat = 170
     var autoUploadFileName = ""

+ 0 - 301
iOSClient/Data/NCDatabase.swift

@@ -30,154 +30,6 @@ protocol DateCompareable {
     var dateKey: Date { get }
 }
 
-class tableAccount: Object, NCUserBaseUrl {
-
-    @objc dynamic var account = ""
-    @objc dynamic var active: Bool = false
-    @objc dynamic var address = ""
-    @objc dynamic var alias = ""
-    @objc dynamic var autoUpload: Bool = false
-    @objc dynamic var autoUploadCreateSubfolder: Bool = false
-    @objc dynamic var autoUploadDirectory = ""
-    @objc dynamic var autoUploadFileName = ""
-    @objc dynamic var autoUploadFull: Bool = false
-    @objc dynamic var autoUploadImage: Bool = false
-    @objc dynamic var autoUploadVideo: Bool = false
-    @objc dynamic var autoUploadWWAnPhoto: Bool = false
-    @objc dynamic var autoUploadWWAnVideo: Bool = false
-    @objc dynamic var backend = ""
-    @objc dynamic var backendCapabilitiesSetDisplayName: Bool = false
-    @objc dynamic var backendCapabilitiesSetPassword: Bool = false
-    @objc dynamic var businessSize: String = ""
-    @objc dynamic var businessType = ""
-    @objc dynamic var city = ""
-    @objc dynamic var country = ""
-    @objc dynamic var displayName = ""
-    @objc dynamic var email = ""
-    @objc dynamic var enabled: Bool = false
-    @objc dynamic var groups = ""
-    @objc dynamic var language = ""
-    @objc dynamic var lastLogin: Int64 = 0
-    @objc dynamic var locale = ""
-    @objc dynamic var mediaPath = ""
-    @objc dynamic var organisation = ""
-    @objc dynamic var password = ""
-    @objc dynamic var phone = ""
-    @objc dynamic var quota: Int64 = 0
-    @objc dynamic var quotaFree: Int64 = 0
-    @objc dynamic var quotaRelative: Double = 0
-    @objc dynamic var quotaTotal: Int64 = 0
-    @objc dynamic var quotaUsed: Int64 = 0
-    @objc dynamic var role = ""
-    @objc dynamic var storageLocation = ""
-    @objc dynamic var subadmin = ""
-    @objc dynamic var twitter = ""
-    @objc dynamic var urlBase = ""
-    @objc dynamic var user = ""
-    @objc dynamic var userId = ""
-    @objc dynamic var userStatusClearAt: NSDate?
-    @objc dynamic var userStatusIcon: String?
-    @objc dynamic var userStatusMessage: String?
-    @objc dynamic var userStatusMessageId: String?
-    @objc dynamic var userStatusMessageIsPredefined: Bool = false
-    @objc dynamic var userStatusStatus: String?
-    @objc dynamic var userStatusStatusIsUserDefined: Bool = false
-    @objc dynamic var website = ""
-    @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 {
-        return "account"
-    }
-}
-
-class tableActivity: Object, DateCompareable {
-    var dateKey: Date { date as Date }
-
-    @objc dynamic var account = ""
-    @objc dynamic var idPrimaryKey = ""
-    @objc dynamic var action = "Activity"
-    @objc dynamic var date = NSDate()
-    @objc dynamic var idActivity: Int = 0
-    @objc dynamic var app = ""
-    @objc dynamic var type = ""
-    @objc dynamic var user = ""
-    @objc dynamic var subject = ""
-    @objc dynamic var subjectRich = ""
-    let subjectRichItem = List<tableActivitySubjectRich>()
-    @objc dynamic var icon = ""
-    @objc dynamic var link = ""
-    @objc dynamic var message = ""
-    @objc dynamic var objectType = ""
-    @objc dynamic var objectId: Int = 0
-    @objc dynamic var objectName = ""
-    @objc dynamic var note = ""
-    @objc dynamic var selector = ""
-    @objc dynamic var verbose: Bool = false
-
-    override static func primaryKey() -> String {
-        return "idPrimaryKey"
-    }
-}
-
-class tableActivityLatestId: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var activityFirstKnown: Int = 0
-    @objc dynamic var activityLastGiven: Int = 0
-
-    override static func primaryKey() -> String {
-        return "account"
-    }
-}
-
-class tableActivityPreview: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var filename = ""
-    @objc dynamic var idPrimaryKey = ""
-    @objc dynamic var idActivity: Int = 0
-    @objc dynamic var source = ""
-    @objc dynamic var link = ""
-    @objc dynamic var mimeType = ""
-    @objc dynamic var fileId: Int = 0
-    @objc dynamic var view = ""
-    @objc dynamic var isMimeTypeIcon: Bool = false
-
-    override static func primaryKey() -> String {
-        return "idPrimaryKey"
-    }
-}
-
-class tableActivitySubjectRich: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var idActivity: Int = 0
-    @objc dynamic var idPrimaryKey = ""
-    @objc dynamic var id = ""
-    @objc dynamic var key = ""
-    @objc dynamic var link = ""
-    @objc dynamic var name = ""
-    @objc dynamic var path = ""
-    @objc dynamic var type = ""
-
-    override static func primaryKey() -> String {
-        return "idPrimaryKey"
-    }
-}
-
 class tableAvatar: Object {
 
     @objc dynamic var date = NSDate()
@@ -246,29 +98,6 @@ class tableDirectEditingCreators: Object {
     @objc dynamic var templates: Int = 0
 }
 
-class tableDashboardWidget: Object {
-    
-    @Persisted(primaryKey: true) var index = ""
-    @Persisted var account = ""
-    @Persisted var id = ""
-    @Persisted var title = ""
-    @Persisted var order: Int = 0
-    @Persisted var iconClass: String?
-    @Persisted var iconUrl: String?
-    @Persisted var widgetUrl: String?
-    @Persisted var itemIconsRound: Bool = false
-}
-
-class tableDashboardWidgetButton: Object {
-
-    @Persisted(primaryKey: true) var index = ""
-    @Persisted var account = ""
-    @Persisted var id = ""
-    @Persisted var type = ""
-    @Persisted var text = ""
-    @Persisted var link = ""
-}
-
 class tableDirectEditingEditors: Object {
 
     @objc dynamic var account = ""
@@ -279,25 +108,6 @@ class tableDirectEditingEditors: Object {
     @objc dynamic var secure: Int = 0
 }
 
-class tableDirectory: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var colorFolder: String?
-    @objc dynamic var e2eEncrypted: Bool = false
-    @objc dynamic var etag = ""
-    @objc dynamic var favorite: Bool = false
-    @objc dynamic var fileId = ""
-    @objc dynamic var ocId = ""
-    @objc dynamic var offline: Bool = false
-    @objc dynamic var permissions = ""
-    @objc dynamic var richWorkspace: String?
-    @objc dynamic var serverUrl = ""
-
-    override static func primaryKey() -> String {
-        return "ocId"
-    }
-}
-
 class tableE2eEncryption: Object {
 
     @objc dynamic var account = ""
@@ -372,99 +182,6 @@ class tableLocalFile: Object {
     }
 }
 
-class tableMetadata: Object, NCUserBaseUrl {
-    override func isEqual(_ object: Any?) -> Bool {
-        if let object = object as? tableMetadata {
-            return self.fileId == object.fileId && self.account == object.account
-                   && self.path == object.path && self.fileName == object.fileName
-        } else {
-            return false
-        }
-    }
-
-    @objc dynamic var account = ""
-    @objc dynamic var assetLocalIdentifier = ""
-    @objc dynamic var checksums = ""
-    @objc dynamic var chunk: Bool = false
-    @objc dynamic var classFile = ""
-    @objc dynamic var commentsUnread: Bool = false
-    @objc dynamic var contentType = ""
-    @objc dynamic var creationDate = NSDate()
-    @objc dynamic var dataFingerprint = ""
-    @objc dynamic var date = NSDate()
-    @objc dynamic var directory: Bool = false
-    @objc dynamic var deleteAssetLocalIdentifier: Bool = false
-    @objc dynamic var downloadURL = ""
-    @objc dynamic var e2eEncrypted: Bool = false
-    @objc dynamic var edited: Bool = false
-    @objc dynamic var etag = ""
-    @objc dynamic var etagResource = ""
-    @objc dynamic var favorite: Bool = false
-    @objc dynamic var fileId = ""
-    @objc dynamic var fileName = ""
-    @objc dynamic var fileNameView = ""
-    @objc dynamic var hasPreview: Bool = false
-    @objc dynamic var iconName = ""
-    @objc dynamic var iconUrl = ""
-    @objc dynamic var isExtractFile: Bool = false
-    @objc dynamic var livePhoto: Bool = false
-    @objc dynamic var mountType = ""
-    @objc dynamic var name = ""                                             // for unifiedSearch is the provider.id
-    @objc dynamic var note = ""
-    @objc dynamic var ocId = ""
-    @objc dynamic var ownerId = ""
-    @objc dynamic var ownerDisplayName = ""
-    @objc public var lock = false
-    @objc public var lockOwner = ""
-    @objc public var lockOwnerEditor = ""
-    @objc public var lockOwnerType = 0
-    @objc public var lockOwnerDisplayName = ""
-    @objc public var lockTime: Date?
-    @objc public var lockTimeOut: Date?
-    @objc dynamic var path = ""
-    @objc dynamic var permissions = ""
-    @objc dynamic var quotaUsedBytes: Int64 = 0
-    @objc dynamic var quotaAvailableBytes: Int64 = 0
-    @objc dynamic var resourceType = ""
-    @objc dynamic var richWorkspace: String?
-    @objc dynamic var serverUrl = ""
-    @objc dynamic var session = ""
-    @objc dynamic var sessionError = ""
-    @objc dynamic var sessionSelector = ""
-    @objc dynamic var sessionTaskIdentifier: Int = 0
-    @objc dynamic var sharePermissionsCollaborationServices: Int = 0
-    let sharePermissionsCloudMesh = List<String>()
-    let shareType = List<Int>()
-    @objc dynamic var size: Int64 = 0
-    @objc dynamic var status: Int = 0
-    @objc dynamic var subline: String?
-    @objc dynamic var trashbinFileName = ""
-    @objc dynamic var trashbinOriginalLocation = ""
-    @objc dynamic var trashbinDeletionTime = NSDate()
-    @objc dynamic var uploadDate = NSDate()
-    @objc dynamic var url = ""
-    @objc dynamic var urlBase = ""
-    @objc dynamic var user = ""
-    @objc dynamic var userId = ""
-
-    override static func primaryKey() -> String {
-        return "ocId"
-    }
-}
-
-extension tableMetadata {
-    var fileExtension: String { (fileNameView as NSString).pathExtension }
-
-    var isPrintable: Bool {
-        classFile == NKCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/")
-    }
-
-    /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else
-    func canUnlock(as user: String) -> Bool {
-        return !lock || (lockOwner == user && lockOwnerType == 0)
-    }
-}
-
 class tablePhotoLibrary: Object {
 
     @objc dynamic var account = ""
@@ -578,21 +295,3 @@ class tableUserStatus: Object {
     @objc dynamic var status: String?
     @objc dynamic var userId: String?
 }
-
-class tableVideo: Object {
-
-    @objc dynamic var account = ""
-    @objc dynamic var duration: Int64 = 0
-    @objc dynamic var ocId = ""
-    @objc dynamic var time: Int64 = 0
-    @objc dynamic var codecNameVideo: String?
-    @objc dynamic var codecNameAudio: String?
-    @objc dynamic var codecAudioChannelLayout: String?
-    @objc dynamic var codecAudioLanguage: String?
-    @objc dynamic var codecMaxCompatibility: Bool = false
-    @objc dynamic var codecQuality: String?
-
-    override static func primaryKey() -> String {
-        return "ocId"
-    }
-}

+ 73 - 0
iOSClient/Data/NCManageDatabase+Account.swift

@@ -25,6 +25,79 @@ import Foundation
 import RealmSwift
 import NextcloudKit
 
+class tableAccount: Object, NCUserBaseUrl {
+
+    @objc dynamic var account = ""
+    @objc dynamic var active: Bool = false
+    @objc dynamic var address = ""
+    @objc dynamic var alias = ""
+    @objc dynamic var autoUpload: Bool = false
+    @objc dynamic var autoUploadCreateSubfolder: Bool = false
+    @objc dynamic var autoUploadDirectory = ""
+    @objc dynamic var autoUploadFileName = ""
+    @objc dynamic var autoUploadFull: Bool = false
+    @objc dynamic var autoUploadImage: Bool = false
+    @objc dynamic var autoUploadVideo: Bool = false
+    @objc dynamic var autoUploadWWAnPhoto: Bool = false
+    @objc dynamic var autoUploadWWAnVideo: Bool = false
+    @objc dynamic var backend = ""
+    @objc dynamic var backendCapabilitiesSetDisplayName: Bool = false
+    @objc dynamic var backendCapabilitiesSetPassword: Bool = false
+    @objc dynamic var businessSize: String = ""
+    @objc dynamic var businessType = ""
+    @objc dynamic var city = ""
+    @objc dynamic var country = ""
+    @objc dynamic var displayName = ""
+    @objc dynamic var email = ""
+    @objc dynamic var enabled: Bool = false
+    @objc dynamic var groups = ""
+    @objc dynamic var language = ""
+    @objc dynamic var lastLogin: Int64 = 0
+    @objc dynamic var locale = ""
+    @objc dynamic var mediaPath = ""
+    @objc dynamic var organisation = ""
+    @objc dynamic var password = ""
+    @objc dynamic var phone = ""
+    @objc dynamic var quota: Int64 = 0
+    @objc dynamic var quotaFree: Int64 = 0
+    @objc dynamic var quotaRelative: Double = 0
+    @objc dynamic var quotaTotal: Int64 = 0
+    @objc dynamic var quotaUsed: Int64 = 0
+    @objc dynamic var role = ""
+    @objc dynamic var storageLocation = ""
+    @objc dynamic var subadmin = ""
+    @objc dynamic var twitter = ""
+    @objc dynamic var urlBase = ""
+    @objc dynamic var user = ""
+    @objc dynamic var userId = ""
+    @objc dynamic var userStatusClearAt: NSDate?
+    @objc dynamic var userStatusIcon: String?
+    @objc dynamic var userStatusMessage: String?
+    @objc dynamic var userStatusMessageId: String?
+    @objc dynamic var userStatusMessageIsPredefined: Bool = false
+    @objc dynamic var userStatusStatus: String?
+    @objc dynamic var userStatusStatusIsUserDefined: Bool = false
+    @objc dynamic var website = ""
+    @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 {
+        return "account"
+    }
+}
+
 extension NCManageDatabase {
 
     @objc func addAccount(_ account: String, urlBase: String, user: String, password: String) {

+ 75 - 0
iOSClient/Data/NCManageDatabase+Activity.swift

@@ -26,6 +26,81 @@ import RealmSwift
 import NextcloudKit
 import SwiftyJSON
 
+class tableActivity: Object, DateCompareable {
+    var dateKey: Date { date as Date }
+
+    @objc dynamic var account = ""
+    @objc dynamic var idPrimaryKey = ""
+    @objc dynamic var action = "Activity"
+    @objc dynamic var date = NSDate()
+    @objc dynamic var idActivity: Int = 0
+    @objc dynamic var app = ""
+    @objc dynamic var type = ""
+    @objc dynamic var user = ""
+    @objc dynamic var subject = ""
+    @objc dynamic var subjectRich = ""
+    let subjectRichItem = List<tableActivitySubjectRich>()
+    @objc dynamic var icon = ""
+    @objc dynamic var link = ""
+    @objc dynamic var message = ""
+    @objc dynamic var objectType = ""
+    @objc dynamic var objectId: Int = 0
+    @objc dynamic var objectName = ""
+    @objc dynamic var note = ""
+    @objc dynamic var selector = ""
+    @objc dynamic var verbose: Bool = false
+
+    override static func primaryKey() -> String {
+        return "idPrimaryKey"
+    }
+}
+
+class tableActivityLatestId: Object {
+
+    @objc dynamic var account = ""
+    @objc dynamic var activityFirstKnown: Int = 0
+    @objc dynamic var activityLastGiven: Int = 0
+
+    override static func primaryKey() -> String {
+        return "account"
+    }
+}
+
+class tableActivityPreview: Object {
+
+    @objc dynamic var account = ""
+    @objc dynamic var filename = ""
+    @objc dynamic var idPrimaryKey = ""
+    @objc dynamic var idActivity: Int = 0
+    @objc dynamic var source = ""
+    @objc dynamic var link = ""
+    @objc dynamic var mimeType = ""
+    @objc dynamic var fileId: Int = 0
+    @objc dynamic var view = ""
+    @objc dynamic var isMimeTypeIcon: Bool = false
+
+    override static func primaryKey() -> String {
+        return "idPrimaryKey"
+    }
+}
+
+class tableActivitySubjectRich: Object {
+
+    @objc dynamic var account = ""
+    @objc dynamic var idActivity: Int = 0
+    @objc dynamic var idPrimaryKey = ""
+    @objc dynamic var id = ""
+    @objc dynamic var key = ""
+    @objc dynamic var link = ""
+    @objc dynamic var name = ""
+    @objc dynamic var path = ""
+    @objc dynamic var type = ""
+
+    override static func primaryKey() -> String {
+        return "idPrimaryKey"
+    }
+}
+
 extension NCManageDatabase {
     
     @objc func addActivity(_ activities: [NKActivity], account: String) {

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

@@ -25,6 +25,29 @@ import Foundation
 import RealmSwift
 import NextcloudKit
 
+class tableDashboardWidget: Object {
+
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var account = ""
+    @Persisted var id = ""
+    @Persisted var title = ""
+    @Persisted var order: Int = 0
+    @Persisted var iconClass: String?
+    @Persisted var iconUrl: String?
+    @Persisted var widgetUrl: String?
+    @Persisted var itemIconsRound: Bool = false
+}
+
+class tableDashboardWidgetButton: Object {
+
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var account = ""
+    @Persisted var id = ""
+    @Persisted var type = ""
+    @Persisted var text = ""
+    @Persisted var link = ""
+}
+
 extension NCManageDatabase {
 
     func getDashboardWidget(account: String, id: String) -> (tableDashboardWidget?, [tableDashboardWidgetButton]?) {

+ 19 - 0
iOSClient/Data/NCManageDatabase+Directory.swift

@@ -25,6 +25,25 @@ import Foundation
 import RealmSwift
 import NextcloudKit
 
+class tableDirectory: Object {
+
+    @objc dynamic var account = ""
+    @objc dynamic var colorFolder: String?
+    @objc dynamic var e2eEncrypted: Bool = false
+    @objc dynamic var etag = ""
+    @objc dynamic var favorite: Bool = false
+    @objc dynamic var fileId = ""
+    @objc dynamic var ocId = ""
+    @objc dynamic var offline: Bool = false
+    @objc dynamic var permissions = ""
+    @objc dynamic var richWorkspace: String?
+    @objc dynamic var serverUrl = ""
+
+    override static func primaryKey() -> String {
+        return "ocId"
+    }
+}
+
 extension NCManageDatabase {
 
     @objc func addDirectory(encrypted: Bool, favorite: Bool, ocId: String, fileId: String, etag: String? = nil, permissions: String? = nil, serverUrl: String, account: String) {

+ 128 - 0
iOSClient/Data/NCManageDatabase+LayoutForView.swift

@@ -0,0 +1,128 @@
+//
+//  NCManageDatabase+LayoutForView.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 28/11/22.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+import RealmSwift
+import NextcloudKit
+
+class NCDBLayoutForView: Object {
+
+    @Persisted(primaryKey: true) var index = ""
+    @Persisted var account = ""
+    @Persisted var keyStore = ""
+    @Persisted var layout: String = NCGlobal.shared.layoutList
+    @Persisted var sort: String = "fileName"
+    @Persisted var ascending: Bool = true
+    @Persisted var groupBy: String = "none"
+    @Persisted var directoryOnTop: Bool = true
+    @Persisted var titleButtonHeader: String = "_sorted_by_name_a_z_"
+    @Persisted var itemForLine: Int = 3
+}
+
+extension NCManageDatabase {
+
+    @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? {
+
+        let realm = try! Realm()
+
+        var keyStore = key
+        if !serverUrl.isEmpty { keyStore = serverUrl}
+        let index = account + " " + keyStore
+
+        var addObject = NCDBLayoutForView()
+
+        do {
+            try realm.write {
+                if let result = realm.objects(NCDBLayoutForView.self).filter("index == %@", index).first {
+                    addObject = result
+                } else {
+                    addObject.index = index
+                }
+                addObject.account = account
+                addObject.keyStore = keyStore
+                if let layout = layout {
+                    addObject.layout = layout
+                }
+                if let sort = sort {
+                    addObject.sort = sort
+                }
+                if let sort = sort {
+                    addObject.sort = sort
+                }
+                if let ascending = ascending {
+                    addObject.ascending = ascending
+                }
+                if let groupBy = groupBy {
+                    addObject.groupBy = groupBy
+                }
+                if let directoryOnTop = directoryOnTop {
+                    addObject.directoryOnTop = directoryOnTop
+                }
+                if let titleButtonHeader = titleButtonHeader {
+                    addObject.titleButtonHeader = titleButtonHeader
+                }
+                if let itemForLine = itemForLine {
+                    addObject.itemForLine = itemForLine
+                }
+                realm.add(addObject, update: .all)
+            }
+        } catch let error {
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
+        }
+
+        return NCDBLayoutForView.init(value: addObject)
+    }
+
+    @discardableResult
+    func setLayoutForView(layoutForView: NCDBLayoutForView) -> NCDBLayoutForView? {
+
+        let realm = try! Realm()
+        let result = NCDBLayoutForView.init(value: layoutForView)
+
+        do {
+            try realm.write {
+                realm.add(result, update: .all)
+            }
+        } catch let error {
+            NKCommon.shared.writeLog("Could not write to database: \(error)")
+            return nil
+        }
+        return NCDBLayoutForView.init(value: result)
+    }
+
+    func getLayoutForView(account: String, key: String, serverUrl: String) -> NCDBLayoutForView? {
+
+        let realm = try! Realm()
+
+        var keyStore = key
+        if !serverUrl.isEmpty { keyStore = serverUrl}
+        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)
+        }
+    }
+}

+ 96 - 3
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -25,6 +25,99 @@ import Foundation
 import RealmSwift
 import NextcloudKit
 
+class tableMetadata: Object, NCUserBaseUrl {
+    override func isEqual(_ object: Any?) -> Bool {
+        if let object = object as? tableMetadata {
+            return self.fileId == object.fileId && self.account == object.account
+                   && self.path == object.path && self.fileName == object.fileName
+        } else {
+            return false
+        }
+    }
+
+    @objc dynamic var account = ""
+    @objc dynamic var assetLocalIdentifier = ""
+    @objc dynamic var checksums = ""
+    @objc dynamic var chunk: Bool = false
+    @objc dynamic var classFile = ""
+    @objc dynamic var commentsUnread: Bool = false
+    @objc dynamic var contentType = ""
+    @objc dynamic var creationDate = NSDate()
+    @objc dynamic var dataFingerprint = ""
+    @objc dynamic var date = NSDate()
+    @objc dynamic var directory: Bool = false
+    @objc dynamic var deleteAssetLocalIdentifier: Bool = false
+    @objc dynamic var downloadURL = ""
+    @objc dynamic var e2eEncrypted: Bool = false
+    @objc dynamic var edited: Bool = false
+    @objc dynamic var etag = ""
+    @objc dynamic var etagResource = ""
+    @objc dynamic var favorite: Bool = false
+    @objc dynamic var fileId = ""
+    @objc dynamic var fileName = ""
+    @objc dynamic var fileNameView = ""
+    @objc dynamic var hasPreview: Bool = false
+    @objc dynamic var iconName = ""
+    @objc dynamic var iconUrl = ""
+    @objc dynamic var isExtractFile: Bool = false
+    @objc dynamic var livePhoto: Bool = false
+    @objc dynamic var mountType = ""
+    @objc dynamic var name = ""                                             // for unifiedSearch is the provider.id
+    @objc dynamic var note = ""
+    @objc dynamic var ocId = ""
+    @objc dynamic var ownerId = ""
+    @objc dynamic var ownerDisplayName = ""
+    @objc public var lock = false
+    @objc public var lockOwner = ""
+    @objc public var lockOwnerEditor = ""
+    @objc public var lockOwnerType = 0
+    @objc public var lockOwnerDisplayName = ""
+    @objc public var lockTime: Date?
+    @objc public var lockTimeOut: Date?
+    @objc dynamic var path = ""
+    @objc dynamic var permissions = ""
+    @objc dynamic var quotaUsedBytes: Int64 = 0
+    @objc dynamic var quotaAvailableBytes: Int64 = 0
+    @objc dynamic var resourceType = ""
+    @objc dynamic var richWorkspace: String?
+    @objc dynamic var serverUrl = ""
+    @objc dynamic var session = ""
+    @objc dynamic var sessionError = ""
+    @objc dynamic var sessionSelector = ""
+    @objc dynamic var sessionTaskIdentifier: Int = 0
+    @objc dynamic var sharePermissionsCollaborationServices: Int = 0
+    let sharePermissionsCloudMesh = List<String>()
+    let shareType = List<Int>()
+    @objc dynamic var size: Int64 = 0
+    @objc dynamic var status: Int = 0
+    @objc dynamic var subline: String?
+    @objc dynamic var trashbinFileName = ""
+    @objc dynamic var trashbinOriginalLocation = ""
+    @objc dynamic var trashbinDeletionTime = NSDate()
+    @objc dynamic var uploadDate = NSDate()
+    @objc dynamic var url = ""
+    @objc dynamic var urlBase = ""
+    @objc dynamic var user = ""
+    @objc dynamic var userId = ""
+
+    override static func primaryKey() -> String {
+        return "ocId"
+    }
+}
+
+extension tableMetadata {
+    var fileExtension: String { (fileNameView as NSString).pathExtension }
+
+    var isPrintable: Bool {
+        classFile == NKCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/")
+    }
+
+    /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else
+    func canUnlock(as user: String) -> Bool {
+        return !lock || (lockOwner == user && lockOwnerType == 0)
+    }
+}
+
 extension NCManageDatabase {
 
     @objc func copyObject(metadata: tableMetadata) -> tableMetadata {
@@ -224,17 +317,17 @@ extension NCManageDatabase {
     @objc func addMetadata(_ metadata: tableMetadata) -> tableMetadata? {
 
         let realm = try! Realm()
-        let returnMetadata = tableMetadata.init(value: metadata)
+        let result = tableMetadata.init(value: metadata)
 
         do {
             try realm.write {
-                realm.add(metadata, update: .all)
+                realm.add(result, update: .all)
             }
         } catch let error {
             NKCommon.shared.writeLog("Could not write to database: \(error)")
             return nil
         }
-        return returnMetadata
+        return tableMetadata.init(value: result)
     }
 
     @objc func addMetadatas(_ metadatas: [tableMetadata]) {

+ 18 - 0
iOSClient/Data/NCManageDatabase+Video.swift

@@ -25,6 +25,24 @@ import Foundation
 import RealmSwift
 import NextcloudKit
 
+class tableVideo: Object {
+
+    @objc dynamic var account = ""
+    @objc dynamic var duration: Int64 = 0
+    @objc dynamic var ocId = ""
+    @objc dynamic var time: Int64 = 0
+    @objc dynamic var codecNameVideo: String?
+    @objc dynamic var codecNameAudio: String?
+    @objc dynamic var codecAudioChannelLayout: String?
+    @objc dynamic var codecAudioLanguage: String?
+    @objc dynamic var codecMaxCompatibility: Bool = false
+    @objc dynamic var codecQuality: String?
+
+    override static func primaryKey() -> String {
+        return "ocId"
+    }
+}
+
 extension NCManageDatabase {
 
     func addVideoTime(metadata: tableMetadata, time: CMTime?, durationTime: CMTime?) {

+ 8 - 16
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -46,7 +46,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     internal var headerMenu: NCSectionHeaderMenu?
     internal var isSearchingMode: Bool = false
 
-    internal var layoutForView: NCGlobal.layoutForViewType?
+    internal var layoutForView: NCDBLayoutForView?
     internal var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() }
 
     private var autoUploadFileName = ""
@@ -90,16 +90,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         self.navigationController?.presentationController?.delegate = self
 
         // CollectionView & layout
+        collectionView.alwaysBounceVertical = true
         listLayout = NCListLayout()
         gridLayout = NCGridLayout()
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
-        gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
-        if layoutForView?.layout == NCGlobal.shared.layoutList {
-            collectionView?.collectionViewLayout = listLayout
-        } else {
-            collectionView?.collectionViewLayout = gridLayout
-        }
-        collectionView.alwaysBounceVertical = true
 
         // Color
         view.backgroundColor = .systemBackground
@@ -172,7 +165,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
 
         appDelegate.activeViewController = self
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl)
         gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
         if layoutForView?.layout == NCGlobal.shared.layoutList {
             collectionView?.collectionViewLayout = listLayout
@@ -319,7 +312,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             self.navigationController?.popToRootViewController(animated: false)
         }
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl)
         gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
         if layoutForView?.layout == NCGlobal.shared.layoutList {
             collectionView?.collectionViewLayout = listLayout
@@ -829,7 +822,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             // list layout
             headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
             layoutForView?.layout = NCGlobal.shared.layoutList
-            NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
             self.groupByField = "name"
             if self.dataSource.groupByField != self.groupByField {
                 self.dataSource.changeGroupByField(self.groupByField)
@@ -844,7 +837,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             // grid layout
             headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
             layoutForView?.layout = NCGlobal.shared.layoutGrid
-            NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
             if isSearchingMode {
                 self.groupByField = "name"
             } else {
@@ -863,7 +856,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     func tapButtonOrder(_ sender: Any) {
 
         let sortMenu = NCSortMenu()
-        sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
+        sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
     }
 
     func tapButton1(_ sender: Any) {
@@ -1012,7 +1005,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: appDelegate.urlBase, userId: appDelegate.userId, account: appDelegate.account)
 
         // get layout for view
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl)
 
         // set GroupField for Grid
         if !isSearchingMode && layoutForView?.layout == NCGlobal.shared.layoutGrid {
@@ -1874,4 +1867,3 @@ extension NCCollectionViewCommon: EasyTipViewDelegate {
         self.tipView?.dismiss()
     }
 }
-

+ 4 - 8
iOSClient/Menu/NCSortMenu.swift

@@ -33,14 +33,14 @@ class NCSortMenu: NSObject {
 
     private var key = ""
 
-    func toggleMenu(viewController: UIViewController, key: String, sortButton: UIButton?, serverUrl: String, hideDirectoryOnTop: Bool = false) {
+    func toggleMenu(viewController: UIViewController, account: String, key: String, sortButton: UIButton?, serverUrl: String, hideDirectoryOnTop: Bool = false) {
 
         self.key = key
         self.sortButton = sortButton
         self.serverUrl = serverUrl
         self.hideDirectoryOnTop = hideDirectoryOnTop
 
-        var layoutForView = NCUtility.shared.getLayoutForView(key: key, serverUrl: serverUrl)
+        guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: account, key: key, serverUrl: serverUrl) else { return }
         var actions = [NCMenuAction]()
         var title = ""
         var icon = UIImage()
@@ -129,9 +129,7 @@ class NCSortMenu: NSObject {
         viewController.presentMenu(with: actions)
     }
 
-    func actionMenu(layoutForView: NCGlobal.layoutForViewType) {
-
-        var layoutForView = layoutForView
+    func actionMenu(layoutForView: NCDBLayoutForView) {
 
         switch layoutForView.sort {
         case "fileName":
@@ -145,9 +143,7 @@ class NCSortMenu: NSObject {
         }
 
         self.sortButton?.setTitle(NSLocalizedString(layoutForView.titleButtonHeader, comment: ""), for: .normal)
-
-        NCUtility.shared.setLayoutForView(key: key, serverUrl: serverUrl, layoutForView: layoutForView)
-
+        NCManageDatabase.shared.setLayoutForView(layoutForView: layoutForView)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": self.serverUrl])
     }
 }

+ 1 - 16
iOSClient/NCGlobal.swift

@@ -69,18 +69,6 @@ class NCGlobal: NSObject {
         var totalBytesExpected: Int64
     }
 
-    // Struct for LayoutForView
-    //
-    struct layoutForViewType {
-        var layout: String
-        var sort: String
-        var ascending: Bool
-        var groupBy: String
-        var directoryOnTop: Bool
-        var titleButtonHeader: String
-        var itemForLine: Int
-    }
-
     // Directory on Group
     //
     @objc let directoryProviderStorage              = "File Provider Storage"
@@ -122,7 +110,7 @@ class NCGlobal: NSObject {
     // Database Realm
     //
     let databaseDefault                             = "nextcloud.realm"
-    let databaseSchemaVersion: UInt64               = 256
+    let databaseSchemaVersion: UInt64               = 257
     let fileAccounts: String                        = "accounts.json"
 
     // Intro selector
@@ -372,9 +360,6 @@ class NCGlobal: NSObject {
     let notificationCenterMenuGotToPageInPDF                    = "menuGotToPageInPDF"
     let notificationCenterMenuDetailClose                       = "menuDetailClose"
 
-    let notificationCenterChangedLocation                       = "changedLocation"
-    let notificationStatusAuthorizationChangedLocation          = "statusAuthorizationChangedLocation"
-
     let notificationCenterDownloadedThumbnail                   = "DownloadedThumbnail"             // userInfo: ocId
 
     let notificationCenterHidePlayerToolBar                     = "hidePlayerToolBar"               // userInfo: ocId

+ 6 - 6
iOSClient/Select/NCSelect.swift

@@ -71,7 +71,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
     private var dataSource = NCDataSource()
     internal var richWorkspaceText: String?
 
-    private var layoutForView: NCGlobal.layoutForViewType?
+    private var layoutForView: NCDBLayoutForView?
     internal var headerMenu: NCSectionHeaderMenu?
 
     private var autoUploadFileName = ""
@@ -174,7 +174,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
         autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName()
         autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: activeAccount.urlBase, userId: activeAccount.userId, account: activeAccount.account)
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: activeAccount.account, key: layoutKey, serverUrl: serverUrl)
         gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
 
         if layoutForView?.layout == NCGlobal.shared.layoutList {
@@ -270,7 +270,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
             // list layout
             headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
             layoutForView?.layout = NCGlobal.shared.layoutList
-            NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: activeAccount.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
 
             self.collectionView.reloadData()
             self.collectionView.collectionViewLayout.invalidateLayout()
@@ -281,7 +281,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
             // grid layout
             headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
             layoutForView?.layout = NCGlobal.shared.layoutGrid
-            NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: activeAccount.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
 
             self.collectionView.reloadData()
             self.collectionView.collectionViewLayout.invalidateLayout()
@@ -292,7 +292,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
     func tapButtonOrder(_ sender: Any) {
 
         let sortMenu = NCSortMenu()
-        sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
+        sortMenu.toggleMenu(viewController: self, account: activeAccount.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
     }
 
     // MARK: - Push metadata
@@ -702,7 +702,7 @@ extension NCSelect {
         var predicate: NSPredicate?
         var groupByField = "name"
         
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: activeAccount.account, key: layoutKey, serverUrl: serverUrl)
 
         // set GroupField for Grid
         if layoutForView?.layout == NCGlobal.shared.layoutGrid {

+ 1 - 1
iOSClient/Transfers/NCTransfers.swift

@@ -49,7 +49,7 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
         super.viewDidLoad()
 
         listLayout.itemHeight = 105
-        NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: NCGlobal.shared.layoutList)
+        NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: NCGlobal.shared.layoutList)
         self.navigationItem.title = titleCurrentFolder
     }
 

+ 6 - 6
iOSClient/Trash/NCTrash.swift

@@ -43,7 +43,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
     internal var selectOcId: [String] = []
 
     var datasource: [tableTrash] = []
-    var layoutForView: NCGlobal.layoutForViewType?
+    var layoutForView: NCDBLayoutForView?
     var listLayout: NCListLayout!
     var gridLayout: NCGridLayout!
 
@@ -88,7 +88,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
         navigationController?.setFileAppreance()
         navigationItem.title = titleCurrentFolder
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "", sort: "date", ascending: false, titleButtonHeader: "_sorted_by_date_more_recent_")
+        layoutForView =  NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "")
         gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
 
         if layoutForView?.layout == NCGlobal.shared.layoutList {
@@ -130,7 +130,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
 
             // list layout
             layoutForView?.layout = NCGlobal.shared.layoutList
-            NCUtility.shared.setLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
 
             self.collectionView.reloadData()
             self.collectionView.collectionViewLayout.invalidateLayout()
@@ -140,7 +140,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
 
             // grid layout
             layoutForView?.layout = NCGlobal.shared.layoutGrid
-            NCUtility.shared.setLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
+            NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
 
             self.collectionView.reloadData()
             self.collectionView.collectionViewLayout.invalidateLayout()
@@ -150,7 +150,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
 
     func tapButtonOrder(_ sender: Any) {
         let sortMenu = NCSortMenu()
-        sortMenu.toggleMenu(viewController: self, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true)
+        sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true)
     }
 
     func tapButtonMore(_ sender: Any) {
@@ -232,7 +232,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
 
     @objc func reloadDataSource(forced: Bool = true) {
 
-        layoutForView = NCUtility.shared.getLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "")
+        layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "")
         datasource.removeAll()
         guard let trashPath = self.getTrashPath(), let tashItems = NCManageDatabase.shared.getTrash(filePath: trashPath, sort: layoutForView?.sort, ascending: layoutForView?.ascending, account: appDelegate.account) else {
             return

+ 0 - 51
iOSClient/Utility/NCUtility.swift

@@ -38,57 +38,6 @@ class NCUtility: NSObject {
         return instance
     }()
 
-    func setLayoutForView(key: String, serverUrl: String, layoutForView: NCGlobal.layoutForViewType) {
-
-        let string =  layoutForView.layout + "|" + layoutForView.sort + "|" + "\(layoutForView.ascending)" + "|" + layoutForView.groupBy + "|" + "\(layoutForView.directoryOnTop)" + "|" + layoutForView.titleButtonHeader + "|" + "\(layoutForView.itemForLine)"
-        var keyStore = key
-
-        if serverUrl != "" {
-            keyStore = serverUrl
-        }
-
-        UICKeyChainStore.setString(string, forKey: keyStore, service: NCGlobal.shared.serviceShareKeyChain)
-    }
-
-    func setLayoutForView(key: String, serverUrl: String, layout: String?) {
-
-        var layoutForView: NCGlobal.layoutForViewType = NCUtility.shared.getLayoutForView(key: key, serverUrl: serverUrl)
-
-        if let layout = layout {
-            layoutForView.layout = layout
-            setLayoutForView(key: key, serverUrl: serverUrl, layoutForView: layoutForView)
-        }
-    }
-
-    func getLayoutForView(key: String, serverUrl: String, sort: String = "fileName", ascending: Bool = true, titleButtonHeader: String = "_sorted_by_name_a_z_") -> (NCGlobal.layoutForViewType) {
-
-        var keyStore = key
-        var layoutForView: NCGlobal.layoutForViewType = NCGlobal.layoutForViewType(layout: NCGlobal.shared.layoutList, sort: sort, ascending: ascending, groupBy: "none", directoryOnTop: true, titleButtonHeader: titleButtonHeader, itemForLine: 3)
-
-        if serverUrl != "" {
-            keyStore = serverUrl
-        }
-
-        guard let string = UICKeyChainStore.string(forKey: keyStore, service: NCGlobal.shared.serviceShareKeyChain) else {
-            setLayoutForView(key: key, serverUrl: serverUrl, layoutForView: layoutForView)
-            return layoutForView
-        }
-
-        let array = string.components(separatedBy: "|")
-        if array.count >= 7 {
-            // version 1
-            layoutForView.layout = array[0]
-            layoutForView.sort = array[1]
-            layoutForView.ascending = NSString(string: array[2]).boolValue
-            layoutForView.groupBy = array[3]
-            layoutForView.directoryOnTop = NSString(string: array[4]).boolValue
-            layoutForView.titleButtonHeader = array[5]
-            layoutForView.itemForLine = Int(NSString(string: array[6]).intValue)
-        }
-
-        return layoutForView
-    }
-
     func convertSVGtoPNGWriteToUserData(svgUrlString: String, fileName: String?, width: CGFloat?, rewrite: Bool, account: String, closure: @escaping (String?) -> Void) {
 
         var fileNamePNG = ""