File: FileProviderExtension%2BCustomActions.swift

package info (click to toggle)
nextcloud-desktop 4.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 40,404 kB
  • sloc: cpp: 118,401; objc: 752; python: 606; sh: 395; ansic: 391; ruby: 174; makefile: 44; javascript: 32; xml: 6
file content (101 lines) | stat: -rw-r--r-- 4,166 bytes parent folder | download
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
/*
 * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

import FileProvider
import NextcloudFileProviderKit
import OSLog

extension FileProviderExtension: NSFileProviderCustomAction {
    func performAction(
        identifier actionIdentifier: NSFileProviderExtensionActionIdentifier,
        onItemsWithIdentifiers itemIdentifiers: [NSFileProviderItemIdentifier],
        completionHandler: @escaping ((any Error)?) -> Void
    ) -> Progress {
        switch actionIdentifier.rawValue {
        case "com.nextcloud.desktopclient.FileProviderExt.KeepDownloadedAction":
            return performKeepDownloadedAction(
                keepDownloaded: true,
                onItemsWithIdentifiers: itemIdentifiers,
                completionHandler: completionHandler
            )
        case "com.nextcloud.desktopclient.FileProviderExt.AutoEvictAction":
            return performKeepDownloadedAction(
                keepDownloaded: false,
                onItemsWithIdentifiers: itemIdentifiers,
                completionHandler: completionHandler
            )
        default:
            logger.error("Unsupported action: \(actionIdentifier.rawValue)")
            completionHandler(NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError))
            return Progress()
        }
    }
    
    private func performKeepDownloadedAction(
        keepDownloaded: Bool,
        onItemsWithIdentifiers itemIdentifiers: [NSFileProviderItemIdentifier],
        completionHandler: @escaping ((any Error)?) -> Void
    ) -> Progress {
        guard let ncAccount else {
            logger.error("Not setting keep offline for items, account not set up yet.")
            completionHandler(NSFileProviderError(.notAuthenticated))
            return Progress()
        }
        guard let dbManager else {
            logger.error("Not setting keep offline for items as database is unreachable.")
            completionHandler(NSFileProviderError(.cannotSynchronize))
            return Progress()
        }

        let progress = Progress()

        // If there are no items, complete successfully immediately.
        if itemIdentifiers.isEmpty {
            logger.info("No items to process for keepDownloaded action.")
            completionHandler(nil)
            return progress
        }

        // Explicitly set totalUnitCount for clarity, though addChild with pendingUnitCount also defines this.
        progress.totalUnitCount = Int64(itemIdentifiers.count)

        Task {
            let localNcKit = self.ncKit
            let localDomain = self.domain

            do {
                try await withThrowingTaskGroup(of: Void.self) { group in
                    for identifier in itemIdentifiers {
                        group.addTask {
                            // This task processes one item.
                            guard let item = await Item.storedItem(
                                identifier: identifier,
                                account: ncAccount,
                                remoteInterface: localNcKit,
                                dbManager: dbManager,
                                log: self.log
                            ) else {
                                throw NSError.fileProviderErrorForNonExistentItem(
                                    withIdentifier: identifier
                                )
                            }
                            try await item.set(keepDownloaded: keepDownloaded, domain: localDomain)
                        }
                    }

                    for try await result in group {
                        progress.completedUnitCount = 1
                    }
                }
                logger.info("All items successfully processed for keepDownloaded=\(keepDownloaded)")
                completionHandler(nil)
            } catch let error {
                logger.error("Error during keepDownloaded=\(keepDownloaded) action: \(error.localizedDescription)")
                completionHandler(error)
            }
        }
        return progress
    }
}