Skip to content

Commit

Permalink
Merge pull request #6930 from nextcloud/bugfix/file-provider-sync-status
Browse files Browse the repository at this point in the history
Reflect File Provider domain sync status in tray icon (macOS VFS)
  • Loading branch information
claucambra authored Jul 23, 2024
2 parents 95e6b7b + 23a8f08 commit 1a79d63
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,29 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte
)
ncAccount = nil
}

func updatedSyncStateReporting(oldActions: Set<UUID>) {
actionsLock.lock()

guard oldActions.isEmpty != syncActions.isEmpty else {
actionsLock.unlock()
return
}

let command = "FILE_PROVIDER_DOMAIN_SYNC_STATE_CHANGE"
var argument: String?
if oldActions.isEmpty, !syncActions.isEmpty {
argument = "SYNC_STARTED"
} else if !oldActions.isEmpty, syncActions.isEmpty {
argument = errorActions.isEmpty ? "SYNC_FINISHED" : "SYNC_FAILED"
errorActions = []
}

actionsLock.unlock()

guard let argument else { return }
Logger.fileProviderExtension.debug("Reporting sync \(argument)")
let message = command + ":" + argument + "\n"
socketClient?.sendMessage(message)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// FileProviderExtension+EnumerationListener.swift
// FileProviderExt
//
// Created by Claudio Cambra on 16/7/24.
//

import Foundation
import NextcloudFileProviderKit

extension FileProviderExtension: EnumerationListener {
func enumerationActionStarted(actionId: UUID) {
insertSyncAction(actionId)
}

func enumerationActionFinished(actionId: UUID) {
removeSyncAction(actionId)
}

func enumerationActionFailed(actionId: UUID, error: Error) {
insertErrorAction(actionId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ import OSLog
return LocalSocketClient(socketPath: socketPath.path, lineProcessor: lineProcessor)
}()

var syncActions = Set<UUID>()
var errorActions = Set<UUID>()
var actionsLock = NSLock()

// Whether or not we are going to recursively scan new folders when they are discovered.
// Apple's recommendation is that we should always scan the file hierarchy fully.
// This does lead to long load times when a file provider domain is initially configured.
Expand Down Expand Up @@ -67,6 +71,32 @@ import OSLog
)
}

func insertSyncAction(_ actionId: UUID) {
actionsLock.lock()
let oldActions = syncActions
syncActions.insert(actionId)
actionsLock.unlock()
updatedSyncStateReporting(oldActions: oldActions)
}

func insertErrorAction(_ actionId: UUID) {
actionsLock.lock()
let oldActions = syncActions
syncActions.remove(actionId)
errorActions.insert(actionId)
actionsLock.unlock()
updatedSyncStateReporting(oldActions: oldActions)
}

func removeSyncAction(_ actionId: UUID) {
actionsLock.lock()
let oldActions = syncActions
syncActions.remove(actionId)
errorActions.remove(actionId)
actionsLock.unlock()
updatedSyncStateReporting(oldActions: oldActions)
}

// MARK: - NSFileProviderReplicatedExtension protocol methods

func item(
Expand All @@ -88,6 +118,9 @@ import OSLog
request: NSFileProviderRequest,
completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void
) -> Progress {
let actionId = UUID()
insertSyncAction(actionId)

Logger.fileProviderExtension.debug(
"Received request to fetch contents of item with identifier: \(itemIdentifier.rawValue, privacy: .public)"
)
Expand All @@ -97,6 +130,7 @@ import OSLog
Logger.fileProviderExtension.error(
"Can't return contents for a specific version as this is not supported."
)
insertErrorAction(actionId)
completionHandler(
nil,
nil,
Expand All @@ -112,6 +146,7 @@ import OSLog
as account not set up yet.
"""
)
insertErrorAction(actionId)
completionHandler(nil, nil, NSFileProviderError(.notAuthenticated))
return Progress()
}
Expand All @@ -124,6 +159,7 @@ import OSLog
"""
)
completionHandler(nil, nil, NSFileProviderError(.noSuchItem))
insertErrorAction(actionId)
return Progress()
}

Expand All @@ -132,6 +168,7 @@ import OSLog
let (localUrl, updatedItem, error) = await item.fetchContents(
domain: self.domain, progress: progress
)
removeSyncAction(actionId)
completionHandler(localUrl, updatedItem, error)
}
return progress
Expand All @@ -147,6 +184,8 @@ import OSLog
NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?
) -> Void
) -> Progress {
let actionId = UUID()
insertSyncAction(actionId)

let tempId = itemTemplate.itemIdentifier.rawValue
Logger.fileProviderExtension.debug(
Expand All @@ -163,6 +202,7 @@ import OSLog
as account not set up yet
"""
)
insertErrorAction(actionId)
completionHandler(
itemTemplate,
NSFileProviderItemFields(),
Expand All @@ -184,9 +224,14 @@ import OSLog
ncAccount: ncAccount,
progress: progress
)

if error != nil {
insertErrorAction(actionId)
signalEnumerator(completionHandler: { _ in })
} else {
removeSyncAction(actionId)
}

completionHandler(
item ?? itemTemplate,
NSFileProviderItemFields(),
Expand All @@ -210,6 +255,8 @@ import OSLog
) -> Progress {
// An item was modified on disk, process the item's modification
// TODO: Handle finder things like tags, other possible item changed fields
let actionId = UUID()
insertSyncAction(actionId)

let identifier = item.itemIdentifier
let ocId = identifier.rawValue
Expand All @@ -224,6 +271,7 @@ import OSLog
Logger.fileProviderExtension.error(
"Not modifying item: \(ocId, privacy: .public) as account not set up yet."
)
insertErrorAction(actionId)
completionHandler(item, [], false, NSFileProviderError(.notAuthenticated))
return Progress()
}
Expand All @@ -232,6 +280,7 @@ import OSLog
Logger.fileProviderExtension.error(
"Not modifying item: \(ocId, privacy: .public) as item not found."
)
insertErrorAction(actionId)
completionHandler(item, [], false, NSFileProviderError(.noSuchItem))
return Progress()
}
Expand All @@ -249,9 +298,14 @@ import OSLog
domain: domain,
progress: progress
)

if error != nil {
insertErrorAction(actionId)
signalEnumerator(completionHandler: { _ in })
} else {
removeSyncAction(actionId)
}

completionHandler(modifiedItem ?? item, [], false, error)
}
return progress
Expand All @@ -264,6 +318,9 @@ import OSLog
request _: NSFileProviderRequest,
completionHandler: @escaping (Error?) -> Void
) -> Progress {
let actionId = UUID()
insertSyncAction(actionId)

Logger.fileProviderExtension.debug(
"Received delete request for item: \(identifier.rawValue, privacy: .public)"
)
Expand All @@ -272,6 +329,7 @@ import OSLog
Logger.fileProviderExtension.error(
"Not deleting item \(identifier.rawValue, privacy: .public), account not set up yet"
)
insertErrorAction(actionId)
completionHandler(NSFileProviderError(.notAuthenticated))
return Progress()
}
Expand All @@ -280,6 +338,7 @@ import OSLog
Logger.fileProviderExtension.error(
"Not deleting item \(identifier.rawValue, privacy: .public), item not found"
)
insertErrorAction(actionId)
completionHandler(NSFileProviderError(.noSuchItem))
return Progress()
}
Expand All @@ -288,7 +347,10 @@ import OSLog
Task {
let error = await item.delete()
if error != nil {
insertErrorAction(actionId)
signalEnumerator(completionHandler: { _ in })
} else {
removeSyncAction(actionId)
}
progress.completedUnitCount = 1
completionHandler(await item.delete())
Expand All @@ -311,7 +373,8 @@ import OSLog
ncAccount: ncAccount,
remoteInterface: ncKit,
domain: domain,
fastEnumeration: config.fastEnumerationEnabled
fastEnumeration: config.fastEnumerationEnabled,
listener: self
)
}

Expand Down Expand Up @@ -342,6 +405,8 @@ import OSLog
materialisedEnumerator.enumerateItems(for: materialisedObserver, startingAt: startingPage)
}

// MARK: - Helper functions

func signalEnumerator(completionHandler: @escaping (_ error: Error?) -> Void) {
guard let fpManager = NSFileProviderManager(for: domain) else {
Logger.fileProviderExtension.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
5307A6E62965C6FA001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E52965C6FA001E0C6A /* NextcloudKit */; };
5307A6E82965DAD8001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E72965DAD8001E0C6A /* NextcloudKit */; };
531522822B8E01C6002E31BE /* ShareTableItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 531522812B8E01C6002E31BE /* ShareTableItemView.xib */; };
532572082C4690340068DEC3 /* FileProviderExtension+EnumerationListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532572072C4690340068DEC3 /* FileProviderExtension+EnumerationListener.swift */; };
5350E4E92B0C534A00F276CB /* ClientCommunicationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5350E4E82B0C534A00F276CB /* ClientCommunicationService.swift */; };
5352B36C29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */; };
5358F2B92BAA0F5300E3C729 /* NextcloudCapabilitiesKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5358F2B82BAA0F5300E3C729 /* NextcloudCapabilitiesKit */; };
Expand Down Expand Up @@ -148,6 +149,7 @@

/* Begin PBXFileReference section */
531522812B8E01C6002E31BE /* ShareTableItemView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShareTableItemView.xib; sourceTree = "<group>"; };
532572072C4690340068DEC3 /* FileProviderExtension+EnumerationListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+EnumerationListener.swift"; sourceTree = "<group>"; };
5350E4E72B0C514400F276CB /* ClientCommunicationProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClientCommunicationProtocol.h; sourceTree = "<group>"; };
5350E4E82B0C534A00F276CB /* ClientCommunicationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientCommunicationService.swift; sourceTree = "<group>"; };
5350E4EA2B0C9CE100F276CB /* FileProviderExt-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FileProviderExt-Bridging-Header.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -294,6 +296,7 @@
53D666602B70C9A70042C03D /* FileProviderConfig.swift */,
538E396C27F4765000FA63D5 /* FileProviderExtension.swift */,
53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */,
532572072C4690340068DEC3 /* FileProviderExtension+EnumerationListener.swift */,
5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */,
536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */,
538E397327F4765000FA63D5 /* FileProviderExt.entitlements */,
Expand Down Expand Up @@ -671,6 +674,7 @@
535AE30E29C0A2CC0042A9BA /* Logger+Extensions.swift in Sources */,
537630952B860D560026BFAB /* FPUIExtensionServiceSource.swift in Sources */,
5350E4E92B0C534A00F276CB /* ClientCommunicationService.swift in Sources */,
532572082C4690340068DEC3 /* FileProviderExtension+EnumerationListener.swift in Sources */,
5352B36C29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ Application::Application(int &argc, char **argv)
AccountSetupCommandLineManager::destroy();

#if defined(BUILD_FILE_PROVIDER_MODULE)
_fileProvider.reset(new Mac::FileProvider);
Mac::FileProvider::instance();
#endif
}

Expand Down
8 changes: 0 additions & 8 deletions src/gui/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ class Folder;
class ShellExtensionsServer;
class SslErrorDialog;

#ifdef Q_OS_MACOS
namespace Mac {
class FileProvider;
}
#endif

/**
* @brief The Application class
* @ingroup gui
Expand Down Expand Up @@ -163,8 +157,6 @@ protected slots:
QScopedPointer<FolderMan> _folderManager;
#if defined(Q_OS_WIN)
QScopedPointer<ShellExtensionsServer> _shellExtensionsServer;
#elif defined(Q_OS_MACOS)
QScopedPointer<Mac::FileProvider> _fileProvider;
#endif
};

Expand Down
1 change: 1 addition & 0 deletions src/gui/macOS/fileprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class FileProvider : public QObject

[[nodiscard]] FileProviderXPC *xpc() const;
[[nodiscard]] FileProviderDomainManager *domainManager() const;
[[nodiscard]] FileProviderSocketServer *socketServer() const;

private slots:
void configureXPC();
Expand Down
5 changes: 5 additions & 0 deletions src/gui/macOS/fileprovider_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,10 @@
return _domainManager.get();
}

FileProviderSocketServer *FileProvider::socketServer() const
{
return _socketServer.get();
}

} // namespace Mac
} // namespace OCC
Loading

0 comments on commit 1a79d63

Please sign in to comment.