Clear notifications when event is read

master
Nicolas Werner 5 years ago
parent 537cc966cc
commit 2022775dd0
  1. 10
      src/Cache.cpp
  2. 1
      src/Cache_p.h
  3. 5
      src/ChatPage.cpp
  4. 30
      src/notifications/Manager.h
  5. 42
      src/notifications/ManagerLinux.cpp
  6. 5
      src/notifications/ManagerMac.mm
  7. 5
      src/notifications/ManagerWin.cpp

@ -829,6 +829,7 @@ Cache::filterReadEvents(const QString &room_id,
void void
Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts) Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts)
{ {
auto user_id = this->localUserId_.toStdString();
for (const auto &receipt : receipts) { for (const auto &receipt : receipts) {
const auto event_id = receipt.first; const auto event_id = receipt.first;
auto event_receipts = receipt.second; 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. // Append the new ones.
for (const auto &event_receipt : event_receipts) for (const auto &[read_by, timestamp] : event_receipts) {
saved_receipts.emplace(event_receipt.first, event_receipt.second); 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. // Save back the merged (or only the new) receipts.
nlohmann::json json_updated_value = saved_receipts; nlohmann::json json_updated_value = saved_receipts;

@ -229,6 +229,7 @@ public:
signals: signals:
void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids); void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
void roomReadStatus(const std::map<QString, bool> &status); void roomReadStatus(const std::map<QString, bool> &status);
void removeNotification(const QString &room_id, const QString &event_id);
private: private:
//! Save an invited room. //! Save an invited room.

@ -645,6 +645,11 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
connect( connect(
cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus); cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus);
connect(cache::client(),
&Cache::removeNotification,
&notificationsManager,
&NotificationsManager::removeNotification);
const bool isInitialized = cache::isInitialized(); const bool isInitialized = cache::isInitialized();
const bool isValid = cache::isFormatValid(); const bool isValid = cache::isFormatValid();

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QHash>
#include <QImage> #include <QImage>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@ -15,6 +16,27 @@ struct roomEventId
QString eventId; 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 class NotificationsManager : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -31,13 +53,21 @@ public:
signals: signals:
void notificationClicked(const QString roomId, const QString eventId); 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) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
public:
void closeNotifications(QString roomId);
private: private:
QDBusInterface dbus; QDBusInterface dbus;
uint showNotification(const QString summary, const QString text, const QImage image); uint showNotification(const QString summary, const QString text, const QImage image);
void closeNotification(uint id);
// notification ID to (room ID, event ID) // notification ID to (room ID, event ID)
QMap<uint, roomEventId> notificationIds; QMap<uint, roomEventId> notificationIds;
QHash<roomEventId, uint> eventToNotificationId;
#endif #endif
// these slots are platform specific (D-Bus only) // these slots are platform specific (D-Bus only)

@ -40,6 +40,7 @@ NotificationsManager::postNotification(const QString &roomid,
{ {
uint id = showNotification(roomname, sender + ": " + text, icon); uint id = showNotification(roomname, sender + ": " + text, icon);
notificationIds[id] = roomEventId{roomid, eventid}; notificationIds[id] = roomEventId{roomid, eventid};
eventToNotificationId[roomEventId{roomid, eventid}] = id;
} }
/** /**
* This function is based on code from * This function is based on code from
@ -54,6 +55,7 @@ NotificationsManager::showNotification(const QString summary,
{ {
QVariantMap hints; QVariantMap hints;
hints["image-data"] = image; hints["image-data"] = image;
hints["sound-name"] = "message-new-instant";
QList<QVariant> argumentList; QList<QVariant> argumentList;
argumentList << "nheko"; // app_name argumentList << "nheko"; // app_name
argumentList << (uint)0; // replace_id argumentList << (uint)0; // replace_id
@ -78,6 +80,44 @@ NotificationsManager::showNotification(const QString summary,
return true; return true;
} }
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 void
NotificationsManager::actionInvoked(uint id, QString action) NotificationsManager::actionInvoked(uint id, QString action)
{ {
@ -91,7 +131,7 @@ void
NotificationsManager::notificationClosed(uint id, uint reason) NotificationsManager::notificationClosed(uint id, uint reason)
{ {
Q_UNUSED(reason); Q_UNUSED(reason);
notificationIds.remove(id); eventToNotificationId.remove(notificationIds.take(id));
} }
/** /**

@ -46,3 +46,8 @@ void
NotificationsManager::notificationClosed(uint, uint) NotificationsManager::notificationClosed(uint, uint)
{ {
} }
void
NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
{}

@ -63,3 +63,8 @@ NotificationsManager::postNotification(const QString &room_id,
void NotificationsManager::actionInvoked(uint, QString) {} void NotificationsManager::actionInvoked(uint, QString) {}
void NotificationsManager::notificationClosed(uint, uint) {} void NotificationsManager::notificationClosed(uint, uint) {}
void
NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
{}

Loading…
Cancel
Save