From 8ccd0368a1ed86bbe291d7f312df43eb44e33eea Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 13 Dec 2022 16:53:36 +0100 Subject: [PATCH] Move file provider domain management to specific class Signed-off-by: Claudio Cambra --- src/gui/CMakeLists.txt | 4 +- src/gui/macOS/fileprovider.h | 20 +- src/gui/macOS/fileprovider_mac.mm | 152 +------------ src/gui/macOS/fileproviderdomainmanager.h | 50 +++++ .../macOS/fileproviderdomainmanager_mac.mm | 204 ++++++++++++++++++ src/gui/macOS/fileproviderinterface.h | 4 - 6 files changed, 265 insertions(+), 169 deletions(-) create mode 100644 src/gui/macOS/fileproviderdomainmanager.h create mode 100644 src/gui/macOS/fileproviderdomainmanager_mac.mm delete mode 100644 src/gui/macOS/fileproviderinterface.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 0311b3318..726308289 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -282,7 +282,9 @@ IF( APPLE ) list(APPEND client_SRCS systray.mm) list(APPEND client_SRCS macOS/fileprovider.h - macOS/fileprovider_mac.mm) + macOS/fileprovider_mac.mm + macOS/fileproviderdomainmanager.h + macOS/fileproviderdomainmanager_mac.mm) if(SPARKLE_FOUND AND BUILD_UPDATER) # Define this, we need to check in updater.cpp diff --git a/src/gui/macOS/fileprovider.h b/src/gui/macOS/fileprovider.h index 8c6ddc654..24ec7f702 100644 --- a/src/gui/macOS/fileprovider.h +++ b/src/gui/macOS/fileprovider.h @@ -12,16 +12,12 @@ * for more details. */ -#ifndef FILEPROVIDER_H -#define FILEPROVIDER_H +#pragma once #include -#include namespace OCC { -class AccountState; - namespace Mac { // NOTE: For the file provider extension to work, the app bundle will @@ -31,23 +27,11 @@ class FileProvider : public QObject { public: static FileProvider *instance(); - ~FileProvider() override; - - void setupFileProviderDomains(); - -private slots: - void addFileProviderDomainForAccount(AccountState *accountState); - void removeFileProviderDomainForAccount(AccountState *accountState); - void setFileProviderForAccountIsConnected(AccountState *accountState); + ~FileProvider() = default; private: explicit FileProvider(QObject *parent = nullptr); - static FileProvider *_instance; - class Private; - QScopedPointer d; }; } // namespace Mac } // namespace OCC - -#endif diff --git a/src/gui/macOS/fileprovider_mac.mm b/src/gui/macOS/fileprovider_mac.mm index a29efa354..65d34da19 100644 --- a/src/gui/macOS/fileprovider_mac.mm +++ b/src/gui/macOS/fileprovider_mac.mm @@ -12,16 +12,12 @@ * for more details. */ - #import -#import #include -#include "gui/accountmanager.h" -#include "gui/accountstate.h" -#include "libsync/account.h" #include "fileprovider.h" +#include "fileproviderdomainmanager.h" namespace OCC { @@ -29,126 +25,15 @@ Q_LOGGING_CATEGORY(lcMacFileProvider, "nextcloud.gui.macfileprovider", QtInfoMsg namespace Mac { -FileProvider *FileProvider::_instance = nullptr; - -class FileProvider::Private { - public: - Private() - { - } - - ~Private() = default; - - void addFileProviderDomain(const AccountState *accountState) - { - const QString accountDisplayName = accountState->account()->displayName(); - const QString accountId = accountState->account()->id(); - - qCDebug(lcMacFileProvider) << "Adding new file provider domain for account with id: " << accountId; - - if(_registeredDomains.contains(accountId) && _registeredDomains.value(accountId) != nil) { - qCDebug(lcMacFileProvider) << "File provider domain for account with id already exists: " << accountId; - return; - } - - NSFileProviderDomain *fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:accountId.toNSString() displayName:accountDisplayName.toNSString()]; - [NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProvider) << "Error adding file provider domain: " << [error code] << [error localizedDescription]; - } - }]; - - _registeredDomains.insert(accountId, fileProviderDomain); - } - - void removeFileProviderDomain(const AccountState *accountState) - { - const QString accountId = accountState->account()->id(); - qCDebug(lcMacFileProvider) << "Removing file provider domain for account with id: " << accountId; - - if(!_registeredDomains.contains(accountId)) { - qCDebug(lcMacFileProvider) << "File provider domain not found for id: " << accountId; - return; - } - - NSFileProviderDomain* fileProviderDomain = _registeredDomains[accountId]; - - [NSFileProviderManager removeDomain:fileProviderDomain completionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProvider) << "Error removing file provider domain: " << [error code] << [error localizedDescription]; - } - }]; - - NSFileProviderDomain* domain = _registeredDomains.take(accountId); - [domain release]; - } - - void removeAllFileProviderDomains() - { - qCDebug(lcMacFileProvider) << "Removing all file provider domains."; - - [NSFileProviderManager removeAllDomainsWithCompletionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProvider) << "Error removing all file provider domains: " << [error code] << [error localizedDescription]; - } - }]; - } - - void setFileProviderDomainConnected(const AccountState *accountState) - { - const QString accountDisplayName = accountState->account()->displayName(); - const QString accountId = accountState->account()->id(); - const bool accountIsConnected = accountState->isConnected(); - - qCDebug(lcMacFileProvider) << "Account state for account changed: " << accountDisplayName << accountIsConnected; - - if(!_registeredDomains.contains(accountId)) { - qCDebug(lcMacFileProvider) << "File provider domain not found for id: " << accountId; - return; - } - - NSFileProviderDomain* accountDomain = _registeredDomains.value(accountId); - NSFileProviderManager* providerManager = [NSFileProviderManager managerForDomain:accountDomain]; - - if(accountIsConnected) { - [providerManager reconnectWithCompletionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProvider) << "Error reconnecting file provider domain: " << accountDisplayName << [error code] << [error localizedDescription]; - } - }]; - } else { - NSString* reason = @"Nextcloud account disconnected."; - const auto isTemporary = accountState->state() != AccountState::SignedOut && accountState->state() != AccountState::ConfigurationError; - NSFileProviderManagerDisconnectionOptions disconnectOption = isTemporary ? 0 : NSFileProviderManagerDisconnectionOptionsTemporary; - - [providerManager disconnectWithReason:reason options:disconnectOption completionHandler:^(NSError *error) { - if(error) { - qCDebug(lcMacFileProvider) << "Error disconnecting file provider domain: " << accountDisplayName << [error code] << [error localizedDescription]; - } - }]; - } - } - -private: - QHash _registeredDomains; -}; +static FileProvider *_instance = nullptr; FileProvider::FileProvider(QObject *parent) : QObject(parent) { - d.reset(new FileProvider::Private()); - - connect(AccountManager::instance(), &AccountManager::accountAdded, - this, &FileProvider::addFileProviderDomainForAccount); - connect(AccountManager::instance(), &AccountManager::accountRemoved, - this, &FileProvider::removeFileProviderDomainForAccount); - - setupFileProviderDomains(); // Initially fetch accounts in manager -} - -FileProvider::~FileProvider() -{ - d->removeAllFileProviderDomains(); + const auto domainManager = FileProviderDomainManager::instance(); + if (domainManager) { + qCDebug(lcMacFileProvider()) << "Initialized file provider domain manager"; + } } FileProvider *FileProvider::instance() @@ -159,30 +44,5 @@ FileProvider *FileProvider::instance() return _instance; } -void FileProvider::setupFileProviderDomains() -{ - for(auto &accountState : AccountManager::instance()->accounts()) { - addFileProviderDomainForAccount(accountState.data()); - } -} - -void FileProvider::addFileProviderDomainForAccount(AccountState *accountState) -{ - d->addFileProviderDomain(accountState); - - connect(accountState, &AccountState::isConnectedChanged, - this, [this, accountState]{ setFileProviderForAccountIsConnected(accountState); }); -} - -void FileProvider::removeFileProviderDomainForAccount(AccountState* accountState) -{ - d->removeFileProviderDomain(accountState); -} - -void FileProvider::setFileProviderForAccountIsConnected(AccountState *accountState) -{ - d->setFileProviderDomainConnected(accountState); -} - } // namespace Mac } // namespace OCC diff --git a/src/gui/macOS/fileproviderdomainmanager.h b/src/gui/macOS/fileproviderdomainmanager.h new file mode 100644 index 000000000..a788bf8dd --- /dev/null +++ b/src/gui/macOS/fileproviderdomainmanager.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include + +namespace OCC { + +class AccountState; + +namespace Mac { + +class FileProviderDomainManager : public QObject +{ + Q_OBJECT + +public: + static FileProviderDomainManager *instance(); + ~FileProviderDomainManager() override; + +private slots: + void setupFileProviderDomains(); + + void addFileProviderDomainForAccount(OCC::AccountState *accountState); + void removeFileProviderDomainForAccount(OCC::AccountState *accountState); + void setFileProviderForAccountIsConnected(OCC::AccountState *accountState); + +private: + explicit FileProviderDomainManager(QObject *parent = nullptr); + static FileProviderDomainManager *_instance; + class Private; + QScopedPointer d; + +}; + +} // namespace Mac + +} // namespace OCC diff --git a/src/gui/macOS/fileproviderdomainmanager_mac.mm b/src/gui/macOS/fileproviderdomainmanager_mac.mm new file mode 100644 index 000000000..6e670763b --- /dev/null +++ b/src/gui/macOS/fileproviderdomainmanager_mac.mm @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2022 by Claudio Cambra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "fileproviderdomainmanager.h" + +#import + +#include + +#include "gui/accountmanager.h" +#include "gui/accountstate.h" +#include "libsync/account.h" + +namespace OCC { + +Q_LOGGING_CATEGORY(lcMacFileProviderDomainManager, "nextcloud.gui.macfileproviderdomainmanager", QtInfoMsg) + +namespace Mac { + +FileProviderDomainManager *FileProviderDomainManager::_instance = nullptr; + +class FileProviderDomainManager::Private { + public: + Private() + { + } + + ~Private() = default; + + void addFileProviderDomain(const AccountState *accountState) + { + const QString accountDisplayName = accountState->account()->displayName(); + const QString accountId = accountState->account()->id(); + + qCDebug(lcMacFileProviderDomainManager) << "Adding new file provider domain for account with id: " << accountId; + + if(_registeredDomains.contains(accountId) && _registeredDomains.value(accountId) != nil) { + qCDebug(lcMacFileProviderDomainManager) << "File provider domain for account with id already exists: " << accountId; + return; + } + + NSFileProviderDomain *fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:accountId.toNSString() + displayName:accountDisplayName.toNSString()]; + [NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError *error) { + if(error) { + qCDebug(lcMacFileProviderDomainManager) << "Error adding file provider domain: " + << [error code] + << [error localizedDescription]; + } + }]; + + _registeredDomains.insert(accountId, fileProviderDomain); + } + + void removeFileProviderDomain(const AccountState *accountState) + { + const QString accountId = accountState->account()->id(); + qCDebug(lcMacFileProviderDomainManager) << "Removing file provider domain for account with id: " << accountId; + + if(!_registeredDomains.contains(accountId)) { + qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << accountId; + return; + } + + NSFileProviderDomain* fileProviderDomain = _registeredDomains[accountId]; + + [NSFileProviderManager removeDomain:fileProviderDomain completionHandler:^(NSError *error) { + if(error) { + qCDebug(lcMacFileProviderDomainManager) << "Error removing file provider domain: " + << [error code] + << [error localizedDescription]; + } + }]; + + NSFileProviderDomain* domain = _registeredDomains.take(accountId); + [domain release]; + } + + void removeAllFileProviderDomains() + { + qCDebug(lcMacFileProviderDomainManager) << "Removing all file provider domains."; + + [NSFileProviderManager removeAllDomainsWithCompletionHandler:^(NSError *error) { + if(error) { + qCDebug(lcMacFileProviderDomainManager) << "Error removing all file provider domains: " + << [error code] + << [error localizedDescription]; + } + }]; + } + + void setFileProviderDomainConnected(const AccountState *accountState) + { + const QString accountDisplayName = accountState->account()->displayName(); + const QString accountId = accountState->account()->id(); + const bool accountIsConnected = accountState->isConnected(); + + qCDebug(lcMacFileProviderDomainManager) << "Account state for account changed: " + << accountDisplayName + << accountIsConnected; + + if(!_registeredDomains.contains(accountId)) { + qCDebug(lcMacFileProviderDomainManager) << "File provider domain not found for id: " << accountId; + return; + } + + NSFileProviderDomain* accountDomain = _registeredDomains.value(accountId); + NSFileProviderManager* providerManager = [NSFileProviderManager managerForDomain:accountDomain]; + + if(accountIsConnected) { + [providerManager reconnectWithCompletionHandler:^(NSError *error) { + if(error) { + qCDebug(lcMacFileProviderDomainManager) << "Error reconnecting file provider domain: " + << accountDisplayName + << [error code] + << [error localizedDescription]; + } + }]; + } else { + NSString* reason = @"Nextcloud account disconnected."; + const auto isTemporary = accountState->state() != AccountState::SignedOut && + accountState->state() != AccountState::ConfigurationError; + NSFileProviderManagerDisconnectionOptions disconnectOption = isTemporary ? 0 : NSFileProviderManagerDisconnectionOptionsTemporary; + + [providerManager disconnectWithReason:reason options:disconnectOption completionHandler:^(NSError *error) { + if(error) { + qCDebug(lcMacFileProviderDomainManager) << "Error disconnecting file provider domain: " + << accountDisplayName + << [error code] + << [error localizedDescription]; + } + }]; + } + } + +private: + QHash _registeredDomains; +}; + +FileProviderDomainManager::FileProviderDomainManager(QObject *parent) + : QObject(parent) +{ + d.reset(new FileProviderDomainManager::Private()); + + connect(AccountManager::instance(), &AccountManager::accountAdded, + this, &FileProviderDomainManager::addFileProviderDomainForAccount); + connect(AccountManager::instance(), &AccountManager::accountRemoved, + this, &FileProviderDomainManager::removeFileProviderDomainForAccount); + + setupFileProviderDomains(); // Initially fetch accounts in manager +} + +FileProviderDomainManager::~FileProviderDomainManager() +{ + d->removeAllFileProviderDomains(); +} + +FileProviderDomainManager *FileProviderDomainManager::instance() +{ + if (!_instance) { + _instance = new FileProviderDomainManager(); + } + return _instance; +} + +void FileProviderDomainManager::setupFileProviderDomains() +{ + for(auto &accountState : AccountManager::instance()->accounts()) { + addFileProviderDomainForAccount(accountState.data()); + } +} + +void FileProviderDomainManager::addFileProviderDomainForAccount(AccountState *accountState) +{ + d->addFileProviderDomain(accountState); + + connect(accountState, &AccountState::isConnectedChanged, + this, [this, accountState]{ setFileProviderForAccountIsConnected(accountState); }); +} + +void FileProviderDomainManager::removeFileProviderDomainForAccount(AccountState* accountState) +{ + d->removeFileProviderDomain(accountState); +} + +void FileProviderDomainManager::setFileProviderForAccountIsConnected(AccountState *accountState) +{ + d->setFileProviderDomainConnected(accountState); +} + +} // namespace Mac + +} // namespace OCC diff --git a/src/gui/macOS/fileproviderinterface.h b/src/gui/macOS/fileproviderinterface.h deleted file mode 100644 index fe722ae04..000000000 --- a/src/gui/macOS/fileproviderinterface.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef FILEPROVIDERINTERFACE_H -#define FILEPROVIDERINTERFACE_H - -#endif // FILEPROVIDERINTERFACE_H