summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--resources/qml/MessageInput.qml4
-rw-r--r--resources/qml/MessageView.qml68
-rw-r--r--src/timeline/TimelineModel.cpp46
-rw-r--r--src/timeline/TimelineModel.h4
4 files changed, 49 insertions, 73 deletions
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index 9e9e5b7a..3759477f 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -136,9 +136,9 @@ Rectangle {
                 padding: 0
                 focus: true
                 onTextChanged: {
-                    if (TimelineManager.timeline) {
+                    if (TimelineManager.timeline)
                         TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text);
-                    }
+
                 }
                 onCursorRectangleChanged: textInput.ensureVisible(cursorRectangle)
                 onCursorPositionChanged: {
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 0858be83..dae3e5d7 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -66,33 +66,25 @@ ListView {
         }
     }
 
-    section {
-        property: "section"
-    }
-
     Component {
         id: sectionHeader
 
         Column {
-            property var modelData
-            property string section
-            property string nextSection
-
             topPadding: 4
             bottomPadding: 4
             spacing: 8
-            visible: !!modelData
-            width: parent.width
-            height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8
+            visible: modelData && (modelData.previousMessageUserId !== modelData.userId || modelData.previousMessageDay !== modelData.day)
+            width: parentWidth
+            height: ((modelData && modelData.previousMessageDay !== modelData.day) ? dateBubble.height + 8 + userName.height : userName.height) + 8
 
             Label {
                 id: dateBubble
 
                 anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
-                visible: section.includes(" ")
-                text: chat.model.formatDateSeparator(modelData.timestamp)
+                visible: modelData && modelData.previousMessageDay !== modelData.day
+                text: modelData ? chat.model.formatDateSeparator(modelData.timestamp) : ""
                 color: colors.text
-                height: fontMetrics.height * 1.4
+                height: Math.round(fontMetrics.height * 1.4)
                 width: contentWidth * 1.2
                 horizontalAlignment: Text.AlignHCenter
                 verticalAlignment: Text.AlignVCenter
@@ -109,26 +101,19 @@ ListView {
                 spacing: 8
 
                 Avatar {
-                    // MouseArea {
-                    //     anchors.fill: parent
-                    //     onClicked: chat.model.openUserProfile(modelData.userId)
-                    //     cursorShape: Qt.PointingHandCursor
-                    //     propagateComposedEvents: true
-                    // }
-
                     width: avatarSize
                     height: avatarSize
-                    url: chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/")
-                    displayName: modelData.userName
-                    userid: modelData.userId
+                    url: modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : ""
+                    displayName: modelData ? modelData.userName : ""
+                    userid: modelData ? modelData.userId : ""
                     onClicked: chat.model.openUserProfile(modelData.userId)
                 }
 
                 Label {
                     id: userName
 
-                    text: TimelineManager.escapeEmoji(modelData.userName)
-                    color: TimelineManager.userColor(modelData.userId, colors.window)
+                    text: modelData ? TimelineManager.escapeEmoji(modelData.userName) : ""
+                    color: TimelineManager.userColor(modelData ? modelData.userId : "", colors.window)
                     textFormat: Text.RichText
 
                     MouseArea {
@@ -143,7 +128,7 @@ ListView {
 
                 Label {
                     color: colors.buttonText
-                    text: TimelineManager.userStatus(modelData.userId)
+                    text: modelData ? TimelineManager.userStatus(modelData.userId) : ""
                     textFormat: Text.PlainText
                     elide: Text.ElideRight
                     width: chat.delegateMaxWidth - parent.spacing * 2 - userName.implicitWidth - avatarSize
@@ -163,31 +148,26 @@ ListView {
     delegate: Item {
         id: wrapper
 
-        // This would normally be previousSection, but our model's order is inverted.
-        property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1
-        property Item section
-
         anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
         width: chat.delegateMaxWidth
         height: section ? section.height + timelinerow.height : timelinerow.height
-        onSectionBoundaryChanged: {
-            if (sectionBoundary) {
-                var properties = {
-                    "modelData": model.dump,
-                    "section": ListView.section,
-                    "nextSection": ListView.nextSection
-                };
-                section = sectionHeader.createObject(wrapper, properties);
-            } else {
-                section.destroy();
-                section = null;
-            }
+
+        Loader {
+            id: section
+
+            property var modelData: model
+            property int parentWidth: parent.width
+
+            active: model.previousMessageUserId !== undefined && model.previousMessageUserId !== model.userId || model.previousMessageDay !== model.day
+            //asynchronous: true
+            sourceComponent: sectionHeader
+            visible: status == Loader.Ready
         }
 
         TimelineRow {
             id: timelinerow
 
-            y: section ? section.y + section.height : 0
+            y: section.active && section.visible ? section.y + section.height : 0
         }
 
         Connections {
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index c6c084cc..5db6f0c2 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -265,14 +265,16 @@ QHash<int, QByteArray>
 TimelineModel::roleNames() const
 {
         return {
-          {Section, "section"},
           {Type, "type"},
           {TypeString, "typeString"},
           {IsOnlyEmoji, "isOnlyEmoji"},
           {Body, "body"},
           {FormattedBody, "formattedBody"},
+          {PreviousMessageUserId, "previousMessageUserId"},
           {UserId, "userId"},
           {UserName, "userName"},
+          {PreviousMessageDay, "previousMessageDay"},
+          {Day, "day"},
           {Timestamp, "timestamp"},
           {Url, "url"},
           {ThumbnailUrl, "thumbnailUrl"},
@@ -323,6 +325,11 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
         case UserName:
                 return QVariant(displayName(QString::fromStdString(acc::sender(event))));
 
+        case Day: {
+                QDateTime prevDate = origin_server_ts(event);
+                prevDate.setTime(QTime());
+                return QVariant(prevDate.toMSecsSinceEpoch());
+        }
         case Timestamp:
                 return QVariant(origin_server_ts(event));
         case Type:
@@ -450,7 +457,6 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
                 QVariantMap m;
                 auto names = roleNames();
 
-                // m.insert(names[Section], data(id, static_cast<int>(Section)));
                 m.insert(names[Type], data(event, static_cast<int>(Type)));
                 m.insert(names[TypeString], data(event, static_cast<int>(TypeString)));
                 m.insert(names[IsOnlyEmoji], data(event, static_cast<int>(IsOnlyEmoji)));
@@ -458,6 +464,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
                 m.insert(names[FormattedBody], data(event, static_cast<int>(FormattedBody)));
                 m.insert(names[UserId], data(event, static_cast<int>(UserId)));
                 m.insert(names[UserName], data(event, static_cast<int>(UserName)));
+                m.insert(names[Day], data(event, static_cast<int>(Day)));
                 m.insert(names[Timestamp], data(event, static_cast<int>(Timestamp)));
                 m.insert(names[Url], data(event, static_cast<int>(Url)));
                 m.insert(names[ThumbnailUrl], data(event, static_cast<int>(ThumbnailUrl)));
@@ -498,30 +505,17 @@ TimelineModel::data(const QModelIndex &index, int role) const
         if (!event)
                 return "";
 
-        if (role == Section) {
-                QDateTime date = origin_server_ts(*event);
-                date.setTime(QTime());
-
-                std::string userId = acc::sender(*event);
-
-                for (int r = rowCount() - index.row(); r < events.size(); r++) {
-                        auto tempEv = events.get(r);
-                        if (!tempEv)
-                                break;
-
-                        QDateTime prevDate = origin_server_ts(*tempEv);
-                        prevDate.setTime(QTime());
-                        if (prevDate != date)
-                                return QString("%2 %1")
-                                  .arg(date.toMSecsSinceEpoch())
-                                  .arg(QString::fromStdString(userId));
-
-                        std::string prevUserId = acc::sender(*tempEv);
-                        if (userId != prevUserId)
-                                break;
-                }
-
-                return QString("%1").arg(QString::fromStdString(userId));
+        if (role == PreviousMessageDay || role == PreviousMessageUserId) {
+                int prevIdx = rowCount() - index.row() - 2;
+                if (prevIdx < 0)
+                        return QVariant();
+                auto tempEv = events.get(prevIdx);
+                if (!tempEv)
+                        return QVariant();
+                if (role == PreviousMessageUserId)
+                        return data(*tempEv, UserId);
+                else
+                        return data(*tempEv, Day);
         }
 
         return data(*event, role);
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 16a2565e..b6b3b5ae 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -159,14 +159,16 @@ public:
 
         enum Roles
         {
-                Section,
                 Type,
                 TypeString,
                 IsOnlyEmoji,
                 Body,
                 FormattedBody,
+                PreviousMessageUserId,
                 UserId,
                 UserName,
+                PreviousMessageDay,
+                Day,
                 Timestamp,
                 Url,
                 ThumbnailUrl,