summary refs log tree commit diff
path: root/src/timeline
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-12-30 04:54:03 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2021-12-30 04:54:03 +0100
commit9a9dbda571a674ecfbf23533c64ec9cb095479ef (patch)
tree3e4ac7250ec9bedc7285c5aec144eb496a08e62e /src/timeline
parentConvert blurhash image format on worker thread (diff)
downloadnheko-9a9dbda571a674ecfbf23533c64ec9cb095479ef.tar.xz
Update presence dynamically and reduce allocations
Diffstat (limited to 'src/timeline')
-rw-r--r--src/timeline/PresenceEmitter.cpp73
-rw-r--r--src/timeline/PresenceEmitter.h26
-rw-r--r--src/timeline/TimelineViewManager.cpp26
-rw-r--r--src/timeline/TimelineViewManager.h5
4 files changed, 104 insertions, 26 deletions
diff --git a/src/timeline/PresenceEmitter.cpp b/src/timeline/PresenceEmitter.cpp
new file mode 100644

index 00000000..c052bf43 --- /dev/null +++ b/src/timeline/PresenceEmitter.cpp
@@ -0,0 +1,73 @@ +#include "PresenceEmitter.h" + +#include <QCache> +#include <Utils.h> + +#include "Cache.h" + +namespace { +struct CacheEntry +{ + QString status; + mtx::presence::PresenceState state; +}; +} + +static QCache<QString, CacheEntry> presences; + +static QString +presenceToStr(mtx::presence::PresenceState state) +{ + switch (state) { + case mtx::presence::PresenceState::offline: + return QStringLiteral("offline"); + case mtx::presence::PresenceState::unavailable: + return QStringLiteral("unavailable"); + case mtx::presence::PresenceState::online: + default: + return QStringLiteral("online"); + } +} + +static CacheEntry * +pullPresence(const QString &id) +{ + auto p = cache::presence(id.toStdString()); + auto c = new CacheEntry{ + utils::replaceEmoji(QString::fromStdString(p.status_msg).toHtmlEscaped()), p.presence}; + presences.insert(id, c); + return c; +} + +void +PresenceEmitter::sync( + const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presences_) +{ + for (const auto &p : presences_) { + auto id = QString::fromStdString(p.sender); + presences.remove(id); + emit presenceChanged(std::move(id)); + } +} + +QString +PresenceEmitter::userPresence(QString id) const +{ + if (id.isEmpty()) + return {}; + else if (auto p = presences[id]) + return presenceToStr(p->state); + else + return presenceToStr(pullPresence(id)->state); +} + +QString +PresenceEmitter::userStatus(QString id) const +{ + if (id.isEmpty()) + return {}; + else if (auto p = presences[id]) + return p->status; + else + return pullPresence(id)->status; +} diff --git a/src/timeline/PresenceEmitter.h b/src/timeline/PresenceEmitter.h new file mode 100644
index 00000000..bf1a9458 --- /dev/null +++ b/src/timeline/PresenceEmitter.h
@@ -0,0 +1,26 @@ +#pragma once + +#include <QObject> + +#include <vector> + +#include <mtx/events.hpp> +#include <mtx/events/presence.hpp> + +class PresenceEmitter : public QObject +{ + Q_OBJECT + +public: + PresenceEmitter(QObject *p = nullptr) + : QObject(p) + {} + + void sync(const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presences); + + Q_INVOKABLE QString userPresence(QString id) const; + Q_INVOKABLE QString userStatus(QString id) const; + +signals: + void presenceChanged(QString userid); +}; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 70a1510a..bab093b0 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp
@@ -124,29 +124,6 @@ TimelineViewManager::userColor(QString id, QColor background) return userColors.value(idx); } -QString -TimelineViewManager::userPresence(QString id) const -{ - if (id.isEmpty()) - return {}; - else - switch (cache::presenceState(id.toStdString())) { - case mtx::presence::PresenceState::offline: - return QStringLiteral("offline"); - case mtx::presence::PresenceState::unavailable: - return QStringLiteral("unavailable"); - case mtx::presence::PresenceState::online: - default: - return QStringLiteral("online"); - } -} - -QString -TimelineViewManager::userStatus(QString id) const -{ - return QString::fromStdString(cache::statusMessage(id.toStdString())); -} - TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *parent) : QObject(parent) , imgProvider(new MxcImageProvider()) @@ -157,6 +134,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par , communities_(new CommunitiesModel(this)) , callManager_(callManager) , verificationManager_(new VerificationManager(this)) + , presenceEmitter(new PresenceEmitter(this)) { qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>(); qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>(); @@ -280,6 +258,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par return new Nheko(); }); qmlRegisterSingletonInstance("im.nheko", 1, 0, "VerificationManager", verificationManager_); + qmlRegisterSingletonInstance("im.nheko", 1, 0, "Presence", presenceEmitter); qmlRegisterSingletonType<SelfVerificationStatus>( "im.nheko", 1, 0, "SelfVerificationStatus", [](QQmlEngine *, QJSEngine *) -> QObject * { auto ptr = new SelfVerificationStatus(); @@ -407,6 +386,7 @@ TimelineViewManager::sync(const mtx::responses::Sync &sync_) { this->rooms_->sync(sync_); this->communities_->sync(sync_); + this->presenceEmitter->sync(sync_.presence); if (isInitialSync_) { this->isInitialSync_ = false; diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 30b3564f..d875fd88 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h
@@ -24,6 +24,7 @@ #include "emoji/Provider.h" #include "encryption/VerificationManager.h" #include "timeline/CommunitiesModel.h" +#include "timeline/PresenceEmitter.h" #include "timeline/RoomlistModel.h" #include "voip/CallManager.h" #include "voip/WebRTCSession.h" @@ -64,9 +65,6 @@ public: Q_INVOKABLE QString escapeEmoji(QString str) const; Q_INVOKABLE QString htmlEscape(QString str) const { return str.toHtmlEscaped(); } - Q_INVOKABLE QString userPresence(QString id) const; - Q_INVOKABLE QString userStatus(QString id) const; - Q_INVOKABLE void openRoomMembers(TimelineModel *room); Q_INVOKABLE void openRoomSettings(QString room_id); Q_INVOKABLE void openInviteUsers(QString roomId); @@ -146,6 +144,7 @@ private: // don't move this above the rooms_ CallManager *callManager_ = nullptr; VerificationManager *verificationManager_ = nullptr; + PresenceEmitter *presenceEmitter = nullptr; QHash<QPair<QString, quint64>, QColor> userColors; };