Evaluate push rules locally
This commit is contained in:
parent
a1dd02d763
commit
37009906bb
10 changed files with 180 additions and 234 deletions
204
src/ChatPage.cpp
204
src/ChatPage.cpp
|
|
@ -136,18 +136,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QObject *parent)
|
|||
Qt::QueuedConnection);
|
||||
connect(this, &ChatPage::leftRoom, this, &ChatPage::removeRoom);
|
||||
connect(this, &ChatPage::changeToRoom, this, &ChatPage::changeRoom, Qt::QueuedConnection);
|
||||
connect(this, &ChatPage::notificationsRetrieved, this, &ChatPage::sendNotifications);
|
||||
connect(this,
|
||||
&ChatPage::highlightedNotifsRetrieved,
|
||||
this,
|
||||
[](const mtx::responses::Notifications ¬if) {
|
||||
try {
|
||||
cache::saveTimelineMentions(notif);
|
||||
} catch (const lmdb::error &e) {
|
||||
nhlog::db()->error("failed to save mentions: {}", e.what());
|
||||
}
|
||||
});
|
||||
|
||||
connect(notificationsManager,
|
||||
&NotificationsManager::notificationClicked,
|
||||
this,
|
||||
|
|
@ -208,18 +196,140 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QObject *parent)
|
|||
// No need to check amounts for this section, as this function internally checks for
|
||||
// duplicates.
|
||||
if (notificationCount && userSettings_->hasNotifications())
|
||||
http::client()->notifications(
|
||||
5,
|
||||
"",
|
||||
"",
|
||||
[this](const mtx::responses::Notifications &res, mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve notifications: {}", err);
|
||||
return;
|
||||
}
|
||||
for (const auto &e : sync.account_data.events) {
|
||||
if (auto newRules =
|
||||
std::get_if<mtx::events::AccountDataEvent<mtx::pushrules::GlobalRuleset>>(&e))
|
||||
pushrules =
|
||||
std::make_unique<mtx::pushrules::PushRuleEvaluator>(newRules->content.global);
|
||||
}
|
||||
if (!pushrules) {
|
||||
auto eventInDb = cache::client()->getAccountData(mtx::events::EventType::PushRules);
|
||||
if (eventInDb) {
|
||||
if (auto newRules =
|
||||
std::get_if<mtx::events::AccountDataEvent<mtx::pushrules::GlobalRuleset>>(
|
||||
&*eventInDb))
|
||||
pushrules =
|
||||
std::make_unique<mtx::pushrules::PushRuleEvaluator>(newRules->content.global);
|
||||
}
|
||||
}
|
||||
if (pushrules) {
|
||||
const auto local_user = utils::localUser().toStdString();
|
||||
|
||||
emit notificationsRetrieved(std::move(res));
|
||||
});
|
||||
for (const auto &[room_id, room] : sync.rooms.join) {
|
||||
// clear old notifications
|
||||
for (const auto &e : room.ephemeral.events) {
|
||||
if (auto receiptsEv =
|
||||
std::get_if<mtx::events::EphemeralEvent<mtx::events::ephemeral::Receipt>>(
|
||||
&e)) {
|
||||
std::vector<QString> receipts;
|
||||
|
||||
for (const auto &[event_id, userReceipts] : receiptsEv->content.receipts) {
|
||||
if (auto r = userReceipts.find(mtx::events::ephemeral::Receipt::Read);
|
||||
r != userReceipts.end()) {
|
||||
for (const auto &[user_id, receipt] : r->second.users) {
|
||||
(void)receipt;
|
||||
|
||||
if (user_id == local_user) {
|
||||
receipts.push_back(QString::fromStdString(event_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (auto r =
|
||||
userReceipts.find(mtx::events::ephemeral::Receipt::ReadPrivate);
|
||||
r != userReceipts.end()) {
|
||||
for (const auto &[user_id, receipt] : r->second.users) {
|
||||
(void)receipt;
|
||||
|
||||
if (user_id == local_user) {
|
||||
receipts.push_back(QString::fromStdString(event_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!receipts.empty())
|
||||
notificationsManager->removeNotifications(
|
||||
QString::fromStdString(room_id), receipts);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate new notifications
|
||||
if (!room.timeline.events.empty() &&
|
||||
(room.unread_notifications.notification_count ||
|
||||
room.unread_notifications.highlight_count)) {
|
||||
auto roomModel =
|
||||
view_manager_->rooms()->getRoomById(QString::fromStdString(room_id));
|
||||
|
||||
if (!roomModel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto currentReadMarker =
|
||||
cache::getEventIndex(room_id, cache::client()->getFullyReadEventId(room_id));
|
||||
|
||||
auto ctx = roomModel->pushrulesRoomContext();
|
||||
for (const auto &event : room.timeline.events) {
|
||||
mtx::events::collections::TimelineEvent te{event};
|
||||
std::visit([room_id = room_id](auto &event_) { event_.room_id = room_id; },
|
||||
te.data);
|
||||
|
||||
if (auto encryptedEvent =
|
||||
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
|
||||
&event)) {
|
||||
MegolmSessionIndex index(room_id, encryptedEvent->content);
|
||||
|
||||
auto result = olm::decryptEvent(index, *encryptedEvent);
|
||||
if (result.event)
|
||||
te.data = result.event.value();
|
||||
}
|
||||
|
||||
auto actions = pushrules->evaluate(te, ctx);
|
||||
if (std::find(actions.begin(),
|
||||
actions.end(),
|
||||
mtx::pushrules::actions::Action{
|
||||
mtx::pushrules::actions::notify{}}) != actions.end()) {
|
||||
auto event_id = mtx::accessors::event_id(event);
|
||||
|
||||
// skip already read events
|
||||
if (currentReadMarker &&
|
||||
currentReadMarker > cache::getEventIndex(room_id, event_id))
|
||||
continue;
|
||||
|
||||
if (!cache::isNotificationSent(event_id)) {
|
||||
// We should only send one notification per event.
|
||||
cache::markSentNotification(event_id);
|
||||
|
||||
// Don't send a notification when the current room is opened.
|
||||
if (isRoomActive(roomModel->roomId()))
|
||||
continue;
|
||||
|
||||
if (userSettings_->hasDesktopNotifications()) {
|
||||
auto info = cache::singleRoomInfo(room_id);
|
||||
|
||||
AvatarProvider::resolve(
|
||||
roomModel->roomAvatarUrl(),
|
||||
96,
|
||||
this,
|
||||
[this, te, room_id = room_id, actions](QPixmap image) {
|
||||
notificationsManager->postNotification(
|
||||
mtx::responses::Notification{
|
||||
.actions = actions,
|
||||
.event = te.data,
|
||||
.read = false,
|
||||
.profile_tag = "",
|
||||
.room_id = room_id,
|
||||
.ts = 0,
|
||||
},
|
||||
image.toImage());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(
|
||||
|
|
@ -394,12 +504,6 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
|||
&Cache::newReadReceipts,
|
||||
view_manager_,
|
||||
&TimelineViewManager::updateReadReceipts);
|
||||
|
||||
connect(cache::client(),
|
||||
&Cache::removeNotification,
|
||||
notificationsManager,
|
||||
&NotificationsManager::removeNotification);
|
||||
|
||||
} catch (const lmdb::error &e) {
|
||||
nhlog::db()->critical("failure during boot: {}", e.what());
|
||||
emit dropToLoginPageCb(tr("Failed to open database, logging out!"));
|
||||
|
|
@ -415,7 +519,6 @@ ChatPage::loadStateFromCache()
|
|||
olm::client()->load(cache::restoreOlmAccount(), cache::client()->pickleSecret());
|
||||
|
||||
emit initializeEmptyViews();
|
||||
emit initializeMentions(cache::getTimelineMentions());
|
||||
|
||||
cache::calculateRoomReadStatus();
|
||||
|
||||
|
|
@ -464,46 +567,6 @@ ChatPage::removeRoom(const QString &room_id)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChatPage::sendNotifications(const mtx::responses::Notifications &res)
|
||||
{
|
||||
for (const auto &item : res.notifications) {
|
||||
const auto event_id = mtx::accessors::event_id(item.event);
|
||||
|
||||
try {
|
||||
if (item.read) {
|
||||
cache::removeReadNotification(event_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cache::isNotificationSent(event_id)) {
|
||||
const auto room_id = QString::fromStdString(item.room_id);
|
||||
|
||||
// We should only send one notification per event.
|
||||
cache::markSentNotification(event_id);
|
||||
|
||||
// Don't send a notification when the current room is opened.
|
||||
if (isRoomActive(room_id))
|
||||
continue;
|
||||
|
||||
if (userSettings_->hasDesktopNotifications()) {
|
||||
auto info = cache::singleRoomInfo(item.room_id);
|
||||
|
||||
AvatarProvider::resolve(QString::fromStdString(info.avatar_url),
|
||||
96,
|
||||
this,
|
||||
[this, item](QPixmap image) {
|
||||
notificationsManager->postNotification(
|
||||
item, image.toImage());
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (const lmdb::error &e) {
|
||||
nhlog::db()->warn("error while sending notification: {}", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChatPage::tryInitialSync()
|
||||
{
|
||||
|
|
@ -596,7 +659,6 @@ ChatPage::startInitialSync()
|
|||
olm::handle_to_device_messages(res.to_device.events);
|
||||
|
||||
emit initializeViews(std::move(res));
|
||||
emit initializeMentions(cache::getTimelineMentions());
|
||||
|
||||
cache::calculateRoomReadStatus();
|
||||
} catch (const lmdb::error &e) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue