summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-04-09 20:52:50 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-04-11 01:09:47 +0200
commit2022775dd052b6b1a1a82c1f418e892e40dd4fc8 (patch)
treeea134a0cda5e0a8b7fa24476b311118b4ed682b4
parent537cc966ccccd7ff645432e7976db9418556aee5 (diff)
Clear notifications when event is read
-rw-r--r--src/Cache.cpp10
-rw-r--r--src/Cache_p.h1
-rw-r--r--src/ChatPage.cpp5
-rw-r--r--src/notifications/Manager.h30
-rw-r--r--src/notifications/ManagerLinux.cpp42
-rw-r--r--src/notifications/ManagerMac.mm5
-rw-r--r--src/notifications/ManagerWin.cpp5
7 files changed, 95 insertions, 3 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index fb2ded7d..bdca76f2 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -829,6 +829,7 @@ Cache::filterReadEvents(const QString &room_id,
void
Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts)
{
+ auto user_id = this->localUserId_.toStdString();
for (const auto &receipt : receipts) {
const auto event_id = receipt.first;
auto event_receipts = receipt.second;
@@ -857,8 +858,13 @@ Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Recei
}
// Append the new ones.
- for (const auto &event_receipt : event_receipts)
- saved_receipts.emplace(event_receipt.first, event_receipt.second);
+ for (const auto &[read_by, timestamp] : event_receipts) {
+ if (read_by == user_id) {
+ emit removeNotification(QString::fromStdString(room_id),
+ QString::fromStdString(event_id));
+ }
+ saved_receipts.emplace(read_by, timestamp);
+ }
// Save back the merged (or only the new) receipts.
nlohmann::json json_updated_value = saved_receipts;
diff --git a/src/Cache_p.h b/src/Cache_p.h
index 14ceafe8..6eae45a9 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -229,6 +229,7 @@ public:
signals:
void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
void roomReadStatus(const std::map<QString, bool> &status);
+ void removeNotification(const QString &room_id, const QString &event_id);
private:
//! Save an invited room.
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 5312ea43..d7d11a12 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -645,6 +645,11 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
connect(
cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus);
+ connect(cache::client(),
+ &Cache::removeNotification,
+ &notificationsManager,
+ &NotificationsManager::removeNotification);
+
const bool isInitialized = cache::isInitialized();
const bool isValid = cache::isFormatValid();
diff --git a/src/notifications/Manager.h b/src/notifications/Manager.h
index 56541ece..6cbecbc6 100644
--- a/src/notifications/Manager.h
+++ b/src/notifications/Manager.h
@@ -1,5 +1,6 @@
#pragma once
+#include <QHash>
#include <QImage>
#include <QObject>
#include <QString>
@@ -15,6 +16,27 @@ struct roomEventId
QString eventId;
};
+inline bool
+operator<(const roomEventId &a, const roomEventId &b)
+{
+ if (a.roomId == b.roomId)
+ return a.eventId < b.eventId;
+ else
+ return a.roomId < b.roomId;
+}
+
+inline bool
+operator==(const roomEventId &a, const roomEventId &b)
+{
+ return a.roomId == b.roomId && a.eventId == b.eventId;
+}
+
+inline uint
+qHash(const roomEventId &v, uint seed)
+{
+ return qHash(v.roomId, seed) ^ qHash(v.eventId, seed);
+}
+
class NotificationsManager : public QObject
{
Q_OBJECT
@@ -31,13 +53,21 @@ public:
signals:
void notificationClicked(const QString roomId, const QString eventId);
+public slots:
+ void removeNotification(const QString &roomId, const QString &eventId);
+
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
+public:
+ void closeNotifications(QString roomId);
+
private:
QDBusInterface dbus;
uint showNotification(const QString summary, const QString text, const QImage image);
+ void closeNotification(uint id);
// notification ID to (room ID, event ID)
QMap<uint, roomEventId> notificationIds;
+ QHash<roomEventId, uint> eventToNotificationId;
#endif
// these slots are platform specific (D-Bus only)
diff --git a/src/notifications/ManagerLinux.cpp b/src/notifications/ManagerLinux.cpp
index 1914f61c..33fcb41d 100644
--- a/src/notifications/ManagerLinux.cpp
+++ b/src/notifications/ManagerLinux.cpp
@@ -40,6 +40,7 @@ NotificationsManager::postNotification(const QString &roomid,
{
uint id = showNotification(roomname, sender + ": " + text, icon);
notificationIds[id] = roomEventId{roomid, eventid};
+ eventToNotificationId[roomEventId{roomid, eventid}] = id;
}
/**
* This function is based on code from
@@ -54,6 +55,7 @@ NotificationsManager::showNotification(const QString summary,
{
QVariantMap hints;
hints["image-data"] = image;
+ hints["sound-name"] = "message-new-instant";
QList<QVariant> argumentList;
argumentList << "nheko"; // app_name
argumentList << (uint)0; // replace_id
@@ -79,6 +81,44 @@ NotificationsManager::showNotification(const QString summary,
}
void
+NotificationsManager::closeNotification(uint id)
+{
+ QList<QVariant> argumentList;
+ argumentList << (uint)id; // replace_id
+
+ static QDBusInterface closeCall("org.freedesktop.Notifications",
+ "/org/freedesktop/Notifications",
+ "org.freedesktop.Notifications");
+ QDBusMessage reply =
+ closeCall.callWithArgumentList(QDBus::AutoDetect, "CloseNotification", argumentList);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qDebug() << "D-Bus Error:" << reply.errorMessage();
+ }
+}
+
+void
+NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
+{
+ roomEventId reId = {roomId, eventId};
+ if (eventToNotificationId.contains(reId)) {
+ for (auto elem = notificationIds.begin(); elem != notificationIds.end(); ++elem) {
+ if (elem.value().roomId != roomId)
+ continue;
+
+ // close all notifications matching the eventId or having a lower
+ // notificationId
+ // This relies on the notificationId not wrapping around. This allows for
+ // approximately 2,147,483,647 notifications, so it is a bit unlikely.
+ // Otherwise we would need to store a 64bit counter instead.
+ closeNotification(elem.key());
+
+ if (elem.value() == reId)
+ break;
+ }
+ }
+}
+
+void
NotificationsManager::actionInvoked(uint id, QString action)
{
if (action == "default" && notificationIds.contains(id)) {
@@ -91,7 +131,7 @@ void
NotificationsManager::notificationClosed(uint id, uint reason)
{
Q_UNUSED(reason);
- notificationIds.remove(id);
+ eventToNotificationId.remove(notificationIds.take(id));
}
/**
diff --git a/src/notifications/ManagerMac.mm b/src/notifications/ManagerMac.mm
index 66ef713f..e46b0b82 100644
--- a/src/notifications/ManagerMac.mm
+++ b/src/notifications/ManagerMac.mm
@@ -46,3 +46,8 @@ void
NotificationsManager::notificationClosed(uint, uint)
{
}
+
+void
+NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
+{}
+
diff --git a/src/notifications/ManagerWin.cpp b/src/notifications/ManagerWin.cpp
index 9cc4da9b..b00bac2e 100644
--- a/src/notifications/ManagerWin.cpp
+++ b/src/notifications/ManagerWin.cpp
@@ -63,3 +63,8 @@ NotificationsManager::postNotification(const QString &room_id,
void NotificationsManager::actionInvoked(uint, QString) {}
void NotificationsManager::notificationClosed(uint, uint) {}
+
+void
+NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
+{}
+