Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
37a8232
fix(activity): Add ActivityFileMenu
claucambra Jul 29, 2026
ff2f01c
fix(activity): Use ActivityFileMenu within ActivityItemContent
claucambra Jul 29, 2026
eadf678
chore(activity): Remove unused Style import in AutoSizingMenu
claucambra Jul 29, 2026
0e3b09c
fix(activity): Add activity file menu test
claucambra Jul 29, 2026
7436946
fix(activity): Add ActivityFileMenuButton
claucambra Jul 29, 2026
022071e
fix(activity): Use file button in activity item content
claucambra Jul 29, 2026
618040e
fix(activity): Include button in UI test
claucambra Jul 29, 2026
ec80ef5
fix(activity): Fix activity file menu sizing
claucambra Jul 29, 2026
15a3001
fix(gui): correctly link search QML module
nilsding Jul 27, 2026
078fe5f
feat(sharing): add new QML module for the new sharing UI
nilsding Apr 1, 2026
474dcb4
feat(sharing): add prototype for new sharing UI
nilsding Apr 1, 2026
a6c997f
feat(sharing): add new SharingManager class
nilsding Apr 20, 2026
4029d74
feat(sharing): add view for share settings
nilsding Apr 20, 2026
56b2400
feat(sharing): split UI parts into separate components
nilsding Apr 20, 2026
e8fbce1
feat(sharing): prepare viewmodel for dynamic sharing items
nilsding Apr 20, 2026
0aaf039
feat(sharing): prototype dynamic view based on listmodel
nilsding Apr 21, 2026
0164f44
feat(sharing): pass sharingModel from main dialog
nilsding Apr 21, 2026
35a5b9d
feat(sharing): filter viewmodel depending on main/settings view
nilsding Apr 21, 2026
ad25826
feat(sharing): add accountstate property to viewmodel
nilsding Apr 21, 2026
1752203
feat(sharing): load model data from features capabilities
nilsding Apr 21, 2026
4a3a15d
feat(sharing): display features depending on expected source types
nilsding Apr 21, 2026
fffc76a
fix(sharing): correct background on hover in header buttons
nilsding Apr 21, 2026
88f43f4
feat(sharing): move recipient types chooser to dialog header
nilsding Apr 27, 2026
dff4e30
fix(sharing): correct margins of window header
nilsding Apr 27, 2026
e3fcb00
feat(sharing): add recipient search
nilsding Apr 28, 2026
1df41ed
feat(sharing): keep track of changes in viewmodel
nilsding Apr 28, 2026
9d4e57c
refactor(sharing): adopt unified sharing API models
nilsding Apr 28, 2026
a716cfd
feat(sharing): display permissions
nilsding Jun 17, 2026
871a815
feat(sharing): add recipients
nilsding Jun 17, 2026
d31f81c
fix(sharing): show detailed permission switches depending on preset s…
nilsding Jul 7, 2026
37c522f
fix(sharing): update permission resource
nilsding Jul 7, 2026
e5efd99
fix(sharing): create link recipients and update permissions
nilsding Jul 8, 2026
403c459
feat(sharing): model share recipients
nilsding Jul 8, 2026
e219b10
refactor(sharing): remove obsolete field delegate code
nilsding Jul 8, 2026
53156a4
feat(sharing): add permission preset selection
nilsding Jul 8, 2026
aee4058
refactor(socketapi): use early returns instead of elsif in processSha…
nilsding Jul 10, 2026
89f91d5
feat(sharing): pass file ID to sharing dialog
nilsding Jul 10, 2026
8b053bf
refactor(sharing): simplify settings page properties
nilsding Jul 16, 2026
077aafe
refactor(sharing): reuse wizard-styled components
nilsding Jul 16, 2026
c27029c
feat(sharing): add unified sharing api class
claucambra Jul 28, 2026
ccf24ca
feat(sharing): Split unified share request into specific types with j…
claucambra Jul 28, 2026
fb0d610
feat(sharing): Remove ocssharingjob
claucambra Jul 28, 2026
afc5be2
feat(sharing): Add timeout to search recipients job
claucambra Jul 28, 2026
6f699c3
feat(sharing): Add debouncing to recipientsearchmodel
claucambra Jul 28, 2026
f677131
feat(sharing): Add unified sharing test
claucambra Jul 28, 2026
54f4f8b
feat(sharing): Add specific update job classes
claucambra Jul 28, 2026
431b3f4
feat(sharing): test for failure states
claucambra Jul 28, 2026
e61e66a
feat(sharing): Allow ocsjob to have multiple values for a given param…
claucambra Jul 28, 2026
8508e3f
feat(sharing): Allow ocsjob to have a JSON body
claucambra Jul 28, 2026
d8af2cc
feat(sharing): Allow ocsjob passing status codes to be modified
claucambra Jul 28, 2026
0aa2c7e
feat(sharing): Finalise api jobs
claucambra Jul 28, 2026
99be208
feat(sharing): adapt tests to new jobs
claucambra Jul 28, 2026
911c8d8
feat(sharing): Do not auto-create share on share dialog completion
claucambra Jul 28, 2026
db2d2db
feat(sharing): Unify node class string def
claucambra Jul 28, 2026
c804d1b
feat(sharing): Remove single share value within sharing controller
claucambra Jul 28, 2026
b794e80
feat(sharing): Verify sharing controller initialises without creating…
claucambra Jul 28, 2026
d80390a
feat(sharing): Use constants in unified sharing test
claucambra Jul 28, 2026
54645cf
feat(sharing): Re-layout sharing window to master/detail view
claucambra Jul 29, 2026
75f87f4
fix(sharing): Ensure correct fileId is passed to new sharing dialog
claucambra Jul 30, 2026
605a3b6
feat(sharing): Add ability to create share
claucambra Jul 30, 2026
7abc355
fix(activity): Remove debugging labels
claucambra Jul 30, 2026
1b08567
feat(activity): Add back button svg
claucambra Jul 30, 2026
c95d847
fix(activity): Use back button icon
claucambra Jul 30, 2026
f14bcb2
feat(activity): Implement master/detail design
claucambra Jul 30, 2026
179df4b
feat(activity): Improve labelling for sharing entries
claucambra Jul 30, 2026
a837608
feat(sharing): Implement share settings as a popup
claucambra Jul 30, 2026
08e54d1
feat(sharing): Improve sharing dialog design
claucambra Jul 30, 2026
ffb659e
feat(sharing): Fix recipients addition and surface failures
claucambra Jul 30, 2026
7308898
feat(sharing): Conditionally add details to share
claucambra Jul 30, 2026
fea6d14
feat(sharing): Place settings below recipients
claucambra Jul 30, 2026
fbe3df3
feat(sharing): Fix alignments
claucambra Jul 30, 2026
361674a
feat(sharing): Implement property setting in controller
claucambra Jul 30, 2026
c499587
feat(sharing): Implement share activation in controller and UI
claucambra Jul 30, 2026
63ec172
feat(sharing): Fix permissions selection layout
claucambra Jul 30, 2026
6bf0769
feat(sharing): Refine design
claucambra Jul 30, 2026
9db3692
feat(sharing): Support full property values
claucambra Jul 30, 2026
417db6b
feat(sharing): Handle recipient instance
claucambra Aug 11, 2026
a047c05
feat(sharing): Handle shareId in search
claucambra Aug 11, 2026
fbbe78d
instance
claucambra Aug 11, 2026
5cec2e2
feat(sharing): Handle various icons for recipients
claucambra Aug 11, 2026
17ada08
feat(sharing): Add secret handling
claucambra Aug 11, 2026
b03b85d
feat(sharing): Handle initiator display name
claucambra Aug 11, 2026
5cac92f
feat(sharing): Fix removal handling
claucambra Aug 11, 2026
bbbc0ca
feat(sharing): Clean up data method index handling and value retrieval
claucambra Aug 11, 2026
756a08e
feat(sharing): Fix return for QML of secret types
claucambra Aug 11, 2026
e380dcd
feat(sharing): Improve recipient delegates
claucambra Aug 11, 2026
a7f5457
feat(sharing): Expand testing to include new feature implementations
claucambra Aug 11, 2026
182245a
feat(sharing): Handle share removal
claucambra Aug 12, 2026
bc24c52
feat(sharing): Handle failure cases for permissions changes
claucambra Aug 12, 2026
b78cacd
feat(sharing): Clean up permissions model
claucambra Aug 12, 2026
b87e7fc
feat(sharing): Match server layout
claucambra Aug 13, 2026
d5139cb
feat(sharing): Add wizard item delegate
claucambra Aug 13, 2026
3c598d2
feat(sharing): Use wizard styling in unified sharing components
claucambra Aug 13, 2026
b52c88d
feat(sharing): Hide titlebar for activities window
claucambra Aug 14, 2026
364d93e
feat(sharing): Fix recipient icon type
claucambra Aug 14, 2026
eb24b00
feat(sharing): Fix loading indication on recipients search field
claucambra Aug 14, 2026
de6abb7
feat(sharing): Match server share creation flow
claucambra Aug 14, 2026
e95bde4
feat(sharing): Display pending shares
claucambra Aug 14, 2026
1c51165
feat(sharing): Adjust layout
claucambra Aug 14, 2026
30f3ba2
feat(sharing): Adjust naming of shares
claucambra Aug 14, 2026
b8e5504
feat(sharing): Add info button to headers
claucambra Aug 14, 2026
96dea4c
feat(sharing): Added internal link and public link support
claucambra Aug 14, 2026
8d0f788
feat(sharing): Fix and improve layout of sharing
claucambra Aug 14, 2026
be48328
feat(sharing): Open QML unified sharing window (when this is supporte…
claucambra Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ precedence = "aggregate"
SPDX-FileCopyrightText = "2018-2025 Google LLC"
SPDX-License-Identifier = "Apache-2.0"

[[annotations]]
path = ["theme/back.svg"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2018-2025 Google LLC"
SPDX-License-Identifier = "Apache-2.0"

[[annotations]]
path = ["theme/security.svg", "theme/file-clock-outline.svg"]
precedence = "aggregate"
Expand Down
3 changes: 3 additions & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
<file>src/gui/tray/TrayWindowHeader.qml</file>
<file>src/gui/activity/qml/ActivityItemContextMenu.qml</file>
<file>src/gui/activity/qml/ActivityItemActions.qml</file>
<file>src/gui/activity/qml/ActivityFileMenu.qml</file>
<file>src/gui/activity/qml/ActivityFileMenuButton.qml</file>
<file>src/gui/activity/qml/ActivityItemContent.qml</file>
<file>src/gui/activity/qml/TalkReplyTextField.qml</file>
<file>src/gui/tray/CallNotificationDialog.qml</file>
Expand Down Expand Up @@ -70,6 +72,7 @@
<file>src/gui/wizard/qml/WizardButton.qml</file>
<file>src/gui/wizard/qml/WizardComboBox.qml</file>
<file>src/gui/wizard/qml/WizardDialogFrame.qml</file>
<file>src/gui/wizard/qml/WizardItemDelegate.qml</file>
<file>src/gui/wizard/qml/WizardTextField.qml</file>
<file>src/gui/macOS/ui/FileProviderFileDelegate.qml</file>
<file>src/gui/integration/FileActionsWindow.qml</file>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,11 @@ public let fpUiExtensionServiceName = NSFileProviderServiceName("com.nextcloud.d
/// Get a server URL for the given local file provider item.
///
func itemServerPath(identifier: NSFileProviderItemIdentifier) async -> NSString?

///
/// Present the unified sharing dialog for the given local file provider item when supported.
///
/// - Returns: `true` when the request was handed to the main app, otherwise `false` so the caller can use the legacy sharing interface.
///
func presentUnifiedSharingDialog(identifier: NSFileProviderItemIdentifier, localPath: NSString) async -> Bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,45 @@ class FPUIExtensionServiceSource: NSObject, NSFileProviderServiceSource, NSXPCLi
let completePath = item.serverUrl + "/" + item.fileName
return completePath.replacingOccurrences(of: baseUrl, with: "") as NSString
}

func presentUnifiedSharingDialog(identifier: NSFileProviderItemIdentifier, localPath: NSString) async -> Bool {
guard let account = fpExtension.ncAccount else {
logger.error("Could not present unified sharing because the account is unavailable.", [.item: identifier])
return false
}

guard let dbManager = fpExtension.dbManager,
let metadata = dbManager.itemMetadata(identifier),
!metadata.fileId.isEmpty
else {
logger.error("Could not present unified sharing because the item metadata or numeric file id is unavailable.", [.item: identifier])
return false
}

let (_, _, responseData, error) = await fpExtension.ncKit.fetchCapabilities(account: account)
guard error == .success else {
logger.error("Could not determine whether unified sharing is supported.", [.item: identifier, .error: error])
return false
}

guard UnifiedSharingCapability.isAvailable(in: responseData) else {
logger.info("Unified sharing is not supported; using the legacy sharing interface.", [.item: identifier])
return false
}

guard let app = fpExtension.app else {
logger.error("Could not present unified sharing because the main app connection is unavailable.", [.item: identifier])
return false
}

let domainIdentifier = fpExtension.domain.identifier.rawValue
app.presentUnifiedSharing(
forItem: metadata.fileId,
localPath: localPath as String,
remoteItemPath: metadata.path,
forDomainIdentifier: domainIdentifier
)
logger.info("Asked the main app to present unified sharing.", [.item: identifier, .domain: fpExtension.domain.identifier])
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: LGPL-3.0-or-later

import Foundation

enum UnifiedSharingCapability {
static func isAvailable(in responseData: Data?) -> Bool {
guard let responseData,
let root = try? JSONSerialization.jsonObject(with: responseData) as? [String: Any],
let ocs = root["ocs"] as? [String: Any],
let data = ocs["data"] as? [String: Any],
let capabilities = data["capabilities"] as? [String: Any]
else {
return false
}

return capabilities.keys.contains("sharing")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)presentFileActions:(NSString *)fileId path:(NSString *)path remoteItemPath:(NSString *)remoteItemPath withDomainIdentifier:(NSString *)domainIdentifier;

/**
* @brief The file provider extension asks the main app to present the unified sharing dialog for an item.
* @param fileId The numeric server file id, equal to the WebDAV `fileid` property.
* @param localPath The local and absolute path of the item.
* @param remoteItemPath The server-side path of the item.
* @param domainIdentifier The file provider domain identifier for the account that owns the item.
*/
- (void)presentUnifiedSharingForItem:(NSString *)fileId
localPath:(NSString *)localPath
remoteItemPath:(NSString *)remoteItemPath
forDomainIdentifier:(NSString *)domainIdentifier
NS_SWIFT_NAME(presentUnifiedSharing(forItem:localPath:remoteItemPath:forDomainIdentifier:));

/**
* @brief The file provider extension asks the main app to open the item's page in the user's web browser.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ private final class CapturingAppProxy: NSObject, AppProtocol {
presentedFileActions.append(fileId)
}

func presentUnifiedSharing(
forItem _: String,
localPath _: String,
remoteItemPath _: String,
forDomainIdentifier _: String
) {}

/// Unused by these tests but required for protocol conformance — see
/// `FileProviderExtensionOpenInBrowserTests` for the dedicated coverage.
func openItemInBrowser(_: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ private final class CapturingAppProxy: NSObject, AppProtocol {
_: String, path _: String, remoteItemPath _: String, withDomainIdentifier _: String
) {}

func presentUnifiedSharing(
forItem _: String,
localPath _: String,
remoteItemPath _: String,
forDomainIdentifier _: String
) {}

func openItemInBrowser(_: String, remoteItemPath _: String, forDomainIdentifier _: String) {}

func copyInternalLink(forItem _: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class QuotaCapturingAppProxy: NSObject, AppProtocol {
var capturedSummaryDomains: [String] = []

func presentFileActions(_: String, path _: String, remoteItemPath _: String, withDomainIdentifier _: String) {}
func presentUnifiedSharing(forItem _: String, localPath _: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func openItemInBrowser(_: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func copyInternalLink(forItem _: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func reportSyncStatus(_: String, forDomainIdentifier _: String) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ private final class SyncStatusCapturingAppProxy: NSObject, AppProtocol {

// The following are unused by these tests but required for protocol conformance.
func presentFileActions(_: String, path _: String, remoteItemPath _: String, withDomainIdentifier _: String) {}
func presentUnifiedSharing(forItem _: String, localPath _: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func openItemInBrowser(_: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func copyInternalLink(forItem _: String, remoteItemPath _: String, forDomainIdentifier _: String) {}
func reportItemExcluded(fromSync _: String, fileName _: String, reason _: String, forDomainIdentifier _: String) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: LGPL-3.0-or-later

import Foundation
@testable import NextcloudFileProviderKit
import Testing

@Suite("Unified sharing capability")
struct UnifiedSharingCapabilityTests {
@Test("Detects the sharing capability")
func detectsSharingCapability() {
let responseData = Data(#"{"ocs":{"data":{"capabilities":{"sharing":{}}}}}"#.utf8)

#expect(UnifiedSharingCapability.isAvailable(in: responseData))
}

@Test("Treats the presence of a null sharing capability as available")
func detectsNullSharingCapability() {
let responseData = Data(#"{"ocs":{"data":{"capabilities":{"sharing":null}}}}"#.utf8)

#expect(UnifiedSharingCapability.isAvailable(in: responseData))
}

@Test("Rejects a capabilities response without sharing")
func rejectsMissingSharingCapability() {
let responseData = Data(#"{"ocs":{"data":{"capabilities":{"files":{}}}}}"#.utf8)

#expect(!UnifiedSharingCapability.isAvailable(in: responseData))
}

@Test("Rejects malformed capability data")
func rejectsMalformedCapabilityData() {
#expect(!UnifiedSharingCapability.isAvailable(in: Data("not json".utf8)))
#expect(!UnifiedSharingCapability.isAvailable(in: nil))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController {

switch (actionIdentifier) {
case "com.nextcloud.desktopclient.FileProviderUIExt.ShareAction":
prepare(childViewController: ShareViewController(itemIdentifiers, serviceResolver: serviceResolver, log: log))
prepareSharingAction(itemIdentifiers: itemIdentifiers)
case "com.nextcloud.desktopclient.FileProviderUIExt.LockFileAction":
prepare(childViewController: LockViewController(itemIdentifiers, locking: true, serviceResolver: serviceResolver, log: log))
case "com.nextcloud.desktopclient.FileProviderUIExt.UnlockFileAction":
Expand Down Expand Up @@ -94,6 +94,42 @@ class DocumentActionViewController: FPUIActionExtensionViewController {
self.view = NSView()
}

// MARK: - Sharing

private func prepareSharingAction(itemIdentifiers: [NSFileProviderItemIdentifier]) {
guard itemIdentifiers.count == 1,
let itemIdentifier = itemIdentifiers.first,
let manager = NSFileProviderManager(for: domain)
else {
prepareLegacySharingAction(itemIdentifiers: itemIdentifiers)
return
}

Task { @MainActor in
do {
let localUrl = try await manager.getUserVisibleURL(for: itemIdentifier)
let service = try await serviceResolver.getService(at: localUrl)
let presented = await service.presentUnifiedSharingDialog(
identifier: itemIdentifier,
localPath: localUrl.path as NSString
)

if presented {
extensionContext.completeRequest()
return
}
} catch {
logger.error("Could not route the sharing action to unified sharing.", [.item: itemIdentifier, .error: error])
}

prepareLegacySharingAction(itemIdentifiers: itemIdentifiers)
}
}

private func prepareLegacySharingAction(itemIdentifiers: [NSFileProviderItemIdentifier]) {
prepare(childViewController: ShareViewController(itemIdentifiers, serviceResolver: serviceResolver, log: log))
}

// MARK: - Eviction

///
Expand Down
12 changes: 8 additions & 4 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ IF(BUILD_UPDATER)
endif()

add_subdirectory(search)
add_subdirectory(sharing)

IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
Expand Down Expand Up @@ -577,9 +578,6 @@ target_link_libraries(nextcloudCore
Qt::QuickWidgets
KF6::Archive
KDAB::kdsingleapplication

nextcloudGuiSearch
nextcloudGuiSearchplugin
)

if(KF6GuiAddons_FOUND)
Expand Down Expand Up @@ -691,7 +689,13 @@ set_target_properties(nextcloud PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)

target_link_libraries(nextcloud PRIVATE nextcloudCore)
target_link_libraries(nextcloud PRIVATE
nextcloudGuiSearch
nextcloudGuiSearchplugin
nextcloudGuiSharing
nextcloudGuiSharingplugin
nextcloudCore
)

if(TARGET PkgConfig::CLOUDPROVIDERS)
message("Building with libcloudproviderssupport")
Expand Down
46 changes: 46 additions & 0 deletions src/gui/activity/qml/ActivityFileMenu.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/

import QtQuick
import QtQuick.Controls
import "../../tray"

Menu {
id: root

required property string filePath
required property bool serverHasIntegration
required property int itemFontPixelSize

signal fileDetailsRequested(string filePath)
signal fileActionsRequested(string filePath)

closePolicy: Menu.CloseOnPressOutsideParent | Menu.CloseOnEscape

property Action fileDetailsAction: Action {
id: fileDetailsAction
objectName: "fileDetailsAction"
text: qsTr("File details")
onTriggered: root.fileDetailsRequested(root.filePath)
}

property Action fileActionsAction: Action {
id: fileActionsAction
objectName: "fileActionsAction"
text: qsTr("File actions")
onTriggered: root.fileActionsRequested(root.filePath)
}

MenuItem {
id: fileDetailsMenuItem
action: root.fileDetailsAction
}

MenuItem {
id: fileActionsMenuItem
action: root.fileActionsAction
visible: root.serverHasIntegration
}
}
51 changes: 51 additions & 0 deletions src/gui/activity/qml/ActivityFileMenuButton.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/

import QtQuick
import QtQuick.Controls

Button {
id: root

required property string filePath
required property bool serverHasIntegration
required property int itemFontPixelSize
required property int buttonWidth
required property int buttonHeight
required property int buttonIconSize

readonly property alias menu: fileMenu

signal fileDetailsRequested(string filePath)
signal fileActionsRequested(string filePath)

width: buttonWidth
height: buttonHeight

icon.name: "view-more-symbolic"
icon.source: "image://svgimage-custom-color/more.svg/" + palette.buttonText
icon.width: buttonIconSize
icon.height: buttonIconSize

ToolTip {
popupType: Qt.platform.os === "windows" ? Popup.Item : Popup.Native
text: qsTr("Open file details")
visible: parent.hovered
}

display: Button.IconOnly
onClicked: fileMenu.visible ? fileMenu.close() : fileMenu.popup()

ActivityFileMenu {
id: fileMenu

filePath: root.filePath
serverHasIntegration: root.serverHasIntegration
itemFontPixelSize: root.itemFontPixelSize

onFileDetailsRequested: path => root.fileDetailsRequested(path)
onFileActionsRequested: path => root.fileActionsRequested(path)
}
}
Loading