prepare code for message bubbles and dynamic message layout

pull/920/head
Malte E 3 years ago
parent fcefdb7ca6
commit 04b47d6882
  1. 146
      resources/qml/TimelineRow.qml
  2. 9
      resources/qml/delegates/MessageDelegate.qml
  3. 2
      resources/qml/delegates/Placeholder.qml
  4. 14
      resources/qml/delegates/Reply.qml
  5. 4
      resources/qml/delegates/TextMessage.qml

@ -71,27 +71,39 @@ Item {
gesturePolicy: TapHandler.ReleaseWithinBounds gesturePolicy: TapHandler.ReleaseWithinBounds
} }
RowLayout { Item {
id: row id: row
anchors.rightMargin: 1 anchors.rightMargin: 1
anchors.leftMargin: Nheko.avatarSize + 16 anchors.leftMargin: Nheko.avatarSize + 16
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: msg.height+reactionRow.height+2
Column { GridLayout {
Layout.fillWidth: true id: msg
Layout.alignment: Qt.AlignTop anchors {
spacing: 4 right: parent.right
Layout.topMargin: 1 left: parent.left
Layout.bottomMargin: 1 top: parent.top
topMargin: 1
bottomMargin: 1
}
rowSpacing: 0
columnSpacing: 0
columns: 2
rows: 2
// fancy reply, if this is a reply // fancy reply, if this is a reply
Reply { Reply {
Layout.row: 0
Layout.column: 0
Layout.fillWidth: true
Layout.margins: 0
id: reply
function fromModel(role) { function fromModel(role) {
return replyTo != "" ? room.dataById(replyTo, role, r.eventId) : null; return replyTo != "" ? room.dataById(replyTo, role, r.eventId) : null;
} }
visible: replyTo visible: replyTo
userColor: r.relatedEventCacheBuster, TimelineManager.userColor(userId, Nheko.colors.base) userColor: r.relatedEventCacheBuster, TimelineManager.userColor(userId, Nheko.colors.base)
blurhash: r.relatedEventCacheBuster, fromModel(Room.Blurhash) ?? "" blurhash: r.relatedEventCacheBuster, fromModel(Room.Blurhash) ?? ""
@ -118,9 +130,12 @@ Item {
// actual message content // actual message content
MessageDelegate { MessageDelegate {
Layout.row: 1
Layout.column: 0
Layout.fillWidth: true
Layout.margins: 2
id: contentItem id: contentItem
width: parent.width
blurhash: r.blurhash blurhash: r.blurhash
body: r.body body: r.body
formattedBody: r.formattedBody formattedBody: r.formattedBody
@ -144,67 +159,76 @@ Item {
isReply: false isReply: false
} }
Reactions { RowLayout {
id: reactionRow Layout.column: 1
Layout.row: 0
Layout.rowSpan: 2
Layout.alignment: Qt.AlignTop | Qt.AlignRight
StatusIndicator {
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredHeight: 16
width: 16
status: r.status
eventId: r.eventId
}
reactions: r.reactions Image {
eventId: r.eventId visible: isEdited || eventId == chat.model.edit
} Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredHeight: 16
Layout.preferredWidth: 16
height: 16
width: 16
sourceSize.width: 16 * Screen.devicePixelRatio
sourceSize.height: 16 * Screen.devicePixelRatio
source: "image://colorimage/:/icons/icons/ui/edit.svg?" + ((eventId == chat.model.edit) ? Nheko.colors.highlight : Nheko.colors.buttonText)
ToolTip.visible: editHovered.hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: qsTr("Edited")
HoverHandler {
id: editHovered
}
} }
StatusIndicator { EncryptionIndicator {
Layout.alignment: Qt.AlignRight | Qt.AlignTop visible: room.isEncrypted
Layout.preferredHeight: 16 encrypted: isEncrypted
width: 16 trust: trustlevel
status: r.status Layout.alignment: Qt.AlignRight | Qt.AlignTop
eventId: r.eventId Layout.preferredHeight: 16
} Layout.preferredWidth: 16
}
Image { Label {
visible: isEdited || eventId == chat.model.edit Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.alignment: Qt.AlignRight | Qt.AlignTop text: timestamp.toLocaleTimeString(Locale.ShortFormat)
Layout.preferredHeight: 16 width: Math.max(implicitWidth, text.length * fontMetrics.maximumCharacterWidth)
Layout.preferredWidth: 16 color: Nheko.inactiveColors.text
height: 16 ToolTip.visible: ma.hovered
width: 16 ToolTip.delay: Nheko.tooltipDelay
sourceSize.width: 16 * Screen.devicePixelRatio ToolTip.text: Qt.formatDateTime(timestamp, Qt.DefaultLocaleLongDate)
sourceSize.height: 16 * Screen.devicePixelRatio
source: "image://colorimage/:/icons/icons/ui/edit.svg?" + ((eventId == chat.model.edit) ? Nheko.colors.highlight : Nheko.colors.buttonText)
ToolTip.visible: editHovered.hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: qsTr("Edited")
HoverHandler {
id: editHovered
}
} HoverHandler {
id: ma
}
EncryptionIndicator { }
visible: room.isEncrypted }
encrypted: isEncrypted
trust: trustlevel
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredHeight: 16
Layout.preferredWidth: 16
} }
Label { Reactions {
Layout.alignment: Qt.AlignRight | Qt.AlignTop anchors {
text: timestamp.toLocaleTimeString(Locale.ShortFormat) top: msg.bottom
width: Math.max(implicitWidth, text.length * fontMetrics.maximumCharacterWidth) left: parent.left
color: Nheko.inactiveColors.text
ToolTip.visible: ma.hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: Qt.formatDateTime(timestamp, Qt.DefaultLocaleLongDate)
HoverHandler {
id: ma
} }
} id: reactionRow
reactions: r.reactions
eventId: r.eventId
}
} }
} }

@ -13,7 +13,7 @@ Item {
required property bool isReply required property bool isReply
property alias child: chooser.child property alias child: chooser.child
property real implicitWidth: (chooser.child && chooser.child.implicitWidth) ? chooser.child.implicitWidth : width // property real implicitWidth: (chooser.child && chooser.child.implicitWidth) ? chooser.child.implicitWidth : width
required property double proportionalHeight required property double proportionalHeight
required property int type required property int type
required property string typeString required property string typeString
@ -35,14 +35,17 @@ Item {
required property int encryptionError required property int encryptionError
required property int relatedEventCacheBuster required property int relatedEventCacheBuster
height: chooser.child ? chooser.child.height : Nheko.paddingLarge Layout.preferredHeight: chooser.child ? chooser.child.height : Nheko.paddingLarge
DelegateChooser { DelegateChooser {
id: chooser id: chooser
//role: "type" //< not supported in our custom implementation, have to use roleValue //role: "type" //< not supported in our custom implementation, have to use roleValue
roleValue: type roleValue: type
anchors.fill: parent //anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
DelegateChoice { DelegateChoice {
roleValue: MtxEvent.UnknownMessage roleValue: MtxEvent.UnknownMessage

@ -10,6 +10,6 @@ MatrixText {
required property string typeString required property string typeString
text: qsTr("unimplemented event: ") + typeString text: qsTr("unimplemented event: ") + typeString
width: parent.width // width: parent.width
color: Nheko.inactiveColors.text color: Nheko.inactiveColors.text
} }

@ -35,7 +35,7 @@ Item {
property int encryptionError property int encryptionError
property int relatedEventCacheBuster property int relatedEventCacheBuster
width: parent.width Layout.preferredHeight: replyContainer.height
height: replyContainer.height height: replyContainer.height
CursorShape { CursorShape {
@ -52,12 +52,12 @@ Item {
color: TimelineManager.userColor(userId, Nheko.colors.base) color: TimelineManager.userColor(userId, Nheko.colors.base)
} }
Column { ColumnLayout {
id: replyContainer id: replyContainer
anchors.left: colorLine.right anchors.left: colorLine.right
anchors.leftMargin: 4
width: parent.width - 8 width: parent.width - 8
spacing: 0
TapHandler { TapHandler {
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
@ -80,6 +80,7 @@ Item {
} }
Text { Text {
Layout.leftMargin: 4
id: userName_ id: userName_
text: TimelineManager.escapeEmoji(userName) text: TimelineManager.escapeEmoji(userName)
@ -94,8 +95,8 @@ Item {
} }
MessageDelegate { MessageDelegate {
Layout.leftMargin: 4
id: reply id: reply
blurhash: r.blurhash blurhash: r.blurhash
body: r.body body: r.body
formattedBody: r.formattedBody formattedBody: r.formattedBody
@ -118,7 +119,7 @@ Item {
encryptionError: r.encryptionError encryptionError: r.encryptionError
// This is disabled so that left clicking the reply goes to its location // This is disabled so that left clicking the reply goes to its location
enabled: false enabled: false
width: parent.width Layout.fillWidth: true
isReply: true isReply: true
} }
@ -128,8 +129,7 @@ Item {
id: backgroundItem id: backgroundItem
z: -1 z: -1
height: replyContainer.height anchors.fill: replyContainer
width: Math.min(Math.max(reply.implicitWidth, userName_.implicitWidth) + 8 + 4, parent.width)
color: Qt.rgba(userColor.r, userColor.g, userColor.b, 0.1) color: Qt.rgba(userColor.r, userColor.g, userColor.b, 0.1)
} }

@ -33,8 +33,8 @@ MatrixText {
blockquote { margin-left: 1em; } blockquote { margin-left: 1em; }
</style> </style>
" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + Nheko.colors.alternateBase + "'>").replace("<del>", "<s>").replace("</del>", "</s>").replace("<strike>", "<s>").replace("</strike>", "</s>") " + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + Nheko.colors.alternateBase + "'>").replace("<del>", "<s>").replace("</del>", "</s>").replace("<strike>", "<s>").replace("</strike>", "</s>")
width: parent.width // width: parent.width
height: isReply ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : undefined //height: isReply ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : undefined
clip: isReply clip: isReply
selectByMouse: !Settings.mobileMode && !isReply selectByMouse: !Settings.mobileMode && !isReply
font.pointSize: (Settings.enlargeEmojiOnlyMessages && isOnlyEmoji > 0 && isOnlyEmoji < 4) ? Settings.fontSize * 3 : Settings.fontSize font.pointSize: (Settings.enlargeEmojiOnlyMessages && isOnlyEmoji > 0 && isOnlyEmoji < 4) ? Settings.fontSize * 3 : Settings.fontSize

Loading…
Cancel
Save