mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-21 20:45:51 +03:00
Merge pull request #6467 from nextcloud/feature/file-provide-file-eviction
This commit is contained in:
commit
0e301e75d9
7 changed files with 139 additions and 57 deletions
|
@ -32,13 +32,25 @@ class FileProviderItem: NSObject, NSFileProviderItem {
|
|||
|
||||
var capabilities: NSFileProviderItemCapabilities {
|
||||
guard !metadata.directory else {
|
||||
return [
|
||||
.allowsAddingSubItems,
|
||||
.allowsContentEnumerating,
|
||||
.allowsReading,
|
||||
.allowsDeleting,
|
||||
.allowsRenaming,
|
||||
]
|
||||
if #available(macOS 13.0, *) {
|
||||
// .allowsEvicting deprecated on macOS 13.0+, use contentPolicy instead
|
||||
return [
|
||||
.allowsAddingSubItems,
|
||||
.allowsContentEnumerating,
|
||||
.allowsReading,
|
||||
.allowsDeleting,
|
||||
.allowsRenaming
|
||||
]
|
||||
} else {
|
||||
return [
|
||||
.allowsAddingSubItems,
|
||||
.allowsContentEnumerating,
|
||||
.allowsReading,
|
||||
.allowsDeleting,
|
||||
.allowsRenaming,
|
||||
.allowsEvicting
|
||||
]
|
||||
}
|
||||
}
|
||||
guard !metadata.lock else {
|
||||
return [.allowsReading]
|
||||
|
@ -49,6 +61,7 @@ class FileProviderItem: NSObject, NSFileProviderItem {
|
|||
.allowsDeleting,
|
||||
.allowsRenaming,
|
||||
.allowsReparenting,
|
||||
.allowsEvicting
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -133,6 +146,11 @@ class FileProviderItem: NSObject, NSFileProviderItem {
|
|||
}
|
||||
}
|
||||
|
||||
@available(macOSApplicationExtension 13.0, *)
|
||||
var contentPolicy: NSFileProviderContentPolicy {
|
||||
.downloadLazily
|
||||
}
|
||||
|
||||
required init(
|
||||
metadata: NextcloudItemMetadataTable,
|
||||
parentItemIdentifier: NSFileProviderItemIdentifier,
|
||||
|
|
|
@ -55,6 +55,7 @@ public slots:
|
|||
void setFastEnumerationEnabledForAccount(const QString &userIdAtHost, const bool setEnabled);
|
||||
|
||||
void createEvictionWindowForAccount(const QString &userIdAtHost);
|
||||
void refreshMaterialisedItemsForAccount(const QString &userIdAtHost);
|
||||
void signalFileProviderDomain(const QString &userIdAtHost);
|
||||
void createDebugArchive(const QString &userIdAtHost);
|
||||
|
||||
|
|
|
@ -185,6 +185,53 @@ public:
|
|||
return _fileProviderDomainSyncStatuses.value(userIdAtHost);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void enumerateMaterialisedFilesForDomainManager(NSFileProviderManager * const managerForDomain,
|
||||
NSFileProviderDomain * const domain)
|
||||
{
|
||||
const id<NSFileProviderEnumerator> enumerator = [managerForDomain enumeratorForMaterializedItems];
|
||||
Q_ASSERT(enumerator != nil);
|
||||
[enumerator retain];
|
||||
|
||||
FileProviderStorageUseEnumerationObserver *const storageUseObserver = [[FileProviderStorageUseEnumerationObserver alloc] init];
|
||||
[storageUseObserver retain];
|
||||
storageUseObserver.enumerationFinishedHandler = ^(NSError *const error) {
|
||||
qCInfo(lcFileProviderSettingsController) << "Enumeration finished for" << domain.identifier;
|
||||
if (error != nil) {
|
||||
qCWarning(lcFileProviderSettingsController) << "Error while enumerating storage use" << error.localizedDescription;
|
||||
[storageUseObserver release];
|
||||
[enumerator release];
|
||||
return;
|
||||
}
|
||||
|
||||
const auto items = storageUseObserver.materialisedItems;
|
||||
Q_ASSERT(items != nil);
|
||||
|
||||
// Remember that OCC::Account::userIdAtHost == domain.identifier for us
|
||||
const auto qDomainIdentifier = QString::fromNSString(domain.identifier);
|
||||
QVector<FileProviderItemMetadata> qMaterialisedItems;
|
||||
qMaterialisedItems.reserve(items.count);
|
||||
for (const id<NSFileProviderItem> item in items) {
|
||||
const auto itemMetadata = FileProviderItemMetadata::fromNSFileProviderItem(item, qDomainIdentifier);
|
||||
const auto storageUsage = _storageUsage.value(qDomainIdentifier) + itemMetadata.documentSize();
|
||||
qCDebug(lcFileProviderSettingsController) << "Adding item" << itemMetadata.identifier()
|
||||
<< "with size" << itemMetadata.documentSize()
|
||||
<< "to storage usage for account" << qDomainIdentifier
|
||||
<< "with total size" << storageUsage;
|
||||
qMaterialisedItems.append(itemMetadata);
|
||||
_storageUsage.insert(qDomainIdentifier, storageUsage);
|
||||
}
|
||||
_materialisedFiles.insert(qDomainIdentifier, qMaterialisedItems);
|
||||
|
||||
emit q->localStorageUsageForAccountChanged(qDomainIdentifier);
|
||||
emit q->materialisedItemsForAccountChanged(qDomainIdentifier);
|
||||
|
||||
[storageUseObserver release];
|
||||
[enumerator release];
|
||||
};
|
||||
[enumerator enumerateItemsForObserver:storageUseObserver startingAtPage:NSFileProviderInitialPageSortedByName];
|
||||
}
|
||||
|
||||
private slots:
|
||||
void updateDomainSyncStatuses()
|
||||
{
|
||||
|
@ -237,47 +284,7 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
const id<NSFileProviderEnumerator> enumerator = [managerForDomain enumeratorForMaterializedItems];
|
||||
Q_ASSERT(enumerator != nil);
|
||||
[enumerator retain];
|
||||
|
||||
FileProviderStorageUseEnumerationObserver *const storageUseObserver = [[FileProviderStorageUseEnumerationObserver alloc] init];
|
||||
[storageUseObserver retain];
|
||||
storageUseObserver.enumerationFinishedHandler = ^(NSError *const error) {
|
||||
qCInfo(lcFileProviderSettingsController) << "Enumeration finished for" << domain.identifier;
|
||||
if (error != nil) {
|
||||
qCWarning(lcFileProviderSettingsController) << "Error while enumerating storage use" << error.localizedDescription;
|
||||
[storageUseObserver release];
|
||||
[enumerator release];
|
||||
return;
|
||||
}
|
||||
|
||||
const auto items = storageUseObserver.materialisedItems;
|
||||
Q_ASSERT(items != nil);
|
||||
|
||||
// Remember that OCC::Account::userIdAtHost == domain.identifier for us
|
||||
const auto qDomainIdentifier = QString::fromNSString(domain.identifier);
|
||||
QVector<FileProviderItemMetadata> qMaterialisedItems;
|
||||
qMaterialisedItems.reserve(items.count);
|
||||
for (const id<NSFileProviderItem> item in items) {
|
||||
const auto itemMetadata = FileProviderItemMetadata::fromNSFileProviderItem(item, qDomainIdentifier);
|
||||
const auto storageUsage = _storageUsage.value(qDomainIdentifier) + itemMetadata.documentSize();
|
||||
qCDebug(lcFileProviderSettingsController) << "Adding item" << itemMetadata.identifier()
|
||||
<< "with size" << itemMetadata.documentSize()
|
||||
<< "to storage usage for account" << qDomainIdentifier
|
||||
<< "with total size" << storageUsage;
|
||||
qMaterialisedItems.append(itemMetadata);
|
||||
_storageUsage.insert(qDomainIdentifier, storageUsage);
|
||||
}
|
||||
_materialisedFiles.insert(qDomainIdentifier, qMaterialisedItems);
|
||||
|
||||
emit q->localStorageUsageForAccountChanged(qDomainIdentifier);
|
||||
emit q->materialisedItemsForAccountChanged(qDomainIdentifier);
|
||||
|
||||
[storageUseObserver release];
|
||||
[enumerator release];
|
||||
};
|
||||
[enumerator enumerateItemsForObserver:storageUseObserver startingAtPage:NSFileProviderInitialPageSortedByName];
|
||||
enumerateMaterialisedFilesForDomainManager(managerForDomain, domain);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
@ -435,7 +442,8 @@ QAbstractListModel *FileProviderSettingsController::materialisedItemsModelForAcc
|
|||
const auto model = new FileProviderMaterialisedItemsModel(this);
|
||||
model->setItems(items);
|
||||
|
||||
connect(this, &FileProviderSettingsController::materialisedItemsForAccountChanged, model, [this, model, userIdAtHost](const QString &accountUserIdAtHost) {
|
||||
connect(this, &FileProviderSettingsController::materialisedItemsForAccountChanged,
|
||||
model, [this, model, userIdAtHost](const QString &accountUserIdAtHost) {
|
||||
if (accountUserIdAtHost != userIdAtHost) {
|
||||
return;
|
||||
}
|
||||
|
@ -457,10 +465,18 @@ void FileProviderSettingsController::createEvictionWindowForAccount(const QStrin
|
|||
{fpMaterialisedItemsModelProp, QVariant::fromValue(model)},
|
||||
});
|
||||
const auto dialog = qobject_cast<QQuickWindow *>(genericDialog);
|
||||
QObject::connect(dialog, SIGNAL(reloadMaterialisedItems(QString)),
|
||||
this, SLOT(refreshMaterialisedItemsForAccount(QString)));
|
||||
Q_ASSERT(dialog);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void FileProviderSettingsController::refreshMaterialisedItemsForAccount(const QString &userIdAtHost)
|
||||
{
|
||||
d->enumerateMaterialisedFilesForDomainManager(FileProviderUtils::managerForDomainIdentifier(userIdAtHost),
|
||||
FileProviderUtils::domainForIdentifier(userIdAtHost));
|
||||
}
|
||||
|
||||
void FileProviderSettingsController::signalFileProviderDomain(const QString &userIdAtHost)
|
||||
{
|
||||
d->signalFileProviderDomain(userIdAtHost);
|
||||
|
|
|
@ -25,21 +25,58 @@ import com.nextcloud.desktopclient 1.0
|
|||
ApplicationWindow {
|
||||
id: root
|
||||
|
||||
signal reloadMaterialisedItems(string accountUserIdAtHost)
|
||||
|
||||
property var materialisedItemsModel: null
|
||||
property string accountUserIdAtHost: ""
|
||||
|
||||
title: qsTr("Evict materialised files")
|
||||
color: Style.backgroundColor
|
||||
flags: Qt.Dialog | Qt.WindowStaysOnTopHint
|
||||
width: 640
|
||||
height: 480
|
||||
|
||||
ListView {
|
||||
Component.onCompleted: reloadMaterialisedItems(accountUserIdAtHost)
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
model: root.materialisedItemsModel
|
||||
delegate: FileProviderFileDelegate {
|
||||
width: parent.width
|
||||
height: 60
|
||||
onEvictItem: root.materialisedItemsModel.evictItem(identifier, domainIdentifier)
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: Style.standardSpacing
|
||||
|
||||
EnforcedPlainTextLabel {
|
||||
text: qsTr("Materialised items")
|
||||
font.bold: true
|
||||
font.pointSize: Style.headerFontPtSize
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
CustomButton {
|
||||
padding: Style.smallSpacing
|
||||
textColor: Style.ncTextColor
|
||||
textColorHovered: Style.ncHeaderTextColor
|
||||
contentsFont.bold: true
|
||||
bgColor: Style.ncBlue
|
||||
text: qsTr("Reload")
|
||||
onClicked: reloadMaterialisedItems(accountUserIdAtHost)
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Layout.leftMargin: Style.standardSpacing
|
||||
Layout.rightMargin: Style.standardSpacing
|
||||
|
||||
clip: true
|
||||
model: root.materialisedItemsModel
|
||||
delegate: FileProviderFileDelegate {
|
||||
width: parent.width
|
||||
height: 60
|
||||
onEvictItem: root.materialisedItemsModel.evictItem(identifier, domainIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,11 +90,12 @@ Item {
|
|||
id: deleteButton
|
||||
|
||||
Layout.minimumWidth: implicitWidth
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
|
||||
text: qsTr("Delete")
|
||||
textColorHovered: Style.ncHeaderTextColor
|
||||
bgColor: Style.errorBoxBackgroundColor
|
||||
contentsFont.bold: true
|
||||
onClicked: root.evictItem(root.identifier, root.domainIdentifier)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ GridLayout {
|
|||
required property real remoteUsedStorage
|
||||
|
||||
Layout.fillWidth: true
|
||||
columns: 2
|
||||
columns: 3
|
||||
|
||||
EnforcedPlainTextLabel {
|
||||
Layout.row: 0
|
||||
|
@ -51,6 +51,14 @@ GridLayout {
|
|||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
|
||||
CustomButton {
|
||||
Layout.row: 0
|
||||
Layout.column: 2
|
||||
Layout.alignment: Layout.AlignRight | Layout.AlignVCenter
|
||||
text: qsTr("Evict local copies...")
|
||||
onPressed: root.evictDialogRequested()
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
Layout.row: 1
|
||||
Layout.columnSpan: root.columns
|
||||
|
|
|
@ -10,6 +10,7 @@ QtObject {
|
|||
|
||||
// Colors
|
||||
readonly property color ncBlue: Theme.wizardHeaderBackgroundColor
|
||||
readonly property color ncHeaderTextColor: Theme.wizardHeaderTitleColor
|
||||
readonly property color ncTextColor: Theme.systemPalette.windowText
|
||||
readonly property color ncTextBrightColor: "white"
|
||||
readonly property color ncSecondaryTextColor: "#808080"
|
||||
|
|
Loading…
Reference in a new issue