Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended files (Test) API #3256

Merged
merged 13 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Brand/Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ import Foundation
// Database Realm
//
let databaseName = "nextcloud.realm"
let databaseSchemaVersion: UInt64 = 368
let databaseSchemaVersion: UInt64 = 369
20 changes: 18 additions & 2 deletions Nextcloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,13 @@
F7C30DFE291BD0B80017149B /* NCNetworkingE2EEDelete.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DFC291BD0B80017149B /* NCNetworkingE2EEDelete.swift */; };
F7C30E00291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DFF291BD2610017149B /* NCNetworkingE2EERename.swift */; };
F7C30E01291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C30DFF291BD2610017149B /* NCNetworkingE2EERename.swift */; };
F7C687E92D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687EA2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687EB2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687EC2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687ED2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687EE2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C687EF2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */; };
F7C7B25028B8AD4500E7115D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
F7C7B25128B8B0C400E7115D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C7B488245EBA4100D93E60 /* NCViewerQuickLook.swift */; };
Expand Down Expand Up @@ -1655,6 +1662,7 @@
F7C30DF9291BCF790017149B /* NCNetworkingE2EECreateFolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EECreateFolder.swift; sourceTree = "<group>"; };
F7C30DFC291BD0B80017149B /* NCNetworkingE2EEDelete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EEDelete.swift; sourceTree = "<group>"; };
F7C30DFF291BD2610017149B /* NCNetworkingE2EERename.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EERename.swift; sourceTree = "<group>"; };
F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+RecommendedFiles.swift"; sourceTree = "<group>"; };
F7C7B488245EBA4100D93E60 /* NCViewerQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerQuickLook.swift; sourceTree = "<group>"; };
F7C9555221F0C4CA0024296E /* NCActivity.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCActivity.storyboard; sourceTree = "<group>"; };
F7C9555421F0C5470024296E /* NCActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivity.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2745,7 +2753,6 @@
F7BAAD951ED5A63D00B7EAD4 /* Data */ = {
isa = PBXGroup;
children = (
AA3494FD2CE65EA9005CC075 /* NCManageDatabase+DownloadLimit.swift */,
F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */,
AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */,
AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */,
Expand All @@ -2756,6 +2763,7 @@
F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */,
F73EF7AE2B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift */,
F78A10BE29322E8A008499B8 /* NCManageDatabase+Directory.swift */,
AA3494FD2CE65EA9005CC075 /* NCManageDatabase+DownloadLimit.swift */,
F72FD3B4297ED49A00075D28 /* NCManageDatabase+E2EE.swift */,
F73EF7B62B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift */,
F73EF7BE2B02250B0087E6E9 /* NCManageDatabase+GPS.swift */,
Expand All @@ -2765,6 +2773,7 @@
AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */,
F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */,
F73EF7C62B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift */,
F7C687E82D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift */,
F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */,
F749B649297B0CBB00087535 /* NCManageDatabase+Share.swift */,
F73EF7CE2B0225BA0087E6E9 /* NCManageDatabase+Tag.swift */,
Expand Down Expand Up @@ -3909,6 +3918,7 @@
F757CC8829E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */,
F79B646326CA661600838ACA /* UIControl+Extension.swift in Sources */,
F73EF7B52B0224350087E6E9 /* NCManageDatabase+DirectEditing.swift in Sources */,
F7C687EF2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F77DD6AE2C5CC093009448FB /* NCSession.swift in Sources */,
F78A10C429322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
F7B769AE2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */,
Expand Down Expand Up @@ -3974,6 +3984,7 @@
F7490E8029882C76009DCE94 /* NCManageDatabase+Avatar.swift in Sources */,
F343A4B82A1E084300DDA874 /* PHAsset+Extension.swift in Sources */,
F78E2D6A29AF02DB0024D4F3 /* Database.swift in Sources */,
F7C687EE2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F7490E7429882BCC009DCE94 /* NCManageDatabase.swift in Sources */,
F7490E6E29882B56009DCE94 /* NCBrand.swift in Sources */,
F73EF7CC2B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */,
Expand Down Expand Up @@ -4122,6 +4133,7 @@
F7817D0129802D5F00FFBC65 /* NCViewCertificateDetails.swift in Sources */,
F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
F7C30DF7291BC0D30017149B /* NCNetworkingE2EEUpload.swift in Sources */,
F7C687EC2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F33918C72C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */,
F78A10C229322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
F713FBE72C31646500F10760 /* NCNetworking+AsyncAwait.swift in Sources */,
Expand Down Expand Up @@ -4213,6 +4225,7 @@
F72429382AFE39A80040AEF3 /* NCLivePhoto.swift in Sources */,
F77ED59528C9CEA400E24ED0 /* ToolbarWidgetView.swift in Sources */,
F78302FB28B4C3EE00B84583 /* NCManageDatabase+Video.swift in Sources */,
F7C687EA2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */,
F33918C52C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */,
F7327E292B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */,
Expand Down Expand Up @@ -4255,6 +4268,7 @@
F711A4E02AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */,
F76D364828A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
F7327E242B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */,
F7C687ED2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F7817D0229802D7700FFBC65 /* NCViewCertificateDetails.swift in Sources */,
F7434B3820E2400600417916 /* NCBrand.swift in Sources */,
F7327E332B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */,
Expand Down Expand Up @@ -4361,6 +4375,7 @@
F76882282C0DD1E7001CF441 /* NCEndToEndInitialize.swift in Sources */,
F702F2CD25EE5B4F008F8E80 /* AppDelegate.swift in Sources */,
F769454022E9F077000A798A /* NCSharePaging.swift in Sources */,
F7C687E92D22BD46004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F74D50352C9855A000BBBF4C /* NCCollectionViewCommon+CollectionViewDataSourcePrefetching.swift in Sources */,
F7802B322BD5584F00D74270 /* NCMedia+DragDrop.swift in Sources */,
F7EE66AD2A20B226009AE765 /* UILabel+Extension.swift in Sources */,
Expand Down Expand Up @@ -4653,6 +4668,7 @@
F749B64C297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */,
F7A8D73F28F181EF008BBE1C /* NCGlobal.swift in Sources */,
F74B6D972A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */,
F7C687EB2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */,
F749B653297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */,
F359D8692A7D03420023F405 /* NCUtility+Exif.swift in Sources */,
F763D29F2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */,
Expand Down Expand Up @@ -5808,7 +5824,7 @@
repositoryURL = "https://github.com/realm/realm-swift";
requirement = {
kind = exactVersion;
version = 10.54.1;
version = 20.0.1;
};
};
F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */ = {
Expand Down
8 changes: 8 additions & 0 deletions iOSClient/Data/NCManageDatabase+Capabilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ extension NCManageDatabase {
let groupfolders: GroupFolders?
let securityguard: SecurityGuard?
let assistant: Assistant?
let recommendations: Recommendations?

enum CodingKeys: String, CodingKey {
case downloadLimit = "downloadlimit"
Expand All @@ -112,6 +113,7 @@ extension NCManageDatabase {
case external, groupfolders
case securityguard = "security_guard"
case assistant
case recommendations
}

struct DownloadLimit: Codable {
Expand Down Expand Up @@ -287,6 +289,10 @@ extension NCManageDatabase {
let enabled: Bool?
let version: String?
}

struct Recommendations: Codable {
let enabled: Bool?
}
}
}
}
Expand Down Expand Up @@ -392,6 +398,8 @@ extension NCManageDatabase {
capabilities.capabilityForbiddenFileNameCharacters = data.capabilities.files?.forbiddenFileNameCharacters ?? []
capabilities.capabilityForbiddenFileNameExtensions = data.capabilities.files?.forbiddenFileNameExtensions ?? []

capabilities.capabilityRecommendations = data.capabilities.recommendations?.enabled ?? false

NCCapabilities.shared.appendCapabilities(account: account, capabilities: capabilities)

return capabilities
Expand Down
155 changes: 155 additions & 0 deletions iOSClient/Data/NCManageDatabase+RecommendedFiles.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// SPDX-FileCopyrightText: Nextcloud GmbH
// SPDX-FileCopyrightText: 2024 Marino Faggiana
// SPDX-License-Identifier: GPL-3.0-or-later

import Foundation
import RealmSwift
import NextcloudKit

class tableRecommendedFiles: Object {
override func isEqual(_ object: Any?) -> Bool {
if let object = object as? tableRecommendedFiles,
self.timestamp == object.timestamp,
self.name == object.name,
self.directory == object.directory,
self.extensionType == object.extensionType,
self.mimeType == object.mimeType,
self.hasPreview == object.hasPreview,
self.reason == object.reason {
return true
} else {
return false
}
}

@Persisted var account = ""
@Persisted var id = ""
@Persisted(primaryKey: true) var primaryKey = ""
@Persisted var timestamp: Date?
@Persisted var name: String = ""
@Persisted var directory: String = ""
@Persisted var extensionType: String = ""
@Persisted var mimeType: String = ""
@Persisted var hasPreview: Bool = false
@Persisted var reason: String = ""

convenience init(account: String, id: String, timestamp: Date?, name: String, directory: String, extensionType: String, mimeType: String, hasPreview: Bool, reason: String) {
self.init()

self.account = account
self.id = id
self.primaryKey = account + id
self.timestamp = timestamp
self.name = name
self.directory = directory
self.extensionType = extensionType
self.mimeType = mimeType
self.hasPreview = hasPreview
self.reason = reason
}
}

extension NCManageDatabase {
func addRecommendedFiles(account: String, recommendations: [NKRecommendation]) {
do {
let realm = try Realm()

try realm.write {
// Removed all objct for account
let results = realm.objects(tableRecommendedFiles.self).filter("account == %@", account)

realm.delete(results)

// Added the new recommendations
for recommendation in recommendations {
let recommendedFile = tableRecommendedFiles(account: account, id: recommendation.id, timestamp: recommendation.timestamp, name: recommendation.name, directory: recommendation.directory, extensionType: recommendation.extensionType, mimeType: recommendation.mimeType, hasPreview: recommendation.hasPreview, reason: recommendation.reason)
realm.add(recommendedFile)
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}

func getResultsRecommendedFiles(account: String) -> Results<tableRecommendedFiles>? {
do {
let realm = try Realm()
let results = realm.objects(tableRecommendedFiles.self).filter("account == %@", account)

return results
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}

return nil
}

func getNKRecommendation(account: String) -> [NKRecommendation] {
var recommendations: [NKRecommendation] = []

do {
let realm = try Realm()
let results = realm.objects(tableRecommendedFiles.self).filter("account == %@", account)

for result in results {
let recommendation = NKRecommendation(id: result.id, timestamp: result.timestamp, name: result.name, directory: result.directory, extensionType: result.extensionType, mimeType: result.mimeType, hasPreview: result.hasPreview, reason: result.reason)
recommendations.append(recommendation)

}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}

return recommendations
}

func deleteRecommendedFiles(account: String, recommendations: [NKRecommendation]) {
do {
let realm = try Realm()

try realm.write {
for recommendation in recommendations {
let primaryKey = account + recommendation.id
let results = realm.objects(tableRecommendedFiles.self).filter("primaryKey == %@", primaryKey)

realm.delete(results)
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}

func compareRecommendations(account: String, newObjects: [NKRecommendation]) -> (changed: [NKRecommendation], added: [NKRecommendation], deleted: [NKRecommendation]) {
var changed = [NKRecommendation]()
var added = [NKRecommendation]()
var deleted = [NKRecommendation]()

let existingObjects = getNKRecommendation(account: account)

let existingDictionary = Dictionary(uniqueKeysWithValues: existingObjects.map { (account + $0.id, $0) })
let newDictionary = Dictionary(uniqueKeysWithValues: newObjects.map { (account + $0.id, $0) })

// Verify objects changed or deleted
for (primaryKey, existingObject) in existingDictionary {
if let newObject = newDictionary[primaryKey] {
// If exists, verify if is changed
if !existingObject.isEqual(newObject) {
changed.append(newObject)
}
} else {
// if do not exists, it's deleted
deleted.append(existingObject)
}
}

// verify new objects
for (primaryKey, newObject) in newDictionary {
if existingDictionary[primaryKey] == nil {
added.append(newObject)
}
}

return (changed, added, deleted)
}
}
5 changes: 3 additions & 2 deletions iOSClient/Data/NCManageDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ class NCManageDatabase: NSObject {
tableDashboardWidget.self,
tableDashboardWidgetButton.self,
NCDBLayoutForView.self,
TableSecurityGuardDiagnostics.self,
tableDownloadLimit.self]
TableSecurityGuardDiagnostics.self]

// Disable file protection for directory DB
// https://docs.mongodb.com/realm/sdk/ios/examples/configure-and-open-a-realm/#std-label-ios-open-a-local-realm
Expand Down Expand Up @@ -198,6 +197,8 @@ class NCManageDatabase: NSObject {
self.clearTable(tableTrash.self, account: account)
self.clearTable(tableUserStatus.self, account: account)
self.clearTable(tableVideo.self, account: account)
self.clearTable(tableDownloadLimit.self, account: account)
self.clearTable(tableRecommendedFiles.self, account: account)
}

func clearTablesE2EE(account: String?) {
Expand Down
6 changes: 6 additions & 0 deletions iOSClient/Files/NCFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ class NCFiles: NCCollectionViewCommon {
}

DispatchQueue.global().async {
if self.isRoot,
NCCapabilities.shared.getCapabilities(account: self.session.account).capabilityRecommendations {
NextcloudKit.shared.getRecommendedFiles(account: self.session.account) { account, recommendations, responseData, error in

}
}
self.networkReadFolder { metadatas, isChanged, error in
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
Expand Down
15 changes: 15 additions & 0 deletions iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,22 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
var lastNumberOfColumns: Int = 0

var session: NCSession.Session {
#if DEBUG
if Thread.isMainThread {
return NCSession.shared.getSession(controller: tabBarController)
} else {
let semaphore = DispatchSemaphore(value: 0)
var session: NCSession.Session!
DispatchQueue.main.async {
session = NCSession.shared.getSession(controller: self.tabBarController)
semaphore.signal()
}
semaphore.wait()
return session
}
#else
NCSession.shared.getSession(controller: tabBarController)
#endif
}

var isLayoutPhoto: Bool {
Expand Down
1 change: 1 addition & 0 deletions iOSClient/NCCapabilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public class NCCapabilities: NSObject {
var capabilityForbiddenFileNameBasenames: [String] = []
var capabilityForbiddenFileNameCharacters: [String] = []
var capabilityForbiddenFileNameExtensions: [String] = []
var capabilityRecommendations: Bool = false
}

private var capabilities = ThreadSafeDictionary<String, Capabilities>()
Expand Down
Loading