Add method to get user visible path for an item metadata
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Tue, 31 Oct 2023 07:43:32 +0000 (15:43 +0800)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Mon, 19 Feb 2024 14:45:14 +0000 (22:45 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
src/gui/macOS/fileprovideritemmetadata.h
src/gui/macOS/fileprovideritemmetadata_mac.mm

index 1decada982d412764d15892f0526d2a7a67754a4..cde6508de5b639d6b363ba5329aa43bd06d9a43c 100644 (file)
@@ -56,6 +56,8 @@ class FileProviderItemMetadata
        Q_PROPERTY(bool shared READ shared CONSTANT)
        Q_PROPERTY(bool sharedByCurrentUser READ sharedByCurrentUser CONSTANT)
 
+    Q_PROPERTY(QString userVisiblePath READ userVisiblePath CONSTANT)
+
 public:
     static FileProviderItemMetadata fromNSFileProviderItem(const void *const nsFileProviderItem, const QString &domainIdentifier);
 
@@ -90,6 +92,8 @@ public:
        bool shared() const;
     bool sharedByCurrentUser() const;
 
+    QString userVisiblePath() const;
+
     // Check equality via identifier, contentVersion, and metadataVersion
     friend bool operator==(const FileProviderItemMetadata &lhs, const FileProviderItemMetadata &rhs);
 
index e5168a4517f220f59c23de728405973bb305358b..daefc5721953630c1092b673481590ec71a18df2 100644 (file)
 
 #include "fileprovideritemmetadata.h"
 
+#include <QLoggingCategory>
+
 #import <Foundation/Foundation.h>
-#import <FileProvider/NSFileProviderItem.h>
+#import <FileProvider/FileProvider.h>
 #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
 
 namespace {
@@ -46,6 +48,8 @@ namespace OCC {
 
 namespace Mac {
 
+Q_LOGGING_CATEGORY(lcMacImplFileProviderItemMetadata, "nextcloud.gui.macfileprovideritemmetadatamacimpl", QtInfoMsg)
+
 FileProviderItemMetadata FileProviderItemMetadata::fromNSFileProviderItem(const void *const nsFileProviderItem, const QString &domainIdentifier)
 {
     FileProviderItemMetadata metadata;
@@ -88,6 +92,81 @@ FileProviderItemMetadata FileProviderItemMetadata::fromNSFileProviderItem(const
     return metadata;
 }
 
+QString FileProviderItemMetadata::userVisiblePath() const
+{
+    qCDebug(lcMacImplFileProviderItemMetadata) << "Getting user visible path";
+
+    const auto id = identifier();
+    const auto domainId = domainIdentifier();
+
+    if (id.isEmpty() || domainId.isEmpty()) {
+        qCWarning(lcMacImplFileProviderItemMetadata) << "Could not fetch user visible path for item, no identifier or domainIdentifier";
+        return QStringLiteral("Unknown");
+    }
+
+    NSString *const nsItemIdentifier = id.toNSString();
+    NSString *const nsDomainIdentifier = domainId.toNSString();
+
+    __block QString returnPath = QObject::tr("Unknown");
+    __block NSFileProviderManager *manager = nil;
+    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+
+    // getDomainsWithCompletionHandler is asynchronous -- we create a dispatch semaphore in order
+    // to wait until it is done. This should tell you that we should not call this method very
+    // often!
+
+    [NSFileProviderManager getDomainsWithCompletionHandler:^(NSArray<NSFileProviderDomain *> *const domains, NSError *const error) {
+        if (error != nil) {
+            qCWarning(lcMacImplFileProviderItemMetadata) << "Error fetching domains:" << error.localizedDescription;
+            dispatch_semaphore_signal(semaphore);
+            return;
+        }
+
+        BOOL foundDomain = NO;
+
+        for (NSFileProviderDomain *const domain in domains) {
+            if ([domain.identifier isEqualToString:nsDomainIdentifier]) {
+                 foundDomain = YES;
+                 manager = [NSFileProviderManager managerForDomain:domain];
+            }
+        }
+
+        if (!foundDomain) {
+            qCWarning(lcMacImplFileProviderItemMetadata) << "No matching item domain, cannot get item path";
+        }
+
+        dispatch_semaphore_signal(semaphore);
+    }];
+
+    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
+
+    if (manager == nil) {
+        qCWarning(lcMacImplFileProviderItemMetadata) << "Null manager, cannot get item path";
+        dispatch_release(semaphore);
+        return returnPath;
+    }
+
+    // getUserVisibleUrl is also async, so wait here too
+
+    [manager getUserVisibleURLForItemIdentifier:nsItemIdentifier
+                              completionHandler:^(NSURL *const userVisibleFile, NSError *const error) {
+        qCDebug(lcMacImplFileProviderItemMetadata) << "Got user visible url for item identifier." << "url:" << userVisibleFile << "error:" << error.localizedDescription;
+
+        if (error != nil) {
+            qCWarning(lcMacImplFileProviderItemMetadata) << "Error fetching user visible url for item identifier." << error.localizedDescription;
+        } else {
+            returnPath = QString::fromNSString(userVisibleFile.path);
+        }
+
+        dispatch_semaphore_signal(semaphore);
+    }];
+
+    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
+    dispatch_release(semaphore);
+
+    return returnPath;
+}
+
 }
 
 }