diff --git a/include/Config.h b/include/Config.h index 805e7c023aa8bcda00b211f1c967e758e4f04126..7d35094ef0c5b82df5cf60e296002c6cf582ef5f 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 d4e4f9839abdbb968a27b6cb7c9ab3ec9fa77972..bb8e0f1a8553ae5351ac487af38c6fea4a0a4b50 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h @@ -18,6 +18,7 @@ #pragma once #include <QAction> +#include <QDateTime> #include <QSharedPointer> #include <QWidget> @@ -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 17b110fce6c2451a00a0fcc7b0945b09241270e3..f1498d1bb00c423bbb687be745657d141b5e0892 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 faada44c70b919ca9c59c6ccc33714ab560ad0e7..caf4634ae01e4776d3cb84f43e6b38264dd74db4 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 3ebbbee0ed59103031b83d51354b6440ecc7f0be..a42edbb75accda80016ee5aa620c771c2097491e 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<mtx::events::msg::Notice { init(); - event_id_ = QString::fromStdString(event.event_id); - const auto sender = QString::fromStdString(event.sender); + event_id_ = QString::fromStdString(event.event_id); + const auto sender = QString::fromStdString(event.sender); + const auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts); + auto body = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped(); descriptionMsg_ = {TimelineViewManager::displayName(sender), sender, " sent a notification", - descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.origin_server_ts))}; - - auto body = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped(); - auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts); + descriptiveTime(timestamp), + timestamp}; generateTimestamp(timestamp); @@ -241,10 +240,7 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Emote> 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<mtx::events::msg::Text> 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 dccc6f37cc2fa57190e106faa690816a9ffebcf6..29da24b3a48a8e7b34639aec5af62efc0bd2c033 100644 --- a/src/timeline/TimelineView.cc +++ b/src/timeline/TimelineView.cc @@ -19,6 +19,7 @@ #include <QFileInfo> #include <QTimer> +#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<TimelineItem *>(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<TimelineItem *>(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 {