#include "syncfileitem.h"
#include "systray.h"
#include "tray/activitylistmodel.h"
-#include "tray/notificationcache.h"
#include "tray/unifiedsearchresultslistmodel.h"
#include "tray/talkreply.h"
#include "userstatusconnector.h"
connect(FolderMan::instance(), &FolderMan::folderListChanged, this, &User::hasLocalFolderChanged);
- connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
-
connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
connect(_account->account().data(), &Account::userStatusChanged, this, &User::statusChanged);
connect(_account.data(), &AccountState::desktopNotificationsAllowedChanged, this, &User::desktopNotificationsAllowedChanged);
connect(this, &User::sendReplyMessage, this, &User::slotSendReplyMessage);
}
-void User::showDesktopNotification(const QString &title, const QString &message)
+void User::showDesktopNotification(const QString &title, const QString &message, const long notificationId)
{
+ // Notification ids are uints, which are 4 bytes. Error activities don't have ids, however, so we generate one.
+ // To avoid possible collisions between the activity ids which are actually the notification ids received from
+ // the server (which are always positive) and our "fake" error activity ids, we assign a negative id to the
+ // error notification.
+ //
+ // To ensure that we can still treat an unsigned int as normal, we use a long, which is 8 bytes.
+
ConfigFile cfg;
if (!cfg.optionalServerNotifications() || !isDesktopNotificationsAllowed()) {
return;
// after one hour, clear the gui log notification store
constexpr qint64 clearGuiLogInterval = 60 * 60 * 1000;
if (_guiLogTimer.elapsed() > clearGuiLogInterval) {
- _notificationCache.clear();
+ _notifiedNotifications.clear();
}
- const NotificationCache::Notification notification { title, message };
- if (_notificationCache.contains(notification)) {
+ if (_notifiedNotifications.contains(notificationId)) {
return;
}
- _notificationCache.insert(notification);
- emit guiLog(notification.title, notification.message);
+ _notifiedNotifications.insert(notificationId);
+ Logger::instance()->postGuiLog(title, message);
// restart the gui log timer now that we show a new notification
_guiLogTimer.start();
}
continue;
}
const auto message = AccountManager::instance()->accounts().count() == 1 ? "" : activity._accName;
- showDesktopNotification(activity._subject, message);
+ showDesktopNotification(activity._subject, message, activity._id); // We assigned the notif. id to the activity id
_activityModel->addNotificationToActivityList(activity);
}
}
activity._accName = folderInstance->accountState()->account()->displayName();
activity._folder = folderAlias;
+ // Error notifications don't have ids by themselves so we will create one for it
+ activity._id = -static_cast<int>(qHash(activity._subject + activity._message));
+
// add 'other errors' to activity list
_activityModel->addErrorToActivityList(activity);
- showDesktopNotification(activity._subject, activity._message);
+ showDesktopNotification(activity._subject, activity._message, activity._id);
if (!_expiredActivitiesCheckTimer.isActive()) {
_expiredActivitiesCheckTimer.start(expiredActivitiesCheckIntervalMsecs);
qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in error " << item->_errorString;
activity._subject = item->_errorString;
+ activity._id = -static_cast<int>(qHash(activity._subject + activity._message));
if (item->_status == SyncFileItem::Status::FileIgnored) {
_activityModel->addIgnoredFileToList(activity);
} else {
// add 'protocol error' to activity list
if (item->_status == SyncFileItem::Status::FileNameInvalid) {
- showDesktopNotification(item->_file, activity._subject);
+ showDesktopNotification(item->_file, activity._subject, activity._id);
}
_activityModel->addErrorToActivityList(activity);
}
#include "accountfwd.h"
#include "accountmanager.h"
#include "folderman.h"
-#include "notificationcache.h"
#include "userstatusselectormodel.h"
#include "userstatusconnector.h"
#include <chrono>
void processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr &item);
signals:
- void guiLog(const QString &, const QString &);
void nameChanged();
void hasLocalFolderChanged();
void serverHasTalkChanged();
bool isActivityOfCurrentAccount(const Folder *folder) const;
bool isUnsolvableConflict(const SyncFileItemPtr &item) const;
- void showDesktopNotification(const QString &title, const QString &message);
+ void showDesktopNotification(const QString &title, const QString &message, const long notificationId);
private:
AccountStatePtr _account;
QHash<AccountState *, QElapsedTimer> _timeSinceLastCheck;
QElapsedTimer _guiLogTimer;
- NotificationCache _notificationCache;
+ QSet<long> _notifiedNotifications;
QMimeDatabase _mimeDb;
// number of currently running notification requests. If non zero,
+++ /dev/null
-#include <QTest>
-
-#include "tray/notificationcache.h"
-
-class TestNotificationCache : public QObject
-{
- Q_OBJECT
-
-private slots:
- void testContains_doesNotContainNotification_returnsFalse()
- {
- OCC::NotificationCache notificationCache;
-
- QVERIFY(!notificationCache.contains({ "Title", { "Message" } }));
- }
-
- void testContains_doesContainNotification_returnTrue()
- {
- OCC::NotificationCache notificationCache;
- const OCC::NotificationCache::Notification notification { "Title", "message" };
-
- notificationCache.insert(notification);
-
- QVERIFY(notificationCache.contains(notification));
- }
-
- void testClear_doesContainNotification_clearNotifications()
- {
- OCC::NotificationCache notificationCache;
- const OCC::NotificationCache::Notification notification { "Title", "message" };
-
- notificationCache.insert(notification);
- notificationCache.clear();
-
- QVERIFY(!notificationCache.contains(notification));
- }
-};
-
-QTEST_GUILESS_MAIN(TestNotificationCache)
-#include "testnotificationcache.moc"