Skip to content

Commit 5c1e50d

Browse files
author
Nextcloud GmbH
committed
Merge remote-tracking branch 'customization/nmc/2023-localization'
2 parents f1aaf52 + f347afd commit 5c1e50d

17 files changed

Lines changed: 629 additions & 80 deletions

File Provider Extension/FileProviderData.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class FileProviderData: NSObject {
173173

174174
if error == .success {
175175
if let metadata = await NCManageDatabase.shared.getMetadataFromOcIdAsync(ocId) {
176-
await NCManageDatabase.shared.addLocalFilesAsync(metadatas: [metadata])
176+
await NCManageDatabase.shared.addLocalFileAsync(metadata: metadata)
177177
}
178178
}
179179

iOSClient/Data/NCManageDatabase+LocalFile.swift

Lines changed: 23 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -29,50 +29,35 @@ extension NCManageDatabase {
2929

3030
// MARK: - Realm Write
3131

32-
/// Adds or updates multiple local file entries corresponding to the given metadata array.
33-
/// Uses async Realm read + single write transaction. Assumes `tableLocalFile` has a primary key.
3432
/// - Parameters:
35-
/// - metadatas: Array of `tableMetadata` to map into `tableLocalFile`.
36-
/// - offline: Optional override for the `offline` flag applied to all items.
37-
func addLocalFilesAsync(metadatas: [tableMetadata], offline: Bool? = nil) async {
38-
guard !metadatas.isEmpty else {
39-
return
40-
}
41-
42-
// Extract ocIds for efficient lookup
43-
let ocIds = metadatas.compactMap { $0.ocId }
44-
guard !ocIds.isEmpty else {
45-
return
33+
/// - metadata: The `tableMetadata` containing file details.
34+
/// - offline: Optional flag to mark the file as available offline.
35+
/// - Returns: Nothing. Realm write is performed asynchronously.
36+
func addLocalFileAsync(metadata: tableMetadata, offline: Bool? = nil) async {
37+
// Read (non-blocking): safely detach from Realm thread
38+
let existing: tableLocalFile? = performRealmRead { realm in
39+
realm.objects(tableLocalFile.self)
40+
.filter(NSPredicate(format: "ocId == %@", metadata.ocId))
41+
.first
42+
.map { tableLocalFile(value: $0) }
4643
}
4744

48-
// Preload existing entries to avoid creating duplicates
49-
let existingMap: [String: tableLocalFile] = await core.performRealmReadAsync { realm in
50-
let existing = realm.objects(tableLocalFile.self)
51-
.filter(NSPredicate(format: "ocId IN %@", ocIds))
52-
return Dictionary(uniqueKeysWithValues:
53-
existing.map { ($0.ocId, tableLocalFile(value: $0)) } // detached copy via value init
54-
)
55-
} ?? [:]
45+
await performRealmWriteAsync { realm in
46+
let addObject = existing ?? tableLocalFile()
5647

57-
await core.performRealmWriteAsync { realm in
58-
for metadata in metadatas {
59-
// Reuse existing object or create a new one
60-
let local = existingMap[metadata.ocId] ?? tableLocalFile()
61-
62-
local.account = metadata.account
63-
local.etag = metadata.etag
64-
local.exifDate = NSDate()
65-
local.exifLatitude = "-1"
66-
local.exifLongitude = "-1"
67-
local.ocId = metadata.ocId
68-
local.fileName = metadata.fileName
69-
70-
if let offline {
71-
local.offline = offline
72-
}
48+
addObject.account = metadata.account
49+
addObject.etag = metadata.etag
50+
addObject.exifDate = NSDate()
51+
addObject.exifLatitude = "-1"
52+
addObject.exifLongitude = "-1"
53+
addObject.ocId = metadata.ocId
54+
addObject.fileName = metadata.fileName
7355

74-
realm.add(local, update: .all)
56+
if let offline {
57+
addObject.offline = offline
7558
}
59+
60+
realm.add(addObject, update: .all)
7661
}
7762
}
7863

iOSClient/NCBackgroundLocationUploadManager.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ class NCBackgroundLocationUploadManager: NSObject, CLLocationManagerDelegate {
102102
}
103103

104104
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
105-
// Must work only in background
106105
guard isAppInBackground else {
107106
return
108107
}
@@ -119,6 +118,14 @@ class NCBackgroundLocationUploadManager: NSObject, CLLocationManagerDelegate {
119118

120119
Task.detached {
121120
await NCAutoUpload.shared.autoUploadBackgroundSync()
121+
if database.openRealmBackground() {
122+
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
123+
let location = locations.last
124+
nkLog(tag: self.global.logTagLocation, emoji: .start, message: "Triggered by location change: \(location?.coordinate.latitude ?? 0), \(location?.coordinate.longitude ?? 0)")
125+
126+
Task.detached {
127+
await NCAutoUpload.shared.autoUploadBackgroundSync()
128+
}
122129
}
123130
}
124131

iOSClient/NCGlobal.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,6 @@ final class NCGlobal: Sendable {
326326
let metadataStatusForScreenAwake = [-1, -2, 1, 2]
327327
let metadataStatusHideInView = [1, 2, 3, 11]
328328
let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15]
329-
let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15]
330329

331330
let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15]
332331
let metadatasStatusInProgress = [-2, 2]
@@ -412,6 +411,8 @@ final class NCGlobal: Sendable {
412411
let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl
413412
let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists
414413

414+
let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error
415+
415416
let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF"
416417
let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF"
417418

iOSClient/Networking/E2EE/NCNetworkingE2EEUpload.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ class NCNetworkingE2EEUpload: NSObject {
219219
await self.database.addMetadataAsync(metadata)
220220
await self.database.addLocalFilesAsync(metadatas: [metadata])
221221
await self.database.addLocalFileAsync(metadata: metadata)
222+
// await self.database.addLocalFileAsync(metadata: metadata)
223+
222224
utility.createImageFileFrom(metadata: metadata)
223225

224226
await NCNetworking.shared.transferDispatcher.notifyAllDelegates { delegate in

iOSClient/Networking/NCConfigServer.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
1-
// SPDX-FileCopyrightText: Nextcloud GmbH
2-
// SPDX-FileCopyrightText: 2022 Marino Faggiana
3-
// SPDX-License-Identifier: GPL-3.0-or-later
1+
//
2+
// NCConfigServer.swift
3+
// Nextcloud
4+
//
5+
// Created by Marino Faggiana on 05/12/22.
6+
// Copyright © 2022 Marino Faggiana. All rights reserved.
7+
//
8+
// Author Marino Faggiana <marino.faggiana@nextcloud.com>
9+
//
10+
// This program is free software: you can redistribute it and/or modify
11+
// it under the terms of the GNU General Public License as published by
12+
// the Free Software Foundation, either version 3 of the License, or
13+
// (at your option) any later version.
14+
//
15+
// This program is distributed in the hope that it will be useful,
16+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
// GNU General Public License for more details.
19+
//
20+
// You should have received a copy of the GNU General Public License
21+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
//
423

524
import Foundation
625
import UIKit

iOSClient/Networking/NCNetworking+Download.swift

Lines changed: 140 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
1-
// SPDX-FileCopyrightText: Nextcloud GmbH
2-
// SPDX-FileCopyrightText: 2024 Marino Faggiana
3-
// SPDX-License-Identifier: GPL-3.0-or-later
1+
//
2+
// NCNetworking+Download.swift
3+
// Nextcloud
4+
//
5+
// Created by Marino Faggiana on 07/02/24.
6+
// Copyright © 2024 Marino Faggiana. All rights reserved.
7+
//
8+
// Author Marino Faggiana <marino.faggiana@nextcloud.com>
9+
//
10+
// This program is free software: you can redistribute it and/or modify
11+
// it under the terms of the GNU General Public License as published by
12+
// the Free Software Foundation, either version 3 of the License, or
13+
// (at your option) any later version.
14+
//
15+
// This program is distributed in the hope that it will be useful,
16+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
// GNU General Public License for more details.
19+
//
20+
// You should have received a copy of the GNU General Public License
21+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
//
423

524
import UIKit
625
import NextcloudKit
@@ -301,23 +320,89 @@ extension NCNetworking {
301320
await NCManageDatabase.shared.clearMetadatasSessionAsync(metadatas: metadatas)
302321
}
303322
} else {
304-
await NCManageDatabase.shared.setOffLocalFileAsync(ocId: metadata.ocId)
323+
nkLog(error: "Downloaded file: " + metadata.serverUrlFileName + ", result: error \(error.errorCode)")
324+
325+
if error.errorCode == NCGlobal.shared.errorResourceNotFound {
326+
self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, urlBase: metadata.urlBase))
327+
328+
await NCManageDatabase.shared.deleteLocalFileAsync(id: metadata.ocId)
329+
await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId)
330+
} else if error.errorCode == NSURLErrorCancelled || error.errorCode == self.global.errorRequestExplicityCancelled {
331+
if let metadata = await NCManageDatabase.shared.setMetadataSessionAsync(ocId: metadata.ocId,
332+
session: "",
333+
sessionTaskIdentifier: 0,
334+
sessionError: "",
335+
selector: "",
336+
status: self.global.metadataStatusNormal) {
337+
await self.transferDispatcher.notifyAllDelegates { delegate in
338+
delegate.transferChange(status: self.global.networkingStatusDownloadCancel,
339+
metadata: metadata,
340+
error: .success)
341+
}
342+
}
343+
} else {
344+
if let metadata = await NCManageDatabase.shared.setMetadataSessionAsync(ocId: metadata.ocId,
345+
session: "",
346+
sessionTaskIdentifier: 0,
347+
sessionError: "",
348+
selector: "",
349+
status: self.global.metadataStatusNormal) {
350+
351+
await self.transferDispatcher.notifyAllDelegates { delegate in
352+
delegate.transferChange(status: NCGlobal.shared.networkingStatusDownloaded,
353+
metadata: metadata,
354+
error: error)
355+
}
356+
}
357+
}
358+
await NCManageDatabase.shared.updateBadge()
305359
}
306-
} else if metadata.directory {
307-
await NCManageDatabase.shared.cleanTablesOcIds(account: metadata.account, userId: metadata.userId, urlBase: metadata.urlBase)
308-
await NCManageDatabase.shared.setDirectoryAsync(serverUrl: metadata.serverUrlFileName, offline: true, metadata: metadata)
309-
await NCNetworking.shared.synchronizationDownload(account: metadata.account, serverUrl: metadata.serverUrlFileName, userId: metadata.userId, urlBase: metadata.urlBase, metadatasInDownload: nil)
310-
} else {
311-
var metadatasSynchronizationOffline: [tableMetadata] = []
312-
metadatasSynchronizationOffline.append(metadata)
313-
if let metadata = await NCManageDatabase.shared.getMetadataLivePhotoAsync(metadata: metadata) {
314-
metadatasSynchronizationOffline.append(metadata)
360+
}
361+
}
362+
363+
// MARK: - Download NextcloudKitDelegate
364+
365+
func downloadingFinish(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
366+
if let httpResponse = (downloadTask.response as? HTTPURLResponse) {
367+
if httpResponse.statusCode >= 200 && httpResponse.statusCode < 300,
368+
let url = downloadTask.currentRequest?.url,
369+
var serverUrl = url.deletingLastPathComponent().absoluteString.removingPercentEncoding {
370+
let fileName = url.lastPathComponent
371+
if serverUrl.hasSuffix("/") { serverUrl = String(serverUrl.dropLast()) }
372+
if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "serverUrl == %@ AND fileName == %@", serverUrl, fileName)) {
373+
let destinationFilePath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileName: metadata.fileName, userId: metadata.userId, urlBase: metadata.urlBase)
374+
do {
375+
if FileManager.default.fileExists(atPath: destinationFilePath) {
376+
try FileManager.default.removeItem(atPath: destinationFilePath)
377+
}
378+
try FileManager.default.copyItem(at: location, to: NSURL.fileURL(withPath: destinationFilePath))
379+
} catch {
380+
print(error)
381+
}
382+
}
315383
}
316-
await NCManageDatabase.shared.addLocalFilesAsync(metadatas: [metadata], offline: true)
317-
for metadata in metadatasSynchronizationOffline {
318-
await NCManageDatabase.shared.setMetadataSessionInWaitDownloadAsync(ocId: metadata.ocId,
319-
session: NCNetworking.shared.sessionDownloadBackground,
320-
selector: NCGlobal.shared.selectorSynchronizationOffline)
384+
}
385+
}
386+
387+
func downloadProgress(_ progress: Float,
388+
totalBytes: Int64,
389+
totalBytesExpected: Int64,
390+
fileName: String,
391+
serverUrl: String,
392+
session: URLSession,
393+
task: URLSessionTask) {
394+
395+
Task {
396+
guard await progressQuantizer.shouldEmit(serverUrlFileName: serverUrl + "/" + fileName, fraction: Double(progress)) else {
397+
return
398+
}
399+
await NCManageDatabase.shared.setMetadataProgress(fileName: fileName, serverUrl: serverUrl, taskIdentifier: task.taskIdentifier, progress: Double(progress))
400+
await self.transferDispatcher.notifyAllDelegates { delegate in
401+
delegate.transferProgressDidUpdate(progress: progress,
402+
totalBytes: totalBytes,
403+
totalBytesExpected: totalBytesExpected,
404+
fileName: fileName,
405+
serverUrl: serverUrl)
321406
}
322407
}
323408

@@ -327,3 +412,40 @@ extension NCNetworking {
327412
}
328413
}
329414
}
415+
416+
class NCOperationDownload: ConcurrentOperation, @unchecked Sendable {
417+
var metadata: tableMetadata
418+
var selector: String
419+
420+
init(metadata: tableMetadata, selector: String) {
421+
self.metadata = tableMetadata.init(value: metadata)
422+
self.selector = selector
423+
}
424+
425+
override func start() {
426+
guard !isCancelled else { return self.finish() }
427+
428+
metadata.session = NCNetworking.shared.sessionDownload
429+
metadata.sessionError = ""
430+
metadata.sessionSelector = selector
431+
metadata.sessionTaskIdentifier = 0
432+
metadata.status = NCGlobal.shared.metadataStatusWaitDownload
433+
434+
// let metadata = NCManageDatabase.shared.addMetadata(metadata)
435+
436+
// NCNetworking.shared.download(metadata: metadata, withNotificationProgressTask: true) {
437+
// } completion: { _, _ in
438+
// self.finish()
439+
// }
440+
Task {
441+
await download(withSelector: self.selector)
442+
}
443+
}
444+
445+
private func download(withSelector selector: String = "") async {
446+
await NCNetworking.shared.downloadFile(metadata: metadata) { _ in
447+
self.finish()
448+
} taskHandler: { _ in }
449+
450+
}
451+
}

iOSClient/Networking/NCNetworking+LivePhoto.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
1-
// SPDX-FileCopyrightText: Nextcloud GmbH
2-
// SPDX-FileCopyrightText: 2024 Marino Faggiana
3-
// SPDX-License-Identifier: GPL-3.0-or-later
1+
//
2+
// NCNetworking+LivePhoto.swift
3+
// Nextcloud
4+
//
5+
// Created by Marino Faggiana on 07/02/24.
6+
// Copyright © 2024 Marino Faggiana. All rights reserved.
7+
//
8+
// Author Marino Faggiana <marino.faggiana@nextcloud.com>
9+
//
10+
// This program is free software: you can redistribute it and/or modify
11+
// it under the terms of the GNU General Public License as published by
12+
// the Free Software Foundation, either version 3 of the License, or
13+
// (at your option) any later version.
14+
//
15+
// This program is distributed in the hope that it will be useful,
16+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
// GNU General Public License for more details.
19+
//
20+
// You should have received a copy of the GNU General Public License
21+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
//
423

524
import UIKit
625
import NextcloudKit

0 commit comments

Comments
 (0)