summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-06-08 01:45:24 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-06-08 01:59:05 +0200
commit96f4169be97715e6b6b45663492e3791ba21ae09 (patch)
tree618753677e69ac590aa2cad267dfd7d31c574bfd /src
parentSmooth scaling for images (diff)
downloadnheko-96f4169be97715e6b6b45663492e3791ba21ae09.tar.xz
Show presence and set custom status messages
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp72
-rw-r--r--src/Cache.h6
-rw-r--r--src/Cache_p.h13
-rw-r--r--src/ChatPage.cpp20
-rw-r--r--src/ChatPage.h6
-rw-r--r--src/UserInfoWidget.cpp24
-rw-r--r--src/UserInfoWidget.h4
-rw-r--r--src/timeline/TimelineViewManager.cpp12
-rw-r--r--src/timeline/TimelineViewManager.h3
9 files changed, 160 insertions, 0 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index 009cbabc..d9d1134e 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -952,6 +952,8 @@ Cache::saveState(const mtx::responses::Sync &res) saveInvites(txn, res.rooms.invite); + savePresence(txn, res.presence); + removeLeftRooms(txn, res.rooms.leave); txn.commit(); @@ -1037,6 +1039,21 @@ Cache::saveInvite(lmdb::txn &txn, } } +void +Cache::savePresence( + lmdb::txn &txn, + const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates) +{ + for (const auto &update : presenceUpdates) { + auto presenceDb = getPresenceDb(txn); + + lmdb::dbi_put(txn, + presenceDb, + lmdb::val(update.sender), + lmdb::val(json(update.content).dump())); + } +} + std::vector<std::string> Cache::roomsWithStateUpdates(const mtx::responses::Sync &res) { @@ -2254,6 +2271,50 @@ Cache::removeAvatarUrl(const QString &room_id, const QString &user_id) AvatarUrls.remove(fmt); } +mtx::presence::PresenceState +Cache::presenceState(const std::string &user_id) +{ + lmdb::val presenceVal; + + auto txn = lmdb::txn::begin(env_); + auto db = getPresenceDb(txn); + auto res = lmdb::dbi_get(txn, db, lmdb::val(user_id), presenceVal); + + mtx::presence::PresenceState state = mtx::presence::offline; + + if (res) { + mtx::events::presence::Presence presence = + json::parse(std::string(presenceVal.data(), presenceVal.size())); + state = presence.presence; + } + + txn.commit(); + + return state; +} + +std::string +Cache::statusMessage(const std::string &user_id) +{ + lmdb::val presenceVal; + + auto txn = lmdb::txn::begin(env_); + auto db = getPresenceDb(txn); + auto res = lmdb::dbi_get(txn, db, lmdb::val(user_id), presenceVal); + + std::string status_msg; + + if (res) { + mtx::events::presence::Presence presence = + json::parse(std::string(presenceVal.data(), presenceVal.size())); + status_msg = presence.status_msg; + } + + txn.commit(); + + return status_msg; +} + void to_json(json &j, const RoomInfo &info) { @@ -2425,6 +2486,17 @@ insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &a instance_->insertAvatarUrl(room_id, user_id, avatar_url); } +mtx::presence::PresenceState +presenceState(const std::string &user_id) +{ + return instance_->presenceState(user_id); +} +std::string +statusMessage(const std::string &user_id) +{ + return instance_->statusMessage(user_id); +} + //! Load saved data for the display names & avatars. void populateMembers() diff --git a/src/Cache.h b/src/Cache.h
index 12465c9d..b5275623 100644 --- a/src/Cache.h +++ b/src/Cache.h
@@ -54,6 +54,12 @@ insertDisplayName(const QString &room_id, const QString &user_id, const QString void insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url); +// presence +mtx::presence::PresenceState +presenceState(const std::string &user_id); +std::string +statusMessage(const std::string &user_id); + //! Load saved data for the display names & avatars. void populateMembers(); diff --git a/src/Cache_p.h b/src/Cache_p.h
index 0d66a608..892b66a5 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h
@@ -52,6 +52,10 @@ public: static QString displayName(const QString &room_id, const QString &user_id); static QString avatarUrl(const QString &room_id, const QString &user_id); + // presence + mtx::presence::PresenceState presenceState(const std::string &user_id); + std::string statusMessage(const std::string &user_id); + static void removeDisplayName(const QString &room_id, const QString &user_id); static void removeAvatarUrl(const QString &room_id, const QString &user_id); @@ -377,6 +381,10 @@ private: void saveInvites(lmdb::txn &txn, const std::map<std::string, mtx::responses::InvitedRoom> &rooms); + void savePresence( + lmdb::txn &txn, + const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates); + //! Sends signals for the rooms that are removed. void removeLeftRooms(lmdb::txn &txn, const std::map<std::string, mtx::responses::LeftRoom> &rooms) @@ -430,6 +438,11 @@ private: return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE); } + lmdb::dbi getPresenceDb(lmdb::txn &txn) + { + return lmdb::dbi::open(txn, "presence", MDB_CREATE); + } + //! Retrieves or creates the database that stores the open OLM sessions between our device //! and the given curve25519 key which represents another device. //! diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index c7f5164a..f2b8253b 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp
@@ -61,6 +61,7 @@ constexpr size_t MAX_ONETIME_KEYS = 50; Q_DECLARE_METATYPE(std::optional<mtx::crypto::EncryptedFile>) Q_DECLARE_METATYPE(std::optional<RelatedInfo>) +Q_DECLARE_METATYPE(mtx::presence::PresenceState) ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent) : QWidget(parent) @@ -72,6 +73,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent) qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>(); qRegisterMetaType<std::optional<RelatedInfo>>(); + qRegisterMetaType<mtx::presence::PresenceState>(); topLayout_ = new QHBoxLayout(this); topLayout_->setSpacing(0); @@ -1221,6 +1223,24 @@ ChatPage::sendTypingNotifications() }); } +QString +ChatPage::status() const +{ + return QString::fromStdString(cache::statusMessage(utils::localUser().toStdString())); +} + +void +ChatPage::setStatus(const QString &status) +{ + http::client()->put_presence_status( + currentPresence(), status.toStdString(), [](mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to set presence status_msg: {}", + err->matrix_error.error); + } + }); +} + void ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::RequestErr err) { diff --git a/src/ChatPage.h b/src/ChatPage.h
index 83b4e76d..72fc3b81 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h
@@ -89,6 +89,11 @@ public: void initiateLogout(); void focusMessageInput(); + QString status() const; + void setStatus(const QString &status); + + mtx::presence::PresenceState currentPresence() const { return mtx::presence::online; } + public slots: void leaveRoom(const QString &room_id); void createRoom(const mtx::requests::CreateRoom &req); @@ -154,6 +159,7 @@ signals: const QImage &icon); void updateGroupsInfo(const mtx::responses::JoinedGroups &groups); + void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state); void themeChanged(); void decryptSidebarChanged(); diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp
index e11aa6aa..38677f25 100644 --- a/src/UserInfoWidget.cpp +++ b/src/UserInfoWidget.cpp
@@ -16,7 +16,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <QInputDialog> #include <QLabel> +#include <QMenu> #include <QPainter> #include <QStyle> #include <QStyleOption> @@ -24,6 +26,7 @@ #include <iostream> +#include "ChatPage.h" #include "Config.h" #include "MainWindow.h" #include "Splitter.h" @@ -105,6 +108,27 @@ UserInfoWidget::UserInfoWidget(QWidget *parent) connect(logoutButton_, &QPushButton::clicked, this, []() { MainWindow::instance()->openLogoutDialog(); }); + + menu = new QMenu(this); + + auto setStatusAction = menu->addAction(tr("Set custom status message")); + connect(setStatusAction, &QAction::triggered, this, [this]() { + bool ok = false; + QString text = QInputDialog::getText(this, + tr("Custom status message"), + tr("Status:"), + QLineEdit::Normal, + ChatPage::instance()->status(), + &ok); + if (ok && !text.isEmpty()) + ChatPage::instance()->setStatus(text); + }); +} + +void +UserInfoWidget::contextMenuEvent(QContextMenuEvent *event) +{ + menu->popup(event->globalPos()); } void diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h
index 575ade52..03ab2cf0 100644 --- a/src/UserInfoWidget.h +++ b/src/UserInfoWidget.h
@@ -26,6 +26,7 @@ class OverlayModal; class QLabel; class QHBoxLayout; class QVBoxLayout; +class QMenu; class UserInfoWidget : public QWidget { @@ -48,6 +49,7 @@ public: protected: void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; + void contextMenuEvent(QContextMenuEvent *) override; private: Avatar *userAvatar_; @@ -70,4 +72,6 @@ private: int logoutButtonSize_; QColor borderColor_; + + QMenu *menu = nullptr; }; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 30abe506..ff457af9 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp
@@ -57,6 +57,18 @@ TimelineViewManager::userColor(QString id, QColor background) return userColors.value(id); } +QString +TimelineViewManager::userPresence(QString id) const +{ + return QString::fromStdString( + mtx::presence::to_string(cache::presenceState(id.toStdString()))); +} +QString +TimelineViewManager::userStatus(QString id) const +{ + return QString::fromStdString(cache::statusMessage(id.toStdString())); +} + TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings, QWidget *parent) : imgProvider(new MxcImageProvider()) , colorImgProvider(new ColorImageProvider()) diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 45a603af..e677ef20 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h
@@ -41,6 +41,9 @@ public: Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const; Q_INVOKABLE QColor userColor(QString id, QColor background); + Q_INVOKABLE QString userPresence(QString id) const; + Q_INVOKABLE QString userStatus(QString id) const; + signals: void clearRoomMessageCount(QString roomid); void updateRoomsLastMessage(QString roomid, const DescInfo &info);