mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-10-30 09:30:47 +03:00
Fixup reply and state event rendering
This commit is contained in:
parent
6c6370c83f
commit
c4d2ec875d
10 changed files with 207 additions and 897 deletions
|
@ -742,7 +742,6 @@ set(QML_SOURCES
|
||||||
resources/qml/delegates/Encrypted.qml
|
resources/qml/delegates/Encrypted.qml
|
||||||
resources/qml/delegates/FileMessage.qml
|
resources/qml/delegates/FileMessage.qml
|
||||||
resources/qml/delegates/ImageMessage.qml
|
resources/qml/delegates/ImageMessage.qml
|
||||||
resources/qml/delegates/MessageDelegate.qml
|
|
||||||
resources/qml/delegates/NoticeMessage.qml
|
resources/qml/delegates/NoticeMessage.qml
|
||||||
resources/qml/delegates/Pill.qml
|
resources/qml/delegates/Pill.qml
|
||||||
resources/qml/delegates/Placeholder.qml
|
resources/qml/delegates/Placeholder.qml
|
||||||
|
|
|
@ -18,7 +18,7 @@ TimelineEvent {
|
||||||
id: wrapper
|
id: wrapper
|
||||||
ListView.delayRemove: true
|
ListView.delayRemove: true
|
||||||
width: chat.delegateMaxWidth
|
width: chat.delegateMaxWidth
|
||||||
height: Math.max((section.item?.height ?? 0) + gridContainer.implicitHeight + reactionRow.implicitHeight + unreadRow.height, 20)
|
height: Math.max((section.item?.height ?? 0) + gridContainer.implicitHeight + reactionRow.implicitHeight + unreadRow.height, 10)
|
||||||
anchors.horizontalCenter: ListView.view.contentItem.horizontalCenter
|
anchors.horizontalCenter: ListView.view.contentItem.horizontalCenter
|
||||||
//room: chatRoot.roommodel
|
//room: chatRoot.roommodel
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ TimelineEvent {
|
||||||
property alias hovered: messageHover.hovered
|
property alias hovered: messageHover.hovered
|
||||||
property bool scrolledToThis: false
|
property bool scrolledToThis: false
|
||||||
|
|
||||||
|
mainInset: (threadId ? (4 + Nheko.paddingSmall) : 0) + 4
|
||||||
|
replyInset: mainInset + 4 + Nheko.paddingSmall
|
||||||
|
|
||||||
maxWidth: chat.delegateMaxWidth - avatarMargin - metadata.width
|
maxWidth: chat.delegateMaxWidth - avatarMargin - metadata.width
|
||||||
|
|
||||||
data: [
|
data: [
|
||||||
|
@ -182,16 +185,21 @@ TimelineEvent {
|
||||||
color: TimelineManager.userColor(wrapper.threadId, palette.base)
|
color: TimelineManager.userColor(wrapper.threadId, palette.base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
visible: wrapper.isStateEvent
|
||||||
|
width: (wrapper.maxWidth - (wrapper.main?.width ?? 0)) / 2
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: contentColumn
|
id: contentColumn
|
||||||
|
|
||||||
AbstractButton {
|
AbstractButton {
|
||||||
id: replyRow
|
id: replyRow
|
||||||
visible: wrapper.reply
|
visible: wrapper.reply
|
||||||
//Layout.fillWidth: true
|
|
||||||
//Layout.maximumHeight: timelineView.height / 8
|
height: replyLine.height
|
||||||
//Layout.preferredWidth: replyRowLay.implicitWidth
|
|
||||||
//Layout.preferredHeight: replyRowLay.implicitHeight
|
|
||||||
|
|
||||||
property color userColor: TimelineManager.userColor(wrapper.reply?.userId ?? '', palette.base)
|
property color userColor: TimelineManager.userColor(wrapper.reply?.userId ?? '', palette.base)
|
||||||
|
|
||||||
|
@ -209,7 +217,7 @@ TimelineEvent {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: replyLine
|
id: replyLine
|
||||||
height: replyCol.height
|
height: Math.min( wrapper.reply?.height, timelineView.height / 5) + Nheko.paddingSmall + replyUserButton.height
|
||||||
color: replyRow.userColor
|
color: replyRow.userColor
|
||||||
width: 4
|
width: 4
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,12 +62,10 @@ EventDelegateChooser {
|
||||||
required property string userId
|
required property string userId
|
||||||
required property string userName
|
required property string userName
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
//Layout.maximumWidth: implicitWidth
|
|
||||||
|
|
||||||
body: ''
|
body: ''
|
||||||
color: palette.buttonText
|
color: palette.buttonText
|
||||||
font.italic: true
|
font.italic: true
|
||||||
|
font.pointSize: Settings.fontSize * 0.8
|
||||||
formatted: ''
|
formatted: ''
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
isOnlyEmoji: false
|
isOnlyEmoji: false
|
||||||
|
@ -202,7 +200,6 @@ EventDelegateChooser {
|
||||||
id: member
|
id: member
|
||||||
|
|
||||||
required property string formattedStateEvent
|
required property string formattedStateEvent
|
||||||
required property bool isReply
|
|
||||||
required property Room room
|
required property Room room
|
||||||
required property string userId
|
required property string userId
|
||||||
required property string userName
|
required property string userName
|
||||||
|
@ -212,7 +209,7 @@ EventDelegateChooser {
|
||||||
body: formatted
|
body: formatted
|
||||||
formatted: member.formattedStateEvent
|
formatted: member.formattedStateEvent
|
||||||
isOnlyEmoji: false
|
isOnlyEmoji: false
|
||||||
isReply: member.isReply
|
isReply: EventDelegateChooser.isReply
|
||||||
isStateEvent: true
|
isStateEvent: true
|
||||||
keepFullText: true
|
keepFullText: true
|
||||||
}
|
}
|
||||||
|
@ -233,7 +230,6 @@ EventDelegateChooser {
|
||||||
|
|
||||||
required property string body
|
required property string body
|
||||||
required property string eventId
|
required property string eventId
|
||||||
required property bool isReply
|
|
||||||
required property Room room
|
required property Room room
|
||||||
required property string userId
|
required property string userId
|
||||||
required property string userName
|
required property string userName
|
||||||
|
@ -243,7 +239,7 @@ EventDelegateChooser {
|
||||||
body: formatted
|
body: formatted
|
||||||
formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
|
formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
|
||||||
isOnlyEmoji: false
|
isOnlyEmoji: false
|
||||||
isReply: tombstone.isReply
|
isReply: EventDelegateChooser.isReply
|
||||||
isStateEvent: true
|
isStateEvent: true
|
||||||
keepFullText: true
|
keepFullText: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Window
|
import QtQuick.Window
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
|
||||||
import im.nheko
|
import im.nheko
|
||||||
|
|
||||||
AbstractButton {
|
AbstractButton {
|
||||||
|
@ -17,16 +16,17 @@ AbstractButton {
|
||||||
required property string blurhash
|
required property string blurhash
|
||||||
required property string body
|
required property string body
|
||||||
required property string filename
|
required property string filename
|
||||||
required property bool isReply
|
|
||||||
required property string eventId
|
required property string eventId
|
||||||
required property int containerHeight
|
required property int containerHeight
|
||||||
property double divisor: isReply ? 5 : 3
|
property double divisor: EventDelegateChooser.isReply ? 5 : 3
|
||||||
|
|
||||||
|
EventDelegateChooser.keepAspectRatio: true
|
||||||
|
EventDelegateChooser.maxWidth: originalWidth
|
||||||
|
EventDelegateChooser.maxHeight: containerHeight / divisor
|
||||||
|
EventDelegateChooser.aspectRatio: proportionalHeight
|
||||||
|
|
||||||
//Layout.maximumWidth: originalWidth
|
|
||||||
Layout.maximumHeight: Math.min(originalHeight, containerHeight / divisor)
|
|
||||||
implicitWidth: height/proportionalHeight
|
|
||||||
implicitHeight: Math.min(Layout.maximumHeight, width*proportionalHeight)
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
enabled: !EventDelegateChooser.isReply
|
||||||
|
|
||||||
state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
|
state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
|
||||||
states: [
|
states: [
|
||||||
|
@ -133,8 +133,8 @@ AbstractButton {
|
||||||
roomm: room
|
roomm: room
|
||||||
play: !Settings.animateImagesOnHover || parent.hovered
|
play: !Settings.animateImagesOnHover || parent.hovered
|
||||||
eventId: parent.eventId
|
eventId: parent.eventId
|
||||||
width: parent.implicitWidth
|
|
||||||
height: parent.implicitHeight
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -143,10 +143,10 @@ AbstractButton {
|
||||||
source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + palette.buttonText)
|
source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + palette.buttonText)
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
sourceSize.width: parent.implicitWidth * Screen.devicePixelRatio
|
sourceSize.width: parent.width * Screen.devicePixelRatio
|
||||||
sourceSize.height: parent.implicitHeight * Screen.devicePixelRatio
|
sourceSize.height: parent.height * Screen.devicePixelRatio
|
||||||
width: parent.implicitWidth
|
|
||||||
height: parent.implicitHeight
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: Settings.openImageExternal ? room.openMedia(eventId) : TimelineManager.openImageOverlay(room, url, eventId, originalWidth, proportionalHeight);
|
onClicked: Settings.openImageExternal ? room.openMedia(eventId) : TimelineManager.openImageOverlay(room, url, eventId, originalWidth, proportionalHeight);
|
||||||
|
@ -154,8 +154,8 @@ AbstractButton {
|
||||||
Item {
|
Item {
|
||||||
id: overlay
|
id: overlay
|
||||||
|
|
||||||
width: parent.implicitWidth
|
anchors.fill: parent
|
||||||
height: parent.implicitHeight
|
|
||||||
visible: parent.hovered
|
visible: parent.hovered
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
|
@ -1,780 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
import QtQuick 2.6
|
|
||||||
import QtQuick.Controls 2.1
|
|
||||||
import QtQuick.Layouts 1.2
|
|
||||||
import im.nheko 1.0
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: d
|
|
||||||
|
|
||||||
required property bool isReply
|
|
||||||
property bool keepFullText: !isReply
|
|
||||||
property alias child: chooser.child
|
|
||||||
//implicitWidth: chooser.child?.implicitWidth ?? 0
|
|
||||||
required property double proportionalHeight
|
|
||||||
required property int type
|
|
||||||
required property string typeString
|
|
||||||
required property int originalWidth
|
|
||||||
required property int duration
|
|
||||||
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 isStateEvent
|
|
||||||
required property string userId
|
|
||||||
required property string userName
|
|
||||||
required property string roomTopic
|
|
||||||
required property string roomName
|
|
||||||
required property string callType
|
|
||||||
required property int encryptionError
|
|
||||||
required property int relatedEventCacheBuster
|
|
||||||
property bool fitsMetadata: (chooser.child && chooser.child.fitsMetadata) ? chooser.child.fitsMetadata : false
|
|
||||||
property int metadataWidth
|
|
||||||
|
|
||||||
implicitWidth: chooser.child?.implicitWidth
|
|
||||||
|
|
||||||
height: chooser.child ? chooser.child.height : Nheko.paddingLarge
|
|
||||||
|
|
||||||
DelegateChooser {
|
|
||||||
id: chooser
|
|
||||||
|
|
||||||
//role: "type" //< not supported in our custom implementation, have to use roleValue
|
|
||||||
roleValue: type
|
|
||||||
//anchors.fill: parent
|
|
||||||
|
|
||||||
width: parent?.width ?? 0 // this should get rid of "cannot read property 'width' of null"
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.UnknownEvent
|
|
||||||
|
|
||||||
Placeholder {
|
|
||||||
typeString: d.typeString
|
|
||||||
text: "Unretrieved event"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Tombstone
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
Layout.fillWidth: true
|
|
||||||
formatted: qsTr("This room was replaced for the following reason: %1").arg(d.body)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
text: qsTr("Go to replacement room")
|
|
||||||
onClicked: room.joinReplacementRoom(eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.TextMessage
|
|
||||||
|
|
||||||
TextMessage {
|
|
||||||
formatted: d.formattedBody
|
|
||||||
body: d.body
|
|
||||||
isOnlyEmoji: d.isOnlyEmoji
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.UnknownMessage
|
|
||||||
|
|
||||||
TextMessage {
|
|
||||||
formatted: d.formattedBody
|
|
||||||
body: d.body
|
|
||||||
isOnlyEmoji: d.isOnlyEmoji
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.ElementEffectMessage
|
|
||||||
|
|
||||||
TextMessage {
|
|
||||||
formatted: d.formattedBody
|
|
||||||
body: d.body
|
|
||||||
isOnlyEmoji: d.isOnlyEmoji
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.NoticeMessage
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
formatted: d.formattedBody
|
|
||||||
body: d.body
|
|
||||||
isOnlyEmoji: d.isOnlyEmoji
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.EmoteMessage
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
formatted: TimelineManager.escapeEmoji(d.userName) + " " + d.formattedBody
|
|
||||||
color: TimelineManager.userColor(d.userId, palette.base)
|
|
||||||
body: d.body
|
|
||||||
isOnlyEmoji: d.isOnlyEmoji
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.ImageMessage
|
|
||||||
|
|
||||||
ImageMessage {
|
|
||||||
type: d.type
|
|
||||||
originalWidth: d.originalWidth
|
|
||||||
proportionalHeight: d.proportionalHeight
|
|
||||||
url: d.url
|
|
||||||
blurhash: d.blurhash
|
|
||||||
body: d.body
|
|
||||||
filename: d.filename
|
|
||||||
isReply: d.isReply
|
|
||||||
eventId: d.eventId
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
containerHeight: timelineView.height
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Sticker
|
|
||||||
|
|
||||||
ImageMessage {
|
|
||||||
type: d.type
|
|
||||||
originalWidth: d.originalWidth
|
|
||||||
proportionalHeight: d.proportionalHeight
|
|
||||||
url: d.url
|
|
||||||
blurhash: d.blurhash
|
|
||||||
body: d.body
|
|
||||||
filename: d.filename
|
|
||||||
isReply: d.isReply
|
|
||||||
eventId: d.eventId
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
containerHeight: timelineView.height
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.FileMessage
|
|
||||||
|
|
||||||
FileMessage {
|
|
||||||
eventId: d.eventId
|
|
||||||
filename: d.filename
|
|
||||||
filesize: d.filesize
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.VideoMessage
|
|
||||||
|
|
||||||
PlayableMediaMessage {
|
|
||||||
proportionalHeight: d.proportionalHeight
|
|
||||||
type: d.type
|
|
||||||
originalWidth: d.originalWidth
|
|
||||||
thumbnailUrl: d.thumbnailUrl
|
|
||||||
eventId: d.eventId
|
|
||||||
url: d.url
|
|
||||||
body: d.body
|
|
||||||
filesize: d.filesize
|
|
||||||
duration: d.duration
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.AudioMessage
|
|
||||||
|
|
||||||
PlayableMediaMessage {
|
|
||||||
proportionalHeight: d.proportionalHeight
|
|
||||||
type: d.type
|
|
||||||
originalWidth: d.originalWidth
|
|
||||||
thumbnailUrl: d.thumbnailUrl
|
|
||||||
eventId: d.eventId
|
|
||||||
url: d.url
|
|
||||||
body: d.body
|
|
||||||
filesize: d.filesize
|
|
||||||
duration: d.duration
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Redacted
|
|
||||||
|
|
||||||
Redacted {
|
|
||||||
metadataWidth: d.metadataWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Redaction
|
|
||||||
|
|
||||||
Pill {
|
|
||||||
text: qsTr("%1 removed a message").arg(d.userName)
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Encryption
|
|
||||||
|
|
||||||
EncryptionEnabled {
|
|
||||||
username: d.userName
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Encrypted
|
|
||||||
|
|
||||||
Encrypted {
|
|
||||||
encryptionError: d.encryptionError
|
|
||||||
eventId: d.eventId
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.ServerAcl
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 changed which servers are allowed in this room.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Name
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.roomName ? qsTr("%2 changed the room name to: %1").arg(d.roomName).arg(d.userName) : qsTr("%1 removed the room name").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Topic
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.roomTopic ? qsTr("%2 changed the topic to: %1").arg(d.roomTopic).arg(d.userName): qsTr("%1 removed the topic").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Avatar
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 changed the room avatar").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.PinnedEvents
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 changed the pinned messages.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.ImagePackInRoom
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatImagePackEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CanonicalAlias
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 changed the addresses for this room.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.SpaceParent
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 changed the parent communities for this room.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.RoomCreate
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 created and configured room: %2").arg(d.userName).arg(room.roomId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallInvite
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: {
|
|
||||||
switch (d.callType) {
|
|
||||||
case "voice":
|
|
||||||
return qsTr("%1 placed a voice call.").arg(d.userName);
|
|
||||||
case "video":
|
|
||||||
return qsTr("%1 placed a video call.").arg(d.userName);
|
|
||||||
default:
|
|
||||||
return qsTr("%1 placed a call.").arg(d.userName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallAnswer
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 answered the call.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallReject
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 rejected the call.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallSelectAnswer
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 select answer").arg(d.userName)
|
|
||||||
// formatted: qsTr("Call answered elsewhere")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallHangUp
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 ended the call.").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallCandidates
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 is negotiating the call...").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.CallNegotiate
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: qsTr("%1 is negotiating the call...").arg(d.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.PowerLevels
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatPowerLevelEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.PolicyRuleUser
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatPolicyRule(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.PolicyRuleRoom
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatPolicyRule(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.PolicyRuleServer
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatPolicyRule(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.RoomJoinRules
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatJoinRuleEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.RoomHistoryVisibility
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatHistoryVisibilityEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.RoomGuestAccess
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatGuestAccessEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.Member
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
Layout.fillWidth: true
|
|
||||||
formatted: d.relatedEventCacheBuster, room.formatMemberEvent(d.eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
visible: d.relatedEventCacheBuster, room.showAcceptKnockButton(d.eventId)
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
text: qsTr("Allow them in")
|
|
||||||
onClicked: room.acceptKnock(eventId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationRequest
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationRequest"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationStart
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationStart"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationReady
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationReady"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationCancel
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationCancel"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationKey
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationKey"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationMac
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationMac"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationDone
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationDone"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationDone
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationDone"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: MtxEvent.KeyVerificationAccept
|
|
||||||
|
|
||||||
NoticeMessage {
|
|
||||||
body: formatted
|
|
||||||
isOnlyEmoji: false
|
|
||||||
isReply: d.isReply
|
|
||||||
keepFullText: d.keepFullText
|
|
||||||
isStateEvent: d.isStateEvent
|
|
||||||
formatted: "KeyVerificationAccept"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
Placeholder {
|
|
||||||
typeString: d.typeString
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -22,7 +22,7 @@ Item {
|
||||||
required property string url
|
required property string url
|
||||||
required property string body
|
required property string body
|
||||||
required property string filesize
|
required property string filesize
|
||||||
property double divisor: isReply ? 4 : 2
|
property double divisor: EventDelegateChooser.isReply ? 5 : 3
|
||||||
property int tempWidth: originalWidth < 1? 400: originalWidth
|
property int tempWidth: originalWidth < 1? 400: originalWidth
|
||||||
implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500
|
implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500
|
||||||
width: Math.min(parent?.width ?? implicitWidth, implicitWidth)
|
width: Math.min(parent?.width ?? implicitWidth, implicitWidth)
|
||||||
|
|
|
@ -48,51 +48,43 @@ AbstractButton {
|
||||||
room: room_
|
room: room_
|
||||||
eventId: r.eventId
|
eventId: r.eventId
|
||||||
replyTo: ""
|
replyTo: ""
|
||||||
|
mainInset: 4 + Nheko.paddingMedium
|
||||||
|
maxWidth: r.maxWidth
|
||||||
|
|
||||||
//height: replyContainer.implicitHeight
|
//height: replyContainer.implicitHeight
|
||||||
data: GridLayout {
|
data: Row {
|
||||||
id: replyContainer
|
id: replyContainer
|
||||||
|
|
||||||
width: r.maxWidth
|
spacing: Nheko.paddingSmall
|
||||||
columns: 2
|
|
||||||
rows: 2
|
|
||||||
columnSpacing: Nheko.paddingMedium
|
|
||||||
rowSpacing: Nheko.paddingSmall
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: colorline
|
id: colorline
|
||||||
|
|
||||||
Layout.preferredWidth: 4
|
width: 4
|
||||||
Layout.rowSpan: 2
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
Layout.row: 0
|
|
||||||
Layout.column: 0
|
|
||||||
|
|
||||||
color: TimelineManager.userColor(r.userId, palette.base)
|
color: TimelineManager.userColor(r.userId, palette.base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
AbstractButton {
|
AbstractButton {
|
||||||
id: usernameBtn
|
id: usernameBtn
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Layout.row: 0
|
contentItem: Label {
|
||||||
Layout.column: 1
|
|
||||||
|
|
||||||
contentItem: ElidedLabel {
|
|
||||||
id: userName_
|
id: userName_
|
||||||
fullText: r.userName
|
text: r.userName
|
||||||
color: r.userColor
|
color: r.userColor
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
width: parent.width
|
width: timelineEvent.main?.width
|
||||||
elideWidth: width
|
|
||||||
}
|
}
|
||||||
onClicked: room.openUserProfile(r.userId)
|
onClicked: room.openUserProfile(r.userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
data: [
|
data: [
|
||||||
colorline, usernameBtn, timelineEvent.main,
|
usernameBtn, timelineEvent.main,
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import im.nheko
|
||||||
MatrixText {
|
MatrixText {
|
||||||
required property string body
|
required property string body
|
||||||
required property bool isOnlyEmoji
|
required property bool isOnlyEmoji
|
||||||
required property bool isReply
|
property bool isReply: EventDelegateChooser.isReply
|
||||||
required property bool keepFullText
|
required property bool keepFullText
|
||||||
required property string formatted
|
required property string formatted
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ MatrixText {
|
||||||
|
|
||||||
//EventDelegateChooser.fillWidth: true
|
//EventDelegateChooser.fillWidth: true
|
||||||
|
|
||||||
clip: !keepFullText
|
|
||||||
selectByMouse: !Settings.mobileMode && !isReply
|
selectByMouse: !Settings.mobileMode && !isReply
|
||||||
enabled: !Settings.mobileMode && !isReply
|
enabled: !Settings.mobileMode && !isReply
|
||||||
hoverEnabled: !Settings.mobileMode
|
hoverEnabled: !Settings.mobileMode
|
||||||
|
|
|
@ -97,6 +97,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
item->setParentItem(&chooser);
|
item->setParentItem(&chooser);
|
||||||
|
item->setParent(&chooser);
|
||||||
|
|
||||||
auto roleNames = chooser.room_->roleNames();
|
auto roleNames = chooser.room_->roleNames();
|
||||||
QHash<QByteArray, int> nameToRole;
|
QHash<QByteArray, int> nameToRole;
|
||||||
|
@ -106,8 +107,6 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
||||||
|
|
||||||
QHash<int, int> roleToPropIdx;
|
QHash<int, int> roleToPropIdx;
|
||||||
std::vector<QModelRoleData> roles;
|
std::vector<QModelRoleData> roles;
|
||||||
bool isReplyNeeded = false;
|
|
||||||
|
|
||||||
// Workaround for https://bugreports.qt.io/browse/QTBUG-98846
|
// Workaround for https://bugreports.qt.io/browse/QTBUG-98846
|
||||||
QHash<QString, RequiredPropertyKey> requiredProperties;
|
QHash<QString, RequiredPropertyKey> requiredProperties;
|
||||||
for (const auto &[propKey, prop] :
|
for (const auto &[propKey, prop] :
|
||||||
|
@ -124,10 +123,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
||||||
if (!prop.isRequired() && !requiredProperties.contains(prop.name()))
|
if (!prop.isRequired() && !requiredProperties.contains(prop.name()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (prop.name() == std::string_view("isReply")) {
|
if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
|
||||||
isReplyNeeded = true;
|
|
||||||
roleToPropIdx.insert(-1, i);
|
|
||||||
} else if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
|
|
||||||
roleToPropIdx.insert(*role, i);
|
roleToPropIdx.insert(*role, i);
|
||||||
roles.emplace_back(*role);
|
roles.emplace_back(*role);
|
||||||
|
|
||||||
|
@ -141,6 +137,11 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
||||||
chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles);
|
chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles);
|
||||||
|
|
||||||
Qt::beginPropertyUpdateGroup();
|
Qt::beginPropertyUpdateGroup();
|
||||||
|
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
||||||
|
qmlAttachedPropertiesObject<EventDelegateChooser>(obj));
|
||||||
|
Q_ASSERT(attached != nullptr);
|
||||||
|
attached->setIsReply(this->forReply);
|
||||||
|
|
||||||
for (const auto &role : roles) {
|
for (const auto &role : roles) {
|
||||||
const auto &roleName = roleNames[role.role()];
|
const auto &roleName = roleNames[role.role()];
|
||||||
// nhlog::ui()->critical("Setting role {}, {} to {}",
|
// nhlog::ui()->critical("Setting role {}, {} to {}",
|
||||||
|
@ -155,22 +156,25 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
||||||
QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req);
|
QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReplyNeeded) {
|
|
||||||
const auto roleName = QByteArray("isReply");
|
|
||||||
// nhlog::ui()->critical("Setting role {} to {}", roleName.toStdString(), forReply);
|
|
||||||
|
|
||||||
// nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[-1]).name());
|
|
||||||
mo->property(roleToPropIdx[-1]).write(obj, forReply);
|
|
||||||
|
|
||||||
if (const auto &req = requiredProperties.find(roleName); req != requiredProperties.end())
|
|
||||||
QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req);
|
|
||||||
}
|
|
||||||
Qt::endPropertyUpdateGroup();
|
Qt::endPropertyUpdateGroup();
|
||||||
|
|
||||||
// setInitialProperties(rolesToSet);
|
// setInitialProperties(rolesToSet);
|
||||||
|
|
||||||
auto update =
|
auto update =
|
||||||
[this, obj, roleToPropIdx = std::move(roleToPropIdx)](const QList<int> &changedRoles) {
|
[this, obj, roleToPropIdx = std::move(roleToPropIdx)](const QList<int> &changedRoles) {
|
||||||
|
if (changedRoles.empty() || changedRoles.contains(TimelineModel::Roles::Type)) {
|
||||||
|
int type = chooser.room_
|
||||||
|
->dataById(currentId,
|
||||||
|
TimelineModel::Roles::Type,
|
||||||
|
forReply ? chooser.eventId_ : QString())
|
||||||
|
.toInt();
|
||||||
|
if (type != oldType) {
|
||||||
|
nhlog::ui()->debug("Type changed!");
|
||||||
|
reset(currentId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<QModelRoleData> rolesToRequest;
|
std::vector<QModelRoleData> rolesToRequest;
|
||||||
|
|
||||||
if (changedRoles.empty()) {
|
if (changedRoles.empty()) {
|
||||||
|
@ -233,6 +237,7 @@ EventDelegateChooser::DelegateIncubator::reset(QString id)
|
||||||
chooser.room_
|
chooser.room_
|
||||||
->dataById(id, TimelineModel::Roles::Type, forReply ? chooser.eventId_ : QString())
|
->dataById(id, TimelineModel::Roles::Type, forReply ? chooser.eventId_ : QString())
|
||||||
.toInt();
|
.toInt();
|
||||||
|
this->oldType = role;
|
||||||
|
|
||||||
for (const auto choice : qAsConst(chooser.choices_)) {
|
for (const auto choice : qAsConst(chooser.choices_)) {
|
||||||
const auto &choiceValue = choice->roleValues();
|
const auto &choiceValue = choice->roleValues();
|
||||||
|
@ -293,41 +298,58 @@ EventDelegateChooser::updatePolish()
|
||||||
|
|
||||||
nhlog::ui()->critical("POLISHING {}", (void *)this);
|
nhlog::ui()->critical("POLISHING {}", (void *)this);
|
||||||
|
|
||||||
if (mainChild) {
|
auto layoutItem = [this](QQuickItem *item, int inset) {
|
||||||
|
if (item) {
|
||||||
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
||||||
qmlAttachedPropertiesObject<EventDelegateChooser>(mainChild));
|
qmlAttachedPropertiesObject<EventDelegateChooser>(item));
|
||||||
Q_ASSERT(attached != nullptr);
|
Q_ASSERT(attached != nullptr);
|
||||||
|
|
||||||
// in theory we could also reset the width, but that doesn't seem to work nicely for text
|
int maxWidth = maxWidth_ - inset;
|
||||||
// areas because of how they cache it.
|
|
||||||
mainChild->setWidth(maxWidth_);
|
|
||||||
mainChild->ensurePolished();
|
|
||||||
auto width = mainChild->implicitWidth();
|
|
||||||
|
|
||||||
if (width > maxWidth_ || attached->fillWidth())
|
// in theory we could also reset the width, but that doesn't seem to work nicely for
|
||||||
width = maxWidth_;
|
// text areas because of how they cache it.
|
||||||
|
if (attached->maxWidth() > 0)
|
||||||
|
item->setWidth(attached->maxWidth());
|
||||||
|
else
|
||||||
|
item->setWidth(maxWidth);
|
||||||
|
item->ensurePolished();
|
||||||
|
auto width = item->implicitWidth();
|
||||||
|
|
||||||
|
if (width < 1 || width > maxWidth)
|
||||||
|
width = maxWidth;
|
||||||
|
|
||||||
|
if (attached->maxWidth() > 0 && width > attached->maxWidth())
|
||||||
|
width = attached->maxWidth();
|
||||||
|
|
||||||
|
if (attached->keepAspectRatio()) {
|
||||||
|
auto height = width * attached->aspectRatio();
|
||||||
|
if (attached->maxHeight() && height > attached->maxHeight()) {
|
||||||
|
height = attached->maxHeight();
|
||||||
|
width = height / attached->aspectRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
item->setHeight(height);
|
||||||
|
}
|
||||||
|
|
||||||
nhlog::ui()->debug(
|
nhlog::ui()->debug(
|
||||||
"Made event delegate width: {}, {}", width, mainChild->metaObject()->className());
|
"Made event delegate width: {}, {}", width, item->metaObject()->className());
|
||||||
mainChild->setWidth(width);
|
item->setWidth(width);
|
||||||
mainChild->ensurePolished();
|
item->ensurePolished();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
layoutItem(mainChild, mainInset_);
|
||||||
|
layoutItem(replyChild, replyInset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replyChild) {
|
void
|
||||||
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
EventDelegateChooserAttachedType::polishChooser()
|
||||||
qmlAttachedPropertiesObject<EventDelegateChooser>(replyChild));
|
{
|
||||||
Q_ASSERT(attached != nullptr);
|
auto p = parent();
|
||||||
|
if (p) {
|
||||||
// in theory we could also reset the width, but that doesn't seem to work nicely for text
|
auto chooser = qobject_cast<EventDelegateChooser *>(p->parent());
|
||||||
// areas because of how they cache it.
|
if (chooser) {
|
||||||
replyChild->setWidth(maxWidth_);
|
chooser->polish();
|
||||||
replyChild->ensurePolished();
|
}
|
||||||
auto width = replyChild->implicitWidth();
|
|
||||||
|
|
||||||
if (width > maxWidth_ || attached->fillWidth())
|
|
||||||
width = maxWidth_;
|
|
||||||
|
|
||||||
replyChild->setWidth(width);
|
|
||||||
replyChild->ensurePolished();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,27 +17,78 @@
|
||||||
class EventDelegateChooserAttachedType : public QObject
|
class EventDelegateChooserAttachedType : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged)
|
Q_PROPERTY(bool keepAspectRatio READ keepAspectRatio WRITE setKeepAspectRatio NOTIFY
|
||||||
|
keepAspectRatioChanged)
|
||||||
|
Q_PROPERTY(double aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged)
|
||||||
|
Q_PROPERTY(int maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
|
||||||
|
Q_PROPERTY(int maxHeight READ maxHeight WRITE setMaxHeight NOTIFY maxHeightChanged)
|
||||||
|
Q_PROPERTY(bool isReply READ isReply WRITE setIsReply NOTIFY isReplyChanged)
|
||||||
|
|
||||||
QML_ANONYMOUS
|
QML_ANONYMOUS
|
||||||
public:
|
public:
|
||||||
EventDelegateChooserAttachedType(QObject *parent)
|
EventDelegateChooserAttachedType(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
bool fillWidth() const { return fillWidth_; }
|
|
||||||
void setFillWidth(bool fill)
|
bool keepAspectRatio() const { return keepAspectRatio_; }
|
||||||
|
void setKeepAspectRatio(bool fill)
|
||||||
{
|
{
|
||||||
fillWidth_ = fill;
|
if (fill != keepAspectRatio_) {
|
||||||
emit fillWidthChanged();
|
keepAspectRatio_ = fill;
|
||||||
|
emit keepAspectRatioChanged();
|
||||||
|
polishChooser();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double aspectRatio() const { return aspectRatio_; }
|
||||||
|
void setAspectRatio(double fill)
|
||||||
|
{
|
||||||
|
aspectRatio_ = fill;
|
||||||
|
emit aspectRatioChanged();
|
||||||
|
polishChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxWidth() const { return maxWidth_; }
|
||||||
|
void setMaxWidth(int fill)
|
||||||
|
{
|
||||||
|
maxWidth_ = fill;
|
||||||
|
emit maxWidthChanged();
|
||||||
|
polishChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxHeight() const { return maxHeight_; }
|
||||||
|
void setMaxHeight(int fill)
|
||||||
|
{
|
||||||
|
maxHeight_ = fill;
|
||||||
|
emit maxHeightChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isReply() const { return isReply_; }
|
||||||
|
void setIsReply(bool fill)
|
||||||
|
{
|
||||||
|
if (fill != isReply_) {
|
||||||
|
isReply_ = fill;
|
||||||
|
emit isReplyChanged();
|
||||||
|
polishChooser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fillWidthChanged();
|
void keepAspectRatioChanged();
|
||||||
|
void aspectRatioChanged();
|
||||||
|
void maxWidthChanged();
|
||||||
|
void maxHeightChanged();
|
||||||
|
void isReplyChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool fillWidth_ = false, keepAspectRatio = false;
|
void polishChooser();
|
||||||
double aspectRatio = 1.;
|
|
||||||
int maxWidth = -1;
|
double aspectRatio_ = 1.;
|
||||||
int maxHeight = -1;
|
int maxWidth_ = -1;
|
||||||
|
int maxHeight_ = -1;
|
||||||
|
bool keepAspectRatio_ = false;
|
||||||
|
bool isReply_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventDelegateChoice : public QObject
|
class EventDelegateChoice : public QObject
|
||||||
|
@ -84,6 +135,8 @@ class EventDelegateChooser : public QQuickItem
|
||||||
Q_PROPERTY(TimelineModel *room READ room WRITE setRoom NOTIFY roomChanged REQUIRED FINAL)
|
Q_PROPERTY(TimelineModel *room READ room WRITE setRoom NOTIFY roomChanged REQUIRED FINAL)
|
||||||
Q_PROPERTY(bool sameWidth READ sameWidth WRITE setSameWidth NOTIFY sameWidthChanged)
|
Q_PROPERTY(bool sameWidth READ sameWidth WRITE setSameWidth NOTIFY sameWidthChanged)
|
||||||
Q_PROPERTY(int maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
|
Q_PROPERTY(int maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
|
||||||
|
Q_PROPERTY(int replyInset READ replyInset WRITE setReplyInset NOTIFY replyInsetChanged)
|
||||||
|
Q_PROPERTY(int mainInset READ mainInset WRITE setMainInset NOTIFY mainInsetChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QQmlListProperty<EventDelegateChoice> choices();
|
QQmlListProperty<EventDelegateChoice> choices();
|
||||||
|
@ -103,7 +156,7 @@ public:
|
||||||
sameWidth_ = width;
|
sameWidth_ = width;
|
||||||
emit sameWidthChanged();
|
emit sameWidthChanged();
|
||||||
}
|
}
|
||||||
bool maxWidth() const { return maxWidth_; }
|
int maxWidth() const { return maxWidth_; }
|
||||||
void setMaxWidth(int width)
|
void setMaxWidth(int width)
|
||||||
{
|
{
|
||||||
maxWidth_ = width;
|
maxWidth_ = width;
|
||||||
|
@ -111,6 +164,22 @@ public:
|
||||||
polish();
|
polish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int replyInset() const { return replyInset_; }
|
||||||
|
void setReplyInset(int width)
|
||||||
|
{
|
||||||
|
replyInset_ = width;
|
||||||
|
emit replyInsetChanged();
|
||||||
|
polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
int mainInset() const { return mainInset_; }
|
||||||
|
void setMainInset(int width)
|
||||||
|
{
|
||||||
|
mainInset_ = width;
|
||||||
|
emit mainInsetChanged();
|
||||||
|
polish();
|
||||||
|
}
|
||||||
|
|
||||||
void setRoom(TimelineModel *m)
|
void setRoom(TimelineModel *m)
|
||||||
{
|
{
|
||||||
if (m != room_) {
|
if (m != room_) {
|
||||||
|
@ -161,6 +230,8 @@ signals:
|
||||||
void replyToChanged();
|
void replyToChanged();
|
||||||
void sameWidthChanged();
|
void sameWidthChanged();
|
||||||
void maxWidthChanged();
|
void maxWidthChanged();
|
||||||
|
void replyInsetChanged();
|
||||||
|
void mainInsetChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct DelegateIncubator final : public QQmlIncubator
|
struct DelegateIncubator final : public QQmlIncubator
|
||||||
|
@ -183,6 +254,7 @@ private:
|
||||||
QString instantiatedId;
|
QString instantiatedId;
|
||||||
int instantiatedRole = -1;
|
int instantiatedRole = -1;
|
||||||
QAbstractItemModel *instantiatedModel = nullptr;
|
QAbstractItemModel *instantiatedModel = nullptr;
|
||||||
|
int oldType = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
QVariant roleValue_;
|
QVariant roleValue_;
|
||||||
|
@ -194,6 +266,8 @@ private:
|
||||||
QString replyId;
|
QString replyId;
|
||||||
bool sameWidth_ = false;
|
bool sameWidth_ = false;
|
||||||
int maxWidth_ = 400;
|
int maxWidth_ = 400;
|
||||||
|
int replyInset_ = 0;
|
||||||
|
int mainInset_ = 0;
|
||||||
|
|
||||||
static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *);
|
static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *);
|
||||||
static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *);
|
static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *);
|
||||||
|
|
Loading…
Reference in a new issue