File: DocumentActionViewController.swift

package info (click to toggle)
nextcloud-desktop 4.0.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 40,740 kB
  • sloc: cpp: 119,301; objc: 752; python: 606; ansic: 389; sh: 377; makefile: 44; javascript: 32; xml: 6
file content (132 lines) | stat: -rw-r--r-- 4,980 bytes parent folder | download | duplicates (3)
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
126
127
128
129
130
131
132
//  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!

    var serviceResolver: ServiceResolver!

    // MARK: - Lifecycle

    func setUp() {
        if log == nil {
            log = FileProviderLog(fileProviderDomainIdentifier: domain.identifier)
        }

        if logger == nil, let log {
            logger = FileProviderLogger(category: "DocumentActionViewController", log: log)
        }

        if serviceResolver == nil, let log {
            serviceResolver = ServiceResolver(log: log)
        }
    }

    func prepare(childViewController: NSViewController) {
        setUp()
        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]) {
        setUp()
        logger?.info("Preparing action: \(actionIdentifier)")

        switch (actionIdentifier) {
            case "com.nextcloud.desktopclient.FileProviderUIExt.ShareAction":
                prepare(childViewController: ShareViewController(itemIdentifiers, serviceResolver: serviceResolver, log: log))
            case "com.nextcloud.desktopclient.FileProviderUIExt.LockFileAction":
                prepare(childViewController: LockViewController(itemIdentifiers, locking: true, serviceResolver: serviceResolver, log: log))
            case "com.nextcloud.desktopclient.FileProviderUIExt.UnlockFileAction":
                prepare(childViewController: LockViewController(itemIdentifiers, locking: false, serviceResolver: serviceResolver, log: log))
            case "com.nextcloud.desktopclient.FileProviderUIExt.EvictAction":
                evict(itemsWithIdentifiers: itemIdentifiers, inDomain: domain);
                extensionContext.completeRequest();
            default:
                return
        }
    }

    override func prepare(forError error: Error) {
        setUp()
        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
        viewController.serviceResolver = serviceResolver

        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()
    }
}