mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-26 13:08:48 +03:00
Fix issues with caching and loading of mentions.
Mentions are now loaded from the cache instead of directly from the web request. Mentions are also properly saved to the cache now (instead of as empty strings). Still lots of tweaks left on this feature.
This commit is contained in:
parent
f2c4162baa
commit
52a2621776
6 changed files with 108 additions and 50 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QMap>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
@ -1232,20 +1233,20 @@ Cache::roomMessages()
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<QString, mtx::responses::Notifications>
|
QMap<QString, mtx::responses::Notifications>
|
||||||
Cache::getTimelineMentions()
|
Cache::getTimelineMentions()
|
||||||
{
|
{
|
||||||
// TODO: Should be read-only, but getMentionsDb will attempt to create a DB
|
// TODO: Should be read-only, but getMentionsDb will attempt to create a DB
|
||||||
// if it doesn't exist, throwing an error.
|
// if it doesn't exist, throwing an error.
|
||||||
auto txn = lmdb::txn::begin(env_, nullptr);
|
auto txn = lmdb::txn::begin(env_, nullptr);
|
||||||
|
|
||||||
std::map<QString, mtx::responses::Notifications> notifs;
|
QMap<QString, mtx::responses::Notifications> notifs;
|
||||||
|
|
||||||
auto room_ids = getRoomIds(txn);
|
auto room_ids = getRoomIds(txn);
|
||||||
|
|
||||||
for (const auto &room_id : room_ids) {
|
for (const auto &room_id : room_ids) {
|
||||||
auto roomNotifs = getTimelineMentionsForRoom(txn, room_id);
|
auto roomNotifs = getTimelineMentionsForRoom(txn, room_id);
|
||||||
notifs.emplace(QString::fromStdString(room_id), roomNotifs);
|
notifs[QString::fromStdString(room_id)] = roomNotifs;
|
||||||
}
|
}
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
@ -1973,11 +1974,11 @@ Cache::getTimelineMentionsForRoom(lmdb::txn &txn, const std::string &room_id)
|
||||||
while (cursor.get(event_id, msg, MDB_NEXT)) {
|
while (cursor.get(event_id, msg, MDB_NEXT)) {
|
||||||
auto obj = json::parse(msg);
|
auto obj = json::parse(msg);
|
||||||
|
|
||||||
if (obj.count("event") == 0 || obj.count("token") == 0)
|
if (obj.count("event") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mtx::responses::Notification notification;
|
mtx::responses::Notification notification;
|
||||||
mtx::responses::from_json(obj.at("notification"), notification);
|
mtx::responses::from_json(obj, notification);
|
||||||
|
|
||||||
notif.notifications.push_back(notification);
|
notif.notifications.push_back(notification);
|
||||||
}
|
}
|
||||||
|
@ -1992,18 +1993,25 @@ Cache::getTimelineMentionsForRoom(lmdb::txn &txn, const std::string &room_id)
|
||||||
void
|
void
|
||||||
Cache::saveTimelineMentions(const mtx::responses::Notifications &res)
|
Cache::saveTimelineMentions(const mtx::responses::Notifications &res)
|
||||||
{
|
{
|
||||||
|
json notif = res;
|
||||||
|
|
||||||
QMap<std::string, QList<mtx::responses::Notification>> notifsByRoom;
|
QMap<std::string, QList<mtx::responses::Notification>> notifsByRoom;
|
||||||
|
|
||||||
// Sort into room-specific 'buckets'
|
// Sort into room-specific 'buckets'
|
||||||
for (const auto ¬if : res.notifications) {
|
for (const auto ¬if : res.notifications) {
|
||||||
|
json val = notif;
|
||||||
notifsByRoom[notif.room_id].push_back(notif);
|
notifsByRoom[notif.room_id].push_back(notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto txn = lmdb::txn::begin(env_);
|
auto txn = lmdb::txn::begin(env_);
|
||||||
// Insert the entire set of mentions for each room at a time.
|
// Insert the entire set of mentions for each room at a time.
|
||||||
for (const auto &room : notifsByRoom.keys()) {
|
QMap<std::string, QList<mtx::responses::Notification>>::const_iterator it =
|
||||||
nhlog::db()->debug("Storing notifications for " + room);
|
notifsByRoom.constBegin();
|
||||||
saveTimelineMentions(txn, room, notifsByRoom[room]);
|
auto end = notifsByRoom.constEnd();
|
||||||
|
while (it != end) {
|
||||||
|
nhlog::db()->debug("Storing notifications for " + it.key());
|
||||||
|
saveTimelineMentions(txn, it.key(), std::move(it.value()));
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
@ -2019,10 +2027,7 @@ Cache::saveTimelineMentions(lmdb::txn &txn,
|
||||||
using namespace mtx::events;
|
using namespace mtx::events;
|
||||||
using namespace mtx::events::state;
|
using namespace mtx::events::state;
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (const auto ¬if : res) {
|
for (const auto ¬if : res) {
|
||||||
nhlog::db()->debug("Storing notification " + std::to_string(i++) + " for room " +
|
|
||||||
room_id);
|
|
||||||
const auto event_id = utils::event_id(notif.event);
|
const auto event_id = utils::event_id(notif.event);
|
||||||
|
|
||||||
// double check that we have the correct room_id...
|
// double check that we have the correct room_id...
|
||||||
|
@ -2030,7 +2035,7 @@ Cache::saveTimelineMentions(lmdb::txn &txn,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
json obj = json::object();
|
json obj = notif;
|
||||||
|
|
||||||
lmdb::dbi_put(txn, db, lmdb::val(event_id), lmdb::val(obj.dump()));
|
lmdb::dbi_put(txn, db, lmdb::val(event_id), lmdb::val(obj.dump()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,7 @@ public:
|
||||||
|
|
||||||
std::map<QString, mtx::responses::Timeline> roomMessages();
|
std::map<QString, mtx::responses::Timeline> roomMessages();
|
||||||
|
|
||||||
std::map<QString, mtx::responses::Notifications> getTimelineMentions();
|
QMap<QString, mtx::responses::Notifications> getTimelineMentions();
|
||||||
|
|
||||||
//! Retrieve all the user ids from a room.
|
//! Retrieve all the user ids from a room.
|
||||||
std::vector<std::string> roomMembers(const std::string &room_id);
|
std::vector<std::string> roomMembers(const std::string &room_id);
|
||||||
|
|
|
@ -153,6 +153,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(top_bar_, &TopRoomBar::mentionsClicked, this, [this](const QPoint &mentionsPos) {
|
connect(top_bar_, &TopRoomBar::mentionsClicked, this, [this](const QPoint &mentionsPos) {
|
||||||
|
if (user_mentions_popup_->isVisible()) {
|
||||||
|
user_mentions_popup_->hide();
|
||||||
|
} else {
|
||||||
http::client()->notifications(
|
http::client()->notifications(
|
||||||
1000,
|
1000,
|
||||||
"",
|
"",
|
||||||
|
@ -160,7 +163,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
[this, mentionsPos](const mtx::responses::Notifications &res,
|
[this, mentionsPos](const mtx::responses::Notifications &res,
|
||||||
mtx::http::RequestErr err) {
|
mtx::http::RequestErr err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
nhlog::net()->warn("failed to retrieve notifications: {} ({})",
|
nhlog::net()->warn(
|
||||||
|
"failed to retrieve notifications: {} ({})",
|
||||||
err->matrix_error.error,
|
err->matrix_error.error,
|
||||||
static_cast<int>(err->status_code));
|
static_cast<int>(err->status_code));
|
||||||
return;
|
return;
|
||||||
|
@ -168,6 +172,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
|
|
||||||
emit highlightedNotifsRetrieved(std::move(res), mentionsPos);
|
emit highlightedNotifsRetrieved(std::move(res), mentionsPos);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
|
connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
|
||||||
|
@ -1001,28 +1006,32 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res)
|
||||||
void
|
void
|
||||||
ChatPage::showNotificationsDialog(const mtx::responses::Notifications &res, const QPoint &widgetPos)
|
ChatPage::showNotificationsDialog(const mtx::responses::Notifications &res, const QPoint &widgetPos)
|
||||||
{
|
{
|
||||||
|
// TODO: Remove notifications from this function call.
|
||||||
|
Q_UNUSED(res);
|
||||||
|
|
||||||
auto notifDialog = user_mentions_popup_;
|
auto notifDialog = user_mentions_popup_;
|
||||||
for (const auto &item : res.notifications) {
|
// for (const auto &item : res.notifications) {
|
||||||
const auto event_id = QString::fromStdString(utils::event_id(item.event));
|
// const auto event_id = QString::fromStdString(utils::event_id(item.event));
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
const auto room_id = QString::fromStdString(item.room_id);
|
// const auto room_id = QString::fromStdString(item.room_id);
|
||||||
const auto user_id = utils::event_sender(item.event);
|
// const auto user_id = utils::event_sender(item.event);
|
||||||
const auto body = utils::event_body(item.event);
|
// const auto body = utils::event_body(item.event);
|
||||||
|
|
||||||
notifDialog->pushItem(event_id, user_id, body, room_id, current_room_);
|
// notifDialog->pushItem(event_id, user_id, body, room_id, current_room_);
|
||||||
|
|
||||||
} catch (const lmdb::error &e) {
|
// } catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("error while sending desktop notification: {}", e.what());
|
// nhlog::db()->warn("error while sending desktop notification: {}",
|
||||||
}
|
// e.what());
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
notifDialog->setGeometry(
|
notifDialog->setGeometry(
|
||||||
widgetPos.x() - (width() / 10), widgetPos.y() + 25, width() / 5, height() / 2);
|
widgetPos.x() - (width() / 10), widgetPos.y() + 25, width() / 5, height() / 2);
|
||||||
// notifDialog->move(widgetPos.x(), widgetPos.y());
|
// notifDialog->move(widgetPos.x(), widgetPos.y());
|
||||||
// notifDialog->setFixedWidth(width() / 10);
|
// notifDialog->setFixedWidth(width() / 10);
|
||||||
// notifDialog->setFixedHeight(height() / 2);
|
// notifDialog->setFixedHeight(height() / 2);
|
||||||
notifDialog->raise();
|
notifDialog->raise();
|
||||||
notifDialog->show();
|
notifDialog->showPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1292,6 +1301,7 @@ ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::Request
|
||||||
|
|
||||||
emit initializeViews(std::move(res.rooms));
|
emit initializeViews(std::move(res.rooms));
|
||||||
emit initializeRoomList(cache::client()->roomInfo());
|
emit initializeRoomList(cache::client()->roomInfo());
|
||||||
|
emit initializeMentions(cache::client()->getTimelineMentions());
|
||||||
|
|
||||||
cache::client()->calculateRoomReadStatus();
|
cache::client()->calculateRoomReadStatus();
|
||||||
emit syncTags(cache::client()->roomInfo().toStdMap());
|
emit syncTags(cache::client()->roomInfo().toStdMap());
|
||||||
|
|
|
@ -140,7 +140,7 @@ signals:
|
||||||
void initializeRoomList(QMap<QString, RoomInfo>);
|
void initializeRoomList(QMap<QString, RoomInfo>);
|
||||||
void initializeViews(const mtx::responses::Rooms &rooms);
|
void initializeViews(const mtx::responses::Rooms &rooms);
|
||||||
void initializeEmptyViews(const std::map<QString, mtx::responses::Timeline> &msgs);
|
void initializeEmptyViews(const std::map<QString, mtx::responses::Timeline> &msgs);
|
||||||
void initializeMentions(const std::map<QString, mtx::responses::Notifications> ¬ifs);
|
void initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs);
|
||||||
void syncUI(const mtx::responses::Rooms &rooms);
|
void syncUI(const mtx::responses::Rooms &rooms);
|
||||||
void syncRoomlist(const std::map<QString, RoomInfo> &updates);
|
void syncRoomlist(const std::map<QString, RoomInfo> &updates);
|
||||||
void syncTags(const std::map<QString, RoomInfo> &updates);
|
void syncTags(const std::map<QString, RoomInfo> &updates);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "Cache.h"
|
||||||
|
#include "ChatPage.h"
|
||||||
#include "UserMentions.h"
|
#include "UserMentions.h"
|
||||||
#include "timeline/TimelineItem.h"
|
#include "timeline/TimelineItem.h"
|
||||||
|
|
||||||
|
@ -9,6 +11,9 @@ using namespace popups;
|
||||||
UserMentions::UserMentions(QWidget *parent)
|
UserMentions::UserMentions(QWidget *parent)
|
||||||
: QWidget{parent}
|
: QWidget{parent}
|
||||||
{
|
{
|
||||||
|
setAttribute(Qt::WA_ShowWithoutActivating, true);
|
||||||
|
setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint);
|
||||||
|
|
||||||
tab_layout_ = new QTabWidget(this);
|
tab_layout_ = new QTabWidget(this);
|
||||||
|
|
||||||
top_layout_ = new QVBoxLayout(this);
|
top_layout_ = new QVBoxLayout(this);
|
||||||
|
@ -37,12 +42,12 @@ UserMentions::UserMentions(QWidget *parent)
|
||||||
local_scroll_layout_ = new QVBoxLayout(local_scroll_widget_);
|
local_scroll_layout_ = new QVBoxLayout(local_scroll_widget_);
|
||||||
local_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
|
local_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
|
||||||
local_scroll_layout_->setSpacing(0);
|
local_scroll_layout_->setSpacing(0);
|
||||||
local_scroll_layout_->setObjectName("localcrollarea");
|
local_scroll_layout_->setObjectName("localscrollarea");
|
||||||
|
|
||||||
all_scroll_layout_ = new QVBoxLayout(all_scroll_widget_);
|
all_scroll_layout_ = new QVBoxLayout(all_scroll_widget_);
|
||||||
all_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
|
all_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
|
||||||
all_scroll_layout_->setSpacing(0);
|
all_scroll_layout_->setSpacing(0);
|
||||||
all_scroll_layout_->setObjectName("allcrollarea");
|
all_scroll_layout_->setObjectName("allscrollarea");
|
||||||
|
|
||||||
local_scroll_area_->setWidget(local_scroll_widget_);
|
local_scroll_area_->setWidget(local_scroll_widget_);
|
||||||
local_scroll_area_->setAlignment(Qt::AlignBottom);
|
local_scroll_area_->setAlignment(Qt::AlignBottom);
|
||||||
|
@ -58,10 +63,46 @@ UserMentions::UserMentions(QWidget *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UserMentions::initializeMentions(const std::map<QString, mtx::responses::Notifications> ¬ifs)
|
UserMentions::initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs)
|
||||||
{
|
{
|
||||||
Q_UNUSED(notifs);
|
nhlog::ui()->debug("Initializing " + std::to_string(notifs.size()) + " notifications.");
|
||||||
// Very TODO:
|
for (auto widget : all_scroll_layout_->findChildren<QWidget *>()) {
|
||||||
|
delete widget;
|
||||||
|
}
|
||||||
|
for (auto widget : local_scroll_layout_->findChildren<QWidget *>()) {
|
||||||
|
delete widget;
|
||||||
|
}
|
||||||
|
for (const auto &item : notifs) {
|
||||||
|
for (const auto notif : item.notifications) {
|
||||||
|
const auto event_id = QString::fromStdString(utils::event_id(notif.event));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const auto room_id = QString::fromStdString(notif.room_id);
|
||||||
|
const auto user_id = utils::event_sender(notif.event);
|
||||||
|
const auto body = utils::event_body(notif.event);
|
||||||
|
|
||||||
|
pushItem(event_id,
|
||||||
|
user_id,
|
||||||
|
body,
|
||||||
|
room_id,
|
||||||
|
ChatPage::instance()->currentRoom());
|
||||||
|
|
||||||
|
} catch (const lmdb::error &e) {
|
||||||
|
nhlog::db()->warn("error while sending desktop notification: {}",
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserMentions::showPopup()
|
||||||
|
{
|
||||||
|
auto notifs = cache::client()->getTimelineMentions();
|
||||||
|
|
||||||
|
initializeMentions(notifs);
|
||||||
|
|
||||||
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <mtx/responses.hpp>
|
#include <mtx/responses.hpp>
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -16,15 +17,16 @@ class UserMentions : public QWidget
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
UserMentions(QWidget *parent = nullptr);
|
UserMentions(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void showPopup();
|
||||||
|
void initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs);
|
||||||
|
|
||||||
|
private:
|
||||||
void pushItem(const QString &event_id,
|
void pushItem(const QString &event_id,
|
||||||
const QString &user_id,
|
const QString &user_id,
|
||||||
const QString &body,
|
const QString &body,
|
||||||
const QString &room_id,
|
const QString &room_id,
|
||||||
const QString ¤t_room_id);
|
const QString ¤t_room_id);
|
||||||
|
|
||||||
void initializeMentions(const std::map<QString, mtx::responses::Notifications> ¬ifs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QTabWidget *tab_layout_;
|
QTabWidget *tab_layout_;
|
||||||
QVBoxLayout *top_layout_;
|
QVBoxLayout *top_layout_;
|
||||||
QVBoxLayout *local_scroll_layout_;
|
QVBoxLayout *local_scroll_layout_;
|
||||||
|
|
Loading…
Reference in a new issue