зеркало из https://github.com/nextcloud/ios.git
Version 5.5.2 (#3005)
This commit is contained in:
Родитель
ca03c1d3a7
Коммит
9e4e7af280
|
@ -58,6 +58,14 @@ class fileProviderData: NSObject {
|
|||
case workingSet
|
||||
}
|
||||
|
||||
struct UploadMetadata {
|
||||
var id: String
|
||||
var metadata: tableMetadata
|
||||
var task: URLSessionUploadTask?
|
||||
}
|
||||
|
||||
var uploadMetadata: [UploadMetadata] = []
|
||||
|
||||
// MARK: -
|
||||
|
||||
func setupAccount(domain: NSFileProviderDomain?, providerExtension: NSFileProviderExtension) -> tableAccount? {
|
||||
|
@ -140,4 +148,17 @@ class fileProviderData: NSObject {
|
|||
fileProviderManager.signalEnumerator(for: .workingSet) { _ in }
|
||||
return item
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
func appendUploadMetadata(id: String, metadata: tableMetadata, task: URLSessionUploadTask?) {
|
||||
if let index = uploadMetadata.firstIndex(where: { $0.id == id }) {
|
||||
uploadMetadata.remove(at: index)
|
||||
}
|
||||
uploadMetadata.append(UploadMetadata(id: id, metadata: metadata, task: task))
|
||||
}
|
||||
|
||||
func getUploadMetadata(id: String) -> UploadMetadata? {
|
||||
return uploadMetadata.filter({ $0.id == id }).first
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,37 +36,45 @@ extension FileProviderExtension: NCNetworkingDelegate {
|
|||
func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: Date?, size: Int64, task: URLSessionTask, error: NKError) {
|
||||
guard let url = task.currentRequest?.url,
|
||||
let metadata = NCManageDatabase.shared.getMetadata(from: url, sessionTaskIdentifier: task.taskIdentifier) else { return }
|
||||
if error == .success, let ocId {
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
|
||||
metadata.fileName = fileName
|
||||
metadata.serverUrl = serverUrl
|
||||
metadata.uploadDate = (date as? NSDate) ?? NSDate()
|
||||
metadata.etag = etag ?? ""
|
||||
metadata.ocId = ocId
|
||||
metadata.size = size
|
||||
if let fileId = NCUtility().ocIdToFileId(ocId: ocId) {
|
||||
metadata.fileId = fileId
|
||||
}
|
||||
metadata.session = ""
|
||||
metadata.sessionError = ""
|
||||
metadata.status = NCGlobal.shared.metadataStatusNormal
|
||||
|
||||
NCManageDatabase.shared.addMetadata(metadata)
|
||||
NCManageDatabase.shared.addLocalFile(metadata: metadata)
|
||||
/// NEW File
|
||||
if ocId != metadata.ocIdTemp {
|
||||
let atPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTemp)
|
||||
let toPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocId)
|
||||
utilityFileSystem.copyFile(atPath: atPath, toPath: toPath)
|
||||
DispatchQueue.global(qos: .userInteractive).async {
|
||||
if error == .success, let ocId {
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
|
||||
metadata.fileName = fileName
|
||||
metadata.serverUrl = serverUrl
|
||||
metadata.uploadDate = (date as? NSDate) ?? NSDate()
|
||||
metadata.etag = etag ?? ""
|
||||
metadata.ocId = ocId
|
||||
metadata.size = size
|
||||
if let fileId = NCUtility().ocIdToFileId(ocId: ocId) {
|
||||
metadata.fileId = fileId
|
||||
}
|
||||
|
||||
metadata.sceneIdentifier = nil
|
||||
metadata.session = ""
|
||||
metadata.sessionError = ""
|
||||
metadata.sessionSelector = ""
|
||||
metadata.sessionDate = nil
|
||||
metadata.sessionTaskIdentifier = 0
|
||||
metadata.status = NCGlobal.shared.metadataStatusNormal
|
||||
|
||||
NCManageDatabase.shared.addMetadata(metadata)
|
||||
NCManageDatabase.shared.addLocalFile(metadata: metadata)
|
||||
/// NEW File
|
||||
if !metadata.ocIdTemp.isEmpty, ocId != metadata.ocIdTemp {
|
||||
let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTemp)
|
||||
let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocId)
|
||||
self.utilityFileSystem.copyFile(atPath: atPath, toPath: toPath)
|
||||
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp))
|
||||
}
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update)
|
||||
} else {
|
||||
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp))
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
|
||||
}
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update)
|
||||
} else {
|
||||
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp))
|
||||
/// SIGNAL
|
||||
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,7 +166,13 @@ class FileProviderExtension: NSFileProviderExtension {
|
|||
override func startProvidingItem(at url: URL, completionHandler: @escaping ((_ error: Error?) -> Void)) {
|
||||
let pathComponents = url.pathComponents
|
||||
let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
|
||||
guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else {
|
||||
var metadata: tableMetadata?
|
||||
if let result = fileProviderData.shared.getUploadMetadata(id: itemIdentifier.rawValue) {
|
||||
metadata = result.metadata
|
||||
} else {
|
||||
metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue)
|
||||
}
|
||||
guard let metadata else {
|
||||
return completionHandler(NSFileProviderError(.noSuchItem))
|
||||
}
|
||||
if metadata.session == NCNetworking.shared.sessionUploadBackgroundExtension {
|
||||
|
@ -200,6 +206,12 @@ class FileProviderExtension: NSFileProviderExtension {
|
|||
return completionHandler(NSFileProviderError(.noSuchItem))
|
||||
}
|
||||
if error == .success {
|
||||
metadata.sceneIdentifier = nil
|
||||
metadata.session = ""
|
||||
metadata.sessionError = ""
|
||||
metadata.sessionSelector = ""
|
||||
metadata.sessionDate = nil
|
||||
metadata.sessionTaskIdentifier = 0
|
||||
metadata.status = NCGlobal.shared.metadataStatusNormal
|
||||
metadata.date = (date as? NSDate) ?? NSDate()
|
||||
metadata.etag = etag ?? ""
|
||||
|
@ -226,16 +238,23 @@ class FileProviderExtension: NSFileProviderExtension {
|
|||
assert(pathComponents.count > 2)
|
||||
let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
|
||||
let fileName = pathComponents[pathComponents.count - 1]
|
||||
guard let metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue) else { return }
|
||||
var metadata: tableMetadata?
|
||||
if let result = fileProviderData.shared.getUploadMetadata(id: itemIdentifier.rawValue) {
|
||||
metadata = result.metadata
|
||||
} else {
|
||||
metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue)
|
||||
}
|
||||
guard let metadata else {
|
||||
return
|
||||
}
|
||||
let serverUrlFileName = metadata.serverUrl + "/" + fileName
|
||||
let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName)
|
||||
utilityFileSystem.copyFile(atPath: url.path, toPath: fileNameLocalPath)
|
||||
|
||||
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
|
||||
session: NCNetworking.shared.sessionUploadBackgroundExtension,
|
||||
sessionError: "",
|
||||
selector: "",
|
||||
status: NCGlobal.shared.metadataStatusUploading)
|
||||
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) {
|
||||
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: url.path, dateCreationFile: nil, dateModificationFile: nil, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) {
|
||||
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
|
||||
status: NCGlobal.shared.metadataStatusUploading,
|
||||
taskIdentifier: task.taskIdentifier)
|
||||
|
@ -304,6 +323,7 @@ class FileProviderExtension: NSFileProviderExtension {
|
|||
status: NCGlobal.shared.metadataStatusUploading,
|
||||
taskIdentifier: task.taskIdentifier)
|
||||
fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(ocIdTemp)) { _ in }
|
||||
fileProviderData.shared.appendUploadMetadata(id: ocIdTemp, metadata: metadata, task: task)
|
||||
}
|
||||
|
||||
let item = FileProviderItem(metadata: tableMetadata.init(value: metadata), parentItemIdentifier: parentItemIdentifier)
|
||||
|
|
|
@ -75,12 +75,12 @@ class fileProviderUtility: NSObject {
|
|||
do {
|
||||
try fileManager.removeItem(atPath: toPath)
|
||||
} catch let error {
|
||||
print("error: \(error)")
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
||||
do {
|
||||
try fileManager.copyItem(atPath: atPath, toPath: toPath)
|
||||
} catch let error {
|
||||
print("error: \(error)")
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,12 +90,28 @@ class fileProviderUtility: NSObject {
|
|||
do {
|
||||
try fileManager.removeItem(atPath: toPath)
|
||||
} catch let error {
|
||||
print("error: \(error)")
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
||||
do {
|
||||
try fileManager.moveItem(atPath: atPath, toPath: toPath)
|
||||
} catch let error {
|
||||
print("error: \(error)")
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
func getFileSize(from url: URL) -> Int64? {
|
||||
do {
|
||||
let attributes = try fileManager.attributesOfItem(atPath: url.path)
|
||||
|
||||
if let fileSize = attributes[FileAttributeKey.size] as? Int64 {
|
||||
return fileSize
|
||||
} else {
|
||||
print("Failed to retrieve file size.")
|
||||
return nil
|
||||
}
|
||||
} catch {
|
||||
print("Error: \(error.localizedDescription)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5414,7 +5414,7 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = NKUJUXUJ3B;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
|
@ -5441,7 +5441,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.5.0;
|
||||
MARKETING_VERSION = 5.5.2;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-v";
|
||||
OTHER_LDFLAGS = "";
|
||||
|
@ -5480,7 +5480,7 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEVELOPMENT_TEAM = NKUJUXUJ3B;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
|
@ -5504,7 +5504,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.5.0;
|
||||
MARKETING_VERSION = 5.5.2;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-v";
|
||||
OTHER_LDFLAGS = "";
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F771E3CF20E2392D00AFB62D"
|
||||
BuildableName = "File Provider Extension.appex"
|
||||
BlueprintName = "File Provider Extension"
|
||||
BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
|
||||
BuildableName = "Nextcloud.app"
|
||||
BlueprintName = "Nextcloud"
|
||||
ReferencedContainer = "container:Nextcloud.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
|
@ -29,9 +29,9 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
|
||||
BuildableName = "Nextcloud.app"
|
||||
BlueprintName = "Nextcloud"
|
||||
BlueprintIdentifier = "F771E3CF20E2392D00AFB62D"
|
||||
BuildableName = "File Provider Extension.appex"
|
||||
BlueprintName = "File Provider Extension"
|
||||
ReferencedContainer = "container:Nextcloud.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
|
|
|
@ -140,6 +140,13 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling {
|
|||
return (nil, "", "")
|
||||
}
|
||||
|
||||
/// Is the user an Admin
|
||||
func isAdminGroup() -> Bool {
|
||||
guard let activeAccount else { return false }
|
||||
let groups = NCManageDatabase.shared.getAccountGroups(account: activeAccount.account)
|
||||
return groups.contains(NCGlobal.shared.groupAdmin)
|
||||
}
|
||||
|
||||
/// Function to know the height of "account" data
|
||||
func getTableViewHeight() -> CGFloat {
|
||||
guard let activeAccount else { return 0 }
|
||||
|
|
|
@ -181,52 +181,54 @@ struct NCAccountSettingsView: View {
|
|||
}
|
||||
///
|
||||
/// Certificate server
|
||||
Button(action: {
|
||||
showServerCertificate.toggle()
|
||||
}, label: {
|
||||
HStack {
|
||||
Image(systemName: "lock")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_certificate_details_", comment: ""))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.textColor))
|
||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))
|
||||
if model.isAdminGroup() {
|
||||
Button(action: {
|
||||
showServerCertificate.toggle()
|
||||
}, label: {
|
||||
HStack {
|
||||
Image(systemName: "lock")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_certificate_details_", comment: ""))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.textColor))
|
||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))
|
||||
}
|
||||
.font(.system(size: 14))
|
||||
})
|
||||
.sheet(isPresented: $showServerCertificate) {
|
||||
if let url = URL(string: model.activeAccount?.urlBase), let host = url.host {
|
||||
certificateDetailsView(host: host, title: NSLocalizedString("_certificate_view_", comment: ""))
|
||||
}
|
||||
}
|
||||
.font(.system(size: 14))
|
||||
})
|
||||
.sheet(isPresented: $showServerCertificate) {
|
||||
if let url = URL(string: model.activeAccount?.urlBase), let host = url.host {
|
||||
certificateDetailsView(host: host, title: NSLocalizedString("_certificate_view_", comment: ""))
|
||||
}
|
||||
}
|
||||
///
|
||||
/// Certificate push
|
||||
Button(action: {
|
||||
showPushCertificate.toggle()
|
||||
}, label: {
|
||||
HStack {
|
||||
Image(systemName: "lock")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_certificate_pn_details_", comment: ""))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.textColor))
|
||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))
|
||||
}
|
||||
.font(.system(size: 14))
|
||||
})
|
||||
.sheet(isPresented: $showPushCertificate) {
|
||||
if let url = URL(string: NCBrandOptions.shared.pushNotificationServerProxy), let host = url.host {
|
||||
certificateDetailsView(host: host, title: NSLocalizedString("_certificate_pn_view_", comment: ""))
|
||||
///
|
||||
/// Certificate push
|
||||
Button(action: {
|
||||
showPushCertificate.toggle()
|
||||
}, label: {
|
||||
HStack {
|
||||
Image(systemName: "lock")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_certificate_pn_details_", comment: ""))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(Color(NCBrandColor.shared.textColor))
|
||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))
|
||||
}
|
||||
.font(.system(size: 14))
|
||||
})
|
||||
.sheet(isPresented: $showPushCertificate) {
|
||||
if let url = URL(string: NCBrandOptions.shared.pushNotificationServerProxy), let host = url.host {
|
||||
certificateDetailsView(host: host, title: NSLocalizedString("_certificate_pn_view_", comment: ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -458,7 +458,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||
let account: String = "\(user) \(urlBase)"
|
||||
|
||||
NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
|
||||
NextcloudKit.shared.getUserProfile { _, userProfile, _, error in
|
||||
NextcloudKit.shared.getUserProfile { account, userProfile, _, error in
|
||||
if error == .success, let userProfile {
|
||||
NCManageDatabase.shared.deleteAccount(account)
|
||||
NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password)
|
||||
|
|
|
@ -407,4 +407,16 @@ extension NCManageDatabase {
|
|||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func getAccountGroups(account: String) -> [String] {
|
||||
do {
|
||||
let realm = try Realm()
|
||||
if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
|
||||
return result.groups.components(separatedBy: ",")
|
||||
}
|
||||
} catch let error as NSError {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,17 +40,47 @@ class NCManageDatabase: NSObject {
|
|||
let utilityFileSystem = NCUtilityFileSystem()
|
||||
|
||||
override init() {
|
||||
let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
|
||||
let databaseFileUrlPath = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName)
|
||||
|
||||
if let databaseFilePath = databaseFileUrlPath?.path {
|
||||
if FileManager.default.fileExists(atPath: databaseFilePath) {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] DATABASE FOUND in " + databaseFilePath)
|
||||
} else {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] DATABASE NOT FOUND in " + databaseFilePath)
|
||||
func migrationSchema(_ migration: Migration, _ oldSchemaVersion: UInt64) {
|
||||
if oldSchemaVersion < 354 {
|
||||
migration.deleteData(forType: NCDBLayoutForView.className())
|
||||
}
|
||||
}
|
||||
|
||||
func compactDB(_ totalBytes: Int, _ usedBytes: Int) -> Bool {
|
||||
// totalBytes refers to the size of the file on disk in bytes (data + free space)
|
||||
// usedBytes refers to the number of bytes used by data in the file
|
||||
// Compact if the file is over 100MB in size and less than 50% 'used'
|
||||
let oneHundredMB = 100 * 1024 * 1024
|
||||
return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
|
||||
}
|
||||
var realm: Realm?
|
||||
let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
|
||||
let databaseFileUrlPath = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName)
|
||||
let bundleUrl: URL = Bundle.main.bundleURL
|
||||
let bundlePathExtension: String = bundleUrl.pathExtension
|
||||
let bundleFileName: String = (bundleUrl.path as NSString).lastPathComponent
|
||||
let isAppex: Bool = bundlePathExtension == "appex"
|
||||
var objectTypesAppex = [tableMetadata.self,
|
||||
tableLocalFile.self,
|
||||
tableDirectory.self,
|
||||
tableTag.self,
|
||||
tableAccount.self,
|
||||
tableCapabilities.self,
|
||||
tablePhotoLibrary.self,
|
||||
tableE2eEncryption.self,
|
||||
tableE2eEncryptionLock.self,
|
||||
tableE2eMetadata12.self,
|
||||
tableE2eMetadata.self,
|
||||
tableE2eUsers.self,
|
||||
tableE2eCounter.self,
|
||||
tableShare.self,
|
||||
tableChunk.self,
|
||||
tableAvatar.self,
|
||||
tableDashboardWidget.self,
|
||||
tableDashboardWidgetButton.self,
|
||||
NCDBLayoutForView.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
|
||||
if let folderPathURL = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud) {
|
||||
|
@ -62,61 +92,49 @@ class NCManageDatabase: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
do {
|
||||
_ = try Realm(configuration: Realm.Configuration(
|
||||
fileURL: databaseFileUrlPath,
|
||||
schemaVersion: databaseSchemaVersion,
|
||||
migrationBlock: { migration, oldSchemaVersion in
|
||||
if oldSchemaVersion < 354 {
|
||||
migration.deleteData(forType: NCDBLayoutForView.className())
|
||||
}
|
||||
}, shouldCompactOnLaunch: { totalBytes, usedBytes in
|
||||
// totalBytes refers to the size of the file on disk in bytes (data + free space)
|
||||
// usedBytes refers to the number of bytes used by data in the file
|
||||
// Compact if the file is over 100MB in size and less than 50% 'used'
|
||||
let oneHundredMB = 100 * 1024 * 1024
|
||||
return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
|
||||
if isAppex {
|
||||
if bundleFileName == "File Provider Extension.appex" {
|
||||
objectTypesAppex = [tableMetadata.self,
|
||||
tableLocalFile.self,
|
||||
tableDirectory.self,
|
||||
tableTag.self,
|
||||
tableAccount.self,
|
||||
tableCapabilities.self]
|
||||
}
|
||||
do {
|
||||
Realm.Configuration.defaultConfiguration =
|
||||
Realm.Configuration(fileURL: databaseFileUrlPath,
|
||||
schemaVersion: databaseSchemaVersion,
|
||||
migrationBlock: { migration, oldSchemaVersion in
|
||||
migrationSchema(migration, oldSchemaVersion)
|
||||
}, shouldCompactOnLaunch: { totalBytes, usedBytes in
|
||||
compactDB(totalBytes, usedBytes)
|
||||
}, objectTypes: objectTypesAppex)
|
||||
realm = try Realm()
|
||||
if let realm, let url = realm.configuration.fileURL {
|
||||
print("Realm is located at: \(url)")
|
||||
}
|
||||
))
|
||||
} catch let error {
|
||||
if let databaseFileUrlPath = databaseFileUrlPath {
|
||||
do {
|
||||
#if !EXTENSION
|
||||
let nkError = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: error.localizedDescription)
|
||||
NCContentPresenter().showError(error: nkError, priority: .max)
|
||||
#endif
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)")
|
||||
try FileManager.default.removeItem(at: databaseFileUrlPath)
|
||||
} catch {}
|
||||
} catch let error {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
Realm.Configuration.defaultConfiguration = Realm.Configuration(
|
||||
fileURL: dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName),
|
||||
schemaVersion: databaseSchemaVersion
|
||||
)
|
||||
|
||||
// Verify Database, if corrupt remove it
|
||||
do {
|
||||
_ = try Realm()
|
||||
} catch let error {
|
||||
if let databaseFileUrlPath = databaseFileUrlPath {
|
||||
do {
|
||||
#if !EXTENSION
|
||||
let nkError = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: error.localizedDescription)
|
||||
NCContentPresenter().showError(error: nkError, priority: .max)
|
||||
#endif
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)")
|
||||
try FileManager.default.removeItem(at: databaseFileUrlPath)
|
||||
} catch { }
|
||||
} else {
|
||||
do {
|
||||
Realm.Configuration.defaultConfiguration =
|
||||
Realm.Configuration(fileURL: databaseFileUrlPath,
|
||||
schemaVersion: databaseSchemaVersion,
|
||||
migrationBlock: { migration, oldSchemaVersion in
|
||||
migrationSchema(migration, oldSchemaVersion)
|
||||
}, shouldCompactOnLaunch: { totalBytes, usedBytes in
|
||||
compactDB(totalBytes, usedBytes)
|
||||
})
|
||||
realm = try Realm()
|
||||
if let realm, let url = realm.configuration.fileURL {
|
||||
print("Realm is located at: \(url)")
|
||||
}
|
||||
} catch let error {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] DATABASE ERROR: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
_ = try Realm()
|
||||
} catch let error as NSError {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not open database: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -184,24 +202,6 @@ class NCManageDatabase: NSObject {
|
|||
self.clearTable(tableE2eCounter.self, account: account)
|
||||
}
|
||||
|
||||
@objc func removeDB() {
|
||||
let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
|
||||
let realmURLs = [
|
||||
realmURL,
|
||||
realmURL.appendingPathExtension("lock"),
|
||||
realmURL.appendingPathExtension("note"),
|
||||
realmURL.appendingPathExtension("management")
|
||||
]
|
||||
|
||||
for URL in realmURLs {
|
||||
do {
|
||||
try FileManager.default.removeItem(at: URL)
|
||||
} catch let error {
|
||||
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getThreadConfined(_ object: Object) -> Any {
|
||||
return ThreadSafeReference(to: object)
|
||||
}
|
||||
|
|
|
@ -596,13 +596,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
|
|||
let image = utility.loadUserImage(for: appDelegate.user, displayName: activeAccount?.displayName, userBaseUrl: appDelegate)
|
||||
let accountButton = AccountSwitcherButton(type: .custom)
|
||||
let accounts = NCManageDatabase.shared.getAllAccountOrderAlias()
|
||||
var childrenAccountSubmenu: [UIMenuElement] = []
|
||||
|
||||
accountButton.setImage(image, for: .normal)
|
||||
accountButton.setImage(image, for: .highlighted)
|
||||
accountButton.semanticContentAttribute = .forceLeftToRight
|
||||
accountButton.sizeToFit()
|
||||
|
||||
if !accounts.isEmpty, !NCBrandOptions.shared.disable_multiaccount {
|
||||
if !accounts.isEmpty {
|
||||
let accountActions: [UIAction] = accounts.map { account in
|
||||
let image = utility.loadUserImage(for: account.user, displayName: account.displayName, userBaseUrl: account)
|
||||
var name: String = ""
|
||||
|
@ -637,8 +638,12 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
|
|||
self.present(accountSettingsController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let addAccountSubmenu = UIMenu(title: "", options: .displayInline, children: [addAccountAction, settingsAccountAction])
|
||||
if !NCBrandOptions.shared.disable_multiaccount {
|
||||
childrenAccountSubmenu.append(addAccountAction)
|
||||
}
|
||||
childrenAccountSubmenu.append(settingsAccountAction)
|
||||
|
||||
let addAccountSubmenu = UIMenu(title: "", options: .displayInline, children: childrenAccountSubmenu)
|
||||
let menu = UIMenu(children: accountActions + [addAccountSubmenu])
|
||||
|
||||
accountButton.menu = menu
|
||||
|
|
|
@ -485,4 +485,8 @@ class NCGlobal: NSObject {
|
|||
// DRAG & DROP
|
||||
//
|
||||
let metadataOcIdDataRepresentation = "text/com.nextcloud.ocId"
|
||||
|
||||
// GROUP AMIN
|
||||
//
|
||||
let groupAdmin = "admin"
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ class NCSettingsAdvancedModel: ObservableObject, ViewOnAppearHandling {
|
|||
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
|
||||
/// Keychain access
|
||||
var keychain = NCKeychain()
|
||||
/// State variable for indicating if the user is in Admin group
|
||||
@Published var isAdminGroup: Bool = false
|
||||
/// State variable for indicating whether hidden files are shown.
|
||||
@Published var showHiddenFiles: Bool = false
|
||||
/// State variable for indicating the most compatible format.
|
||||
|
@ -65,6 +67,8 @@ class NCSettingsAdvancedModel: ObservableObject, ViewOnAppearHandling {
|
|||
|
||||
/// Triggered when the view appears.
|
||||
func onViewAppear() {
|
||||
let groups = NCManageDatabase.shared.getAccountGroups(account: appDelegate.account)
|
||||
isAdminGroup = groups.contains(NCGlobal.shared.groupAdmin)
|
||||
showHiddenFiles = keychain.showHiddenFiles
|
||||
mostCompatible = keychain.formatCompatibility
|
||||
livePhoto = keychain.livePhoto
|
||||
|
@ -73,6 +77,7 @@ class NCSettingsAdvancedModel: ObservableObject, ViewOnAppearHandling {
|
|||
crashReporter = keychain.disableCrashservice
|
||||
selectedLogLevel = LogLevel(rawValue: keychain.logLevel) ?? .standard
|
||||
selectedInterval = CacheDeletionInterval(rawValue: keychain.cleanUpDay) ?? .never
|
||||
|
||||
DispatchQueue.global().async {
|
||||
self.calculateSize()
|
||||
}
|
||||
|
|
|
@ -182,26 +182,28 @@ struct NCSettingsAdvancedView: View {
|
|||
Text(NSLocalizedString("_diagnostics_", comment: ""))
|
||||
}, footer: { })
|
||||
/// Set Log Level() & Capabilities
|
||||
Section(content: {
|
||||
NavigationLink(destination: LazyView {
|
||||
NCCapabilitiesView(model: NCCapabilitiesModel())
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "list.bullet")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 25, height: 25)
|
||||
.foregroundColor(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_capabilities_", comment: ""))
|
||||
if model.isAdminGroup {
|
||||
Section(content: {
|
||||
NavigationLink(destination: LazyView {
|
||||
NCCapabilitiesView(model: NCCapabilitiesModel())
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "list.bullet")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.font(Font.system(.body).weight(.light))
|
||||
.frame(width: 25, height: 25)
|
||||
.foregroundColor(Color(NCBrandColor.shared.iconImageColor))
|
||||
Text(NSLocalizedString("_capabilities_", comment: ""))
|
||||
}
|
||||
.font(.system(size: 16))
|
||||
}
|
||||
.font(.system(size: 16))
|
||||
}
|
||||
}, header: {
|
||||
Text(NSLocalizedString("_capabilities_", comment: ""))
|
||||
}, footer: {
|
||||
Text(NSLocalizedString("_capabilities_footer_", comment: ""))
|
||||
})
|
||||
}, header: {
|
||||
Text(NSLocalizedString("_capabilities_", comment: ""))
|
||||
}, footer: {
|
||||
Text(NSLocalizedString("_capabilities_footer_", comment: ""))
|
||||
})
|
||||
}
|
||||
}
|
||||
/// Delete in Cache & Clear Cache
|
||||
Section(content: {
|
||||
|
|
Двоичные данные
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
Двоичные данные
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
Двоичный файл не отображается.
Двоичные данные
iOSClient/Supporting Files/fr.lproj/Localizable.strings
Двоичные данные
iOSClient/Supporting Files/fr.lproj/Localizable.strings
Двоичный файл не отображается.
|
@ -108,7 +108,7 @@ class NCContentPresenter: NSObject {
|
|||
DispatchQueue.main.asyncAfter(deadline: .now() + afterDelay) {
|
||||
switch error.errorCode {
|
||||
case Int(CFNetworkErrors.cfurlErrorNotConnectedToInternet.rawValue):
|
||||
let image = UIImage(named: "InfoNetwork")!.image(color: .white, size: 20)
|
||||
let image = UIImage(named: "InfoNetwork")?.image(color: .white, size: 20)
|
||||
self.noteTop(text: NSLocalizedString(title, comment: ""), image: image, color: .lightGray, delay: delay, priority: .max)
|
||||
default:
|
||||
var responseMessage = ""
|
||||
|
|
Загрузка…
Ссылка в новой задаче