diff --git a/harmonyqml/backend/signal_manager.py b/harmonyqml/backend/signal_manager.py index 8b04645a..a463f20c 100644 --- a/harmonyqml/backend/signal_manager.py +++ b/harmonyqml/backend/signal_manager.py @@ -96,19 +96,17 @@ class SignalManager(QObject): date_time = QDateTime.fromMSecsSinceEpoch(edict["server_timestamp"]) new_event = RoomEvent(type=etype, date_time=date_time, dict=edict) - # Insert event in model at the right position, based on timestamps - # to keep them sorted by date of arrival. - # Iterate in reverse, since a new event is more likely to be appended, - # but events can arrive out of order. - if not model or model[-1].date_time < new_event.date_time: + # Model is sorted from newest to oldest message + insert_at = None + for i, event in enumerate(model): + if new_event.date_time > event.date_time: + insert_at = i + break + + if insert_at is None: model.append(new_event) else: - for i, event in enumerate(reversed(model)): - if event.date_time < new_event.date_time: - model.insert(-i, new_event) - break - else: - model.insert(0, new_event) + model.insert(insert_at, new_event) def onRoomTypingUsersUpdated( diff --git a/harmonyqml/components/chat/Daybreak.qml b/harmonyqml/components/chat/Daybreak.qml index bfc9172e..8652ce0d 100644 --- a/harmonyqml/components/chat/Daybreak.qml +++ b/harmonyqml/components/chat/Daybreak.qml @@ -5,8 +5,8 @@ Base.HLabel { text: date_time.toLocaleDateString() width: rootCol.width horizontalAlignment: Text.AlignHCenter - topPadding: rootCol.isFirstMessage ? 0 : rootCol.verticalPadding * 4 - bottomPadding: rootCol.verticalPadding * 2 + topPadding: rootCol.isFirstMessage ? 0 : rootCol.standardSpacing + bottomPadding: rootCol.standardSpacing font.pixelSize: normalSize * 1.1 color: "darkolivegreen" } diff --git a/harmonyqml/components/chat/MessageContent.qml b/harmonyqml/components/chat/MessageContent.qml index cdcd2203..305f9f12 100644 --- a/harmonyqml/components/chat/MessageContent.qml +++ b/harmonyqml/components/chat/MessageContent.qml @@ -50,6 +50,7 @@ Row { leftPadding: horizontalPadding rightPadding: horizontalPadding + topPadding: nameLabel.visible ? 0 : verticalPadding bottomPadding: verticalPadding Layout.minimumWidth: nameLabel.implicitWidth diff --git a/harmonyqml/components/chat/MessageDelegate.qml b/harmonyqml/components/chat/MessageDelegate.qml index 6272e98a..61ea8536 100644 --- a/harmonyqml/components/chat/MessageDelegate.qml +++ b/harmonyqml/components/chat/MessageDelegate.qml @@ -4,13 +4,20 @@ import QtQuick.Layouts 1.4 import "../base" as Base Column { - id: rootCol + id: "rootCol" function mins_between(date1, date2) { + console.log(Math.round((((date2 - date1) % 86400000) % 3600000) / 60000)) return Math.round((((date2 - date1) % 86400000) % 3600000) / 60000) } - readonly property bool isMessage: type.startsWith("RoomMessage") + function is_message(type_) { return type_.startsWith("RoomMessage") } + + readonly property var previousItem: + index < messageListView.model.count - 1 ? + messageListView.model.get(index + 1) : null + + readonly property bool isMessage: is_message(type) readonly property bool isUndecryptableEvent: type === "OlmEvent" || type === "MegolmEvent" @@ -21,37 +28,38 @@ Column { readonly property bool isOwn: chatPage.user_id === dict.sender - readonly property var previousData: - index > 0 ? messageListView.model.get(index - 1) : null - - readonly property bool isFirstMessage: ! previousData + readonly property bool isFirstMessage: ! previousItem readonly property bool combine: ! isFirstMessage && - previousData.isMessage === isMessage && - previousData.dict.sender === dict.sender && - mins_between(previousData.date_time, date_time) <= 5 + ! talkBreak && + ! dayBreak && + is_message(previousItem.type) === isMessage && + previousItem.dict.sender === dict.sender && + mins_between(previousItem.date_time, date_time) <= 5 readonly property bool dayBreak: isFirstMessage || - previousData.date_time.getDay() != date_time.getDay() + date_time.getDay() != previousItem.date_time.getDay() readonly property bool talkBreak: ! isFirstMessage && ! dayBreak && - mins_between(previousData.date_time, date_time) >= 20 + mins_between(previousItem.date_time, date_time) >= 20 - property int standardSpacing: 8 + property int standardSpacing: 16 property int horizontalPadding: 7 property int verticalPadding: 5 width: parent.width topPadding: - previousData === null ? 0 : - talkBreak ? standardSpacing * 6 : - combine ? standardSpacing / 2 : - standardSpacing * 1.2 + ! previousItem ? 0 : + talkBreak ? standardSpacing * 3 : + combine ? standardSpacing / 4 : + standardSpacing + + //Text { text: rootCol.topPadding } Daybreak { visible: dayBreak } diff --git a/harmonyqml/components/chat/MessageList.qml b/harmonyqml/components/chat/MessageList.qml index 145373d0..ba7aa5b5 100644 --- a/harmonyqml/components/chat/MessageList.qml +++ b/harmonyqml/components/chat/MessageList.qml @@ -13,18 +13,27 @@ Rectangle { ListView { id: messageListView anchors.fill: parent - model: Backend.models.roomEvents.get(chatPage.room.room_id) delegate: MessageDelegate {} + model: Backend.models.roomEvents.get(chatPage.room.room_id) //highlight: Rectangle {color: "lightsteelblue"; radius: 5} clip: true topMargin: space bottomMargin: space + verticalLayoutDirection: ListView.BottomToTop // Keep x scroll pages cached, to limit images having to be // reloaded from network. cacheBuffer: height * 6 - //Component.onCompleted: positionViewAtEnd() + function goToEnd() { + messageListView.positionViewAtEnd() + //messageListView.flick(0, -messageListView.bottomMargin * 100) + } + + //Connections { + //target: messageListView.model + //onChanged: goToEnd() + //} } } diff --git a/harmonyqml/components/side_pane/utils.js b/harmonyqml/components/side_pane/utils.js index 097bb764..c4f32d9a 100644 --- a/harmonyqml/components/side_pane/utils.js +++ b/harmonyqml/components/side_pane/utils.js @@ -4,7 +4,7 @@ function get_last_room_event_text(room_id) { var eventsModel = Backend.models.roomEvents.get(room_id) - for (var i = -1; i >= -eventsModel.count; i--) { + for (var i = 0; i < eventsModel.count; i++) { var ev = eventsModel.get(i) if (ev.type !== "RoomMemberEvent") {