diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index c33896afd..8a72db228 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -32,6 +32,7 @@ #include "notificationsmanager.h" #include "user.h" #include "utils.h" +#include "neochatconfig.h" #include @@ -63,7 +64,11 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS NotificationsManager::instance().postNotification(id(), lastEvent->id(), displayName(), sender->displayname(this), eventToString(*lastEvent), avatar(128)); }); - connect(this, &Room::aboutToAddHistoricalMessages, this, &NeoChatRoom::readMarkerLoadedChanged); + connect(this, &Room::aboutToAddHistoricalMessages, + this, &NeoChatRoom::readMarkerLoadedChanged); + + connect(this, &Quotient::Room::eventsHistoryJobChanged, + this, &NeoChatRoom::lastActiveTimeChanged); } void NeoChatRoom::uploadFile(const QUrl &url, const QString &body) @@ -120,37 +125,48 @@ void NeoChatRoom::sendTypingNotification(bool isTyping) connection()->callApi(BackgroundRequest, localUser()->id(), id(), isTyping, 10000); } -QString NeoChatRoom::lastEvent() const +const RoomMessageEvent *NeoChatRoom::lastEvent(bool ignoreStateEvent) const { - for (auto i = messageEvents().rbegin(); i < messageEvents().rend(); i++) { - const RoomEvent *evt = i->get(); + for (auto timelineItem = messageEvents().rbegin(); timelineItem < messageEvents().rend(); timelineItem++) { + const RoomEvent *event = timelineItem->get(); - if (is(*evt) || is(*evt)) { + if (is(*event) || is(*event)) { continue; } - if (evt->isRedacted()) { + if (event->isRedacted()) { continue; } - if (evt->isStateEvent() && static_cast(*evt).repeatsState()) { + if (event->isStateEvent() && (ignoreStateEvent || !NeoChatConfig::self()->showLeaveJoinEvent() || static_cast(*event).repeatsState())) { continue; } - if (auto e = eventCast(evt)) { - if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) { + if (auto roomEvent = eventCast(event)) { + if (!roomEvent->replacedEvent().isEmpty() && roomEvent->replacedEvent() != roomEvent->id()) { continue; } } - if (connection()->isIgnored(user(evt->senderId()))) { + if (connection()->isIgnored(user(event->senderId()))) { continue; } - return user(evt->senderId())->displayname() + (evt->isStateEvent() ? " " : ": ") + eventToString(*evt); + if (auto lastEvent = eventCast(event)) { + return lastEvent; + } } - return ""; + return nullptr; } +QString NeoChatRoom::lastEventToString() const +{ + if (auto event = lastEvent()) { + return user(event->senderId())->displayname() + (event->isStateEvent() ? " " : ": ") + eventToString(*event); + } + return QLatin1String(""); +} + + bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const { return highlights.contains(e); @@ -201,11 +217,22 @@ void NeoChatRoom::countChanged() } } -QDateTime NeoChatRoom::lastActiveTime() const +QDateTime NeoChatRoom::lastActiveTime() { if (timelineSize() == 0) { + QTimer::singleShot(0, this, [=]() { + if (localUser()) { + getPreviousContent(10); + } + }); return QDateTime(); } + + if (auto event = lastEvent(true)) { + return event->originTimestamp(); + } + + // no message found, take last event return messageEvents().rbegin()->get()->originTimestamp(); } diff --git a/src/neochatroom.h b/src/neochatroom.h index 9734cdc91..847a750b8 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -31,16 +31,31 @@ class NeoChatRoom : public Room Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY fileUploadingProgressChanged) Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged) + Q_PROPERTY(QDateTime lastActiveTime READ lastActiveTime NOTIFY lastActiveTimeChanged) public: explicit NeoChatRoom(Connection *connection, QString roomId, JoinState joinState = {}); [[nodiscard]] QVariantList getUsersTyping() const; - [[nodiscard]] QString lastEvent() const; - bool isEventHighlighted(const Quotient::RoomEvent *e) const; + /// Get the interesting last event. + /// + /// This function respect the showLeaveJoinEvent setting and discard + /// other not interesting events. This function can return an empty pointer + /// when the room is empty of RoomMessageEvent. + [[nodiscard]] const RoomMessageEvent *lastEvent(bool ignoreStateEvent = false) const; - [[nodiscard]] QDateTime lastActiveTime() const; + /// Convenient way to get the last event but in a string format. + /// + /// \see lastEvent + [[nodiscard]] QString lastEventToString() const; + + /// Convenient way to get the QDateTime of the last event. + /// + /// \see lastEvent + [[nodiscard]] QDateTime lastActiveTime(); + + bool isEventHighlighted(const Quotient::RoomEvent *e) const; [[nodiscard]] bool hasFileUploading() const { @@ -112,6 +127,7 @@ Q_SIGNALS: void fileUploadingProgressChanged(); void backgroundChanged(); void readMarkerLoadedChanged(); + void lastActiveTimeChanged(); public Q_SLOTS: void uploadFile(const QUrl &url, const QString &body = ""); diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index 94202b794..edb7fcc12 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -136,15 +136,19 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room) if (room->timelineSize() == 0) { return; } - const RoomEvent *lastEvent = room->messageEvents().rbegin()->get(); - if (lastEvent->isStateEvent()) { + auto *lastEvent = room->lastEvent(); + + if (!lastEvent) { return; } - User *sender = room->user(lastEvent->senderId()); - if (sender == room->localUser()) { - return; + + if (!lastEvent->isStateEvent()) { + User *sender = room->user(lastEvent->senderId()); + if (sender == room->localUser()) { + return; + } + Q_EMIT newMessage(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); } - Q_EMIT newMessage(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); }); connect(room, &Room::highlightCountChanged, this, [=] { if (room->highlightCount() == 0) { @@ -153,15 +157,19 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room) if (room->timelineSize() == 0) { return; } - const RoomEvent *lastEvent = room->messageEvents().rbegin()->get(); - if (lastEvent->isStateEvent()) { + auto *lastEvent = room->lastEvent(); + + if (!lastEvent) { return; } - User *sender = room->user(lastEvent->senderId()); - if (sender == room->localUser()) { - return; + + if (!lastEvent->isStateEvent()) { + User *sender = room->user(lastEvent->senderId()); + if (sender == room->localUser()) { + return; + } + Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); } - Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); }); connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount); } @@ -279,7 +287,7 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const return room->highlightCount(); } if (role == LastEventRole) { - return room->lastEvent(); + return room->lastEventToString(); } if (role == LastActiveTimeRole) { return room->lastActiveTime();