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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -17,6 +17,7 @@ target_sources(LibNeoChat PRIVATE
|
||||
filetransferpseudojob.cpp
|
||||
filetype.cpp
|
||||
linkpreviewer.cpp
|
||||
neochatdatetime.cpp
|
||||
roomlastmessageprovider.cpp
|
||||
spacehierarchycache.cpp
|
||||
texthandler.cpp
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
52
src/libneochat/neochatdatetime.cpp
Normal file
52
src/libneochat/neochatdatetime.cpp
Normal 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"
|
||||
93
src/libneochat/neochatdatetime.h
Normal file
93
src/libneochat/neochatdatetime.h
Normal 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;
|
||||
};
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user