Improve time handling in NeoChat

This introduces a new NeoChatDateTime object that wraps a QDateTime. The intent is that it can be passed to QML and has a series of functions that format the QDateTime into the various string representations we need.

This means we only have to send the single object to QML and then the correct string can be grabbed from there, simplifying the backend. It is also easy to add a new representation if needed as a function with a QString output and Q_PROPERTY can be added and then it will be available.
This commit is contained in:
James Graham
2026-01-25 13:01:31 +00:00
parent 72416884d4
commit 275d221f75
23 changed files with 222 additions and 186 deletions

View File

@@ -40,7 +40,6 @@ private Q_SLOTS:
void nullSingleLineDisplayName();
void time();
void nullTime();
void timeString();
void highlighted();
void nullHighlighted();
void hidden();
@@ -100,12 +99,12 @@ void EventHandlerTest::time()
{
const auto event = room->messageEvents().at(0).get();
QCOMPARE(EventHandler::time(room, event), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)));
QCOMPARE(EventHandler::dateTime(room, event), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)));
const auto txID = room->postJson("m.room.message"_L1, event->fullJson());
QCOMPARE(room->pendingEvents().size(), 1);
const auto pendingIt = room->findPendingEvent(txID);
QCOMPARE(EventHandler::time(room, pendingIt->event(), true), pendingIt->lastUpdated());
QCOMPARE(EventHandler::dateTime(room, pendingIt->event(), true), pendingIt->lastUpdated());
room->discardMessage(txID);
QCOMPARE(room->pendingEvents().size(), 0);
@@ -114,40 +113,10 @@ void EventHandlerTest::time()
void EventHandlerTest::nullTime()
{
QTest::ignoreMessage(QtWarningMsg, "time called with room set to nullptr.");
QCOMPARE(EventHandler::time(nullptr, nullptr), QDateTime());
QCOMPARE(EventHandler::dateTime(nullptr, nullptr), QDateTime());
QTest::ignoreMessage(QtWarningMsg, "time called with event set to nullptr.");
QCOMPARE(EventHandler::time(room, nullptr), QDateTime());
}
void EventHandlerTest::timeString()
{
const auto event = room->messageEvents().at(0).get();
KFormat format;
QCOMPARE(EventHandler::timeString(room, event, false),
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().time(), QLocale::ShortFormat));
QCOMPARE(EventHandler::timeString(room, event, true),
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().date(), QLocale::ShortFormat));
QCOMPARE(EventHandler::timeString(room, event, u"hh:mm"_s),
QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::LocalTime)).toString(u"hh:mm"_s));
const auto txID = room->postJson("m.room.message"_L1, event->fullJson());
QCOMPARE(room->pendingEvents().size(), 1);
const auto pendingIt = room->findPendingEvent(txID);
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::ShortFormat, true),
QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::ShortFormat));
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::ShortFormat, true),
format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::ShortFormat));
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::LongFormat, true),
QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::LongFormat));
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::LongFormat, true),
format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::LongFormat));
room->discardMessage(txID);
QCOMPARE(room->pendingEvents().size(), 0);
QCOMPARE(EventHandler::dateTime(room, nullptr), QDateTime());
}
void EventHandlerTest::highlighted()

View File

@@ -20,9 +20,9 @@ Components.AbstractMaximizeComponent {
property NeochatRoomMember author
/**
* @brief The timestamp of the message.
* @brief The timestamp of the event as a NeoChatDateTime.
*/
property var time
required property NeoChatDateTime dateTime
/**
* @brief The code text to show.
@@ -64,7 +64,7 @@ Components.AbstractMaximizeComponent {
}
QQC2.Label {
id: dateTimeLabel
text: root.time.toLocaleString(Qt.locale(), Locale.ShortFormat)
text: root.dateTime.relativeDateTime
color: Kirigami.Theme.disabledTextColor
elide: Text.ElideRight
}

View File

@@ -382,10 +382,10 @@ Kirigami.Page {
popup.open();
}
function onShowMaximizedCode(author, time, codeText, language) {
function onShowMaximizedCode(author, dateTime, codeText, language) {
(Qt.createComponent('org.kde.neochat', 'CodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
author: author,
time: time,
dateTime: dateTime,
codeText: codeText,
language: language
}) as CodeMaximizeComponent).open();

View File

@@ -286,12 +286,12 @@ void RoomManager::maximizeMedia(const QString &eventId)
Q_EMIT showMaximizedMedia(index);
}
void RoomManager::maximizeCode(NeochatRoomMember *author, const QDateTime &time, const QString &codeText, const QString &language)
void RoomManager::maximizeCode(NeochatRoomMember *author, const NeoChatDateTime &dateTime, const QString &codeText, const QString &language)
{
if (codeText.isEmpty()) {
return;
}
Q_EMIT showMaximizedCode(author, time, codeText, language);
Q_EMIT showMaximizedCode(author, dateTime, codeText, language);
}
void RoomManager::requestFullScreenClose()

View File

@@ -23,6 +23,7 @@
#include "models/timelinemodel.h"
#include "models/userlistmodel.h"
#include "models/widgetmodel.h"
#include "neochatdatetime.h"
#include "neochatroommember.h"
class NeoChatRoom;
@@ -218,7 +219,7 @@ public:
*/
Q_INVOKABLE void maximizeMedia(const QString &eventId);
Q_INVOKABLE void maximizeCode(NeochatRoomMember *author, const QDateTime &time, const QString &codeText, const QString &language);
Q_INVOKABLE void maximizeCode(NeochatRoomMember *author, const NeoChatDateTime &time, const QString &codeText, const QString &language);
/**
* @brief Request that any full screen overlay currently open closes.
@@ -292,7 +293,7 @@ Q_SIGNALS:
/**
* @brief Request a block of code is shown maximized.
*/
void showMaximizedCode(NeochatRoomMember *author, const QDateTime &time, const QString &codeText, const QString &language);
void showMaximizedCode(NeochatRoomMember *author, const NeoChatDateTime &dateTime, const QString &codeText, const QString &language);
/**
* @brief Request that any full screen overlay closes.

View File

@@ -17,6 +17,7 @@ target_sources(LibNeoChat PRIVATE
filetransferpseudojob.cpp
filetype.cpp
linkpreviewer.cpp
neochatdatetime.cpp
roomlastmessageprovider.cpp
spacehierarchycache.cpp
texthandler.cpp

View File

@@ -93,7 +93,7 @@ QString EventHandler::singleLineAuthorDisplayname(const NeoChatRoom *room, const
return displayName;
}
QDateTime EventHandler::time(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending)
NeoChatDateTime EventHandler::dateTime(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending)
{
if (room == nullptr) {
qCWarning(EventHandling) << "time called with room set to nullptr.";
@@ -114,25 +114,6 @@ QDateTime EventHandler::time(const NeoChatRoom *room, const Quotient::RoomEvent
return event->originTimestamp();
}
QString EventHandler::timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool relative, QLocale::FormatType format, bool isPending)
{
auto ts = time(room, event, isPending);
if (ts.isValid()) {
if (relative) {
KFormat formatter;
return formatter.formatRelativeDate(ts.toLocalTime().date(), format);
} else {
return QLocale().toString(ts.toLocalTime().time(), format);
}
}
return {};
}
QString EventHandler::timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, const QString &format, bool isPending)
{
return time(room, event, isPending).toLocalTime().toString(format);
}
bool EventHandler::isHighlighted(const NeoChatRoom *room, const Quotient::RoomEvent *event)
{
if (room == nullptr) {

View File

@@ -7,6 +7,8 @@
#include <QString>
#include <Quotient/events/eventcontent.h>
#include "neochatdatetime.h"
namespace Quotient
{
namespace EventContent
@@ -64,41 +66,7 @@ public:
/**
* @brief Return a QDateTime object for the event timestamp.
*/
static QDateTime time(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false);
/**
* @brief Return a QString for the event timestamp.
*
* This is intended to return a string that is read for display in the UI without
* any further manipulation required.
*
* @param relative whether the string is realtive to the current date, i.e.
* Yesterday or Wednesday, etc.
* @param format the QLocale::FormatType to use.
* @param isPending whether the event is pending as this cannot be derived from
* just the event object.
* @param lastUpdated the time the event was last updated locally as this cannot be
* obtained from the event.
*/
static QString timeString(const NeoChatRoom *room,
const Quotient::RoomEvent *event,
bool relative,
QLocale::FormatType format = QLocale::ShortFormat,
bool isPending = false);
/**
* @brief Return a QString for the event timestamp.
*
* This is intended to return a string that is read for display in the UI without
* any further manipulation required.
*
* @param format the format to use as a string.
* @param isPending whether the event is pending as this cannot be derived from
* just the event object.
* @param lastUpdated the time the event was last updated locally as this cannot be
* obtained from the event.
*/
static QString timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, const QString &format, bool isPending = false);
static NeoChatDateTime dateTime(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false);
/**
* @brief Whether the event should be highlighted in the timeline.

View File

@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: 2026 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "neochatdatetime.h"
#include <KFormat>
using namespace Qt::Literals::StringLiterals;
NeoChatDateTime::NeoChatDateTime(QDateTime dateTime)
: m_dateTime(dateTime)
{
}
QDateTime NeoChatDateTime::dateTime() const
{
return m_dateTime;
}
QString NeoChatDateTime::hourMinuteString() const
{
return m_dateTime.toLocalTime().toString(u"hh:mm"_s);
}
QString NeoChatDateTime::shortDateTime() const
{
return QLocale().toString(m_dateTime.toLocalTime(), QLocale::ShortFormat);
}
QString NeoChatDateTime::relativeDate() const
{
KFormat formatter;
return formatter.formatRelativeDate(m_dateTime.toLocalTime().date(), QLocale::ShortFormat);
}
QString NeoChatDateTime::relativeDateTime() const
{
KFormat formatter;
return formatter.formatRelativeDateTime(m_dateTime.toLocalTime(), QLocale::ShortFormat);
}
bool NeoChatDateTime::isValid() const
{
return m_dateTime.isValid();
}
bool NeoChatDateTime::operator==(const QDateTime &right) const
{
return m_dateTime == right;
}
#include "moc_neochatdatetime.cpp"

View File

@@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: 2026 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <QDateTime>
#include <QQmlEngine>
/**
* @class NeoChatDateTime
*
* This class is a helper for converting a QDateTime into the various format required in NeoChat.
*
* The intention is that this can be passed to QML and then the various Q_Properties
* can be called to get the date/time in the desired format reading for viewing in
* the UI.
*/
class NeoChatDateTime
{
Q_GADGET
QML_ELEMENT
/**
* @brief The base QDateTime used to generate the other values.
*/
Q_PROPERTY(QDateTime dateTime READ dateTime CONSTANT)
/**
* @brief The time formatted as "hh:mm".
*/
Q_PROPERTY(QString hourMinuteString READ hourMinuteString CONSTANT)
/**
* @brief The date and time formatted as per QLocale::ShortFormat for your locale.
*/
Q_PROPERTY(QString shortDateTime READ shortDateTime CONSTANT)
/**
* @brief The date formatted as relative to now.
*
* If the date falls within one week before or after the current date
* then a relative date string will be returned, such as:
* - Yesterday
* - Today
* - Tomorrow
* - Last Tuesday
* - Next Wednesday
*
* If the date falls outside this period then the format QLocale::ShortFormat
* for your locale is used.
*/
Q_PROPERTY(QString relativeDate READ relativeDate CONSTANT)
/**
* @brief The time and date formatted as relative to now.
*
* The format is "RelativeDate, hh::mm"
*
* If the date falls within one week before or after the current date
* then a relative date string will be returned, such as:
* - Yesterday
* - Today
* - Tomorrow
* - Last Tuesday
* - Next Wednesday
*
* If the date falls outside this period then the format QLocale::ShortFormat
* for your locale is used.
*/
Q_PROPERTY(QString relativeDateTime READ relativeDateTime CONSTANT)
/**
* @brief Whether this object has a valid date time.
*/
Q_PROPERTY(bool isValid READ isValid CONSTANT)
public:
NeoChatDateTime(QDateTime dateTime = {});
QDateTime dateTime() const;
QString hourMinuteString() const;
QString shortDateTime() const;
QString relativeDate() const;
QString relativeDateTime() const;
bool isValid() const;
bool operator==(const QDateTime &right) const;
private:
QDateTime m_dateTime;
};

View File

@@ -27,14 +27,9 @@ RowLayout {
required property var author
/**
* @brief The timestamp of the message.
* @brief The timestamp of the event as a NeoChatDateTime.
*/
required property var time
/**
* @brief The timestamp of the message as a string.
*/
required property string timeString
required property NeoChatDateTime dateTime
Layout.fillWidth: true
Layout.maximumWidth: Message.maxContentWidth
@@ -83,11 +78,11 @@ RowLayout {
}
QQC2.Label {
id: timeLabel
text: root.timeString
text: root.dateTime.hourMinuteString
horizontalAlignment: Text.AlignRight
color: Kirigami.Theme.disabledTextColor
QQC2.ToolTip.visible: timeHoverHandler.hovered
QQC2.ToolTip.text: root.time.toLocaleString(Qt.locale(), Locale.ShortFormat)
QQC2.ToolTip.text: root.dateTime.shortDateTime
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
HoverHandler {

View File

@@ -28,9 +28,9 @@ QQC2.Control {
required property NeochatRoomMember author
/**
* @brief The timestamp of the message.
* @brief The timestamp of the event as a NeoChatDateTime.
*/
required property var time
required property NeoChatDateTime dateTime
/**
* @brief The display text of the message.
@@ -164,12 +164,12 @@ QQC2.Control {
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
}
QQC2.Button {
visible: root.time.toString() !== "Invalid Date"
visible: root.dateTime.isValid
icon.name: "view-fullscreen"
text: i18nc("@action:button", "Maximize")
display: QQC2.AbstractButton.IconOnly
onClicked: RoomManager.maximizeCode(root.author, root.time, root.display, root.componentAttributes.class);
onClicked: RoomManager.maximizeCode(root.author, root.dateTime, root.display, root.componentAttributes.class);
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered

View File

@@ -16,6 +16,7 @@
#include "contentprovider.h"
#include "eventhandler.h"
#include "models/reactionmodel.h"
#include "neochatdatetime.h"
#include "neochatroom.h"
#include "texthandler.h"
@@ -123,22 +124,13 @@ void EventMessageContentModel::initializeModel()
resetModel();
}
QDateTime EventMessageContentModel::time() const
NeoChatDateTime EventMessageContentModel::dateTime() const
{
const auto event = m_room->getEvent(m_eventId);
if (event.first == nullptr) {
return MessageContentModel::time();
return MessageContentModel::dateTime();
};
return EventHandler::time(m_room, event.first, m_currentState == Pending);
}
QString EventMessageContentModel::timeString() const
{
const auto event = m_room->getEvent(m_eventId);
if (event.first == nullptr) {
return MessageContentModel::timeString();
};
return EventHandler::timeString(m_room, event.first, u"hh:mm"_s, m_currentState == Pending);
return EventHandler::dateTime(m_room, event.first, m_currentState == Pending);
}
QString EventMessageContentModel::authorId() const
@@ -254,12 +246,7 @@ void EventMessageContentModel::resetModel()
return;
}
m_components += MessageComponent{MessageComponentType::Author,
QString(),
{
{u"time"_s, EventHandler::time(m_room, event.first, m_currentState == Pending)},
{u"timeString"_s, EventHandler::timeString(m_room, event.first, u"hh:mm"_s, m_currentState == Pending)},
}};
m_components += MessageComponent{MessageComponentType::Author, {}, {}};
m_components += messageContentComponents();
endResetModel();

View File

@@ -52,8 +52,7 @@ Q_SIGNALS:
private:
void initializeModel();
QDateTime time() const override;
QString timeString() const override;
NeoChatDateTime dateTime() const override;
QString authorId() const override;
QString threadRootId() const override;

View File

@@ -10,6 +10,7 @@
#include "chatbarcache.h"
#include "contentprovider.h"
#include "neochatconnection.h"
#include "neochatdatetime.h"
#include "texthandler.h"
using namespace Quotient;
@@ -79,16 +80,11 @@ QString MessageContentModel::eventId() const
return m_eventId;
}
QDateTime MessageContentModel::time() const
NeoChatDateTime MessageContentModel::dateTime() const
{
return QDateTime::currentDateTime();
}
QString MessageContentModel::timeString() const
{
return time().toLocalTime().toString(u"hh:mm"_s);
}
QString MessageContentModel::authorId() const
{
return m_room->localMember().id();
@@ -136,11 +132,8 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
if (role == EventIdRole) {
return eventId();
}
if (role == TimeRole) {
return time();
}
if (role == TimeStringRole) {
return timeString();
if (role == DateTimeRole) {
return QVariant::fromValue(dateTime());
}
if (role == AuthorRole) {
return QVariant::fromValue<NeochatRoomMember *>(author());
@@ -199,8 +192,7 @@ QHash<int, QByteArray> MessageContentModel::roleNamesStatic()
roles[MessageContentModel::ComponentTypeRole] = "componentType";
roles[MessageContentModel::ComponentAttributesRole] = "componentAttributes";
roles[MessageContentModel::EventIdRole] = "eventId";
roles[MessageContentModel::TimeRole] = "time";
roles[MessageContentModel::TimeStringRole] = "timeString";
roles[MessageContentModel::DateTimeRole] = "dateTime";
roles[MessageContentModel::AuthorRole] = "author";
roles[MessageContentModel::FileTransferInfoRole] = "fileTransferInfo";
roles[MessageContentModel::ItineraryModelRole] = "itineraryModel";

View File

@@ -21,6 +21,8 @@
#include "neochatroom.h"
#include "neochatroommember.h"
class NeoChatDateTime;
/**
* @class MessageContentModel
*
@@ -47,8 +49,7 @@ public:
ComponentTypeRole = Qt::UserRole, /**< The type of component to visualise the message. */
ComponentAttributesRole, /**< The attributes of the component. */
EventIdRole, /**< The matrix event ID of the event. */
TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */
TimeStringRole, /**< The timestamp for when the event was sent as a string (in QLocale::ShortFormat). */
DateTimeRole, /**< The timestamp for when the event was sent (as a NeoChatDateTime). */
AuthorRole, /**< The author of the event. */
FileTransferInfoRole, /**< FileTransferInfo for any downloading files. */
ItineraryModelRole, /**< The itinerary model for a file. */
@@ -125,18 +126,11 @@ protected:
QString m_eventId;
/**
* @brief QDateTime for the message.
* @brief NeoChatDateTime for the message.
*
* The default implementation returns the current time.
*/
virtual QDateTime time() const;
/**
* @brief Time for the message as a string in the from "hh:mm".
*
* The default implementation returns the current time.
*/
virtual QString timeString() const;
virtual NeoChatDateTime dateTime() const;
/**
* @brief The author of the message.

View File

@@ -50,9 +50,9 @@ MessageDelegateBase {
required property MessageContentModel contentModel
/**
* @brief The date of the event as a string.
* @brief The timestamp of the event as a NeoChatDateTime.
*/
required property string section
required property NeoChatDateTime dateTime
/**
* @brief A model with the first 5 other user read markers for this message.
@@ -203,7 +203,7 @@ MessageDelegateBase {
sectionComponent: Kirigami.ListSectionHeader {
horizontalPadding: 0
text: root.section
text: root.dateTime.relativeDate
}
readMarkerComponent: AvatarFlow {

View File

@@ -13,6 +13,11 @@ import org.kde.neochat
TimelineDelegate {
id: root
/**
* @brief The timestamp of the event as a NeoChatDateTime.
*/
required property NeoChatDateTime dateTime
property bool isTemporaryHighlighted: false
onIsTemporaryHighlightedChanged: if (isTemporaryHighlighted) {
temporaryHighlightTimer.start();
@@ -39,7 +44,7 @@ TimelineDelegate {
}
contentItem: QQC2.Label {
text: i18nc("Relative time since the room was last read", "Last read: %1", time)
text: i18nc("Relative time since the room was last read", "Last read: %1", root.dateTime.relativeDateTime)
}
background: Kirigami.ShadowedRectangle {

View File

@@ -49,9 +49,9 @@ TimelineDelegate {
required property bool showSection
/**
* @brief The date of the event as a string.
* @brief The timestamp of the event as a NeoChatDateTime.
*/
required property string section
required property NeoChatDateTime dateTime
/**
* @brief A model with the first 5 other user read markers for this message.
@@ -80,7 +80,7 @@ TimelineDelegate {
Layout.fillWidth: true
visible: root.showSection
horizontalPadding: 0
text: root.section
text: root.dateTime.relativeDate
}
RowLayout {
Layout.fillWidth: true

View File

@@ -7,6 +7,7 @@
#include <Quotient/room.h>
#include "messagefiltermodel.h"
#include "neochatdatetime.h"
#include "timelinemessagemodel.h"
using namespace Qt::StringLiterals;
@@ -34,8 +35,9 @@ QVariant MediaMessageFilterModel::data(const QModelIndex &index, int role) const
// We need to catch this one and return true if the next media object was
// on a different day.
if (role == TimelineMessageModel::ShowSectionRole) {
const auto day = mapToSource(index).data(TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date();
const auto previousEventDay = mapToSource(this->index(index.row() + 1, 0)).data(TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date();
const auto day = mapToSource(index).data(TimelineMessageModel::DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date();
const auto previousEventDay =
mapToSource(this->index(index.row() + 1, 0)).data(TimelineMessageModel::DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date();
return day != previousEventDay;
}

View File

@@ -9,6 +9,7 @@
#include "enums/delegatetype.h"
#include "messagemodel.h"
#include "models/timelinemodel.h"
#include "neochatdatetime.h"
using namespace Quotient;
@@ -179,9 +180,13 @@ bool MessageFilterModel::showAuthor(QModelIndex index) const
if (data(i, TimelineMessageModel::SpecialMarksRole) != EventStatus::Hidden && !itemData(i).empty()) {
return data(i, TimelineMessageModel::AuthorRole) != data(index, TimelineMessageModel::AuthorRole)
|| data(i, TimelineMessageModel::DelegateTypeRole) == DelegateType::State
|| data(i, TimelineMessageModel::TimeRole).toDateTime().msecsTo(data(index, TimelineMessageModel::TimeRole).toDateTime()) > 600000
|| data(i, TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date().day()
!= data(index, TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date().day();
|| data(i, TimelineMessageModel::DateTimeRole)
.value<NeoChatDateTime>()
.dateTime()
.msecsTo(data(index, TimelineMessageModel::DateTimeRole).value<NeoChatDateTime>().dateTime())
> 600000
|| data(i, TimelineMessageModel::DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date().day()
!= data(index, TimelineMessageModel::DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date().day();
}
}

View File

@@ -17,8 +17,9 @@
#include "enums/messagecomponenttype.h"
#include "eventhandler.h"
#include "events/pollevent.h"
#include "models/reactionmodel.h"
#include "models/eventmessagecontentmodel.h"
#include "models/reactionmodel.h"
#include "neochatdatetime.h"
#include "neochatroommember.h"
using namespace Quotient;
@@ -108,11 +109,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const
switch (role) {
case DelegateTypeRole:
return DelegateType::ReadMarker;
case TimeRole: {
const QDateTime eventDate = data(index(m_lastReadEventIndex.row() + 1, 0), TimeRole).toDateTime().toLocalTime();
static const KFormat format;
return format.formatRelativeDateTime(eventDate, QLocale::ShortFormat);
}
case DateTimeRole:
return data(index(m_lastReadEventIndex.row() + 1, 0), DateTimeRole);
case SpecialMarksRole:
// Check if all the earlier events in the timeline are hidden. If so hide this.
for (auto r = row - 1; r >= 0; --r) {
@@ -228,12 +226,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const
return {};
}
if (role == TimeRole) {
return EventHandler::time(eventRoom, &event.value().get(), isPending);
}
if (role == SectionRole) {
return EventHandler::timeString(eventRoom, &event.value().get(), true, QLocale::ShortFormat, isPending);
if (role == DateTimeRole) {
return QVariant::fromValue(EventHandler::dateTime(eventRoom, &event.value().get(), isPending));
}
if (role == IsThreadedRole) {
@@ -265,8 +259,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const
// While the row is removed the subsequent row indexes are not changed so we need to skip over the removed index.
// See - https://doc.qt.io/qt-5/qabstractitemmodel.html#beginRemoveRows
if (data(i, SpecialMarksRole) != EventStatus::Hidden && !itemData(i).empty()) {
const auto day = data(idx, TimeRole).toDateTime().toLocalTime().date().dayOfYear();
const auto previousEventDay = data(i, TimeRole).toDateTime().toLocalTime().date().dayOfYear();
const auto day = data(idx, DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date().dayOfYear();
const auto previousEventDay = data(i, DateTimeRole).value<NeoChatDateTime>().dateTime().toLocalTime().date().dayOfYear();
return day != previousEventDay;
}
}
@@ -340,8 +334,7 @@ QHash<int, QByteArray> MessageModel::roleNames() const
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[DelegateTypeRole] = "delegateType";
roles[EventIdRole] = "eventId";
roles[TimeRole] = "time";
roles[SectionRole] = "section";
roles[DateTimeRole] = "dateTime";
roles[AuthorRole] = "author";
roles[HighlightRole] = "isHighlighted";
roles[SpecialMarksRole] = "marks";

View File

@@ -60,8 +60,7 @@ public:
enum EventRoles {
DelegateTypeRole = Qt::UserRole + 1, /**< The delegate type of the message. */
EventIdRole, /**< The matrix event ID of the event. */
TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */
SectionRole, /**< The date of the event as a string. */
DateTimeRole, /**< The timestamp for when the event was sent (as a NeoChatDateTime). */
AuthorRole, /**< The author of the event. */
HighlightRole, /**< Whether the event should be highlighted. */
SpecialMarksRole, /**< Whether the event is hidden or not. */