Port DelegateContextMenu to ConvergentContextMenu

This commit is contained in:
Carl Schwan
2025-01-03 17:23:24 +01:00
parent c43563a804
commit f0e0979366
4 changed files with 240 additions and 279 deletions

View File

@@ -9,6 +9,7 @@ import Qt.labs.qmlmodels
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kirigamiaddons.delegates as Delegates
import org.kde.neochat import org.kde.neochat
@@ -25,7 +26,7 @@ import org.kde.neochat
* For event types that need alternate actions this class can be used as a base and * For event types that need alternate actions this class can be used as a base and
* the actions and nested actions can be overwritten to show the alternate items. * the actions and nested actions can be overwritten to show the alternate items.
*/ */
Loader { KirigamiComponents.ConvergentContextMenu {
id: root id: root
/** /**
@@ -62,25 +63,6 @@ Loader {
*/ */
property string hoveredLink: "" property string hoveredLink: ""
/**
* @brief The list of menu item actions that have sub-actions.
*
* Each action will be instantiated as a single line that open a sub menu.
*/
property list<Kirigami.Action> nestedActions
/**
* @brief The main list of menu item actions.
*
* Each action will be instantiated as a single line in the menu.
*/
property list<Kirigami.Action> actions
/**
* @brief Whether the web search menu should be shown or not.
*/
property bool enableWebSearch: true
/** /**
* Some common actions shared between menus * Some common actions shared between menus
*/ */
@@ -112,7 +94,7 @@ Loader {
} }
} }
component ReplyMessageAction: Kirigami.Action { component ReplyMessageAction: QQC2.Action {
text: i18n("Reply") text: i18n("Reply")
icon.name: "mail-replied-symbolic" icon.name: "mail-replied-symbolic"
onTriggered: { onTriggered: {
@@ -150,90 +132,70 @@ Loader {
} }
} }
Component { headerContentItem: RowLayout {
id: regularMenu spacing: Kirigami.Units.largeSpacing
QQC2.Menu { KirigamiComponents.Avatar {
id: menu source: root.author.avatarUrl
Instantiator {
model: root.nestedActions
delegate: QQC2.Menu {
id: menuItem
visible: modelData.visible
title: modelData.text
icon: modelData.icon
Instantiator { Layout.preferredWidth: Kirigami.Units.gridUnit * 2
model: modelData.children Layout.preferredHeight: Kirigami.Units.gridUnit * 2
delegate: QQC2.MenuItem { Layout.alignment: Qt.AlignTop
text: modelData.text
icon.name: modelData.icon.name
onTriggered: modelData.trigger()
} }
onObjectAdded: (index, object) => {
menuItem.insertItem(0, object); ColumnLayout {
spacing: 0
Layout.fillWidth: true
Kirigami.Heading {
level: 4
text: root.author.htmlSafeDisplayName
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
QQC2.Label {
text: root.plainText
textFormat: Text.PlainText
elide: Text.ElideRight
onLinkActivated: RoomManager.resolveResource(link, "join")
Layout.fillWidth: true
} }
} }
onObjectAdded: (index, object) => {
object.visible = false;
menu.addMenu(object);
}
} }
Kirigami.Action {
visible: Kirigami.Settings.isMobile
displayComponent: RowLayout {
spacing: 0
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
Repeater { Repeater {
model: root.actions model: ["👍", "👎️", "😄", "🎉", "🚀", "👀"]
DelegateChooser { delegate: Delegates.RoundedItemDelegate {
role: "separator" Layout.fillWidth: true
DelegateChoice { Layout.fillHeight: true
roleValue: true
QQC2.MenuSeparator { contentItem: Kirigami.Heading {
visible: modelData.visible horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.family: "emoji"
text: modelData
}
onClicked: {
currentRoom.toggleReaction(eventId, modelData);
root.item.close();
}
}
}
} }
} }
DelegateChoice { /*
roleValue: false
QQC2.MenuItem {
visible: modelData.visible
action: modelData
onClicked: root.item.close()
}
}
}
}
QQC2.Menu {
id: webshortcutmenu
title: i18n("Search for '%1'", webshortcutmodel.trunkatedSearchText)
icon.name: "search-symbolic"
property bool isVisible: webshortcutmodel.enabled && root.enableWebSearch
Component.onCompleted: {
webshortcutmenu.parent.visible = isVisible;
}
onIsVisibleChanged: webshortcutmenu.parent.visible = isVisible
Instantiator {
model: WebShortcutModel {
id: webshortcutmodel
selectedText: root.selectedText.length > 0 ? root.selectedText : root.plainText
onOpenUrl: url => RoomManager.resolveResource(url.toString())
}
delegate: QQC2.MenuItem {
text: model.display
icon.name: model.decoration
onTriggered: webshortcutmodel.trigger(model.edit)
}
onObjectAdded: (index, object) => webshortcutmenu.insertItem(0, object)
}
QQC2.MenuSeparator {}
QQC2.MenuItem {
text: i18n("Configure Web Shortcuts...")
icon.name: "configure"
visible: !Controller.isFlatpak
onTriggered: webshortcutmodel.configureWebShortcuts()
}
}
} }
} }
Component { Component {
@@ -330,31 +292,6 @@ Loader {
Kirigami.Separator { Kirigami.Separator {
Layout.fillWidth: true Layout.fillWidth: true
} }
RowLayout {
spacing: 0
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
Repeater {
model: ["👍", "👎️", "😄", "🎉", "🚀", "👀"]
delegate: QQC2.ItemDelegate {
Layout.fillWidth: true
Layout.fillHeight: true
contentItem: Kirigami.Heading {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.family: "emoji"
text: modelData
}
onClicked: {
currentRoom.toggleReaction(eventId, modelData);
root.item.close();
}
}
}
}
Kirigami.Separator { Kirigami.Separator {
Layout.fillWidth: true Layout.fillWidth: true
} }
@@ -422,5 +359,5 @@ Loader {
} else { } else {
item.popup(); item.popup();
} }
} }*/
} }

View File

@@ -33,27 +33,21 @@ DelegateContextMenu {
*/ */
required property var progressInfo required property var progressInfo
// Web search isn't useful for images DelegateContextMenu.ReplyMessageAction {}
enableWebSearch: false
/**
* @brief The main list of menu item actions.
*
* Each action will be instantiated as a single line in the menu.
*/
property list<Kirigami.Action> actions: [
DelegateContextMenu.ReplyMessageAction {},
Kirigami.Action { Kirigami.Action {
separator: true separator: true
}, }
Kirigami.Action {
QQC2.Action {
text: i18nc("@action:inmenu", "Open Image") text: i18nc("@action:inmenu", "Open Image")
icon.name: "document-open" icon.name: "document-open"
onTriggered: { onTriggered: {
currentRoom.openEventMediaExternally(root.eventId); currentRoom.openEventMediaExternally(root.eventId);
} }
}, }
Kirigami.Action {
QQC2.Action {
text: i18nc("@action:inmenu", "Save Image…") text: i18nc("@action:inmenu", "Save Image…")
icon.name: "document-save" icon.name: "document-save"
onTriggered: { onTriggered: {
@@ -61,17 +55,20 @@ DelegateContextMenu {
dialog.selectedFile = currentRoom.fileNameToDownload(eventId); dialog.selectedFile = currentRoom.fileNameToDownload(eventId);
dialog.open(); dialog.open();
} }
}, }
Kirigami.Action {
QQC2.Action {
text: i18nc("@action:inmenu", "Copy Image") text: i18nc("@action:inmenu", "Copy Image")
icon.name: "edit-copy" icon.name: "edit-copy"
onTriggered: { onTriggered: {
currentRoom.copyEventMedia(root.eventId); currentRoom.copyEventMedia(root.eventId);
} }
}, }
Kirigami.Action { Kirigami.Action {
separator: true separator: true
}, }
Kirigami.Action { Kirigami.Action {
visible: author.id === currentRoom.localMember.id || currentRoom.canSendState("redact") visible: author.id === currentRoom.localMember.id || currentRoom.canSendState("redact")
text: i18n("Remove") text: i18n("Remove")
@@ -91,24 +88,21 @@ DelegateContextMenu {
currentRoom.redactEvent(root.eventId, reason); currentRoom.redactEvent(root.eventId, reason);
}); });
} }
}, }
DelegateContextMenu.ReportMessageAction {},
DelegateContextMenu.ShowUserAction {}, DelegateContextMenu.ReportMessageAction {}
DelegateContextMenu.ShowUserAction {}
Kirigami.Action { Kirigami.Action {
separator: true separator: true
visible: viewSourceAction.visible visible: viewSourceAction.visible
}, }
DelegateContextMenu.ViewSourceAction { DelegateContextMenu.ViewSourceAction {
id: viewSourceAction id: viewSourceAction
} }
]
/**
* @brief The list of menu item actions that have sub-actions.
*
* Each action will be instantiated as a single line that opens a sub menu.
*/
property list<Kirigami.Action> nestedActions: [
ShareAction { ShareAction {
id: shareAction id: shareAction
inputData: { inputData: {
@@ -119,11 +113,8 @@ DelegateContextMenu {
eventId: root.eventId eventId: root.eventId
property string filename: Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(eventId) property string filename: Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(eventId)
} }
]
Component { readonly property Component saveAsDialog: Dialogs.FileDialog {
id: saveAsDialog
Dialogs.FileDialog {
fileMode: Dialogs.FileDialog.SaveFile fileMode: Dialogs.FileDialog.SaveFile
currentFolder: NeoChatConfig.lastSaveDirectory.length > 0 ? NeoChatConfig.lastSaveDirectory : Core.StandardPaths.writableLocation(Core.StandardPaths.DownloadLocation) currentFolder: NeoChatConfig.lastSaveDirectory.length > 0 ? NeoChatConfig.lastSaveDirectory : Core.StandardPaths.writableLocation(Core.StandardPaths.DownloadLocation)
onAccepted: { onAccepted: {
@@ -135,5 +126,4 @@ DelegateContextMenu {
currentRoom.downloadFile(eventId, selectedFile); currentRoom.downloadFile(eventId, selectedFile);
} }
} }
}
} }

View File

@@ -32,7 +32,6 @@ DelegateContextMenu {
*/ */
required property string htmlText required property string htmlText
actions: [
Kirigami.Action { Kirigami.Action {
text: i18n("Edit") text: i18n("Edit")
icon.name: "document-edit" icon.name: "document-edit"
@@ -42,9 +41,11 @@ DelegateContextMenu {
currentRoom.mainCache.threadId = ""; currentRoom.mainCache.threadId = "";
} }
visible: root.author.isLocalMember && root.messageComponentType === MessageComponentType.Text visible: root.author.isLocalMember && root.messageComponentType === MessageComponentType.Text
}, }
DelegateContextMenu.ReplyMessageAction {},
Kirigami.Action { DelegateContextMenu.ReplyMessageAction {}
QQC2.Action {
text: i18nc("@action:inmenu As in 'Forward this message'", "Forward…") text: i18nc("@action:inmenu As in 'Forward this message'", "Forward…")
icon.name: "mail-forward-symbolic" icon.name: "mail-forward-symbolic"
onTriggered: { onTriggered: {
@@ -59,40 +60,73 @@ DelegateContextMenu {
page.closeDialog(); page.closeDialog();
}); });
} }
}, }
Kirigami.Action { Kirigami.Action {
separator: true separator: true
}, }
DelegateContextMenu.RemoveMessageAction {}, DelegateContextMenu.RemoveMessageAction {}
Kirigami.Action { Kirigami.Action {
text: i18nc("@action:inmenu", "Copy Link Address") text: i18nc("@action:inmenu", "Copy Link Address")
icon.name: "edit-copy" icon.name: "edit-copy"
visible: root.hoveredLink.length > 0 visible: root.hoveredLink.length > 0
onTriggered: Clipboard.saveText(root.hoveredLink) onTriggered: Clipboard.saveText(root.hoveredLink)
}, }
Kirigami.Action { QQC2.Action {
text: i18nc("@action:inmenu", "Copy Text") text: i18nc("@action:inmenu", "Copy Text")
icon.name: "edit-copy" icon.name: "edit-copy"
onTriggered: Clipboard.saveText(root.selectedText.length > 0 ? root.selectedText : root.plainText) onTriggered: Clipboard.saveText(root.selectedText.length > 0 ? root.selectedText : root.plainText)
}, }
Kirigami.Action { QQC2.Action {
text: i18nc("@action:inmenu", "Copy Message Link") text: i18nc("@action:inmenu", "Copy Message Link")
icon.name: "edit-copy" icon.name: "edit-copy"
onTriggered: { onTriggered: {
Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + root.eventId); Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + root.eventId);
} }
}, }
Kirigami.Action { Kirigami.Action {
separator: true separator: true
}, }
DelegateContextMenu.ReportMessageAction {}, DelegateContextMenu.ReportMessageAction {}
DelegateContextMenu.ShowUserAction {}, DelegateContextMenu.ShowUserAction {}
Kirigami.Action { Kirigami.Action {
separator: true separator: true
visible: viewSourceAction.visible visible: viewSourceAction.visible
}, }
DelegateContextMenu.ViewSourceAction { DelegateContextMenu.ViewSourceAction {
id: viewSourceAction id: viewSourceAction
} }
]
Kirigami.Action {
separator: true
visible: webShortcutModel.enabled
}
Kirigami.Action {
id: webShortcutModelAction
text: i18n("Search for '%1'", webshortcutModel.trunkatedSearchText)
icon.name: "search-symbolic"
visible: webshortcutModel.enabled
readonly property Instantiator instantiator: Instantiator {
model: WebShortcutModel {
id: webshortcutModel
selectedText: root.selectedText.length > 0 ? root.selectedText : root.plainText
onOpenUrl: url => RoomManager.resolveResource(url.toString())
}
delegate: QQC2.Action {
text: model.display
icon.name: model.decoration
onTriggered: webshortcutModel.trigger(model.edit)
}
onObjectAdded: (index, object) => webShortcutModelAction.children.push(object)
}
}
Kirigami.Action {
text: i18n("Configure Web Shortcuts...")
icon.name: "configure"
visible: !Controller.isFlatpak && webshortcutModel.enabled
onTriggered: webshortcutmodel.configureWebShortcuts()
}
} }

View File

@@ -255,7 +255,7 @@ Kirigami.Page {
plainText: plainText, plainText: plainText,
htmlText: htmlText, htmlText: htmlText,
}); });
contextMenu.open(); contextMenu.popup();
} }
function onShowFileMenu(eventId, author, messageComponentType, plainText, mimeType, progressInfo, isThread) { function onShowFileMenu(eventId, author, messageComponentType, plainText, mimeType, progressInfo, isThread) {
@@ -266,7 +266,7 @@ Kirigami.Page {
mimeType: mimeType, mimeType: mimeType,
progressInfo: progressInfo, progressInfo: progressInfo,
}); });
contextMenu.open(); contextMenu.popup();
} }
function onShowMaximizedMedia(index) { function onShowMaximizedMedia(index) {