Perform lock/unlock procedure in lock view controller
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Tue, 30 Jul 2024 10:52:06 +0000 (18:52 +0800)
committerMatthieu Gallien <matthieu_gallien@yahoo.fr>
Thu, 12 Sep 2024 08:15:58 +0000 (10:15 +0200)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Locking/LockViewController.swift

index 4116ff7bc7b38fe2678fb505c4a0dbeba0379139..0916041f602461c83779d4a7a7ac3c04339c4e30 100644 (file)
@@ -7,6 +7,7 @@
 
 import AppKit
 import FileProvider
+import NextcloudFileProviderKit
 import NextcloudKit
 import OSLog
 import QuickLookThumbnailing
@@ -67,6 +68,7 @@ class LockViewController: NSViewController {
             }
             await updateFileDetailsDisplay(itemUrl: itemUrl)
             itemUrl.stopAccessingSecurityScopedResource()
+            await lockOrUnlockFile(localItemUrl: itemUrl)
         } catch let error {
             let errorString = "Error processing item: \(error)"
             Logger.lockViewController.error("\(errorString, privacy: .public)")
@@ -101,4 +103,88 @@ class LockViewController: NSViewController {
             fileThumbnail?.nsImage ?? 
             NSImage(systemSymbolName: "doc", accessibilityDescription: "doc")
     }
+
+    private func lockOrUnlockFile(localItemUrl: URL) async {
+        descriptionLabel.stringValue = "Fetching file details…"
+
+        guard let itemIdentifier = await withCheckedContinuation({
+            (continuation: CheckedContinuation<NSFileProviderItemIdentifier?, Never>) -> Void in
+            NSFileProviderManager.getIdentifierForUserVisibleFile(
+                at: localItemUrl
+            ) { identifier, domainIdentifier, error in
+                defer { continuation.resume(returning: identifier) }
+                guard error == nil else {
+                    self.presentError("No item with identifier: \(error.debugDescription)")
+                    return
+                }
+            }
+        }) else {
+            presentError("Could not get identifier for item, no shares can be acquired.")
+            return
+        }
+
+        do {
+            let connection = try await serviceConnection(url: localItemUrl, interruptionHandler: {
+                Logger.lockViewController.error("Service connection interrupted")
+            })
+            guard let serverPath = await connection.itemServerPath(identifier: itemIdentifier),
+                  let credentials = await connection.credentials() as? Dictionary<String, String>,
+                  let account = Account(dictionary: credentials),
+                  !account.password.isEmpty
+            else {
+                presentError("Failed to get details from File Provider Extension.")
+                return
+            }
+            let serverPathString = serverPath as String
+            let itemServerRelativePath = serverPathString
+            let kit = NextcloudKit()
+            kit.setup(
+                user: account.username,
+                userId: account.username,
+                password: account.password,
+                urlBase: account.serverUrl
+            )
+            // guard let capabilities = await fetchCapabilities() else {
+            guard let itemMetadata = await fetchItemMetadata(
+                itemRelativePath: serverPathString, kit: kit
+            ) else {
+                presentError("Could not get item metadata.")
+                return
+            }
+
+            // Run lock state checks
+            if locking {
+                guard !itemMetadata.lock else {
+                    presentError("File is already locked.")
+                    return
+                }
+            } else {
+                guard itemMetadata.lock else {
+                    presentError("File is already unlocked.")
+                    return
+                }
+            }
+
+            descriptionLabel.stringValue =
+                "Communicating with server, \(locking ? "locking" : "unlocking") file…"
+            
+            await withCheckedContinuation { continuation in
+                kit.lockUnlockFile(
+                    serverUrlFileName: itemServerRelativePath,
+                    shouldLock: locking,
+                    completion: { account, error in
+                        if error == .success {
+                            self.descriptionLabel.stringValue =
+                                "File \(self.locking ? "locked" : "unlocked")!"
+                            continuation.resume()
+                        } else {
+                            self.presentError("Could not lock file: \(error).")
+                        }
+                    }
+                )
+            }
+        } catch let error {
+            presentError("Could not lock file: \(error).")
+        }
+    }
 }