diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h
index f94d0c47..ab4fbd47 100644
--- a/include/timeline/TimelineView.h
+++ b/include/timeline/TimelineView.h
@@ -186,6 +186,21 @@ private:
void updateLastSender(const QString &user_id, TimelineDirection direction);
void notifyForLastEvent();
void notifyForLastEvent(const TimelineEvent &event);
+ //! Keep track of the sender and the timestamp of the current message.
+ void saveLastMessageInfo(const QString &sender, const QDateTime &datetime)
+ {
+ lastSender_ = sender;
+ lastMsgTimestamp_ = datetime;
+ }
+ void saveFirstMessageInfo(const QString &sender, const QDateTime &datetime)
+ {
+ firstSender_ = sender;
+ firstMsgTimestamp_ = datetime;
+ }
+ //! Keep track of the sender and the timestamp of the current message.
+ void saveMessageInfo(const QString &sender,
+ uint64_t origin_server_ts,
+ TimelineDirection direction);
TimelineEvent findFirstViewableEvent(const std::vector<TimelineEvent> &events);
TimelineEvent findLastViewableEvent(const std::vector<TimelineEvent> &events);
@@ -218,7 +233,9 @@ private:
// Used to determine whether or not we should prefix a message with the
// sender's name.
- bool isSenderRendered(const QString &user_id, TimelineDirection direction);
+ bool isSenderRendered(const QString &user_id,
+ uint64_t origin_server_ts,
+ TimelineDirection direction);
bool isPendingMessage(const QString &txnid, const QString &sender, const QString &userid);
void removePendingMessage(const QString &txnid);
@@ -226,6 +243,8 @@ private:
bool isDuplicate(const QString &event_id) { return eventIds_.contains(event_id); }
void handleNewUserMessage(PendingMessage msg);
+ bool isDateDifference(const QDateTime &first,
+ const QDateTime &second = QDateTime::currentDateTime()) const;
// Return nullptr if the event couldn't be parsed.
TimelineItem *parseMessageEvent(const mtx::events::collections::TimelineEvents &event,
@@ -238,8 +257,11 @@ private:
ScrollBar *scrollbar_;
QWidget *scroll_widget_;
- QString lastSender_;
QString firstSender_;
+ QDateTime firstMsgTimestamp_;
+ QString lastSender_;
+ QDateTime lastMsgTimestamp_;
+
QString room_id_;
QString prev_batch_token_;
QString local_user_;
@@ -289,7 +311,7 @@ TimelineView::addUserMessage(const QString &url,
const QString &mime,
uint64_t size)
{
- auto with_sender = lastSender_ != local_user_;
+ auto with_sender = (lastSender_ != local_user_) || isDateDifference(lastMsgTimestamp_);
auto trimmed = QFileInfo{filename}.fileName(); // Trim file path.
auto widget = new Widget(client_, url, trimmed, size, this);
@@ -303,7 +325,8 @@ TimelineView::addUserMessage(const QString &url,
QApplication::processEvents();
- lastSender_ = local_user_;
+ // Keep track of the sender and the timestamp of the current message.
+ saveLastMessageInfo(local_user_, QDateTime::currentDateTime());
int txn_id = client_->incrementTransactionId();
@@ -343,9 +366,9 @@ TimelineView::processMessageEvent(const Event &event, TimelineDirection directio
return nullptr;
}
- auto with_sender = isSenderRendered(sender, direction);
+ auto with_sender = isSenderRendered(sender, event.origin_server_ts, direction);
- updateLastSender(sender, direction);
+ saveMessageInfo(sender, event.origin_server_ts, direction);
auto item = createTimelineItem<Event>(event, with_sender);
@@ -368,9 +391,9 @@ TimelineView::processMessageEvent(const Event &event, TimelineDirection directio
return nullptr;
}
- auto with_sender = isSenderRendered(sender, direction);
+ auto with_sender = isSenderRendered(sender, event.origin_server_ts, direction);
- updateLastSender(sender, direction);
+ saveMessageInfo(sender, event.origin_server_ts, direction);
auto item = createTimelineItem<Event, Widget>(event, with_sender);
diff --git a/src/timeline/TimelineView.cc b/src/timeline/TimelineView.cc
index 3a8e1c3d..8781f90e 100644
--- a/src/timeline/TimelineView.cc
+++ b/src/timeline/TimelineView.cc
@@ -323,6 +323,7 @@ TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
// Reset the sender of the first message in the timeline
// cause we're about to insert a new one.
firstSender_.clear();
+ firstMsgTimestamp_ = QDateTime();
// Parse in reverse order to determine where we should not show sender's
// name.
@@ -352,7 +353,8 @@ TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
// If this batch is the first being rendered (i.e the first and the last
// events originate from this batch), set the last sender.
if (lastSender_.isEmpty() && !items.empty())
- lastSender_ = items.at(0)->descriptionMessage().userid;
+ saveLastMessageInfo(items.at(0)->descriptionMessage().userid,
+ items.at(0)->descriptionMessage().datetime);
}
void
@@ -453,12 +455,19 @@ TimelineView::updateLastSender(const QString &user_id, TimelineDirection directi
}
bool
-TimelineView::isSenderRendered(const QString &user_id, TimelineDirection direction)
+TimelineView::isSenderRendered(const QString &user_id,
+ uint64_t origin_server_ts,
+ TimelineDirection direction)
{
- if (direction == TimelineDirection::Bottom)
- return lastSender_ != user_id;
- else
- return firstSender_ != user_id;
+ if (direction == TimelineDirection::Bottom) {
+ return (lastSender_ != user_id) ||
+ isDateDifference(lastMsgTimestamp_,
+ QDateTime::fromMSecsSinceEpoch(origin_server_ts));
+ } else {
+ return (firstSender_ != user_id) ||
+ isDateDifference(firstMsgTimestamp_,
+ QDateTime::fromMSecsSinceEpoch(origin_server_ts));
+ }
}
void
@@ -529,7 +538,7 @@ TimelineView::updatePendingMessage(int txn_id, QString event_id)
void
TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body)
{
- auto with_sender = lastSender_ != local_user_;
+ auto with_sender = (lastSender_ != local_user_) || isDateDifference(lastMsgTimestamp_);
TimelineItem *view_item =
new TimelineItem(ty, local_user_, body, with_sender, room_id_, scroll_widget_);
@@ -540,7 +549,7 @@ TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body)
QApplication::processEvents();
- lastSender_ = local_user_;
+ saveLastMessageInfo(local_user_, QDateTime::currentDateTime());
int txn_id = client_->incrementTransactionId();
PendingMessage message(ty, txn_id, body, "", "", -1, "", view_item);
@@ -774,16 +783,20 @@ TimelineView::removeEvent(const QString &event_id)
// If we deleted the last item in the timeline...
if (!nextItem && prevItem)
- lastSender_ = prevItem->descriptionMessage().userid;
+ saveLastMessageInfo(prevItem->descriptionMessage().userid,
+ prevItem->descriptionMessage().datetime);
// If we deleted the first item in the timeline...
if (!prevItem && nextItem)
- firstSender_ = nextItem->descriptionMessage().userid;
+ saveFirstMessageInfo(nextItem->descriptionMessage().userid,
+ nextItem->descriptionMessage().datetime);
// If we deleted the only item in the timeline...
if (!prevItem && !nextItem) {
firstSender_.clear();
+ firstMsgTimestamp_ = QDateTime();
lastSender_.clear();
+ lastMsgTimestamp_ = QDateTime();
}
// Finally remove the event.
@@ -835,3 +848,29 @@ TimelineView::getEventType(const mtx::events::collections::TimelineEvents &event
{
return mpark::visit([](auto msg) { return msg.type; }, event);
}
+
+void
+TimelineView::saveMessageInfo(const QString &sender,
+ uint64_t origin_server_ts,
+ TimelineDirection direction)
+{
+ updateLastSender(sender, direction);
+
+ if (direction == TimelineDirection::Bottom)
+ lastMsgTimestamp_ = QDateTime::fromMSecsSinceEpoch(origin_server_ts);
+ else
+ firstMsgTimestamp_ = QDateTime::fromMSecsSinceEpoch(origin_server_ts);
+}
+
+bool
+TimelineView::isDateDifference(const QDateTime &first, const QDateTime &second) const
+{
+ // Check if the dates are in a different day.
+ if (std::abs(first.daysTo(second)) != 0)
+ return true;
+
+ const uint64_t diffInSeconds = std::abs(first.msecsTo(second)) / 1000;
+ constexpr uint64_t fifteenMins = 15 * 60;
+
+ return diffInSeconds > fifteenMins;
+}
|