matrixion/resources/qml/TimelineRow.qml

331 lines
13 KiB
QML
Raw Normal View History

// SPDX-FileCopyrightText: Nheko Contributors
//
2021-03-05 02:35:15 +03:00
// SPDX-License-Identifier: GPL-3.0-or-later
2020-10-08 22:11:21 +03:00
import "./delegates"
import "./emoji"
2022-03-27 22:23:40 +03:00
import QtQuick 2.15
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.13
import im.nheko 1.0
2022-03-24 03:35:42 +03:00
AbstractButton {
id: r
required property double proportionalHeight
required property int type
required property string typeString
required property int originalWidth
required property string blurhash
required property string body
required property string formattedBody
required property string eventId
required property string filename
required property string filesize
required property string url
required property string thumbnailUrl
required property bool isOnlyEmoji
required property bool isSender
required property bool isEncrypted
required property bool isEditable
required property bool isEdited
required property bool isStateEvent
required property string replyTo
2022-09-30 04:27:05 +03:00
required property string threadId
required property string userId
required property string userName
2021-07-12 02:28:09 +03:00
required property string roomTopic
required property string roomName
required property string callType
required property var reactions
required property int trustlevel
required property int notificationlevel
required property int encryptionError
2022-03-21 02:48:27 +03:00
required property int duration
required property var timestamp
required property int status
required property int index
required property int relatedEventCacheBuster
2022-03-24 03:35:42 +03:00
hoverEnabled: true
2022-02-15 01:13:17 +03:00
width: parent.width
height: row.height+(reactionRow.height > 0 ? reactionRow.height-2 : 0 )+unreadRow.height
2020-10-08 22:11:21 +03:00
Rectangle {
2022-02-15 01:13:17 +03:00
color: (Settings.messageHoverHighlight && hovered) ? Nheko.colors.alternateBase : "transparent"
anchors.fill: parent
// this looks better without margins
2022-03-24 03:35:42 +03:00
TapHandler {
acceptedButtons: Qt.RightButton
2022-09-30 04:27:05 +03:00
onSingleTapped: messageContextMenu.show(eventId, threadId, type, isSender, isEncrypted, isEditable, contentItem.child.hoveredLink, contentItem.child.copyText)
2022-03-24 03:35:42 +03:00
gesturePolicy: TapHandler.ReleaseWithinBounds
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
2022-03-24 03:35:42 +03:00
}
}
2021-02-14 03:28:28 +03:00
2022-09-30 04:27:05 +03:00
onPressAndHold: messageContextMenu.show(eventId, threadId, type, isSender, isEncrypted, isEditable, contentItem.child.hoveredLink, contentItem.child.copyText)
onDoubleClicked: room.reply = eventId
2020-10-08 22:11:21 +03:00
2022-03-27 22:23:40 +03:00
DragHandler {
id: draghandler
yAxis.enabled: false
xAxis.maximum: 100
xAxis.minimum: -100
onActiveChanged: {
if(!active && (x < -70 || x > 70))
room.reply = eventId
2022-03-27 22:23:40 +03:00
}
}
states: State {
name: "dragging"
when: draghandler.active
}
transitions: Transition {
from: "dragging"
to: ""
PropertyAnimation {
target: r
properties: "x"
easing.type: Easing.InOutQuad
to: 0
duration: 100
}
}
onClicked: {
let link = contentItem.child.linkAt != undefined && contentItem.child.linkAt(pressX-row.x-msg.x, pressY-row.y-msg.y-contentItem.y);
if (link) {
Nheko.openLink(link)
}
}
2022-03-24 03:35:42 +03:00
Rectangle {
2020-10-08 22:11:21 +03:00
id: row
property bool bubbleOnRight : isSender && Settings.bubbles
anchors.leftMargin: isStateEvent || Settings.smallAvatars? 0 : Nheko.avatarSize+8 // align bubble with section header
anchors.left: isStateEvent? undefined : (bubbleOnRight? undefined : parent.left)
anchors.right: isStateEvent? undefined: (bubbleOnRight? parent.right : undefined)
anchors.horizontalCenter: isStateEvent? parent.horizontalCenter : undefined
property int maxWidth: (parent.width-(Settings.smallAvatars || isStateEvent? 0 : Nheko.avatarSize+8))*(Settings.bubbles && !isStateEvent? 0.9 : 1)
width: Settings.bubbles? Math.min(maxWidth,Math.max(reply.implicitWidth+8,contentItem.implicitWidth+metadata.width+20)) : maxWidth
2022-03-24 03:35:42 +03:00
height: msg.height+msg.anchors.margins*2
2022-03-24 03:35:42 +03:00
property color userColor: TimelineManager.userColor(userId, Nheko.colors.base)
property color bgColor: Nheko.colors.base
color: (Settings.bubbles && !isStateEvent) ? Qt.tint(bgColor, Qt.hsla(userColor.hslHue, 0.5, userColor.hslLightness, 0.2)) : "#00000000"
radius: 4
border.width: r.notificationlevel == MtxEvent.Highlight ? 1 : 0
border.color: Nheko.theme.red
2022-02-05 01:12:30 +03:00
2022-03-24 03:35:42 +03:00
GridLayout {
anchors {
left: parent.left
top: parent.top
right: parent.right
margins: (Settings.bubbles && ! isStateEvent)? 4 : 2
leftMargin: 4
rightMargin: 4
2022-03-24 03:35:42 +03:00
}
id: msg
rowSpacing: 0
2022-02-05 23:53:21 +03:00
columnSpacing: 2
columns: Settings.bubbles? 1 : 2
rows: Settings.bubbles? 3 : 2
2020-10-08 22:11:21 +03:00
// fancy reply, if this is a reply
Reply {
Layout.row: 0
Layout.column: 0
Layout.fillWidth: true
Layout.maximumWidth: Settings.bubbles? Number.MAX_VALUE : implicitWidth
2022-02-05 23:53:21 +03:00
Layout.bottomMargin: visible? 2 : 0
Layout.preferredHeight: height
id: reply
2021-07-12 23:28:01 +03:00
function fromModel(role) {
return replyTo != "" ? room.dataById(replyTo, role, r.eventId) : null;
2021-07-12 23:28:01 +03:00
}
visible: replyTo
userColor: r.relatedEventCacheBuster, TimelineManager.userColor(userId, Nheko.colors.base)
blurhash: r.relatedEventCacheBuster, fromModel(Room.Blurhash) ?? ""
body: r.relatedEventCacheBuster, fromModel(Room.Body) ?? ""
formattedBody: r.relatedEventCacheBuster, fromModel(Room.FormattedBody) ?? ""
2021-07-12 23:28:01 +03:00
eventId: fromModel(Room.EventId) ?? ""
filename: r.relatedEventCacheBuster, fromModel(Room.Filename) ?? ""
filesize: r.relatedEventCacheBuster, fromModel(Room.Filesize) ?? ""
proportionalHeight: r.relatedEventCacheBuster, fromModel(Room.ProportionalHeight) ?? 1
type: r.relatedEventCacheBuster, fromModel(Room.Type) ?? MtxEvent.UnknownMessage
typeString: r.relatedEventCacheBuster, fromModel(Room.TypeString) ?? ""
url: r.relatedEventCacheBuster, fromModel(Room.Url) ?? ""
originalWidth: r.relatedEventCacheBuster, fromModel(Room.OriginalWidth) ?? 0
isOnlyEmoji: r.relatedEventCacheBuster, fromModel(Room.IsOnlyEmoji) ?? false
isStateEvent: r.relatedEventCacheBuster, fromModel(Room.IsStateEvent) ?? false
userId: r.relatedEventCacheBuster, fromModel(Room.UserId) ?? ""
userName: r.relatedEventCacheBuster, fromModel(Room.UserName) ?? ""
thumbnailUrl: r.relatedEventCacheBuster, fromModel(Room.ThumbnailUrl) ?? ""
2022-03-21 02:48:27 +03:00
duration: r.relatedEventCacheBuster, fromModel(Room.Duration) ?? ""
roomTopic: r.relatedEventCacheBuster, fromModel(Room.RoomTopic) ?? ""
roomName: r.relatedEventCacheBuster, fromModel(Room.RoomName) ?? ""
callType: r.relatedEventCacheBuster, fromModel(Room.CallType) ?? ""
encryptionError: r.relatedEventCacheBuster, fromModel(Room.EncryptionError) ?? ""
relatedEventCacheBuster: r.relatedEventCacheBuster, fromModel(Room.RelatedEventCacheBuster) ?? 0
2020-10-08 22:11:21 +03:00
}
// actual message content
MessageDelegate {
Layout.row: 1
Layout.column: 0
Layout.fillWidth: true
Layout.preferredHeight: height
2020-10-08 22:11:21 +03:00
id: contentItem
blurhash: r.blurhash
body: r.body
formattedBody: r.formattedBody
eventId: r.eventId
filename: r.filename
filesize: r.filesize
proportionalHeight: r.proportionalHeight
type: r.type
typeString: r.typeString ?? ""
url: r.url
thumbnailUrl: r.thumbnailUrl
2022-03-21 02:48:27 +03:00
duration: r.duration
originalWidth: r.originalWidth
isOnlyEmoji: r.isOnlyEmoji
isStateEvent: r.isStateEvent
userId: r.userId
userName: r.userName
2021-07-12 02:28:09 +03:00
roomTopic: r.roomTopic
roomName: r.roomName
callType: r.callType
encryptionError: r.encryptionError
relatedEventCacheBuster: r.relatedEventCacheBuster
isReply: false
2022-02-14 23:07:03 +03:00
metadataWidth: metadata.width
2020-10-08 22:11:21 +03:00
}
2022-03-01 05:12:57 +03:00
Row {
id: metadata
Layout.column: Settings.bubbles? 0 : 1
Layout.row: Settings.bubbles? 2 : 0
Layout.rowSpan: Settings.bubbles? 1 : 2
Layout.bottomMargin: -2
2022-02-14 23:15:16 +03:00
Layout.topMargin: (contentItem.fitsMetadata && Settings.bubbles)? -height-Layout.bottomMargin : 0
Layout.alignment: Qt.AlignTop | Qt.AlignRight
Layout.preferredWidth: implicitWidth
visible: !isStateEvent
2022-03-01 05:12:57 +03:00
spacing: 2
2022-02-05 23:53:21 +03:00
property double scaling: Settings.bubbles? 0.75 : 1
2022-03-01 05:12:57 +03:00
property int iconSize: Math.floor(fontMetrics.ascent*scaling)
StatusIndicator {
Layout.alignment: Qt.AlignRight | Qt.AlignTop
2022-03-01 05:12:57 +03:00
height: parent.iconSize
width: parent.iconSize
status: r.status
eventId: r.eventId
2022-03-01 05:12:57 +03:00
anchors.verticalCenter: ts.verticalCenter
}
2020-10-08 22:11:21 +03:00
Image {
visible: isEdited || eventId == room.edit
Layout.alignment: Qt.AlignRight | Qt.AlignTop
2022-03-01 05:12:57 +03:00
height: parent.iconSize
width: parent.iconSize
sourceSize.width: parent.iconSize * Screen.devicePixelRatio
sourceSize.height: parent.iconSize * Screen.devicePixelRatio
source: "image://colorimage/:/icons/icons/ui/edit.svg?" + ((eventId == room.edit) ? Nheko.colors.highlight : Nheko.colors.buttonText)
ToolTip.visible: editHovered.hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: qsTr("Edited")
2022-03-01 05:12:57 +03:00
anchors.verticalCenter: ts.verticalCenter
HoverHandler {
id: editHovered
}
2020-10-08 22:11:21 +03:00
}
2020-10-08 22:11:21 +03:00
2022-10-04 01:38:59 +03:00
ImageButton {
visible: threadId
Layout.alignment: Qt.AlignRight | Qt.AlignTop
height: parent.iconSize
width: parent.iconSize
image: ":/icons/icons/ui/thread.svg"
buttonTextColor: TimelineManager.userColor(threadId, Nheko.colors.base)
ToolTip.visible: hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: qsTr("Part of a thread")
anchors.verticalCenter: ts.verticalCenter
onClicked: room.thread = threadId
}
EncryptionIndicator {
visible: room.isEncrypted
encrypted: isEncrypted
trust: trustlevel
Layout.alignment: Qt.AlignRight | Qt.AlignTop
2022-03-01 05:12:57 +03:00
height: parent.iconSize
width: parent.iconSize
sourceSize.width: parent.iconSize * Screen.devicePixelRatio
sourceSize.height: parent.iconSize * Screen.devicePixelRatio
anchors.verticalCenter: ts.verticalCenter
}
2020-10-08 22:11:21 +03:00
Label {
2022-03-01 05:12:57 +03:00
id: ts
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredWidth: implicitWidth
text: timestamp.toLocaleTimeString(Locale.ShortFormat)
color: Nheko.inactiveColors.text
ToolTip.visible: ma.hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: Qt.formatDateTime(timestamp, Qt.DefaultLocaleLongDate)
2022-03-01 05:12:57 +03:00
font.pointSize: fontMetrics.font.pointSize*parent.scaling
HoverHandler {
id: ma
}
2020-10-08 22:11:21 +03:00
}
}
2021-11-11 06:43:37 +03:00
}
2022-02-05 23:53:21 +03:00
}
2022-02-05 23:53:21 +03:00
Reactions {
anchors {
top: row.bottom
topMargin: -4
left: row.bubbleOnRight? undefined : row.left
right: row.bubbleOnRight? row.right : undefined
2022-02-05 23:53:21 +03:00
}
width: row.maxWidth
layoutDirection: row.bubbleOnRight? Qt.RightToLeft : Qt.LeftToRight
2021-11-11 06:43:37 +03:00
2022-02-05 23:53:21 +03:00
id: reactionRow
2020-10-08 22:11:21 +03:00
2022-02-05 23:53:21 +03:00
reactions: r.reactions
eventId: r.eventId
2020-10-08 22:11:21 +03:00
}
Rectangle {
id: unreadRow
anchors {
top: reactionRow.bottom
topMargin: 5
2022-12-18 07:57:40 +03:00
left: parent.left
right: parent.right
}
color: Nheko.colors.highlight
2022-12-18 07:57:40 +03:00
visible: (r.index > 0 && (room.fullyReadEventId == r.eventId))
height: visible ? 3 : 0
}
}