mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 03:00:46 +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/FileMessage.qml
|
||||
resources/qml/delegates/ImageMessage.qml
|
||||
resources/qml/delegates/MessageDelegate.qml
|
||||
resources/qml/delegates/NoticeMessage.qml
|
||||
resources/qml/delegates/Pill.qml
|
||||
resources/qml/delegates/Placeholder.qml
|
||||
|
|
|
@ -18,7 +18,7 @@ TimelineEvent {
|
|||
id: wrapper
|
||||
ListView.delayRemove: true
|
||||
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
|
||||
//room: chatRoot.roommodel
|
||||
|
||||
|
@ -51,6 +51,9 @@ TimelineEvent {
|
|||
property alias hovered: messageHover.hovered
|
||||
property bool scrolledToThis: false
|
||||
|
||||
mainInset: (threadId ? (4 + Nheko.paddingSmall) : 0) + 4
|
||||
replyInset: mainInset + 4 + Nheko.paddingSmall
|
||||
|
||||
maxWidth: chat.delegateMaxWidth - avatarMargin - metadata.width
|
||||
|
||||
data: [
|
||||
|
@ -182,16 +185,21 @@ TimelineEvent {
|
|||
color: TimelineManager.userColor(wrapper.threadId, palette.base)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: wrapper.isStateEvent
|
||||
width: (wrapper.maxWidth - (wrapper.main?.width ?? 0)) / 2
|
||||
height: 1
|
||||
}
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
|
||||
AbstractButton {
|
||||
id: replyRow
|
||||
visible: wrapper.reply
|
||||
//Layout.fillWidth: true
|
||||
//Layout.maximumHeight: timelineView.height / 8
|
||||
//Layout.preferredWidth: replyRowLay.implicitWidth
|
||||
//Layout.preferredHeight: replyRowLay.implicitHeight
|
||||
|
||||
height: replyLine.height
|
||||
|
||||
property color userColor: TimelineManager.userColor(wrapper.reply?.userId ?? '', palette.base)
|
||||
|
||||
|
@ -209,7 +217,7 @@ TimelineEvent {
|
|||
|
||||
Rectangle {
|
||||
id: replyLine
|
||||
height: replyCol.height
|
||||
height: Math.min( wrapper.reply?.height, timelineView.height / 5) + Nheko.paddingSmall + replyUserButton.height
|
||||
color: replyRow.userColor
|
||||
width: 4
|
||||
}
|
||||
|
|
|
@ -62,12 +62,10 @@ EventDelegateChooser {
|
|||
required property string userId
|
||||
required property string userName
|
||||
|
||||
Layout.fillWidth: true
|
||||
//Layout.maximumWidth: implicitWidth
|
||||
|
||||
body: ''
|
||||
color: palette.buttonText
|
||||
font.italic: true
|
||||
font.pointSize: Settings.fontSize * 0.8
|
||||
formatted: ''
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
isOnlyEmoji: false
|
||||
|
@ -202,7 +200,6 @@ EventDelegateChooser {
|
|||
id: member
|
||||
|
||||
required property string formattedStateEvent
|
||||
required property bool isReply
|
||||
required property Room room
|
||||
required property string userId
|
||||
required property string userName
|
||||
|
@ -212,7 +209,7 @@ EventDelegateChooser {
|
|||
body: formatted
|
||||
formatted: member.formattedStateEvent
|
||||
isOnlyEmoji: false
|
||||
isReply: member.isReply
|
||||
isReply: EventDelegateChooser.isReply
|
||||
isStateEvent: true
|
||||
keepFullText: true
|
||||
}
|
||||
|
@ -233,7 +230,6 @@ EventDelegateChooser {
|
|||
|
||||
required property string body
|
||||
required property string eventId
|
||||
required property bool isReply
|
||||
required property Room room
|
||||
required property string userId
|
||||
required property string userName
|
||||
|
@ -243,7 +239,7 @@ EventDelegateChooser {
|
|||
body: formatted
|
||||
formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
|
||||
isOnlyEmoji: false
|
||||
isReply: tombstone.isReply
|
||||
isReply: EventDelegateChooser.isReply
|
||||
isStateEvent: true
|
||||
keepFullText: true
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import im.nheko
|
||||
|
||||
AbstractButton {
|
||||
|
@ -17,16 +16,17 @@ AbstractButton {
|
|||
required property string blurhash
|
||||
required property string body
|
||||
required property string filename
|
||||
required property bool isReply
|
||||
required property string eventId
|
||||
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
|
||||
enabled: !EventDelegateChooser.isReply
|
||||
|
||||
state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
|
||||
states: [
|
||||
|
@ -133,8 +133,8 @@ AbstractButton {
|
|||
roomm: room
|
||||
play: !Settings.animateImagesOnHover || parent.hovered
|
||||
eventId: parent.eventId
|
||||
width: parent.implicitWidth
|
||||
height: parent.implicitHeight
|
||||
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Image {
|
||||
|
@ -143,10 +143,10 @@ AbstractButton {
|
|||
source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + palette.buttonText)
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
sourceSize.width: parent.implicitWidth * Screen.devicePixelRatio
|
||||
sourceSize.height: parent.implicitHeight * Screen.devicePixelRatio
|
||||
width: parent.implicitWidth
|
||||
height: parent.implicitHeight
|
||||
sourceSize.width: parent.width * Screen.devicePixelRatio
|
||||
sourceSize.height: parent.height * Screen.devicePixelRatio
|
||||
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
onClicked: Settings.openImageExternal ? room.openMedia(eventId) : TimelineManager.openImageOverlay(room, url, eventId, originalWidth, proportionalHeight);
|
||||
|
@ -154,8 +154,8 @@ AbstractButton {
|
|||
Item {
|
||||
id: overlay
|
||||
|
||||
width: parent.implicitWidth
|
||||
height: parent.implicitHeight
|
||||
anchors.fill: parent
|
||||
|
||||
visible: parent.hovered
|
||||
|
||||
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 body
|
||||
required property string filesize
|
||||
property double divisor: isReply ? 4 : 2
|
||||
property double divisor: EventDelegateChooser.isReply ? 5 : 3
|
||||
property int tempWidth: originalWidth < 1? 400: originalWidth
|
||||
implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500
|
||||
width: Math.min(parent?.width ?? implicitWidth, implicitWidth)
|
||||
|
|
|
@ -48,51 +48,43 @@ AbstractButton {
|
|||
room: room_
|
||||
eventId: r.eventId
|
||||
replyTo: ""
|
||||
mainInset: 4 + Nheko.paddingMedium
|
||||
maxWidth: r.maxWidth
|
||||
|
||||
//height: replyContainer.implicitHeight
|
||||
data: GridLayout {
|
||||
data: Row {
|
||||
id: replyContainer
|
||||
|
||||
width: r.maxWidth
|
||||
columns: 2
|
||||
rows: 2
|
||||
columnSpacing: Nheko.paddingMedium
|
||||
rowSpacing: Nheko.paddingSmall
|
||||
spacing: Nheko.paddingSmall
|
||||
|
||||
Rectangle {
|
||||
id: colorline
|
||||
|
||||
Layout.preferredWidth: 4
|
||||
Layout.rowSpan: 2
|
||||
Layout.fillHeight: true
|
||||
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
width: 4
|
||||
|
||||
color: TimelineManager.userColor(r.userId, palette.base)
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 0
|
||||
|
||||
AbstractButton {
|
||||
id: usernameBtn
|
||||
Layout.fillWidth: true
|
||||
|
||||
Layout.row: 0
|
||||
Layout.column: 1
|
||||
|
||||
contentItem: ElidedLabel {
|
||||
contentItem: Label {
|
||||
id: userName_
|
||||
fullText: r.userName
|
||||
text: r.userName
|
||||
color: r.userColor
|
||||
textFormat: Text.RichText
|
||||
width: parent.width
|
||||
elideWidth: width
|
||||
width: timelineEvent.main?.width
|
||||
}
|
||||
onClicked: room.openUserProfile(r.userId)
|
||||
}
|
||||
|
||||
data: [
|
||||
colorline, usernameBtn, timelineEvent.main,
|
||||
usernameBtn, timelineEvent.main,
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import im.nheko
|
|||
MatrixText {
|
||||
required property string body
|
||||
required property bool isOnlyEmoji
|
||||
required property bool isReply
|
||||
property bool isReply: EventDelegateChooser.isReply
|
||||
required property bool keepFullText
|
||||
required property string formatted
|
||||
|
||||
|
@ -45,7 +45,6 @@ MatrixText {
|
|||
|
||||
//EventDelegateChooser.fillWidth: true
|
||||
|
||||
clip: !keepFullText
|
||||
selectByMouse: !Settings.mobileMode && !isReply
|
||||
enabled: !Settings.mobileMode && !isReply
|
||||
hoverEnabled: !Settings.mobileMode
|
||||
|
|
|
@ -97,6 +97,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
|||
return;
|
||||
|
||||
item->setParentItem(&chooser);
|
||||
item->setParent(&chooser);
|
||||
|
||||
auto roleNames = chooser.room_->roleNames();
|
||||
QHash<QByteArray, int> nameToRole;
|
||||
|
@ -106,8 +107,6 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
|||
|
||||
QHash<int, int> roleToPropIdx;
|
||||
std::vector<QModelRoleData> roles;
|
||||
bool isReplyNeeded = false;
|
||||
|
||||
// Workaround for https://bugreports.qt.io/browse/QTBUG-98846
|
||||
QHash<QString, RequiredPropertyKey> requiredProperties;
|
||||
for (const auto &[propKey, prop] :
|
||||
|
@ -124,10 +123,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
|||
if (!prop.isRequired() && !requiredProperties.contains(prop.name()))
|
||||
continue;
|
||||
|
||||
if (prop.name() == std::string_view("isReply")) {
|
||||
isReplyNeeded = true;
|
||||
roleToPropIdx.insert(-1, i);
|
||||
} else if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
|
||||
if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
|
||||
roleToPropIdx.insert(*role, i);
|
||||
roles.emplace_back(*role);
|
||||
|
||||
|
@ -141,6 +137,11 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
|||
chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles);
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
||||
qmlAttachedPropertiesObject<EventDelegateChooser>(obj));
|
||||
Q_ASSERT(attached != nullptr);
|
||||
attached->setIsReply(this->forReply);
|
||||
|
||||
for (const auto &role : roles) {
|
||||
const auto &roleName = roleNames[role.role()];
|
||||
// nhlog::ui()->critical("Setting role {}, {} to {}",
|
||||
|
@ -155,22 +156,25 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
|
|||
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();
|
||||
|
||||
// setInitialProperties(rolesToSet);
|
||||
|
||||
auto update =
|
||||
[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;
|
||||
|
||||
if (changedRoles.empty()) {
|
||||
|
@ -233,6 +237,7 @@ EventDelegateChooser::DelegateIncubator::reset(QString id)
|
|||
chooser.room_
|
||||
->dataById(id, TimelineModel::Roles::Type, forReply ? chooser.eventId_ : QString())
|
||||
.toInt();
|
||||
this->oldType = role;
|
||||
|
||||
for (const auto choice : qAsConst(chooser.choices_)) {
|
||||
const auto &choiceValue = choice->roleValues();
|
||||
|
@ -293,41 +298,58 @@ EventDelegateChooser::updatePolish()
|
|||
|
||||
nhlog::ui()->critical("POLISHING {}", (void *)this);
|
||||
|
||||
if (mainChild) {
|
||||
auto layoutItem = [this](QQuickItem *item, int inset) {
|
||||
if (item) {
|
||||
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
||||
qmlAttachedPropertiesObject<EventDelegateChooser>(mainChild));
|
||||
qmlAttachedPropertiesObject<EventDelegateChooser>(item));
|
||||
Q_ASSERT(attached != nullptr);
|
||||
|
||||
// in theory we could also reset the width, but that doesn't seem to work nicely for text
|
||||
// areas because of how they cache it.
|
||||
mainChild->setWidth(maxWidth_);
|
||||
mainChild->ensurePolished();
|
||||
auto width = mainChild->implicitWidth();
|
||||
int maxWidth = maxWidth_ - inset;
|
||||
|
||||
if (width > maxWidth_ || attached->fillWidth())
|
||||
width = maxWidth_;
|
||||
// in theory we could also reset the width, but that doesn't seem to work nicely for
|
||||
// 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(
|
||||
"Made event delegate width: {}, {}", width, mainChild->metaObject()->className());
|
||||
mainChild->setWidth(width);
|
||||
mainChild->ensurePolished();
|
||||
"Made event delegate width: {}, {}", width, item->metaObject()->className());
|
||||
item->setWidth(width);
|
||||
item->ensurePolished();
|
||||
}
|
||||
};
|
||||
|
||||
layoutItem(mainChild, mainInset_);
|
||||
layoutItem(replyChild, replyInset_);
|
||||
}
|
||||
|
||||
if (replyChild) {
|
||||
auto attached = qobject_cast<EventDelegateChooserAttachedType *>(
|
||||
qmlAttachedPropertiesObject<EventDelegateChooser>(replyChild));
|
||||
Q_ASSERT(attached != nullptr);
|
||||
|
||||
// in theory we could also reset the width, but that doesn't seem to work nicely for text
|
||||
// areas because of how they cache it.
|
||||
replyChild->setWidth(maxWidth_);
|
||||
replyChild->ensurePolished();
|
||||
auto width = replyChild->implicitWidth();
|
||||
|
||||
if (width > maxWidth_ || attached->fillWidth())
|
||||
width = maxWidth_;
|
||||
|
||||
replyChild->setWidth(width);
|
||||
replyChild->ensurePolished();
|
||||
void
|
||||
EventDelegateChooserAttachedType::polishChooser()
|
||||
{
|
||||
auto p = parent();
|
||||
if (p) {
|
||||
auto chooser = qobject_cast<EventDelegateChooser *>(p->parent());
|
||||
if (chooser) {
|
||||
chooser->polish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,27 +17,78 @@
|
|||
class EventDelegateChooserAttachedType : public QObject
|
||||
{
|
||||
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
|
||||
public:
|
||||
EventDelegateChooserAttachedType(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
bool fillWidth() const { return fillWidth_; }
|
||||
void setFillWidth(bool fill)
|
||||
|
||||
bool keepAspectRatio() const { return keepAspectRatio_; }
|
||||
void setKeepAspectRatio(bool fill)
|
||||
{
|
||||
fillWidth_ = fill;
|
||||
emit fillWidthChanged();
|
||||
if (fill != keepAspectRatio_) {
|
||||
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:
|
||||
void fillWidthChanged();
|
||||
void keepAspectRatioChanged();
|
||||
void aspectRatioChanged();
|
||||
void maxWidthChanged();
|
||||
void maxHeightChanged();
|
||||
void isReplyChanged();
|
||||
|
||||
private:
|
||||
bool fillWidth_ = false, keepAspectRatio = false;
|
||||
double aspectRatio = 1.;
|
||||
int maxWidth = -1;
|
||||
int maxHeight = -1;
|
||||
void polishChooser();
|
||||
|
||||
double aspectRatio_ = 1.;
|
||||
int maxWidth_ = -1;
|
||||
int maxHeight_ = -1;
|
||||
bool keepAspectRatio_ = false;
|
||||
bool isReply_ = false;
|
||||
};
|
||||
|
||||
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(bool sameWidth READ sameWidth WRITE setSameWidth NOTIFY sameWidthChanged)
|
||||
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:
|
||||
QQmlListProperty<EventDelegateChoice> choices();
|
||||
|
@ -103,7 +156,7 @@ public:
|
|||
sameWidth_ = width;
|
||||
emit sameWidthChanged();
|
||||
}
|
||||
bool maxWidth() const { return maxWidth_; }
|
||||
int maxWidth() const { return maxWidth_; }
|
||||
void setMaxWidth(int width)
|
||||
{
|
||||
maxWidth_ = width;
|
||||
|
@ -111,6 +164,22 @@ public:
|
|||
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)
|
||||
{
|
||||
if (m != room_) {
|
||||
|
@ -161,6 +230,8 @@ signals:
|
|||
void replyToChanged();
|
||||
void sameWidthChanged();
|
||||
void maxWidthChanged();
|
||||
void replyInsetChanged();
|
||||
void mainInsetChanged();
|
||||
|
||||
private:
|
||||
struct DelegateIncubator final : public QQmlIncubator
|
||||
|
@ -183,6 +254,7 @@ private:
|
|||
QString instantiatedId;
|
||||
int instantiatedRole = -1;
|
||||
QAbstractItemModel *instantiatedModel = nullptr;
|
||||
int oldType = -1;
|
||||
};
|
||||
|
||||
QVariant roleValue_;
|
||||
|
@ -194,6 +266,8 @@ private:
|
|||
QString replyId;
|
||||
bool sameWidth_ = false;
|
||||
int maxWidth_ = 400;
|
||||
int replyInset_ = 0;
|
||||
int mainInset_ = 0;
|
||||
|
||||
static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *);
|
||||
static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *);
|
||||
|
|
Loading…
Reference in a new issue