From 026c049d62408dd7214ab17f94539533242ab95d Mon Sep 17 00:00:00 2001 From: miruka Date: Tue, 17 Dec 2019 03:45:00 -0400 Subject: [PATCH] Improve message delegate code, fix multiple issues - Fix the ListView not auto-scrolling like it should when message delegates changed height, such as when images were loaded - Fix messed up delegate positions overlapping each others when movements happen - Fix previous/nextItem binding broken due to imperative modification - Fix "messageBodyWidth" binding loop --- TODO.md | 5 +-- src/qml/Base/HNoticePage.qml | 11 +++--- src/qml/Chat/Timeline/EventContent.qml | 18 ++++----- src/qml/Chat/Timeline/EventDelegate.qml | 52 ++++++++++++++----------- src/qml/Chat/Timeline/EventFile.qml | 8 ++-- src/qml/Chat/Timeline/EventImage.qml | 2 +- 6 files changed, 47 insertions(+), 49 deletions(-) diff --git a/TODO.md b/TODO.md index a0705593..eb1339c3 100644 --- a/TODO.md +++ b/TODO.md @@ -49,18 +49,15 @@ ## Issues +- Room pane slightly overlaps chat at small width - invisible uploaded mxc images? - first undecryptable message - Join button 502 - Leave box button focus -- two upload delegates height bug - Pausing uploads doesn't work well, servers end up dropping the connection - Pause upload, switch to other room, then come back, wrong state displayed -- Messed up message delegates position -- Event delegates changing height don't scroll the list - - In the "Leave me" room, "join > Hi > left" aren't combined - When selecting text and scrolling up, selection stops working after a while - Ensure all the text that should be copied is copied diff --git a/src/qml/Base/HNoticePage.qml b/src/qml/Base/HNoticePage.qml index cacb7eac..33ad06e3 100644 --- a/src/qml/Base/HNoticePage.qml +++ b/src/qml/Base/HNoticePage.qml @@ -18,17 +18,16 @@ HRowLayout { leftPadding: theme.spacing rightPadding: leftPadding - Layout.margins: theme.spacing - Layout.alignment: Qt.AlignCenter - Layout.maximumWidth: - parent.width - Layout.leftMargin - Layout.rightMargin - - opacity: width > Layout.leftMargin + Layout.rightMargin ? 1 : 0 + opacity: width > 16 * theme.uiScale ? 1 : 0 background: Rectangle { id: noticeLabelBackground color: theme.controls.box.background radius: theme.controls.box.radius } + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: implicitWidth + Layout.maximumWidth: parent.width } } diff --git a/src/qml/Chat/Timeline/EventContent.qml b/src/qml/Chat/Timeline/EventContent.qml index 86bbc813..1eff8143 100644 --- a/src/qml/Chat/Timeline/EventContent.qml +++ b/src/qml/Chat/Timeline/EventContent.qml @@ -27,16 +27,15 @@ HRowLayout { readonly property string hoveredLink: contentLabel.hoveredLink readonly property bool hoveredSelectable: contentHover.hovered - readonly property int messageBodyWidth: - width - (avatarWrapper.visible ? avatarWrapper.width : 0) - - spacing * Math.max(0, (visibleChildren.length - 1)) - readonly property int xOffset: onRight ? contentLabel.width - contentLabel.paintedWidth - contentLabel.leftPadding - contentLabel.rightPadding : 0 + // 600px max with a 16px font + readonly property int maxMessageWidth: theme.fontSize.normal * 0.5 * 75 + TapHandler { enabled: debugMode @@ -116,11 +115,8 @@ HRowLayout { transform: Translate { x: xOffset } - Layout.maximumWidth: Math.min( - // 600px with 16px font - theme.fontSize.normal * 0.5 * 75, - messageBodyWidth - leftPadding - rightPadding, - ) + Layout.maximumWidth: eventContent.maxMessageWidth + Layout.fillWidth: true function selectAllText() { // Select the message body without the date or name @@ -162,10 +158,10 @@ HRowLayout { HRepeater { id: linksRepeater - model: eventDelegate.currentItem.links + model: eventDelegate.currentModel.links EventMediaLoader { - singleMediaInfo: eventDelegate.currentItem + singleMediaInfo: eventDelegate.currentModel mediaUrl: modelData showSender: pureMedia ? senderText : "" showDate: pureMedia ? timeText : "" diff --git a/src/qml/Chat/Timeline/EventDelegate.qml b/src/qml/Chat/Timeline/EventDelegate.qml index 8854b1e4..201244b6 100644 --- a/src/qml/Chat/Timeline/EventDelegate.qml +++ b/src/qml/Chat/Timeline/EventDelegate.qml @@ -3,15 +3,9 @@ import QtQuick.Layouts 1.12 import "../../Base" import "../../utils.js" as Utils -Column { +HColumnLayout { id: eventDelegate width: eventList.width - topPadding: - model.event_type === "RoomCreateEvent" ? 0 : - dayBreak ? theme.spacing * 4 : - talkBreak ? theme.spacing * 6 : - combine ? theme.spacing / 2 : - theme.spacing * 2 enum Media { Page, File, Image, Video, Audio } @@ -19,23 +13,18 @@ Column { property var hoveredMediaTypeUrl: [] // Remember timeline goes from newest message at index 0 to oldest - property var previousItem: eventList.model.get(model.index + 1) - property var nextItem: eventList.model.get(model.index - 1) - readonly property QtObject currentItem: model - property int modelIndex: model.index - onModelIndexChanged: { - previousItem = eventList.model.get(model.index + 1) - nextItem = eventList.model.get(model.index - 1) - } + readonly property var previousModel: eventList.model.get(model.index + 1) + readonly property var nextModel: eventList.model.get(model.index - 1) + readonly property QtObject currentModel: model property bool isOwn: chat.userId === model.sender_id property bool onRight: eventList.ownEventsOnRight && isOwn - property bool combine: eventList.canCombine(previousItem, model) - property bool talkBreak: eventList.canTalkBreak(previousItem, model) - property bool dayBreak: eventList.canDayBreak(previousItem, model) + property bool combine: eventList.canCombine(previousModel, model) + property bool talkBreak: eventList.canTalkBreak(previousModel, model) + property bool dayBreak: eventList.canDayBreak(previousModel, model) readonly property bool smallAvatar: - eventList.canCombine(model, nextItem) && + eventList.canCombine(model, nextModel) && (model.event_type === "RoomMessageEmote" || ! (model.event_type.startsWith("RoomMessage") || model.event_type.startsWith("RoomEncrypted"))) @@ -60,6 +49,12 @@ Column { Qt.ArrowCursor + readonly property int separationSpacing: + dayBreak ? theme.spacing * 4 : + talkBreak ? theme.spacing * 6 : + combine ? theme.spacing / 2 : + theme.spacing * 2 + // Needed because of eventList's MouseArea which steals the // HSelectableLabel's MouseArea hover events onCursorShapeChanged: eventList.cursorShape = cursorShape @@ -87,20 +82,31 @@ Column { } + Item { + + Layout.fillWidth: true + Layout.preferredHeight: + model.event_type === "RoomCreateEvent" ? 0 : separationSpacing + } + Daybreak { visible: dayBreak - width: eventDelegate.width + + Layout.fillWidth: true + Layout.minimumWidth: parent.width } Item { visible: dayBreak - width: parent.width - height: topPadding + + Layout.fillWidth: true + Layout.preferredHeight: separationSpacing } EventContent { id: eventContent - width: parent.width + + Layout.fillWidth: true Behavior on x { HNumberAnimation {} } } diff --git a/src/qml/Chat/Timeline/EventFile.qml b/src/qml/Chat/Timeline/EventFile.qml index 7ad0d39b..5a4ffafe 100644 --- a/src/qml/Chat/Timeline/EventFile.qml +++ b/src/qml/Chat/Timeline/EventFile.qml @@ -5,10 +5,10 @@ import "../../utils.js" as Utils HTile { id: file - width: Math.max( - Math.min(eventContent.messageBodyWidth, - theme.chat.message.fileMinWidth), - Math.min(eventContent.messageBodyWidth, implicitWidth), + width: Math.min( + eventDelegate.width, + eventContent.maxMessageWidth, + Math.max(theme.chat.message.fileMinWidth, implicitWidth), ) height: Math.max(theme.chat.message.avatarSize, implicitHeight) diff --git a/src/qml/Chat/Timeline/EventImage.qml b/src/qml/Chat/Timeline/EventImage.qml index 6e9204f4..354b800f 100644 --- a/src/qml/Chat/Timeline/EventImage.qml +++ b/src/qml/Chat/Timeline/EventImage.qml @@ -49,7 +49,7 @@ HMxcImage { // Maximum display size Math.min( eventList.height * maxHeight, - eventContent.messageBodyWidth * Math.min(1, theme.uiScale), + eventContent.maxMessageWidth * Math.min(1, theme.uiScale), // XXX ), eventList.height * maxHeight, )