Add Overlay sheet for message actions
This commit is contained in:
@@ -1,38 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2019 Black Hat <bhat@encom.eu.org>
|
||||||
|
* SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
*
|
||||||
|
* SPDX-LicenseIdentifier: GPL-3.0-only
|
||||||
|
*/
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
import QtQuick.Controls 2.12
|
import QtQuick.Controls 2.12 as QQC2
|
||||||
|
import QtQuick.Layouts 1.12
|
||||||
|
import org.kde.kirigami 2.13 as Kirigami
|
||||||
|
|
||||||
import Spectral.Dialog 2.0
|
import Spectral.Dialog 2.0
|
||||||
|
|
||||||
Menu {
|
Kirigami.OverlaySheet {
|
||||||
readonly property string selectedText: contentLabel.selectedText
|
|
||||||
|
|
||||||
signal viewSource()
|
|
||||||
signal reply()
|
|
||||||
signal redact()
|
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
Item {
|
required property var author;
|
||||||
width: parent.width
|
required property string message;
|
||||||
height: 32
|
|
||||||
|
|
||||||
|
signal viewSource()
|
||||||
|
signal reply(var author, string message)
|
||||||
|
signal remove()
|
||||||
|
|
||||||
|
parent: applicationWindow().overlay
|
||||||
|
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
QQC2.Control {
|
||||||
|
leftPadding: Kirigami.Units.largeSpacing
|
||||||
|
rightPadding: Kirigami.Units.largeSpacing
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: headerLayout.implicitHeight
|
||||||
|
contentItem: RowLayout {
|
||||||
|
id: headerLayout
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
Kirigami.Avatar {
|
||||||
|
source: author.avatarMediaId ? "image://mxc/" + author.avatarMediaId : ""
|
||||||
|
Layout.preferredWidth: Kirigami.Units.iconSizes.large
|
||||||
|
Layout.preferredHeight: Kirigami.Units.iconSizes.large
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Kirigami.Heading {
|
||||||
|
level: 3
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: author.displayName
|
||||||
|
}
|
||||||
|
QQC2.Label {
|
||||||
|
text: message
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: ["👍", "👎️", "😄", "🎉", "🚀", "👀"]
|
model: ["👍", "👎️", "😄", "🎉", "🚀", "👀"]
|
||||||
|
delegate: QQC2.ItemDelegate {
|
||||||
delegate: ItemDelegate {
|
|
||||||
width: 32
|
width: 32
|
||||||
height: 32
|
height: 32
|
||||||
|
|
||||||
contentItem: Label {
|
contentItem: QQC2.Label {
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
|
font.family: "emoji"
|
||||||
text: modelData
|
text: modelData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,27 +78,34 @@ Menu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Kirigami.BasicListItem {
|
||||||
|
action: Kirigami.Action {
|
||||||
|
text: i18n("Reply")
|
||||||
|
icon.name: "reply"
|
||||||
|
onTriggered: reply(author, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kirigami.BasicListItem {
|
||||||
|
action: Kirigami.Action {
|
||||||
|
text: i18n("Remove")
|
||||||
|
icon.name: "edit-delete-remove"
|
||||||
|
icon.color: "red"
|
||||||
|
onTriggered: remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kirigami.BasicListItem {
|
||||||
|
action: Kirigami.Action {
|
||||||
|
text: i18n("Copy")
|
||||||
|
icon.name: "copy"
|
||||||
|
onTriggered: Clibpoard.setText(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kirigami.BasicListItem {
|
||||||
|
action: Kirigami.Action {
|
||||||
|
text: i18n("View Source")
|
||||||
|
icon.name: "code-context"
|
||||||
|
onTriggered: viewSource()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuSeparator {}
|
|
||||||
|
|
||||||
MenuItem {
|
|
||||||
text: "View Source"
|
|
||||||
|
|
||||||
onTriggered: viewSource()
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem {
|
|
||||||
text: "Reply"
|
|
||||||
|
|
||||||
onTriggered: reply()
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem {
|
|
||||||
text: "Redact"
|
|
||||||
|
|
||||||
onTriggered: redact()
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosed: destroy()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ Control {
|
|||||||
|
|
||||||
property alias isReply: replyItem.visible
|
property alias isReply: replyItem.visible
|
||||||
property bool isReaction: false
|
property bool isReaction: false
|
||||||
property var replyModel
|
property var replyUser
|
||||||
readonly property var replyUser: replyModel ? replyModel.author : null
|
property string replyEventID
|
||||||
readonly property string replyEventID: replyModel ? replyModel.eventId : ""
|
property string replyContent
|
||||||
readonly property string replyContent: replyModel ? replyModel.display : ""
|
|
||||||
|
|
||||||
property alias isAutoCompleting: autoCompleteListView.visible
|
property alias isAutoCompleting: autoCompleteListView.visible
|
||||||
property var autoCompleteModel
|
property var autoCompleteModel
|
||||||
@@ -75,10 +74,7 @@ Control {
|
|||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
text: replyUser ? replyUser.displayName : "No name"
|
text: replyUser ? replyUser.displayName : "No name"
|
||||||
color: "white"
|
|
||||||
font.weight: Font.Medium
|
|
||||||
rightPadding: 8
|
rightPadding: 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,6 +413,7 @@ Control {
|
|||||||
messageEventType = RoomMessageEvent.Notice
|
messageEventType = RoomMessageEvent.Notice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(replyContent, replyUser, replyEventID, messageEventType);
|
||||||
currentRoom.postArbitaryMessage(text, messageEventType, replyEventID)
|
currentRoom.postArbitaryMessage(text, messageEventType, replyEventID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,7 +441,9 @@ Control {
|
|||||||
|
|
||||||
function clearReply() {
|
function clearReply() {
|
||||||
isReply = false
|
isReply = false
|
||||||
replyModel = null
|
replyUser = null;
|
||||||
|
replyContent = "";
|
||||||
|
replyEventID = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function focus() {
|
function focus() {
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ Kirigami.ScrollablePage {
|
|||||||
id: messageListView
|
id: messageListView
|
||||||
|
|
||||||
spacing: Kirigami.Units.smallSpacing
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
clip: true
|
||||||
|
|
||||||
displayMarginBeginning: 100
|
displayMarginBeginning: 100
|
||||||
displayMarginEnd: 100
|
displayMarginEnd: 100
|
||||||
@@ -152,6 +153,7 @@ Kirigami.ScrollablePage {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
delegate: DelegateChooser {
|
delegate: DelegateChooser {
|
||||||
|
id: timelineDelegateChooser
|
||||||
role: "eventType"
|
role: "eventType"
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
@@ -182,11 +184,16 @@ Kirigami.ScrollablePage {
|
|||||||
roleValue: "message"
|
roleValue: "message"
|
||||||
delegate: TimelineContainer {
|
delegate: TimelineContainer {
|
||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
|
MouseArea {
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: openMessageContext(author, display, eventId, toolTip);
|
||||||
|
}
|
||||||
innerObject: MessageDelegate {
|
innerObject: MessageDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.maximumWidth: messageListView.width
|
Layout.maximumWidth: messageListView.width
|
||||||
|
|
||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
@@ -292,4 +299,42 @@ Kirigami.ScrollablePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
background: Item {}
|
background: Item {}
|
||||||
|
|
||||||
|
function openMessageContext(author, message, eventId, toolTip, model) {
|
||||||
|
const contextMenu = messageDelegateContextMenu.createObject(root, {
|
||||||
|
'author': author,
|
||||||
|
'message': message
|
||||||
|
});
|
||||||
|
contextMenu.viewSource.connect(function() {
|
||||||
|
messageSourceDialog.createObject(root, {
|
||||||
|
'sourceText': toolTip,
|
||||||
|
}).open();
|
||||||
|
contextMenu.close();
|
||||||
|
});
|
||||||
|
contextMenu.reply.connect(function(replyUser, replyContent) {
|
||||||
|
chatTextInput.replyUser = replyUser;
|
||||||
|
chatTextInput.replyEventID = eventId;
|
||||||
|
chatTextInput.replyContent = replyContent;
|
||||||
|
chatTextInput.isReply = true;
|
||||||
|
chatTextInput.focus();
|
||||||
|
contextMenu.close();
|
||||||
|
})
|
||||||
|
contextMenu.remove.connect(function() {
|
||||||
|
currentRoom.redactEvent(eventId);
|
||||||
|
contextMenu.close();
|
||||||
|
})
|
||||||
|
contextMenu.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: messageDelegateContextMenu
|
||||||
|
|
||||||
|
MessageDelegateContextMenu {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: messageSourceDialog
|
||||||
|
|
||||||
|
MessageSourceDialog {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user