From 5943e961da40fa20d6bf3e3b72eeb6b0241b2833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Bari?= Date: Mon, 14 Jul 2025 22:06:22 +0200 Subject: [PATCH 1/2] Determining availability recursively for context menu actions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tamás Bari --- src/gui/socketapi/socketapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp index 6c2234168d263..117a6628cef61 100644 --- a/src/gui/socketapi/socketapi.cpp +++ b/src/gui/socketapi/socketapi.cpp @@ -1428,7 +1428,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe }; for (const auto &file : files) { auto fileData = FileData::get(file); - auto availability = syncFolder->vfs().availability(fileData.folderRelativePath, Vfs::AvailabilityRecursivity::NotRecursiveAvailability); + auto availability = syncFolder->vfs().availability(fileData.folderRelativePath, Vfs::AvailabilityRecursivity::RecursiveAvailability); if (!availability) { if (availability.error() == Vfs::AvailabilityError::DbError) availability = VfsItemAvailability::Mixed; From 8efa680f2d34324ac61e122335cfd6ab3d1757d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Bari?= Date: Mon, 14 Jul 2025 22:09:16 +0200 Subject: [PATCH 2/2] Making recursive availability check slightly more efficient. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tamás Bari --- src/libsync/vfs/cfapi/vfs_cfapi.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/libsync/vfs/cfapi/vfs_cfapi.cpp b/src/libsync/vfs/cfapi/vfs_cfapi.cpp index d292f23fc74e5..2c14c764eeff2 100644 --- a/src/libsync/vfs/cfapi/vfs_cfapi.cpp +++ b/src/libsync/vfs/cfapi/vfs_cfapi.cpp @@ -531,14 +531,12 @@ VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinState }; const auto dir = QDir(info.absoluteFilePath()); Q_ASSERT(dir.exists()); - const auto children = dir.entryList(); - return std::accumulate(std::cbegin(children), std::cend(children), dirState, [=](const HydratationAndPinStates ¤tState, const QString &name) { - if (name == QStringLiteral("..") || name == QStringLiteral(".")) { - return currentState; - } + + // if the folderPath.isEmpty() we don't want to end up having path "/example.file" because this will lead to double slash later, when appending to "SyncFolder/" + const auto pathPrefix = folderPath.isEmpty() ? QString() : folderPath + QDir::separator(); - // if the folderPath.isEmpty() we don't want to end up having path "/example.file" because this will lead to double slash later, when appending to "SyncFolder/" - const auto path = folderPath.isEmpty() ? name : folderPath + '/' + name; + auto accumulatorOperation = [=](const HydratationAndPinStates ¤tState, const QString &name) { + const auto path = pathPrefix + name; const auto states = computeRecursiveHydrationAndPinStates(path, currentState.pinState); return HydratationAndPinStates { states.pinState, @@ -547,7 +545,17 @@ VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinState states.hydrationStatus.hasDehydrated || currentState.hydrationStatus.hasDehydrated, } }; - }); + }; + + auto currentState = dirState; + for( const auto& child : dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot) ) { + if (currentState.hydrationStatus.hasHydrated && currentState.hydrationStatus.hasDehydrated) { + // Already found hydrated and dehydrated entries. All subsequent checks will yield the same result. + break; + } + currentState = accumulatorOperation( currentState, child ); + } + return currentState; } else { // file case const auto isDehydrated = isDehydratedPlaceholder(info.absoluteFilePath()); return {