This commit is contained in:
Julian Thanner 2025-10-22 10:57:29 -05:00 committed by GitHub
commit 95423e8fbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 130 additions and 0 deletions

View File

@ -29,6 +29,30 @@ Q_LOGGING_CATEGORY(lcMacFileProviderDomainManager, "nextcloud.gui.macfileprovide
// are consistent throughout these classes
namespace {
// Helper function to get custom folder name directly from NSUserDefaults
// without going through FileProviderSettingsController singleton to avoid
// circular dependency during initialization
QString customFolderNameFromUserDefaults(const QString &accountId)
{
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
NSString *customFolderNamesKey = @"customFolderNames";
NSDictionary<NSString *, NSString *> *customFolderNames =
(NSDictionary<NSString *, NSString *> *)[userDefaults objectForKey:customFolderNamesKey];
if (customFolderNames == nil) {
return QString();
}
NSString *folderName = [customFolderNames objectForKey:accountId.toNSString()];
if (folderName == nil) {
return QString();
}
return QString::fromNSString(folderName);
}
QString uuidDomainIdentifierForAccount(const OCC::Account * const account)
{
Q_ASSERT(account);
@ -72,6 +96,20 @@ inline QString uuidDomainIdentifierForAccount(const OCC::AccountPtr account)
inline QString domainDisplayNameForAccount(const OCC::Account * const account)
{
Q_ASSERT(account);
const auto accountId = account->userIdAtHostWithPort();
// Access custom folder name directly from NSUserDefaults to avoid circular dependency
// with FileProviderSettingsController singleton during initialization
const auto customFolderName = customFolderNameFromUserDefaults(accountId);
if (!customFolderName.isEmpty()) {
qCDebug(OCC::lcMacFileProviderDomainManager) << "Using custom folder name"
<< customFolderName
<< "for account"
<< accountId;
return customFolderName;
}
return account->displayName();
}

View File

@ -37,6 +37,7 @@ public:
[[nodiscard]] Q_INVOKABLE float remoteStorageUsageGbForAccount(const QString &userIdAtHost) const;
[[nodiscard]] Q_INVOKABLE bool trashDeletionEnabledForAccount(const QString &userIdAtHost) const;
[[nodiscard]] Q_INVOKABLE bool trashDeletionSetForAccount(const QString &userIdAtHost) const;
[[nodiscard]] Q_INVOKABLE QString customFolderNameForAccount(const QString &userIdAtHost) const;
[[nodiscard]] Q_INVOKABLE QAbstractListModel *materialisedItemsModelForAccount(const QString &userIdAtHost);
[[nodiscard]] Q_INVOKABLE FileProviderDomainSyncStatus *domainSyncStatusForAccount(const QString &userIdAtHost) const;
@ -44,6 +45,7 @@ public:
public slots:
void setVfsEnabledForAccount(const QString &userIdAtHost, const bool setEnabled, const bool showInformationDialog = true);
void setTrashDeletionEnabledForAccount(const QString &userIdAtHost, const bool setEnabled);
void setCustomFolderNameForAccount(const QString &userIdAtHost, const QString &folderName);
void resetVfsForAccount(const QString &userIdAtHost);
void createEvictionWindowForAccount(const QString &userIdAtHost);
@ -57,6 +59,7 @@ signals:
void materialisedItemsForAccountChanged(const QString &userIdAtHost);
void trashDeletionEnabledForAccountChanged(const QString &userIdAtHost);
void trashDeletionSetForAccountChanged(const QString &userIdAtHost);
void customFolderNameForAccountChanged(const QString &userIdAtHost);
private:
explicit FileProviderSettingsController(QObject *parent = nullptr);

View File

@ -31,6 +31,7 @@ constexpr auto fpMaterialisedItemsModelProp = "materialisedItemsModel";
// NSUserDefaults entries
constexpr auto enabledAccountsSettingsKey = "enabledAccounts";
constexpr auto customFolderNamesSettingsKey = "customFolderNames";
float gbFromBytesWithOneDecimal(const unsigned long long bytes)
{
@ -182,6 +183,48 @@ public:
return _fileProviderDomainSyncStatuses.value(userIdAtHost);
}
[[nodiscard]] QString customFolderNameForAccount(const QString &userIdAtHost) const
{
NSDictionary<NSString *, NSString *> *const customFolderNames = nsCustomFolderNames();
if (customFolderNames == nil) {
return QString();
}
NSString *const folderName = [customFolderNames objectForKey:userIdAtHost.toNSString()];
if (folderName == nil) {
return QString();
}
return QString::fromNSString(folderName);
}
void setCustomFolderNameForAccount(const QString &userIdAtHost, const QString &folderName)
{
qCInfo(lcFileProviderSettingsController) << "Setting custom folder name for account"
<< userIdAtHost
<< "to"
<< folderName;
NSDictionary<NSString *, NSString *> *customFolderNames = nsCustomFolderNames();
if (customFolderNames == nil) {
customFolderNames = @{};
}
NSMutableDictionary<NSString *, NSString *> *const mutableCustomFolderNames = customFolderNames.mutableCopy;
if (folderName.isEmpty()) {
[mutableCustomFolderNames removeObjectForKey:userIdAtHost.toNSString()];
} else {
[mutableCustomFolderNames setObject:folderName.toNSString() forKey:userIdAtHost.toNSString()];
}
[_userDefaults setObject:mutableCustomFolderNames forKey:_customFolderNamesKey];
[_userDefaults synchronize];
}
public slots:
// NOTE: This method will release the provided args so make sure to retain them beforehand
void enumerateMaterialisedFilesForDomainManager(NSFileProviderManager * const managerForDomain,
@ -253,6 +296,11 @@ private:
{
return (NSArray<NSString *> *)[_userDefaults objectForKey:_accountsKey];
}
[[nodiscard]] NSDictionary<NSString *, NSString *> *nsCustomFolderNames() const
{
return (NSDictionary<NSString *, NSString *> *)[_userDefaults objectForKey:_customFolderNamesKey];
}
void fetchMaterialisedFilesStorageUsage()
{
@ -313,6 +361,7 @@ private:
FileProviderSettingsController *q = nullptr;
NSUserDefaults *_userDefaults = NSUserDefaults.standardUserDefaults;
NSString *_accountsKey = [NSString stringWithUTF8String:enabledAccountsSettingsKey];
NSString *_customFolderNamesKey = [NSString stringWithUTF8String:customFolderNamesSettingsKey];
QHash<QString, QVector<FileProviderItemMetadata>> _materialisedFiles;
QHash<QString, unsigned long long> _storageUsage;
QHash<QString, FileProviderDomainSyncStatus*> _fileProviderDomainSyncStatuses;
@ -514,6 +563,17 @@ FileProviderDomainSyncStatus *FileProviderSettingsController::domainSyncStatusFo
return d->domainSyncStatusForAccount(userIdAtHost);
}
QString FileProviderSettingsController::customFolderNameForAccount(const QString &userIdAtHost) const
{
return d->customFolderNameForAccount(userIdAtHost);
}
void FileProviderSettingsController::setCustomFolderNameForAccount(const QString &userIdAtHost, const QString &folderName)
{
d->setCustomFolderNameForAccount(userIdAtHost, folderName);
emit customFolderNameForAccountChanged(userIdAtHost);
}
void FileProviderSettingsController::resetVfsForAccount(const QString &userIdAtHost)
{
qCInfo(lcFileProviderSettingsController) << "Resetting virtual files environment for account" << userIdAtHost;

View File

@ -54,6 +54,35 @@ Page {
onClicked: root.controller.setVfsEnabledForAccount(root.accountUserIdAtHost, checked)
}
RowLayout {
Layout.fillWidth: true
spacing: Style.standardSpacing
EnforcedPlainTextLabel {
text: qsTr("Custom folder name:")
Layout.preferredWidth: 150
}
TextField {
id: customFolderNameField
Layout.fillWidth: true
placeholderText: qsTr("Enter custom folder name (leave empty for default)")
text: root.controller.customFolderNameForAccount(root.accountUserIdAtHost)
onEditingFinished: root.controller.setCustomFolderNameForAccount(root.accountUserIdAtHost, text)
Connections {
target: root.controller
function onCustomFolderNameForAccountChanged(accountUserIdAtHost) {
if (root.accountUserIdAtHost !== accountUserIdAtHost) {
return;
}
customFolderNameField.text = root.controller.customFolderNameForAccount(root.accountUserIdAtHost);
}
}
}
}
Loader {
id: vfsSettingsLoader