Minor optimizations to the timeline delegates
* Use anchors instead of Layouts * Don't use Loader for message display name * Lazy load the emoji popup
This commit is contained in:
@@ -237,7 +237,6 @@ Item {
|
|||||||
function onEditing(editContent, editFormatedContent) {
|
function onEditing(editContent, editFormatedContent) {
|
||||||
// Set the input field in edit mode
|
// Set the input field in edit mode
|
||||||
root.inputFieldText = editContent;
|
root.inputFieldText = editContent;
|
||||||
//root.replyContent = editContent;
|
|
||||||
|
|
||||||
// clean autocompletion list
|
// clean autocompletion list
|
||||||
chatBar.userAutocompleted = {};
|
chatBar.userAutocompleted = {};
|
||||||
@@ -253,6 +252,7 @@ Item {
|
|||||||
while ((match = regex.exec(editFormatedContent.toString())) !== null) {
|
while ((match = regex.exec(editFormatedContent.toString())) !== null) {
|
||||||
chatBar.userAutocompleted[match[2]] = match[1];
|
chatBar.userAutocompleted[match[2]] = match[1];
|
||||||
}
|
}
|
||||||
|
chatBox.forceActiveFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,48 +11,63 @@ import org.kde.kirigami 2.15 as Kirigami
|
|||||||
import org.kde.neochat 1.0
|
import org.kde.neochat 1.0
|
||||||
import NeoChat.Component.Timeline 1.0
|
import NeoChat.Component.Timeline 1.0
|
||||||
|
|
||||||
QQC2.AbstractButton {
|
MouseArea {
|
||||||
visible: replyVisible
|
id: replyButton
|
||||||
Component.onCompleted: parent.Layout.fillWidth = true
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: replyName.implicitHeight + replyText.implicitHeight + Kirigami.Units.largeSpacing
|
||||||
|
implicitWidth: Math.min(bubbleMaxWidth, Math.max(replyText.implicitWidth, replyName.implicitWidth)) + Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3
|
||||||
|
Component.onCompleted: {
|
||||||
|
parent.Layout.fillWidth = true;
|
||||||
|
parent.Layout.preferredWidth = Qt.binding(function() { return implicitWidth; })
|
||||||
|
parent.Layout.maximumWidth = Qt.binding(function() { return bubbleMaxWidth + Kirigami.Units.largeSpacing * 2; })
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: replyLeftBorder
|
||||||
|
width: Kirigami.Units.smallSpacing
|
||||||
|
height: parent.height
|
||||||
|
color: Kirigami.Theme.highlightColor
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: RowLayout {
|
Kirigami.Avatar {
|
||||||
Layout.fillWidth: true
|
id: avatatReply
|
||||||
|
anchors.left: replyLeftBorder.right
|
||||||
|
anchors.leftMargin: Kirigami.Units.smallSpacing
|
||||||
|
width: Kirigami.Units.gridUnit
|
||||||
|
height: Kirigami.Units.gridUnit
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
visible: Config.showAvatarInTimeline
|
||||||
|
source: reply.author.avatarMediaId ? ("image://mxc/" + reply.author.avatarMediaId) : ""
|
||||||
|
name: reply.author.name || ""
|
||||||
|
color: reply.author.color
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
QQC2.Label {
|
||||||
Layout.preferredWidth: Kirigami.Units.smallSpacing
|
id: replyName
|
||||||
Layout.fillHeight: true
|
anchors {
|
||||||
|
left: avatatReply.right
|
||||||
color: Kirigami.Theme.highlightColor
|
leftMargin: Kirigami.Units.smallSpacing
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: Kirigami.Units.smallSpacing
|
||||||
}
|
}
|
||||||
|
text: reply.author.displayName
|
||||||
|
color: reply.author.color
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
Kirigami.Avatar {
|
TextDelegate {
|
||||||
Layout.preferredWidth: Kirigami.Units.gridUnit
|
id: replyText
|
||||||
Layout.preferredHeight: Kirigami.Units.gridUnit
|
anchors {
|
||||||
Layout.alignment: Qt.AlignTop
|
left: avatatReply.right
|
||||||
visible: Config.showAvatarInTimeline
|
top: replyName.bottom
|
||||||
source: replyVisible && reply.author.avatarMediaId ? ("image://mxc/" + reply.author.avatarMediaId) : ""
|
leftMargin: Kirigami.Units.smallSpacing
|
||||||
name: replyVisible ? (reply.author.name || "") : "H"
|
topMargin: Kirigami.Units.smallSpacing
|
||||||
color: replyVisible ? reply.author.color : Kirigami.Theme.highlightColor
|
right: parent.right
|
||||||
}
|
rightMargin: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: replyLayout
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
QQC2.Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: replyVisible ? reply.author.displayName : ""
|
|
||||||
color: replyVisible ? reply.author.color: null
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
TextDelegate {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: 0
|
|
||||||
text: replyVisible ? ("<style>pre {white-space: pre-wrap} a{text-decoration: none; color: " + Kirigami.Theme.linkColor + ";} .user-pill{}</style>" + reply.display) : ""
|
|
||||||
textFormat: Text.RichText
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
textMessage: reply.display
|
||||||
|
textFormat: Text.RichText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.kde.kirigami 2.15 as Kirigami
|
|||||||
|
|
||||||
Kirigami.Heading {
|
Kirigami.Heading {
|
||||||
level: 4
|
level: 4
|
||||||
text: section
|
text: model.showSection ? section : ""
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
topPadding: Kirigami.Units.largeSpacing * 2
|
topPadding: Kirigami.Units.largeSpacing * 2
|
||||||
bottomPadding: Kirigami.Units.smallSpacing
|
bottomPadding: Kirigami.Units.smallSpacing
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ TextEdit {
|
|||||||
readonly property var isEmoji: /^(<span style='.*'>)?(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/
|
readonly property var isEmoji: /^(<span style='.*'>)?(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/
|
||||||
|
|
||||||
property bool isEmote: false
|
property bool isEmote: false
|
||||||
|
property string textMessage: model.display
|
||||||
|
|
||||||
text: "<style>
|
text: "<style>
|
||||||
table {
|
table {
|
||||||
@@ -39,10 +40,10 @@ a{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.user-pill{}
|
.user-pill{}
|
||||||
</style>" + (isEmote ? "* <a href='https://matrix.to/#/" + author.id + "' style='color: " + author.color + "'>" + author.displayName + "</a> " : "") + model.display + (isEdited ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
|
</style>" + (isEmote ? "* <a href='https://matrix.to/#/" + author.id + "' style='color: " + author.color + "'>" + author.displayName + "</a> " : "") + textMessage + (isEdited ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
|
||||||
|
|
||||||
color: Kirigami.Theme.textColor
|
color: Kirigami.Theme.textColor
|
||||||
font.pointSize: !replyVisible && isEmoji.test(model.display) ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize
|
font.pointSize: model.reply === undefined && isEmoji.test(model.display) ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize
|
||||||
selectByMouse: !Kirigami.Settings.isMobile
|
selectByMouse: !Kirigami.Settings.isMobile
|
||||||
readOnly: true
|
readOnly: true
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|||||||
@@ -15,18 +15,13 @@ import NeoChat.Dialog 1.0
|
|||||||
QQC2.ItemDelegate {
|
QQC2.ItemDelegate {
|
||||||
id: messageDelegate
|
id: messageDelegate
|
||||||
default property alias innerObject : column.children
|
default property alias innerObject : column.children
|
||||||
readonly property bool sentByMe: author.isLocalUser
|
// readonly property bool failed: marks == EventStatus.SendingFailed
|
||||||
readonly property bool darkBackground: !sentByMe
|
property bool isLoaded
|
||||||
readonly property bool replyVisible: reply ?? false
|
|
||||||
readonly property bool failed: marks == EventStatus.SendingFailed
|
|
||||||
readonly property color authorColor: eventType == "notice" ? Kirigami.Theme.activeTextColor : author.color
|
|
||||||
readonly property color replyAuthorColor: replyVisible ? reply.author.color : Kirigami.Theme.focusColor
|
|
||||||
|
|
||||||
property bool isEmote: false
|
property bool isEmote: false
|
||||||
property bool cardBackground: true
|
property bool cardBackground: true
|
||||||
property bool isLoaded
|
|
||||||
|
|
||||||
property var hoverComponent
|
readonly property int bubbleMaxWidth: Math.min(width - Kirigami.Units.gridUnit * 2 - Kirigami.Units.largeSpacing * 4, Kirigami.Units.gridUnit * 20)
|
||||||
|
|
||||||
signal saveFileAs()
|
signal saveFileAs()
|
||||||
signal openExternally()
|
signal openExternally()
|
||||||
@@ -34,9 +29,8 @@ QQC2.ItemDelegate {
|
|||||||
|
|
||||||
topPadding: 0
|
topPadding: 0
|
||||||
bottomPadding: 0
|
bottomPadding: 0
|
||||||
|
background: null
|
||||||
//height: mainColumn.childrenRect.height + (readMarker ? Kirigami.Units.smallSpacing : 0)
|
property Item hoverComponent
|
||||||
//height: mainColumn.implicitHeight + (readMarker ? Kirigami.Units.smallSpacing : 0)
|
|
||||||
|
|
||||||
// show hover actions
|
// show hover actions
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
@@ -47,160 +41,154 @@ QQC2.ItemDelegate {
|
|||||||
|
|
||||||
// updates the global hover component to point to this delegate, and update its position
|
// updates the global hover component to point to this delegate, and update its position
|
||||||
function updateHoverComponent() {
|
function updateHoverComponent() {
|
||||||
hoverComponent.bubble = bubble
|
if (hoverComponent) {
|
||||||
hoverComponent.updateFunction = updateHoverComponent;
|
hoverComponent.bubble = bubble
|
||||||
hoverComponent.event = model
|
hoverComponent.updateFunction = updateHoverComponent;
|
||||||
|
hoverComponent.event = model
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
height: sectionDelegate.height + Math.max(avatar.height, bubble.implicitHeight) + loader.height + (model.showAuthor ? Kirigami.Units.smallSpacing : 0)
|
||||||
id: mainColumn
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
SectionDelegate {
|
SectionDelegate {
|
||||||
id: sectionDelegate
|
id: sectionDelegate
|
||||||
Layout.maximumWidth: parent.width
|
width: parent.width
|
||||||
Layout.alignment: Qt.AlignHCenter
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Kirigami.Units.gridUnit * 2 + Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
|
||||||
|
visible: model.showSection
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
}
|
||||||
|
|
||||||
visible: showSection
|
Kirigami.Avatar {
|
||||||
|
id: avatar
|
||||||
|
width: Kirigami.Units.gridUnit * 2
|
||||||
|
height: width
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: width
|
||||||
|
anchors {
|
||||||
|
top: sectionDelegate.bottom
|
||||||
|
topMargin: model.showAuthor ? Kirigami.Units.smallSpacing * 2 : Kirigami.Units.smallSpacing
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: Kirigami.Units.largeSpacing
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
visible: model.showAuthor && Config.showAvatarInTimeline
|
||||||
id: root
|
name: model.author.name ?? model.author.displayName
|
||||||
|
source: model.author.avatarMediaId ? ("image://mxc/" + model.author.avatarMediaId) : ""
|
||||||
|
color: model.author.color
|
||||||
|
|
||||||
spacing: Kirigami.Units.smallSpacing
|
MouseArea {
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
anchors.fill: parent
|
||||||
Layout.rightMargin: Kirigami.Units.smallSpacing
|
onClicked: {
|
||||||
Layout.bottomMargin: 0
|
userDetailDialog.createObject(QQC2.ApplicationWindow.overlay, {
|
||||||
Layout.topMargin: model.showAuthor ? Kirigami.Units.smallSpacing : 0
|
room: currentRoom,
|
||||||
Layout.fillWidth: true
|
user: author.object,
|
||||||
|
displayName: author.displayName,
|
||||||
Kirigami.Avatar {
|
avatarMediaId: author.avatarMediaId,
|
||||||
Layout.minimumWidth: Kirigami.Units.gridUnit * 2
|
avatarUrl: author.avatarUrl
|
||||||
Layout.minimumHeight: Kirigami.Units.gridUnit * 2
|
}).open();
|
||||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 2
|
|
||||||
Layout.maximumHeight: Kirigami.Units.gridUnit * 2
|
|
||||||
sourceSize.width: Kirigami.Units.gridUnit * 2
|
|
||||||
sourceSize.height: Kirigami.Units.gridUnit * 2
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
|
|
||||||
visible: model.showAuthor && Config.showAvatarInTimeline
|
|
||||||
name: author.name ?? author.displayName
|
|
||||||
source: author.avatarMediaId ? ("image://mxc/" + author.avatarMediaId) : ""
|
|
||||||
color: author.color
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: userDetailDialog
|
|
||||||
|
|
||||||
UserDetailDialog {}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: userDetailDialog.createObject(QQC2.ApplicationWindow.overlay, {"room": currentRoom, "user": author.object, "displayName": author.displayName, "avatarMediaId": author.avatarMediaId, "avatarUrl": author.avatarUrl}).open()
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.Control {
|
||||||
|
id: bubble
|
||||||
|
topPadding: Kirigami.Units.largeSpacing
|
||||||
|
bottomPadding: 0
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors {
|
||||||
|
top: avatar.top
|
||||||
|
left: avatar.right
|
||||||
|
leftMargin: Kirigami.Units.smallSpacing
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
id: column
|
||||||
|
spacing: 0
|
||||||
Item {
|
Item {
|
||||||
Layout.minimumWidth: Kirigami.Units.gridUnit * 2
|
id: rowLayout
|
||||||
Layout.preferredHeight: 1
|
visible: model.showAuthor && !isEmote
|
||||||
visible: !model.showAuthor && Config.showAvatarInTimeline
|
|
||||||
}
|
|
||||||
|
|
||||||
QQC2.Control {
|
|
||||||
id: bubble
|
|
||||||
implicitHeight: contentItem.implicitHeight + topPadding
|
|
||||||
topPadding: Kirigami.Units.largeSpacing
|
|
||||||
bottomPadding: 0
|
|
||||||
leftPadding: 0
|
|
||||||
rightPadding: 0
|
|
||||||
hoverEnabled: true
|
|
||||||
Layout.maximumWidth: mainColumn.width - Kirigami.Units.gridUnit * 2 - Kirigami.Units.largeSpacing * 2
|
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
id: column
|
|
||||||
spacing: 0
|
|
||||||
Loader {
|
|
||||||
id: topRow
|
|
||||||
active: model.showAuthor && !isEmote
|
|
||||||
visible: active
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
|
||||||
Layout.bottomMargin: visible ? Kirigami.Units.smallSpacing : 0
|
|
||||||
|
|
||||||
sourceComponent: RowLayout {
|
|
||||||
id: rowLayout
|
|
||||||
|
|
||||||
QQC2.Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
topInset: 0
|
|
||||||
|
|
||||||
visible: model.showAuthor && !isEmote
|
|
||||||
|
|
||||||
text: author.displayName
|
|
||||||
font.weight: Font.Bold
|
|
||||||
color: author.color
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
}
|
|
||||||
QQC2.Label {
|
|
||||||
visible: model.showAuthor && !isEmote
|
|
||||||
text: time.toLocaleTimeString(Locale.ShortFormat)
|
|
||||||
color: Kirigami.Theme.disabledTextColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loader {
|
|
||||||
id: replyLoader
|
|
||||||
source: 'qrc:imports/NeoChat/Component/Timeline/ReplyComponent.qml'
|
|
||||||
active: replyVisible
|
|
||||||
visible: active
|
|
||||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: replyLoader.item
|
|
||||||
function onClicked() {
|
|
||||||
replyClicked(reply.eventId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Kirigami.ShadowedRectangle {
|
|
||||||
visible: cardBackground
|
|
||||||
color: model.isHighlighted ? Kirigami.Theme.positiveBackgroundColor : Kirigami.Theme.backgroundColor
|
|
||||||
radius: Kirigami.Units.smallSpacing
|
|
||||||
shadow.size: Kirigami.Units.smallSpacing
|
|
||||||
shadow.color: !model.isHighlighted ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
|
||||||
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
|
||||||
border.width: Kirigami.Units.devicePixelRatio
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.preferredWidth: nameLabel.implicitWidth + timeLabel.implicitWidth + Kirigami.Units.largeSpacing
|
||||||
|
Layout.maximumWidth: bubbleMaxWidth - Kirigami.Units.largeSpacing * 2
|
||||||
|
implicitHeight: visible ? nameLabel.implicitHeight : 0
|
||||||
|
|
||||||
|
QQC2.Label {
|
||||||
|
id: nameLabel
|
||||||
|
topInset: 0
|
||||||
|
|
||||||
|
visible: model.showAuthor && !isEmote
|
||||||
|
anchors.left: rowLayout.left
|
||||||
|
anchors.right: timeLabel.left
|
||||||
|
anchors.rightMargin: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
text: visible ? author.displayName : ""
|
||||||
|
font.weight: Font.Bold
|
||||||
|
color: author.color
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
QQC2.Label {
|
||||||
|
id: timeLabel
|
||||||
|
anchors.right: rowLayout.right
|
||||||
|
visible: model.showAuthor && !isEmote
|
||||||
|
text: visible ? time.toLocaleTimeString(Locale.ShortFormat) : ""
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loader {
|
||||||
|
id: replyLoader
|
||||||
|
active: model.reply !== undefined
|
||||||
|
source: 'qrc:imports/NeoChat/Component/Timeline/ReplyComponent.qml'
|
||||||
|
visible: active
|
||||||
|
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: replyLoader.item
|
||||||
|
function onClicked() {
|
||||||
|
replyClicked(reply.eventId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loader {
|
|
||||||
id: loader
|
background: Kirigami.ShadowedRectangle {
|
||||||
Layout.fillWidth: true
|
visible: cardBackground
|
||||||
Layout.leftMargin: Kirigami.Units.gridUnit * 2 + Kirigami.Units.largeSpacing * 2
|
color: model.isHighlighted ? Kirigami.Theme.positiveBackgroundColor : Kirigami.Theme.backgroundColor
|
||||||
Layout.topMargin: active ? Kirigami.Units.smallSpacing : 0
|
radius: Kirigami.Units.smallSpacing
|
||||||
//Layout.bottomMargin: readMarker ? Kirigami.Units.smallSpacing : 0
|
shadow.size: Kirigami.Units.smallSpacing
|
||||||
active: eventType !== "state" && eventType !== "notice" && reaction != undefined && reaction.length > 0
|
shadow.color: !model.isHighlighted ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||||
visible: active
|
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||||
sourceComponent: ReactionDelegate { }
|
border.width: Kirigami.Units.devicePixelRatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Item {
|
Loader {
|
||||||
Rectangle {
|
id: loader
|
||||||
width: parent.width * 0.9
|
anchors {
|
||||||
x: parent.width * 0.05
|
left: parent.left
|
||||||
height: Kirigami.Units.smallSpacing / 2
|
leftMargin: Kirigami.Units.gridUnit * 2 + Kirigami.Units.largeSpacing * 2
|
||||||
anchors.bottom: parent.bottom
|
right: parent.right
|
||||||
visible: readMarker
|
top: bubble.bottom
|
||||||
color: Kirigami.Theme.positiveTextColor
|
topMargin: active ? Kirigami.Units.smallSpacing : 0
|
||||||
}
|
}
|
||||||
|
height: active ? item.implicitHeight + Kirigami.Units.smallSpacing : 0
|
||||||
|
//Layout.bottomMargin: readMarker ? Kirigami.Units.smallSpacing : 0
|
||||||
|
active: eventType !== "state" && eventType !== "notice" && reaction != undefined && reaction.length > 0
|
||||||
|
visible: active
|
||||||
|
sourceComponent: ReactionDelegate { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width * 0.9
|
||||||
|
x: parent.width * 0.05
|
||||||
|
height: Kirigami.Units.smallSpacing / 2
|
||||||
|
anchors.top: loader.bottom
|
||||||
|
visible: readMarker
|
||||||
|
color: Kirigami.Theme.positiveTextColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,31 +16,33 @@ Loader {
|
|||||||
required property var author
|
required property var author
|
||||||
required property string message
|
required property string message
|
||||||
required property string eventId
|
required property string eventId
|
||||||
|
property string eventType: ""
|
||||||
|
property string formattedBody: ""
|
||||||
required property string source
|
required property string source
|
||||||
|
|
||||||
property list<Kirigami.Action> actions: [
|
property list<Kirigami.Action> actions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
text: i18n("Edit")
|
||||||
|
icon.name: "document-edit"
|
||||||
|
onTriggered: ChatBoxHelper.edit(message, formattedBody, eventId);
|
||||||
|
visible: eventType.length > 0 && author.id === Controller.activeConnection.localUserId && (eventType === "emote" || eventType === "message")
|
||||||
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("Reply")
|
text: i18n("Reply")
|
||||||
icon.name: "mail-replied-symbolic"
|
icon.name: "mail-replied-symbolic"
|
||||||
onTriggered: {
|
onTriggered: ChatBoxHelper.replyToMessage(eventId, message, author);
|
||||||
ChatBoxHelper.replyToMessage(eventId, message, author);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
visible: author.id === currentRoom.localUser.id || currentRoom.canSendState("redact")
|
visible: author.id === currentRoom.localUser.id || currentRoom.canSendState("redact")
|
||||||
text: i18n("Remove")
|
text: i18n("Remove")
|
||||||
icon.name: "edit-delete-remove"
|
icon.name: "edit-delete-remove"
|
||||||
icon.color: "red"
|
icon.color: "red"
|
||||||
onTriggered: {
|
onTriggered: currentRoom.redactEvent(eventId);
|
||||||
currentRoom.redactEvent(eventId);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("Copy")
|
text: i18n("Copy")
|
||||||
icon.name: "edit-copy"
|
icon.name: "edit-copy"
|
||||||
onTriggered: {
|
onTriggered: Clipboard.saveText(message)
|
||||||
Clipboard.saveText(message)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("View Source")
|
text: i18n("View Source")
|
||||||
@@ -54,6 +56,17 @@ Loader {
|
|||||||
Component {
|
Component {
|
||||||
id: regularMenu
|
id: regularMenu
|
||||||
|
|
||||||
|
QQC2.Menu {
|
||||||
|
Repeater {
|
||||||
|
model: loadRoot.actions
|
||||||
|
QQC2.MenuItem {
|
||||||
|
visible: modelData.visible
|
||||||
|
action: modelData
|
||||||
|
onClicked: loadRoot.item.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
Kirigami.OverlaySheet {
|
Kirigami.OverlaySheet {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
@@ -133,18 +146,8 @@ Loader {
|
|||||||
Kirigami.Separator {
|
Kirigami.Separator {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Repeater {
|
|
||||||
model: loadRoot.actions
|
|
||||||
Kirigami.BasicListItem {
|
|
||||||
visible: modelData.visible
|
|
||||||
action: modelData
|
|
||||||
onClicked: {
|
|
||||||
loadRoot.item.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: mobileMenu
|
id: mobileMenu
|
||||||
@@ -254,7 +257,11 @@ Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onStatusChanged: if (status == Loader.Ready) {
|
onStatusChanged: if (status == Loader.Ready) {
|
||||||
item.open();
|
if (Kirigami.Settings.isMobile) {
|
||||||
|
item.open();
|
||||||
|
} else {
|
||||||
|
item.popup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ Kirigami.ScrollablePage {
|
|||||||
hoverActions.updateFunction();
|
hoverActions.updateFunction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: hoverActions
|
id: hoverActions
|
||||||
property var event
|
property var event
|
||||||
@@ -382,22 +383,21 @@ Kirigami.ScrollablePage {
|
|||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
isEmote: true
|
isEmote: true
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
isEmote: true
|
isEmote: true
|
||||||
Layout.maximumWidth: emoteContainer.width - Kirigami.Units.gridUnit * 2 - Kirigami.Units.largeSpacing * 4
|
Layout.maximumWidth: emoteContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
|
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openMessageContext(author, model.display, eventId, toolTip)
|
onTapped: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openMessageContext(author, model.display, eventId, toolTip)
|
onLongPressed: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,21 +410,20 @@ Kirigami.ScrollablePage {
|
|||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
Layout.maximumWidth: messageContainer.width - Kirigami.Units.gridUnit * 2 - Kirigami.Units.largeSpacing * 4
|
Layout.maximumWidth: messageContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openMessageContext(author, model.display, eventId, toolTip)
|
onTapped: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openMessageContext(author, model.display, eventId, toolTip)
|
onLongPressed: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -438,9 +437,8 @@ Kirigami.ScrollablePage {
|
|||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
Layout.maximumWidth: noticeContainer.width - Kirigami.Units.gridUnit * 2 - Kirigami.Units.largeSpacing * 4
|
Layout.maximumWidth: noticeContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
|
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
|
||||||
@@ -451,18 +449,18 @@ Kirigami.ScrollablePage {
|
|||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "image"
|
roleValue: "image"
|
||||||
delegate: TimelineContainer {
|
delegate: TimelineContainer {
|
||||||
|
id: imageContainer
|
||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
|
width: messageListView.width
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: ImageDelegate {
|
innerObject: ImageDelegate {
|
||||||
Layout.minimumWidth: Kirigami.Units.gridUnit * 10
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 15
|
||||||
Layout.fillWidth: true
|
Layout.maximumWidth: imageContainer.bubbleMaxWidth
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.preferredHeight: info.h / info.w * width
|
Layout.preferredHeight: info.h / info.w * width
|
||||||
Layout.maximumHeight: Kirigami.Units.gridUnit * 15
|
Layout.maximumHeight: Kirigami.Units.gridUnit * 20
|
||||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
||||||
@@ -484,7 +482,6 @@ Kirigami.ScrollablePage {
|
|||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
hoverComponent: hoverActions
|
||||||
cardBackground: false
|
cardBackground: false
|
||||||
|
|
||||||
@@ -500,14 +497,15 @@ Kirigami.ScrollablePage {
|
|||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "audio"
|
roleValue: "audio"
|
||||||
delegate: TimelineContainer {
|
delegate: TimelineContainer {
|
||||||
|
id: audioContainer
|
||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
hoverComponent: hoverActions
|
|
||||||
|
|
||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: AudioDelegate {
|
innerObject: AudioDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: audioContainer.bubbleMaxWidth
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
||||||
@@ -523,16 +521,15 @@ Kirigami.ScrollablePage {
|
|||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "video"
|
roleValue: "video"
|
||||||
delegate: TimelineContainer {
|
delegate: TimelineContainer {
|
||||||
|
id: videoContainer
|
||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
hoverComponent: hoverActions
|
|
||||||
|
|
||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: VideoDelegate {
|
innerObject: VideoDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.minimumWidth: Kirigami.Units.gridUnit * 10
|
Layout.maximumWidth: videoContainer.bubbleMaxWidth
|
||||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
|
|
||||||
Layout.preferredHeight: content.info.h / content.info.w * width
|
Layout.preferredHeight: content.info.h / content.info.w * width
|
||||||
Layout.maximumHeight: Kirigami.Units.gridUnit * 15
|
Layout.maximumHeight: Kirigami.Units.gridUnit * 15
|
||||||
Layout.minimumHeight: Kirigami.Units.gridUnit * 5
|
Layout.minimumHeight: Kirigami.Units.gridUnit * 5
|
||||||
@@ -552,15 +549,14 @@ Kirigami.ScrollablePage {
|
|||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "file"
|
roleValue: "file"
|
||||||
delegate: TimelineContainer {
|
delegate: TimelineContainer {
|
||||||
|
id: fileContainer
|
||||||
width: messageListView.width
|
width: messageListView.width
|
||||||
|
|
||||||
hoverComponent: hoverActions
|
|
||||||
|
|
||||||
isLoaded: timelineDelegateChooser.delegateLoaded
|
isLoaded: timelineDelegateChooser.delegateLoaded
|
||||||
onReplyClicked: goToEvent(eventID)
|
onReplyClicked: goToEvent(eventID)
|
||||||
|
|
||||||
innerObject: FileDelegate {
|
innerObject: FileDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: fileContainer.bubbleMaxWidth
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
||||||
@@ -818,23 +814,26 @@ Kirigami.ScrollablePage {
|
|||||||
/// Open message context dialog for file and videos
|
/// Open message context dialog for file and videos
|
||||||
function openFileContext(author, message, eventId, source, progressInfo, file) {
|
function openFileContext(author, message, eventId, source, progressInfo, file) {
|
||||||
const contextMenu = fileDelegateContextMenu.createObject(page, {
|
const contextMenu = fileDelegateContextMenu.createObject(page, {
|
||||||
'author': author,
|
author: author,
|
||||||
'message': message,
|
message: message,
|
||||||
'eventId': eventId,
|
eventId: eventId,
|
||||||
'source': source,
|
source: source,
|
||||||
'file': file,
|
file: file,
|
||||||
'progressInfo': progressInfo,
|
progressInfo: progressInfo,
|
||||||
});
|
});
|
||||||
contextMenu.open();
|
contextMenu.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open context menu for normal message
|
/// Open context menu for normal message
|
||||||
function openMessageContext(author, message, eventId, source) {
|
function openMessageContext(author, message, eventId, source, eventType, formattedBody) {
|
||||||
|
console.log("message", message)
|
||||||
const contextMenu = messageDelegateContextMenu.createObject(page, {
|
const contextMenu = messageDelegateContextMenu.createObject(page, {
|
||||||
'author': author,
|
author: author,
|
||||||
'message': message,
|
message: message,
|
||||||
'eventId': eventId,
|
eventId: eventId,
|
||||||
'source': source,
|
formattedBody: formattedBody,
|
||||||
|
source: source,
|
||||||
|
eventType: eventType
|
||||||
});
|
});
|
||||||
contextMenu.open();
|
contextMenu.open();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user