1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-2.0-or-later
import FileProviderUI
import NextcloudFileProviderKit
import OSLog
class DocumentActionViewController: FPUIActionExtensionViewController {
var domain: NSFileProviderDomain {
guard let identifier = extensionContext.domainIdentifier else {
fatalError("not expected to be called with default domain")
}
return NSFileProviderDomain(
identifier: NSFileProviderDomainIdentifier(rawValue: identifier.rawValue),
displayName: ""
)
}
///
/// To be passed down in the hierarchy to all subordinate code.
///
var log: (any FileProviderLogging)!
///
/// To be used by this view controller only.
///
/// Child view controllers must set up their own for clarity.
///
var logger: FileProviderLogger!
// MARK: - Lifecycle
func setUpLogger() {
if log == nil {
log = FileProviderLog(fileProviderDomainIdentifier: domain.identifier)
}
if logger == nil, let log {
logger = FileProviderLogger(category: "DocumentActionViewController", log: log)
}
}
func prepare(childViewController: NSViewController) {
setUpLogger()
addChild(childViewController)
view.addSubview(childViewController.view)
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: childViewController.view.leadingAnchor),
view.trailingAnchor.constraint(equalTo: childViewController.view.trailingAnchor),
view.topAnchor.constraint(equalTo: childViewController.view.topAnchor),
view.bottomAnchor.constraint(equalTo: childViewController.view.bottomAnchor)
])
}
override func prepare(forAction actionIdentifier: String, itemIdentifiers: [NSFileProviderItemIdentifier]) {
setUpLogger()
logger?.info("Preparing action: \(actionIdentifier)")
switch (actionIdentifier) {
case "com.nextcloud.desktopclient.FileProviderUIExt.ShareAction":
prepare(childViewController: ShareViewController(itemIdentifiers, log: log))
case "com.nextcloud.desktopclient.FileProviderUIExt.LockFileAction":
prepare(childViewController: LockViewController(itemIdentifiers, locking: true, log: log))
case "com.nextcloud.desktopclient.FileProviderUIExt.UnlockFileAction":
prepare(childViewController: LockViewController(itemIdentifiers, locking: false, log: log))
case "com.nextcloud.desktopclient.FileProviderUIExt.EvictAction":
evict(itemsWithIdentifiers: itemIdentifiers, inDomain: domain);
extensionContext.completeRequest();
default:
return
}
}
override func prepare(forError error: Error) {
setUpLogger()
logger?.info("Preparing for error.", [.error: error])
let storyboard = NSStoryboard(name: "Authentication", bundle: Bundle(for: type(of: self)))
let viewController = storyboard.instantiateInitialController() as! AuthenticationViewController
viewController.log = log
prepare(childViewController: viewController)
}
override public func loadView() {
self.view = NSView()
}
// MARK: - Eviction
///
/// Use a file provider domain manager to evict all items identified by the given array.
///
func evict(itemsWithIdentifiers identifiers: [NSFileProviderItemIdentifier], inDomain domain: NSFileProviderDomain) async {
logger?.debug("Starting eviction process…")
guard let manager = NSFileProviderManager(for: domain) else {
logger?.error("Could not get file provider domain manager.", [.domain: domain.identifier])
return;
}
do {
for itemIdentifier in identifiers {
logger?.error("Evicting item: \(itemIdentifier.rawValue)")
try await manager.evictItem(identifier: itemIdentifier)
}
} catch let error {
logger?.error("Error evicting item: \(error.localizedDescription)")
}
}
///
/// Synchronous wrapper of ``evict(itemsWithIdentifiers:inDomain:)-67w8c``.
///
func evict(itemsWithIdentifiers identifiers: [NSFileProviderItemIdentifier], inDomain domain: NSFileProviderDomain) {
let semaphore = DispatchSemaphore(value: 0)
Task {
await evict(itemsWithIdentifiers: identifiers, inDomain: domain)
semaphore.signal()
}
semaphore.wait()
}
}
|