summaryrefslogtreecommitdiff
path: root/buteo-plugins/buteo-sync-plugin-mastodon-notifications
diff options
context:
space:
mode:
Diffstat (limited to 'buteo-plugins/buteo-sync-plugin-mastodon-notifications')
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp87
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.h9
2 files changed, 93 insertions, 3 deletions
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
index 8d21782..98dbbc8 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
@@ -57,6 +57,7 @@ namespace {
const char *const NotificationIdHint = "x-nemo.sociald.notification-id";
const char *const LastFetchedNotificationIdKey = "LastFetchedNotificationId";
const int NotificationsPageLimit = 80;
+ const uint NotificationDismissedReason = 1;
//% "mentioned you"
const char *const TrIdMentionedYou = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-mentioned_you");
@@ -240,13 +241,14 @@ namespace {
return QString();
}
- bool hasActiveNotificationsForAccount(int accountId)
+ bool hasActiveNotificationsForAccount(int accountId, const Notification *ignoredNotification = 0)
{
bool hasActiveNotifications = false;
const QList<QObject *> notifications = Notification::notifications();
foreach (QObject *object, notifications) {
Notification *notification = qobject_cast<Notification *>(object);
if (notification
+ && notification != ignoredNotification
&& notification->category() == QLatin1String(NotificationCategory)
&& notification->hintValue("x-nemo.sociald.account-id").toInt() == accountId) {
hasActiveNotifications = true;
@@ -312,6 +314,7 @@ void MastodonNotificationsSyncAdaptor::purgeDataForOldAccount(int oldId, SocialN
{
closeAccountNotifications(oldId);
+ m_accessTokens.remove(oldId);
m_pendingSyncStates.remove(oldId);
m_lastMarkedReadIds.remove(oldId);
saveLastFetchedId(oldId, QString());
@@ -319,6 +322,7 @@ void MastodonNotificationsSyncAdaptor::purgeDataForOldAccount(int oldId, SocialN
void MastodonNotificationsSyncAdaptor::beginSync(int accountId, const QString &accessToken)
{
+ m_accessTokens.insert(accountId, accessToken);
m_pendingSyncStates.remove(accountId);
requestUnreadMarker(accountId, accessToken);
}
@@ -465,6 +469,7 @@ void MastodonNotificationsSyncAdaptor::finishedUnreadMarkerHandler()
PendingSyncState state;
state.accessToken = accessToken;
+ state.markerKnown = true;
state.unreadFloorId = markerId;
state.lastFetchedId = loadLastFetchedId(accountId);
if (state.lastFetchedId.isEmpty() && !markerId.isEmpty()) {
@@ -576,6 +581,9 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
if (!isError && ok) {
if (!notifications.size()) {
qCDebug(lcMastodonNotifications) << "no notifications received for account" << accountId;
+ if (state.markerKnown) {
+ closeAccountNotifications(accountId);
+ }
m_pendingSyncStates.remove(accountId);
decrementSemaphore(accountId);
return;
@@ -599,6 +607,10 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
pageMinNotificationId = notificationId;
}
+ if (state.markerKnown) {
+ state.unreadNotificationIds.insert(notificationId);
+ }
+
if (state.maxFetchedId.isEmpty()
|| compareNotificationIds(notificationId, state.maxFetchedId) > 0) {
state.maxFetchedId = notificationId;
@@ -703,6 +715,10 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
}
}
+ if (state.markerKnown) {
+ closeAccountNotifications(accountId, state.unreadNotificationIds);
+ }
+
if (!state.maxFetchedId.isEmpty()
&& (state.lastFetchedId.isEmpty()
|| compareNotificationIds(state.maxFetchedId, state.lastFetchedId) > 0)) {
@@ -715,10 +731,10 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
const QString currentMarkerId = m_lastMarkedReadIds.value(accountId);
if (!markerId.isEmpty()
&& !state.accessToken.isEmpty()
- && !hasActiveNotificationsForAccount(accountId)
+ && state.markerKnown
&& (currentMarkerId.isEmpty()
|| compareNotificationIds(markerId, currentMarkerId) > 0)) {
- requestMarkRead(accountId, state.accessToken, markerId);
+ maybeMarkAccountNotificationsRead(accountId, state.accessToken);
}
} else {
qCWarning(lcMastodonNotifications) << "unable to parse notifications data from request with account" << accountId
@@ -795,6 +811,70 @@ void MastodonNotificationsSyncAdaptor::publishSystemNotification(int accountId,
}
}
+void MastodonNotificationsSyncAdaptor::notificationClosedWithReason(uint reason)
+{
+ Notification *notification = qobject_cast<Notification *>(sender());
+ removeCachedNotification(notification);
+ if (reason == NotificationDismissedReason) {
+ markReadFromNotification(notification);
+ }
+}
+
+void MastodonNotificationsSyncAdaptor::maybeMarkAccountNotificationsRead(int accountId,
+ const QString &accessToken,
+ Notification *ignoredNotification)
+{
+ if (accountId <= 0 || accessToken.isEmpty()) {
+ return;
+ }
+
+ if (hasActiveNotificationsForAccount(accountId, ignoredNotification)) {
+ return;
+ }
+
+ const QString lastReadId = loadLastFetchedId(accountId);
+ if (lastReadId.isEmpty()) {
+ return;
+ }
+
+ const QString currentMarkerId = m_lastMarkedReadIds.value(accountId);
+ if (!currentMarkerId.isEmpty() && compareNotificationIds(lastReadId, currentMarkerId) <= 0) {
+ return;
+ }
+
+ requestMarkRead(accountId, accessToken, lastReadId);
+}
+
+void MastodonNotificationsSyncAdaptor::markReadFromNotification(Notification *notification)
+{
+ if (!notification) {
+ return;
+ }
+
+ const int accountId = notification->hintValue("x-nemo.sociald.account-id").toInt();
+ const QString accessToken = m_accessTokens.value(accountId).trimmed();
+ if (accountId <= 0 || accessToken.isEmpty()) {
+ return;
+ }
+
+ maybeMarkAccountNotificationsRead(accountId, accessToken, notification);
+}
+
+void MastodonNotificationsSyncAdaptor::removeCachedNotification(Notification *notification)
+{
+ if (!notification) {
+ return;
+ }
+
+ const int accountId = notification->hintValue("x-nemo.sociald.account-id").toInt();
+ const QString notificationId = notification->hintValue(NotificationIdHint).toString();
+ if (accountId <= 0 || notificationId.isEmpty()) {
+ return;
+ }
+
+ m_notificationObjects.remove(notificationObjectKey(accountId, notificationId));
+}
+
void MastodonNotificationsSyncAdaptor::closeAccountNotifications(int accountId,
const QSet<QString> &keepNotificationIds)
{
@@ -859,6 +939,7 @@ Notification *MastodonNotificationsSyncAdaptor::createNotification(int accountId
notification->setHintValue("x-nemo-priority", 100); // Show on lockscreen
notification->setCategory(QLatin1String(NotificationCategory));
+ connect(notification, SIGNAL(closed(uint)), this, SLOT(notificationClosedWithReason(uint)), Qt::UniqueConnection);
m_notificationObjects.insert(objectKey, notification);
return notification;
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.h b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.h
index 4c667fa..0e9106c 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.h
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.h
@@ -57,9 +57,11 @@ private:
struct PendingSyncState {
QString accessToken;
+ bool markerKnown = false;
QString unreadFloorId;
QString lastFetchedId;
QString maxFetchedId;
+ QSet<QString> unreadNotificationIds;
QHash<QString, PendingNotification> pendingNotifications;
};
@@ -80,13 +82,20 @@ private:
Notification *findNotification(int accountId, const QString &notificationId);
void closeAccountNotifications(int accountId, const QSet<QString> &keepNotificationIds = QSet<QString>());
static QString notificationObjectKey(int accountId, const QString &notificationId);
+ void maybeMarkAccountNotificationsRead(int accountId,
+ const QString &accessToken,
+ Notification *ignoredNotification = 0);
+ void markReadFromNotification(Notification *notification);
+ void removeCachedNotification(Notification *notification);
private Q_SLOTS:
void finishedUnreadMarkerHandler();
void finishedNotificationsHandler();
void finishedMarkReadHandler();
+ void notificationClosedWithReason(uint reason);
private:
+ QHash<int, QString> m_accessTokens;
QHash<int, PendingSyncState> m_pendingSyncStates;
QHash<int, QString> m_lastMarkedReadIds;
QHash<QString, Notification *> m_notificationObjects;