summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2023-08-25 20:43:04 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2023-08-25 20:43:04 +0200
commitb187440e68334b828d7271ac3d51dfd4fd24b18d (patch)
treeaa9199968eb18245357128c1e51aac598d058257
parentaef0cb988438a125802c90ee41032c13ef6f8fec (diff)
Reimplement reply delegate by moving out the timeline event without layout
-rw-r--r--CMakeLists.txt1
-rw-r--r--resources/qml/Completer.qml5
-rw-r--r--resources/qml/ForwardCompleter.qml18
-rw-r--r--resources/qml/MatrixText.qml23
-rw-r--r--resources/qml/MessageView.qml313
-rw-r--r--resources/qml/Reactions.qml2
-rw-r--r--resources/qml/ReplyPopup.qml16
-rw-r--r--resources/qml/RoomList.qml2
-rw-r--r--resources/qml/Root.qml25
-rw-r--r--resources/qml/TimelineEvent.qml255
-rw-r--r--resources/qml/TimelineRow.qml3
-rw-r--r--resources/qml/TopBar.qml17
-rw-r--r--resources/qml/delegates/Reply.qml132
13 files changed, 352 insertions, 460 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01070a82..548d5303 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -713,6 +713,7 @@ set(QML_SOURCES
resources/qml/UploadBox.qml
resources/qml/MessageInput.qml
resources/qml/MessageView.qml
+ resources/qml/TimelineEvent.qml
resources/qml/PrivacyScreen.qml
resources/qml/Reactions.qml
resources/qml/ReplyPopup.qml
diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index 590d5bb8..9ebe0a40 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -145,7 +145,6 @@ Control {
roleValue: "user"
RowLayout {
-
anchors.centerIn: centerRowContent ? parent : undefined
spacing: rowSpacing
@@ -171,7 +170,6 @@ Control {
roleValue: "emoji"
RowLayout {
-
anchors.centerIn: parent
spacing: rowSpacing
@@ -207,7 +205,6 @@ Control {
roleValue: "command"
RowLayout {
-
anchors.centerIn: parent
spacing: rowSpacing
@@ -226,7 +223,6 @@ Control {
roleValue: "room"
RowLayout {
-
anchors.centerIn: centerRowContent ? parent : undefined
spacing: rowSpacing
@@ -251,7 +247,6 @@ Control {
roleValue: "roomAliases"
RowLayout {
-
anchors.centerIn: parent
spacing: rowSpacing
diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml
index 0174e0f6..6f95c663 100644
--- a/resources/qml/ForwardCompleter.qml
+++ b/resources/qml/ForwardCompleter.qml
@@ -54,24 +54,8 @@ Popup {
Reply {
id: replyPreview
- property var modelData: room ? room.getDump(mid, "") : {}
-
- blurhash: modelData.blurhash ?? ""
- body: modelData.body ?? ""
- encryptionError: modelData.encryptionError ?? ""
- eventId: modelData.eventId ?? ""
- filename: modelData.filename ?? ""
- filesize: modelData.filesize ?? ""
- formattedBody: modelData.formattedBody ?? ""
- isOnlyEmoji: modelData.isOnlyEmoji ?? false
- originalWidth: modelData.originalWidth ?? 0
- proportionalHeight: modelData.proportionalHeight ?? 1
- type: modelData.type ?? MtxEvent.UnknownMessage
- typeString: modelData.typeString ?? ""
- url: modelData.url ?? ""
+ eventId: mid
userColor: TimelineManager.userColor(modelData.userId, palette.window)
- userId: modelData.userId ?? ""
- userName: modelData.userName ?? ""
width: parent.width
}
MatrixTextField {
diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml
index de15e078..bf953d56 100644
--- a/resources/qml/MatrixText.qml
+++ b/resources/qml/MatrixText.qml
@@ -11,25 +11,24 @@ TextArea {
property alias cursorShape: cs.cursorShape
- leftInset: 0
- bottomInset: 0
- rightInset: 0
- topInset: 0
- leftPadding: 0
- bottomPadding: 0
- rightPadding: 0
- topPadding: 0
- background: null
-
ToolTip.text: hoveredLink
ToolTip.visible: hoveredLink || false
+ background: null
+ bottomInset: 0
+ bottomPadding: 0
// this always has to be enabled, otherwise you can't click links anymore!
//enabled: selectByMouse
color: palette.text
focus: false
+ leftInset: 0
+ leftPadding: 0
readOnly: true
+ rightInset: 0
+ rightPadding: 0
selectByMouse: !Settings.mobileMode
textFormat: TextEdit.RichText
+ topInset: 0
+ topPadding: 0
wrapMode: Text.Wrap
// Setting a tooltip delay makes the hover text empty .-.
@@ -40,8 +39,8 @@ TextArea {
onLinkActivated: Nheko.openLink(link)
// propagate events up
- onPressAndHold: (event) => event.accepted = false
- onPressed: (event) => event.accepted = (event.button == Qt.LeftButton)
+ onPressAndHold: event => event.accepted = false
+ onPressed: event => event.accepted = (event.button == Qt.LeftButton)
NhekoCursorShape {
id: cs
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 976312f2..2df9b731 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -59,7 +59,7 @@ Item {
spacing: 2
verticalLayoutDirection: ListView.BottomToTop
- delegate: EventDelegateChooser {
+ delegate: TimelineEvent {
id: wrapper
ListView.delayRemove: true
width: chat.delegateMaxWidth
@@ -69,7 +69,6 @@ Item {
required property var day
required property bool isSender
- required property bool isStateEvent
//required property var previousMessageDay
//required property bool previousMessageIsStateEvent
//required property string previousMessageUserId
@@ -145,6 +144,8 @@ Item {
}
ColumnLayout {
+ spacing: 0
+
AbstractButton {
id: replyUserButton
Layout.fillWidth: true
@@ -222,314 +223,6 @@ Item {
opacity: 0.2
}
]
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.TextMessage,
- MtxEvent.NoticeMessage,
- MtxEvent.ElementEffectMessage,
- MtxEvent.UnknownMessage,
- ]
- TextMessage {
- keepFullText: true
- required property string userId
- required property string userName
- required property string formattedBody
- required property int type
-
- color: type == MtxEvent.NoticeMessage ? palette.buttonText : palette.text
- font.italic: type == MtxEvent.NoticeMessage
- formatted: formattedBody
-
- Layout.fillWidth: true
- //Layout.maximumWidth: implicitWidth
-
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.EmoteMessage,
- ]
- TextMessage {
- keepFullText: true
- required property string userId
- required property string userName
- required property string formattedBody
-
- formatted: TimelineManager.escapeEmoji(userName) + " " + formattedBody
-
- color: TimelineManager.userColor(userId, palette.base)
- font.italic: true
-
- Layout.fillWidth: true
- //Layout.maximumWidth: implicitWidth
-
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.CanonicalAlias,
- MtxEvent.ServerAcl,
- MtxEvent.Name,
- MtxEvent.Topic,
- MtxEvent.Avatar,
- MtxEvent.PinnedEvents,
- MtxEvent.ImagePackInRoom,
- MtxEvent.SpaceParent,
- MtxEvent.RoomCreate,
- MtxEvent.PowerLevels,
- MtxEvent.PolicyRuleUser,
- MtxEvent.PolicyRuleRoom,
- MtxEvent.PolicyRuleServer,
- MtxEvent.RoomJoinRules,
- MtxEvent.RoomHistoryVisibility,
- MtxEvent.RoomGuestAccess,
- ]
- TextMessage {
- keepFullText: true
-
- required property string userId
- required property string userName
- required property string formattedStateEvent
-
- isOnlyEmoji: false
- text: formattedStateEvent
- formatted: ''
- body: ''
- horizontalAlignment: Text.AlignHCenter
-
- color: palette.buttonText
- font.italic: true
-
- Layout.fillWidth: true
- //Layout.maximumWidth: implicitWidth
-
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.CallInvite,
- ]
- TextMessage {
- keepFullText: true
-
- required property string userId
- required property string userName
- required property string callType
-
- isOnlyEmoji: false
- body: formatted
- formatted: {
- switch (callType) {
- case "voice":
- return qsTr("%1 placed a voice call.").arg(TimelineManager.escapeEmoji(userName));
- case "video":
- return qsTr("%1 placed a video call.").arg(TimelineManager.escapeEmoji(userName));
- default:
- return qsTr("%1 placed a call.").arg(TimelineManager.escapeEmoji(userName));
- }
- }
-
- color: palette.buttonText
- font.italic: true
-
- Layout.fillWidth: true
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.CallAnswer,
- MtxEvent.CallReject,
- MtxEvent.CallSelectAnswer,
- MtxEvent.CallHangUp,
- MtxEvent.CallCandidates,
- MtxEvent.CallNegotiate,
- ]
- TextMessage {
- keepFullText: true
-
- required property string userId
- required property string userName
- required property int type
-
- isOnlyEmoji: false
- body: formatted
- formatted: {
- switch (type) {
- case MtxEvent.CallAnswer:
- return qsTr("%1 answered the call.").arg(TimelineManager.escapeEmoji(userName));
- case MtxEvent.CallReject:
- return qsTr("%1 rejected the call.").arg(TimelineManager.escapeEmoji(userName));
- case MtxEvent.CallSelectAnswer:
- return qsTr("%1 selected answer.").arg(TimelineManager.escapeEmoji(userName));
- case MtxEvent.CallHangUp:
- return qsTr("%1 ended the call.").arg(TimelineManager.escapeEmoji(userName));
- case MtxEvent.CallCandidates:
- return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
- case MtxEvent.CallNegotiate:
- return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
- }
- }
-
- color: palette.buttonText
- font.italic: true
-
- Layout.fillWidth: true
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.ImageMessage,
- MtxEvent.Sticker,
- ]
- ImageMessage {
- Layout.fillWidth: true
-
- containerHeight: timelineView.height
- Layout.maximumWidth: tempWidth
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.FileMessage,
- ]
- FileMessage {
- Layout.fillWidth: true
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.VideoMessage,
- MtxEvent.AudioMessage,
- ]
- PlayableMediaMessage {
- Layout.fillWidth: true
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.Encrypted,
- ]
- Encrypted {
- Layout.fillWidth: true
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.Encryption,
- ]
- EncryptionEnabled {
- Layout.fillWidth: true
- }
- }
-
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.Redacted
- ]
-
- Redacted {
- Layout.fillWidth: true
-
- required property string userId
- required property string userName
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.Member
- ]
-
- ColumnLayout {
- id: member
-
- required property string userId
- required property string userName
-
- required property bool isReply
- required property Room room
- required property string formattedStateEvent
-
- NoticeMessage {
- body: formatted
- isOnlyEmoji: false
- isReply: tombstone.isReply
- keepFullText: true
- isStateEvent: true
- Layout.fillWidth: true
- formatted: member.formattedStateEvent
- }
-
- Button {
- visible: room.showAcceptKnockButton(eventId)
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("Allow them in")
- onClicked: room.acceptKnock(member.eventId)
- }
-
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- MtxEvent.Tombstone
- ]
-
- ColumnLayout {
- id: tombstone
-
- required property string userId
- required property string userName
-
- required property string body
- required property bool isReply
- required property Room room
- required property string eventId
-
- NoticeMessage {
- body: formatted
- isOnlyEmoji: false
- isReply: tombstone.isReply
- keepFullText: true
- isStateEvent: true
- Layout.fillWidth: true
- formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
- }
-
- Button {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("Go to replacement room")
- onClicked: tombstone.room.joinReplacementRoom(tombstone.eventId)
- }
-
- }
- }
-
- EventDelegateChoice {
- roleValues: [
- ]
- MatrixText {
- Layout.fillWidth: true
-
- required property string typeString
-
- text: "Unsupported: " + typeString
-
- required property string userId
- required property string userName
- }
- }
}
footer: Item {
anchors.horizontalCenter: parent.horizontalCenter
diff --git a/resources/qml/Reactions.qml b/resources/qml/Reactions.qml
index eff62fc1..5b994145 100644
--- a/resources/qml/Reactions.qml
+++ b/resources/qml/Reactions.qml
@@ -74,10 +74,10 @@ Flow {
anchors.verticalCenter: divider.verticalCenter
fillMode: Image.PreserveAspectFit
height: textMetrics.height
+ mipmap: true
source: modelData.key.startsWith("mxc://") ? (modelData.key.replace("mxc://", "image://MxcImage/") + "?scale") : ""
visible: modelData.key.startsWith("mxc://")
width: textMetrics.height
- mipmap: true
}
Rectangle {
id: divider
diff --git a/resources/qml/ReplyPopup.qml b/resources/qml/ReplyPopup.qml
index ce24297c..64c58e56 100644
--- a/resources/qml/ReplyPopup.qml
+++ b/resources/qml/ReplyPopup.qml
@@ -29,22 +29,8 @@ Rectangle {
anchors.rightMargin: replyPopup.width < 450 ? 2 * (22 + 16) : 3 * (22 + 16)
anchors.top: parent.top
anchors.topMargin: Nheko.paddingSmall
- blurhash: modelData.blurhash ?? ""
- body: modelData.body ?? ""
- encryptionError: modelData.encryptionError ?? 0
- eventId: modelData.eventId ?? ""
- filename: modelData.filename ?? ""
- filesize: modelData.filesize ?? ""
- formattedBody: modelData.formattedBody ?? ""
- isOnlyEmoji: modelData.isOnlyEmoji ?? false
- originalWidth: modelData.originalWidth ?? 0
- proportionalHeight: modelData.proportionalHeight ?? 1
- type: modelData.type ?? MtxEvent.UnknownMessage
- typeString: modelData.typeString ?? ""
- url: modelData.url ?? ""
+ eventId: room.reply ?? ""
userColor: TimelineManager.userColor(modelData.userId, palette.window)
- userId: modelData.userId ?? ""
- userName: modelData.userName ?? ""
visible: room && room.reply
width: parent.width
}
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml
index 20e5b95b..0c432189 100644
--- a/resources/qml/RoomList.qml
+++ b/resources/qml/RoomList.qml
@@ -728,9 +728,9 @@ Page {
}
Platform.MenuItem {
text: qsTr("Mark as read")
+
onTriggered: Rooms.getRoomById(roomContextMenu.roomid).markRoomAsRead()
}
-
Platform.MenuItem {
text: qsTr("Room settings")
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 1e8a6a27..09a8f442 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -355,7 +355,6 @@ Pane {
onAccepted: UIA.continue3pidReceived()
}
-
Connections {
function onConfirm3pidToken() {
uiaConfirmationLinkDialog.open();
@@ -363,6 +362,18 @@ Pane {
function onEmail() {
uiaEmailPrompt.show();
}
+ function onFallbackAuth(fallback) {
+ var component = Qt.createComponent("qrc:/resources/qml/dialogs/FallbackAuthDialog.qml");
+ if (component.status == Component.Ready) {
+ var dialog = component.createObject(timelineRoot, {
+ "fallback": fallback
+ });
+ dialog.show();
+ destroyOnClose(dialog);
+ } else {
+ console.error("Failed to create component: " + component.errorString());
+ }
+ }
function onPassword() {
console.log("UIA: password needed");
uiaPassPrompt.show();
@@ -385,18 +396,6 @@ Pane {
console.error("Failed to create component: " + component.errorString());
}
}
- function onFallbackAuth(fallback) {
- var component = Qt.createComponent("qrc:/resources/qml/dialogs/FallbackAuthDialog.qml");
- if (component.status == Component.Ready) {
- var dialog = component.createObject(timelineRoot, {
- "fallback": fallback
- });
- dialog.show();
- destroyOnClose(dialog);
- } else {
- console.error("Failed to create component: " + component.errorString());
- }
- }
target: UIA
}
diff --git a/resources/qml/TimelineEvent.qml b/resources/qml/TimelineEvent.qml
new file mode 100644
index 00000000..787fb7dc
--- /dev/null
+++ b/resources/qml/TimelineEvent.qml
@@ -0,0 +1,255 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import "./components"
+import "./delegates"
+import "./emoji"
+import "./ui"
+import "./dialogs"
+import Qt.labs.platform 1.1 as Platform
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.2
+import QtQuick.Window 2.13
+import im.nheko 1.0
+
+EventDelegateChooser {
+ id: wrapper
+
+ required property bool isStateEvent
+
+ EventDelegateChoice {
+ roleValues: [MtxEvent.TextMessage, MtxEvent.NoticeMessage, MtxEvent.ElementEffectMessage, MtxEvent.UnknownMessage,]
+
+ TextMessage {
+ required property string formattedBody
+ required property int type
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ //Layout.maximumWidth: implicitWidth
+
+ color: type == MtxEvent.NoticeMessage ? palette.buttonText : palette.text
+ font.italic: type == MtxEvent.NoticeMessage
+ formatted: formattedBody
+ keepFullText: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.EmoteMessage,]
+
+ TextMessage {
+ required property string formattedBody
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ //Layout.maximumWidth: implicitWidth
+
+ color: TimelineManager.userColor(userId, palette.base)
+ font.italic: true
+ formatted: TimelineManager.escapeEmoji(userName) + " " + formattedBody
+ keepFullText: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.CanonicalAlias, MtxEvent.ServerAcl, MtxEvent.Name, MtxEvent.Topic, MtxEvent.Avatar, MtxEvent.PinnedEvents, MtxEvent.ImagePackInRoom, MtxEvent.SpaceParent, MtxEvent.RoomCreate, MtxEvent.PowerLevels, MtxEvent.PolicyRuleUser, MtxEvent.PolicyRuleRoom, MtxEvent.PolicyRuleServer, MtxEvent.RoomJoinRules, MtxEvent.RoomHistoryVisibility, MtxEvent.RoomGuestAccess,]
+
+ TextMessage {
+ required property string formattedStateEvent
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ //Layout.maximumWidth: implicitWidth
+
+ body: ''
+ color: palette.buttonText
+ font.italic: true
+ formatted: ''
+ horizontalAlignment: Text.AlignHCenter
+ isOnlyEmoji: false
+ keepFullText: true
+ text: formattedStateEvent
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.CallInvite,]
+
+ TextMessage {
+ required property string callType
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ body: formatted
+ color: palette.buttonText
+ font.italic: true
+ formatted: {
+ switch (callType) {
+ case "voice":
+ return qsTr("%1 placed a voice call.").arg(TimelineManager.escapeEmoji(userName));
+ case "video":
+ return qsTr("%1 placed a video call.").arg(TimelineManager.escapeEmoji(userName));
+ default:
+ return qsTr("%1 placed a call.").arg(TimelineManager.escapeEmoji(userName));
+ }
+ }
+ isOnlyEmoji: false
+ keepFullText: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.CallAnswer, MtxEvent.CallReject, MtxEvent.CallSelectAnswer, MtxEvent.CallHangUp, MtxEvent.CallCandidates, MtxEvent.CallNegotiate,]
+
+ TextMessage {
+ required property int type
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ body: formatted
+ color: palette.buttonText
+ font.italic: true
+ formatted: {
+ switch (type) {
+ case MtxEvent.CallAnswer:
+ return qsTr("%1 answered the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallReject:
+ return qsTr("%1 rejected the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallSelectAnswer:
+ return qsTr("%1 selected answer.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallHangUp:
+ return qsTr("%1 ended the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallCandidates:
+ return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallNegotiate:
+ return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
+ }
+ }
+ isOnlyEmoji: false
+ keepFullText: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.ImageMessage, MtxEvent.Sticker,]
+
+ ImageMessage {
+ Layout.fillWidth: true
+ Layout.maximumWidth: tempWidth
+ containerHeight: timelineView.height
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.FileMessage,]
+
+ FileMessage {
+ Layout.fillWidth: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.VideoMessage, MtxEvent.AudioMessage,]
+
+ PlayableMediaMessage {
+ Layout.fillWidth: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.Encrypted,]
+
+ Encrypted {
+ Layout.fillWidth: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.Encryption,]
+
+ EncryptionEnabled {
+ Layout.fillWidth: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.Redacted]
+
+ Redacted {
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.Member]
+
+ ColumnLayout {
+ id: member
+
+ required property string formattedStateEvent
+ required property bool isReply
+ required property Room room
+ required property string userId
+ required property string userName
+
+ NoticeMessage {
+ Layout.fillWidth: true
+ body: formatted
+ formatted: member.formattedStateEvent
+ isOnlyEmoji: false
+ isReply: member.isReply
+ isStateEvent: true
+ keepFullText: true
+ }
+ Button {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Allow them in")
+ visible: room.showAcceptKnockButton(eventId)
+
+ onClicked: room.acceptKnock(member.eventId)
+ }
+ }
+ }
+ EventDelegateChoice {
+ roleValues: [MtxEvent.Tombstone]
+
+ ColumnLayout {
+ id: tombstone
+
+ required property string body
+ required property string eventId
+ required property bool isReply
+ required property Room room
+ required property string userId
+ required property string userName
+
+ NoticeMessage {
+ Layout.fillWidth: true
+ body: formatted
+ formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
+ isOnlyEmoji: false
+ isReply: tombstone.isReply
+ isStateEvent: true
+ keepFullText: true
+ }
+ Button {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Go to replacement room")
+
+ onClicked: tombstone.room.joinReplacementRoom(tombstone.eventId)
+ }
+ }
+ }
+ EventDelegateChoice {
+ roleValues: []
+
+ MatrixText {
+ required property string typeString
+ required property string userId
+ required property string userName
+
+ Layout.fillWidth: true
+ text: "Unsupported: " + typeString
+ }
+ }
+}
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index 64fa80b1..539882ed 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -147,7 +147,8 @@ AbstractButton {
columns: Settings.bubbles ? 1 : 2
rowSpacing: 0
rows: Settings.bubbles ? 3 : 2
-/*
+
+ /*
anchors {
left: parent.left
leftMargin: 4
diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml
index 699595e6..4c70348b 100644
--- a/resources/qml/TopBar.qml
+++ b/resources/qml/TopBar.qml
@@ -286,24 +286,9 @@ Pane {
property var e: room ? room.getDump(modelData, "pins") : {}
Layout.fillWidth: true
- Layout.preferredHeight: height
- blu