From c4dfa826612bf37424dca8b5246dcc4e9118336e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 26 Nov 2020 23:06:03 +0100 Subject: [PATCH] SocketAPI: Overhaul ui for 'available locally' vs 'online only' For #6815 --- src/gui/socketapi.cpp | 81 ++++++++++++++++++++++++------------------- src/gui/socketapi.h | 7 ++-- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index 27681d1f8..62fa674c7 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -686,26 +686,19 @@ void SocketApi::command_OPEN_PRIVATE_LINK(const QString &localFile, SocketListen fetchPrivateLinkUrlHelper(localFile, &SocketApi::openPrivateLink); } -void SocketApi::command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketListener *) +void SocketApi::command_MAKE_AVAILABLE_LOCALLY(const QString &filesArg, SocketListener *) { QStringList files = filesArg.split(QLatin1Char('\x1e')); // Record Separator for (const auto &file : files) { auto data = FileData::get(file); - auto record = data.journalRecord(); - if (!record.isValid()) - continue; - bool isDir = QFileInfo(data.localPath).isDir(); - if (record._type != ItemTypeVirtualFile && !isDir) - continue; if (!data.folder) continue; - // For directories, update their pin state so new files are available locally too - if (isDir) { - data.folder->journalDb()->setPinStateForPath( - data.folderRelativePath.toUtf8(), PinState::AlwaysLocal); - } + // Update the pin state on all items + auto pinPath = data.folderRelativePathNoVfsSuffix().toUtf8(); + data.folder->journalDb()->wipePinStateForPathAndBelow(pinPath); + data.folder->journalDb()->setPinStateForPath(pinPath, PinState::AlwaysLocal); // Trigger the recursive download data.folder->downloadVirtualFile(data.folderRelativePath); @@ -713,7 +706,7 @@ void SocketApi::command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketLis } /* Go over all the files and replace them by a virtual file */ -void SocketApi::command_REPLACE_VIRTUAL_FILE(const QString &filesArg, SocketListener *) +void SocketApi::command_MAKE_ONLINE_ONLY(const QString &filesArg, SocketListener *) { QStringList files = filesArg.split(QLatin1Char('\x1e')); // Record Separator @@ -722,11 +715,10 @@ void SocketApi::command_REPLACE_VIRTUAL_FILE(const QString &filesArg, SocketList if (!data.folder) continue; - // For directories, update the pin state so new files are available online-only - if (QFileInfo(data.localPath).isDir()) { - data.folder->journalDb()->setPinStateForPath( - data.folderRelativePath.toUtf8(), PinState::OnlineOnly); - } + // Update the pin state on all items + auto pinPath = data.folderRelativePathNoVfsSuffix().toUtf8(); + data.folder->journalDb()->wipePinStateForPathAndBelow(pinPath); + data.folder->journalDb()->setPinStateForPath(pinPath, PinState::OnlineOnly); // Trigger recursive dehydration data.folder->dehydrateFile(data.folderRelativePath); @@ -902,6 +894,16 @@ SocketApi::FileData SocketApi::FileData::get(const QString &localFile) return data; } +QString SocketApi::FileData::folderRelativePathNoVfsSuffix() const +{ + auto result = folderRelativePath; + QString virtualFileExt = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX); + if (result.endsWith(virtualFileExt)) { + result.chop(virtualFileExt.size()); + } + return result; +} + SyncFileStatus SocketApi::FileData::syncFileStatus() const { if (!folder) @@ -1006,27 +1008,36 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe } } - // Virtual file download action - if (syncFolder) { - bool hasVirtualFile = false; - bool hasNormalFiles = false; - bool hasDir = false; + // File availability actions + if (syncFolder && syncFolder->supportsVirtualFiles()) { + bool hasAlwaysLocal = false; + bool hasOnlineOnly = false; for (const auto &file : files) { - if (QFileInfo(file).isDir()) { - hasDir = true; - } else if (!hasVirtualFile || !hasNormalFiles) { - auto record = FileData::get(file).journalRecord(); - if (record.isValid()) { - hasVirtualFile |= record._type == ItemTypeVirtualFile; - hasNormalFiles |= record._type == ItemTypeFile; - } + auto path = FileData::get(file).folderRelativePathNoVfsSuffix(); + auto pinState = syncFolder->journalDb()->effectivePinStateForPath(path.toUtf8()); + if (!pinState) { + // db error + hasAlwaysLocal = true; + hasOnlineOnly = true; + } else if (*pinState == PinState::AlwaysLocal) { + hasAlwaysLocal = true; + } else if (*pinState == PinState::OnlineOnly) { + hasOnlineOnly = true; } } - if (hasVirtualFile || (hasDir && syncFolder->supportsVirtualFiles())) - listener->sendMessage(QLatin1String("MENU_ITEM:DOWNLOAD_VIRTUAL_FILE::") + tr("Keep updated locally, download if necessary", "", files.size())); - if ((hasNormalFiles || hasDir) && syncFolder->supportsVirtualFiles()) - listener->sendMessage(QLatin1String("MENU_ITEM:REPLACE_VIRTUAL_FILE::") + tr("Make available on demand, clear local data", "", files.size())); + // TODO: Should be a submenu, should use menu item checkmarks where available, should use icons + if (hasAlwaysLocal && !hasOnlineOnly) { + listener->sendMessage(QLatin1String("MENU_ITEM:CURRENT_PIN:d:") + tr("Currently available locally")); + listener->sendMessage(QLatin1String("MENU_ITEM:MAKE_ONLINE_ONLY::") + tr("Make available online only")); + } else if (hasOnlineOnly && !hasAlwaysLocal) { + listener->sendMessage(QLatin1String("MENU_ITEM:CURRENT_PIN:d:") + tr("Currently available online only")); + listener->sendMessage(QLatin1String("MENU_ITEM:MAKE_AVAILABLE_LOCALLY::") + tr("Make available locally")); + } else if (hasOnlineOnly && hasAlwaysLocal) { + listener->sendMessage(QLatin1String("MENU_ITEM:CURRENT_PIN:d:") + tr("Current availability is mixed")); + listener->sendMessage(QLatin1String("MENU_ITEM:MAKE_AVAILABLE_LOCALLY::") + tr("Make all available locally")); + listener->sendMessage(QLatin1String("MENU_ITEM:MAKE_ONLINE_ONLY::") + tr("Make all available online only")); + } } listener->sendMessage(QString("GET_MENU_ITEMS:END")); diff --git a/src/gui/socketapi.h b/src/gui/socketapi.h index e16bee72a..d23c3df52 100644 --- a/src/gui/socketapi.h +++ b/src/gui/socketapi.h @@ -81,6 +81,9 @@ private: SyncJournalFileRecord journalRecord() const; FileData parentFolder() const; + // Relative path of the file locally, without any vfs suffix + QString folderRelativePathNoVfsSuffix() const; + Folder *folder; // Absolute path of the file locally. (May be a virtual file) QString localPath; @@ -109,8 +112,8 @@ private: Q_INVOKABLE void command_COPY_PRIVATE_LINK(const QString &localFile, SocketListener *listener); Q_INVOKABLE void command_EMAIL_PRIVATE_LINK(const QString &localFile, SocketListener *listener); Q_INVOKABLE void command_OPEN_PRIVATE_LINK(const QString &localFile, SocketListener *listener); - Q_INVOKABLE void command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketListener *listener); - Q_INVOKABLE void command_REPLACE_VIRTUAL_FILE(const QString &filesArg, SocketListener *listener); + Q_INVOKABLE void command_MAKE_AVAILABLE_LOCALLY(const QString &filesArg, SocketListener *listener); + Q_INVOKABLE void command_MAKE_ONLINE_ONLY(const QString &filesArg, SocketListener *listener); Q_INVOKABLE void command_RESOLVE_CONFLICT(const QString &localFile, SocketListener *listener); Q_INVOKABLE void command_DELETE_ITEM(const QString &localFile, SocketListener *listener); Q_INVOKABLE void command_MOVE_ITEM(const QString &localFile, SocketListener *listener); -- 2.30.2