diff --git a/include/Config.h b/include/Config.h index 805e7c02..7d35094e 100644 --- a/include/Config.h +++ b/include/Config.h @@ -79,7 +79,8 @@ static constexpr int headerSpacing = 7; static constexpr int headerLeftMargin = 15; namespace fonts { -static constexpr int timestamp = 10; +static constexpr int timestamp = 10; +static constexpr int dateSeparator = conf::fontSize - 2; } // namespace fonts } // namespace timeline diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h index d4e4f983..bb8e0f1a 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -35,6 +36,7 @@ struct DescInfo QString userid; QString body; QString timestamp; + QDateTime datetime; }; class RoomInfoListItem : public QWidget diff --git a/include/timeline/TimelineItem.h b/include/timeline/TimelineItem.h index 17b110fc..f1498d1b 100644 --- a/include/timeline/TimelineItem.h +++ b/include/timeline/TimelineItem.h @@ -142,7 +142,7 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, auto timestamp = QDateTime::currentDateTime(); descriptionMsg_ = { - "You", userid, QString(" %1").arg(msgDescription), descriptiveTime(timestamp)}; + "You", userid, QString(" %1").arg(msgDescription), descriptiveTime(timestamp), timestamp}; generateTimestamp(timestamp); @@ -183,7 +183,8 @@ TimelineItem::setupWidgetLayout(Widget *widget, descriptionMsg_ = {sender == settings.value("auth/user_id") ? "You" : displayName, sender, msgDescription, - descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.origin_server_ts))}; + descriptiveTime(timestamp), + timestamp}; generateTimestamp(timestamp); diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h index faada44c..caf4634a 100644 --- a/include/timeline/TimelineView.h +++ b/include/timeline/TimelineView.h @@ -91,6 +91,7 @@ public: void addUserMessage(const QString &url, const QString &filename); void updatePendingMessage(int txn_id, QString event_id); void scrollDown(); + void addDateSeparator(QDateTime datetime, int position); public slots: void sliderRangeChanged(int min, int max); diff --git a/src/timeline/TimelineItem.cc b/src/timeline/TimelineItem.cc index 3ebbbee0..a42edbb7 100644 --- a/src/timeline/TimelineItem.cc +++ b/src/timeline/TimelineItem.cc @@ -73,10 +73,9 @@ TimelineItem::TimelineItem(mtx::events::MessageType ty, if (ty == mtx::events::MessageType::Emote) { body = QString("* %1 %2").arg(displayName).arg(body); - descriptionMsg_ = {"", userid, body, descriptiveTime(timestamp)}; + descriptionMsg_ = {"", userid, body, descriptiveTime(timestamp), timestamp}; } else { - descriptionMsg_ = { - "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime())}; + descriptionMsg_ = {"You: ", userid, body, descriptiveTime(timestamp), timestamp}; } body = body.toHtmlEscaped(); @@ -189,16 +188,16 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent auto displayName = TimelineViewManager::displayName(sender); auto emoteMsg = QString("* %1 %2").arg(displayName).arg(body); - descriptionMsg_ = {"", - sender, - emoteMsg, - descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.origin_server_ts))}; + descriptionMsg_ = {"", sender, emoteMsg, descriptiveTime(timestamp), timestamp}; generateTimestamp(timestamp); emoteMsg = emoteMsg.toHtmlEscaped(); @@ -286,7 +282,8 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent descriptionMsg_ = {sender == settings.value("auth/user_id") ? "You" : displayName, sender, QString(": %1").arg(body), - descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.origin_server_ts))}; + descriptiveTime(timestamp), + timestamp}; generateTimestamp(timestamp); diff --git a/src/timeline/TimelineView.cc b/src/timeline/TimelineView.cc index dccc6f37..29da24b3 100644 --- a/src/timeline/TimelineView.cc +++ b/src/timeline/TimelineView.cc @@ -19,6 +19,7 @@ #include #include +#include "Config.h" #include "FloatingButton.h" #include "RoomMessages.h" @@ -368,10 +369,38 @@ TimelineView::isSenderRendered(const QString &user_id, TimelineDirection directi void TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction) { - if (direction == TimelineDirection::Bottom) + const auto newDate = item->descriptionMessage().datetime; + + if (direction == TimelineDirection::Bottom) { + const auto lastItemPosition = scroll_layout_->count() - 1; + auto lastItem = + static_cast(scroll_layout_->itemAt(lastItemPosition)->widget()); + + if (lastItem) { + auto oldDate = lastItem->descriptionMessage().datetime; + + if (oldDate.daysTo(newDate) != 0) + addDateSeparator(newDate, lastItemPosition); + } + scroll_layout_->addWidget(item); - else + } else { + // The first item (position 0) is a stretch widget that pushes + // the widgets to the bottom of the page. + if (scroll_layout_->count() > 1) { + auto firstItem = + static_cast(scroll_layout_->itemAt(1)->widget()); + + if (firstItem) { + auto oldDate = firstItem->descriptionMessage().datetime; + + if (newDate.daysTo(oldDate) != 0) + addDateSeparator(oldDate, 1); + } + } + scroll_layout_->insertWidget(1, item); + } } void @@ -563,6 +592,36 @@ TimelineView::event(QEvent *event) return QWidget::event(event); } +void +TimelineView::addDateSeparator(QDateTime datetime, int position) +{ + auto now = QDateTime::currentDateTime(); + auto days = now.daysTo(datetime); + + QString fmt; + QLabel *separator; + + if (now.date().year() != datetime.date().year()) + fmt = QString("ddd d MMMM yy"); + else + fmt = QString("ddd d MMMM"); + + if (days == 0) + separator = new QLabel(tr("Today")); + else if (std::abs(days) == 1) + separator = new QLabel(tr("Yesterday")); + else + separator = new QLabel(datetime.toString(fmt)); + + if (separator) { + separator->setStyleSheet( + QString("font-size: %1px").arg(conf::timeline::fonts::dateSeparator)); + separator->setAlignment(Qt::AlignCenter); + separator->setContentsMargins(0, 15, 0, 15); + scroll_layout_->insertWidget(position, separator); + } +} + QString TimelineView::getEventSender(const mtx::events::collections::TimelineEvents &event) const {