Move file provider domain management to specific class

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
Claudio Cambra 2022-12-13 16:53:36 +01:00
parent 8ff2c24e8b
commit 8ccd0368a1
No known key found for this signature in database
GPG key ID: C839200C384636B0
6 changed files with 265 additions and 169 deletions

View file

@ -282,7 +282,9 @@ IF( APPLE )
list(APPEND client_SRCS systray.mm) list(APPEND client_SRCS systray.mm)
list(APPEND client_SRCS list(APPEND client_SRCS
macOS/fileprovider.h macOS/fileprovider.h
macOS/fileprovider_mac.mm) macOS/fileprovider_mac.mm
macOS/fileproviderdomainmanager.h
macOS/fileproviderdomainmanager_mac.mm)
if(SPARKLE_FOUND AND BUILD_UPDATER) if(SPARKLE_FOUND AND BUILD_UPDATER)
# Define this, we need to check in updater.cpp # Define this, we need to check in updater.cpp

View file

@ -12,16 +12,12 @@
* for more details. * for more details.
*/ */
#ifndef FILEPROVIDER_H #pragma once
#define FILEPROVIDER_H
#include <QObject> #include <QObject>
#include <QScopedPointer>
namespace OCC { namespace OCC {
class AccountState;
namespace Mac { namespace Mac {
// NOTE: For the file provider extension to work, the app bundle will // NOTE: For the file provider extension to work, the app bundle will
@ -31,23 +27,11 @@ class FileProvider : public QObject
{ {
public: public:
static FileProvider *instance(); static FileProvider *instance();
~FileProvider() override; ~FileProvider() = default;
void setupFileProviderDomains();
private slots:
void addFileProviderDomainForAccount(AccountState *accountState);
void removeFileProviderDomainForAccount(AccountState *accountState);
void setFileProviderForAccountIsConnected(AccountState *accountState);
private: private:
explicit FileProvider(QObject *parent = nullptr); explicit FileProvider(QObject *parent = nullptr);
static FileProvider *_instance;
class Private;
QScopedPointer<Private> d;
}; };
} // namespace Mac } // namespace Mac
} // namespace OCC } // namespace OCC
#endif

View file

@ -12,16 +12,12 @@
* for more details. * for more details.
*/ */
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <FileProvider/FileProvider.h>
#include <QLoggingCategory> #include <QLoggingCategory>
#include "gui/accountmanager.h"
#include "gui/accountstate.h"
#include "libsync/account.h"
#include "fileprovider.h" #include "fileprovider.h"
#include "fileproviderdomainmanager.h"
namespace OCC { namespace OCC {
@ -29,126 +25,15 @@ Q_LOGGING_CATEGORY(lcMacFileProvider, "nextcloud.gui.macfileprovider", QtInfoMsg
namespace Mac { namespace Mac {
FileProvider *FileProvider::_instance = nullptr; static 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<QString, NSFileProviderDomain*> _registeredDomains;
};
FileProvider::FileProvider(QObject *parent) FileProvider::FileProvider(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
d.reset(new FileProvider::Private()); const auto domainManager = FileProviderDomainManager::instance();
if (domainManager) {
connect(AccountManager::instance(), &AccountManager::accountAdded, qCDebug(lcMacFileProvider()) << "Initialized file provider domain manager";
this, &FileProvider::addFileProviderDomainForAccount); }
connect(AccountManager::instance(), &AccountManager::accountRemoved,
this, &FileProvider::removeFileProviderDomainForAccount);
setupFileProviderDomains(); // Initially fetch accounts in manager
}
FileProvider::~FileProvider()
{
d->removeAllFileProviderDomains();
} }
FileProvider *FileProvider::instance() FileProvider *FileProvider::instance()
@ -159,30 +44,5 @@ FileProvider *FileProvider::instance()
return _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 Mac
} // namespace OCC } // namespace OCC

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* 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 <QObject>
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<Private> d;
};
} // namespace Mac
} // namespace OCC

View file

@ -0,0 +1,204 @@
/*
* Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* 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 <FileProvider/FileProvider.h>
#include <QLoggingCategory>
#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<QString, NSFileProviderDomain*> _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

View file

@ -1,4 +0,0 @@
#ifndef FILEPROVIDERINTERFACE_H
#define FILEPROVIDERINTERFACE_H
#endif // FILEPROVIDERINTERFACE_H