diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e991d554..f220c24cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,6 +369,8 @@ set(${PROJECT_NAME}_SOURCES src/model/chathistory.cpp src/model/toxclientstandards.h src/model/ibootstraplistgenerator.h + src/model/notificationgenerator.h + src/model/notificationgenerator.cpp src/net/bootstrapnodeupdater.cpp src/net/bootstrapnodeupdater.h src/net/avatarbroadcaster.cpp diff --git a/cmake/Testing.cmake b/cmake/Testing.cmake index d92674e39..40052b8db 100644 --- a/cmake/Testing.cmake +++ b/cmake/Testing.cmake @@ -48,6 +48,7 @@ auto_test(model groupmessagedispatcher) auto_test(model messageprocessor) auto_test(model sessionchatlog) auto_test(model exiftransform) +auto_test(model notificationgenerator) if (UNIX) auto_test(platform posixsignalnotifier) diff --git a/src/model/notificationdata.h b/src/model/notificationdata.h new file mode 100644 index 000000000..8e0ac30a9 --- /dev/null +++ b/src/model/notificationdata.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +struct NotificationData +{ + QString title; + QString message; + QPixmap pixmap; +}; diff --git a/src/model/notificationgenerator.cpp b/src/model/notificationgenerator.cpp new file mode 100644 index 000000000..8e0948f00 --- /dev/null +++ b/src/model/notificationgenerator.cpp @@ -0,0 +1,247 @@ +#include "notificationgenerator.h" +#include "src/chatlog/content/filetransferwidget.h" + +#include + +namespace +{ + size_t getNumMessages( + const QHash& friendNotifications, + const QHash& groupNotifications) + { + auto numMessages = std::accumulate(friendNotifications.begin(), friendNotifications.end(), 0); + numMessages = std::accumulate(groupNotifications.begin(), groupNotifications.end(), numMessages); + + return numMessages; + } + + size_t getNumChats( + const QHash& friendNotifications, + const QHash& groupNotifications) + { + return friendNotifications.size() + groupNotifications.size(); + } + + QString generateMultiChatTitle(size_t numChats, size_t numMessages) + { + // FIXME: how do I tr this + return QObject::tr("%1 messages from %2 chats") + .arg(numMessages) + .arg(numChats); + } + + template + QString generateSingleChatTitle( + const QHash numNotifications, + T contact) + { + if (numNotifications[contact] > 1) + { + return QObject::tr("%1 messages from %2") + .arg(numNotifications[contact]) + .arg(contact->getDisplayedName()); + } + else + { + return QObject::tr("%1") + .arg(contact->getDisplayedName()); + } + } + + QString generateTitle( + const QHash& friendNotifications, + const QHash& groupNotifications, + const Friend* f) + { + auto numChats = getNumChats(friendNotifications, groupNotifications); + if (numChats > 1) + { + return generateMultiChatTitle(numChats, getNumMessages(friendNotifications, groupNotifications)); + } + else + { + return generateSingleChatTitle(friendNotifications, f); + } + } + + QString generateTitle( + const QHash& friendNotifications, + const QHash& groupNotifications, + const Group* g) + { + auto numChats = getNumChats(friendNotifications, groupNotifications); + if (numChats > 1) + { + return generateMultiChatTitle(numChats, getNumMessages(friendNotifications, groupNotifications)); + } + else + { + return generateSingleChatTitle(groupNotifications, g); + } + } + + QString generateContent( + const QHash& friendNotifications, + const QHash& groupNotifications, + QString lastMessage, + const ToxPk& sender) + { + assert(friendNotifications.size() > 0 || groupNotifications.size() > 0); + + auto numChats = getNumChats(friendNotifications, groupNotifications); + if (numChats > 1) { + // Copy all names into a vector to simplify formatting logic between + // multiple lists + std::vector displayNames; + displayNames.reserve(numChats); + + for (auto it = friendNotifications.begin(); it != friendNotifications.end(); ++it) { + displayNames.push_back(it.key()->getDisplayedName()); + } + + for (auto it = groupNotifications.begin(); it != groupNotifications.end(); ++it) { + displayNames.push_back(it.key()->getDisplayedName()); + } + + assert(displayNames.size() > 0); + + // Lexiographically sort all display names to ensure consistent formatting + QCollator collator; + std::sort(displayNames.begin(), displayNames.end(), [&] (const QString& a, const QString& b) { + return collator.compare(a, b) < 1; + }); + + auto it = displayNames.begin(); + + QString ret = *it; + + while (++it != displayNames.end()) { + ret += ", " + *it; + } + + return ret; + } + else { + if (groupNotifications.size() == 1) { + return groupNotifications.begin().key()->getPeerList()[sender] + ": " + lastMessage; + } + + return lastMessage; + } + } + + QPixmap getSenderAvatar(Profile* profile, const ToxPk& sender) + { + return profile ? profile->loadAvatar(sender) : QPixmap(); + } +} // namespace + +NotificationGenerator::NotificationGenerator( + INotificationSettings const& notificationSettings, + Profile* profile) + : notificationSettings(notificationSettings) + , profile(profile) +{} + +NotificationData NotificationGenerator::friendMessageNotification(const Friend* f, const QString& message) +{ + friendNotifications[f]++; + + NotificationData ret; + + if (notificationSettings.getNotifyHide()) { + ret.title = tr("New message"); + return ret; + } + + ret.title = generateTitle(friendNotifications, groupNotifications, f); + ret.message = generateContent(friendNotifications, groupNotifications, message, f->getPublicKey()); + ret.pixmap = getSenderAvatar(profile, f->getPublicKey()); + + return ret; +} + +NotificationData NotificationGenerator::groupMessageNotification(const Group* g, const ToxPk& sender, const QString& message) +{ + groupNotifications[g]++; + + NotificationData ret; + + if (notificationSettings.getNotifyHide()){ + ret.title = tr("New group message"); + return ret; + } + + ret.title = generateTitle(friendNotifications, groupNotifications, g); + ret.message = generateContent(friendNotifications, groupNotifications, message, sender); + ret.pixmap = getSenderAvatar(profile, sender); + + return ret; +} + +NotificationData NotificationGenerator::fileTransferNotification(const Friend* f, const QString& filename, size_t fileSize) +{ + friendNotifications[f]++; + + NotificationData ret; + + if (notificationSettings.getNotifyHide()) { + ret.title = tr("Incoming file transfer"); + return ret; + } + + auto numChats = getNumChats(friendNotifications, groupNotifications); + auto numMessages = getNumMessages(friendNotifications, groupNotifications); + + if (numChats > 1 || numMessages > 1) + { + ret.title = generateTitle(friendNotifications, groupNotifications, f); + ret.message = generateContent(friendNotifications, groupNotifications, tr("Incoming file transfer"), f->getPublicKey()); + } + else + { + ret.title = f->getDisplayedName() + " - " + tr("File sent"); + ret.message = filename + " (" + FileTransferWidget::getHumanReadableSize(fileSize) + ")"; + } + + ret.pixmap = getSenderAvatar(profile, f->getPublicKey()); + + return ret; +} + +NotificationData NotificationGenerator::groupInvitationNotification(const Friend* from) +{ + NotificationData ret; + + if (notificationSettings.getNotifyHide()) { + ret.title = tr("Group invite received"); + return ret; + } + + ret.title = from->getDisplayedName() + tr(" invites you to join a group."); + ret.message = ""; + ret.pixmap = getSenderAvatar(profile, from->getPublicKey()); + + return ret; +} + +NotificationData NotificationGenerator::friendRequestNotification(const ToxPk& sender, const QString& message) +{ + NotificationData ret; + + if (notificationSettings.getNotifyHide()) { + ret.title = tr("Friend request received"); + return ret; + } + + ret.title = sender.toString() + tr(" sent you a friend request."); + ret.message = message; + + return ret; +} + +void NotificationGenerator::onNotificationActivated() +{ + friendNotifications = {}; + groupNotifications = {}; +} diff --git a/src/model/notificationgenerator.h b/src/model/notificationgenerator.h new file mode 100644 index 000000000..13000e19e --- /dev/null +++ b/src/model/notificationgenerator.h @@ -0,0 +1,38 @@ +#pragma once + + +#include "notificationdata.h" +#include "friend.h" +#include "group.h" + +#include "src/persistence/inotificationsettings.h" +#include "src/persistence/profile.h" + +#include +#include + +class NotificationGenerator : public QObject +{ +public: + NotificationGenerator( + INotificationSettings const& notificationSettings, + // Optional profile input to lookup avatars. Avatar lookup is not + // currently mockable so we allow profile to be nullptr for unit + // testing + Profile* profile); + + NotificationData friendMessageNotification(const Friend* f, const QString& message); + NotificationData groupMessageNotification(const Group* g, const ToxPk& sender, const QString& message); + NotificationData fileTransferNotification(const Friend* f, const QString& filename, size_t fileSize); + NotificationData groupInvitationNotification(const Friend* from); + NotificationData friendRequestNotification(const ToxPk& sender, const QString& message); + +public slots: + void onNotificationActivated(); + +private: + INotificationSettings const& notificationSettings; + Profile* profile; + QHash friendNotifications; + QHash groupNotifications; +}; diff --git a/src/persistence/igroupsettings.h b/src/persistence/igroupsettings.h index 1c283822b..158fc484c 100644 --- a/src/persistence/igroupsettings.h +++ b/src/persistence/igroupsettings.h @@ -27,6 +27,4 @@ public: virtual ~IGroupSettings() = default; virtual QStringList getBlackList() const = 0; virtual void setBlackList(const QStringList& blist) = 0; - virtual bool getGroupAlwaysNotify() const = 0; - virtual void setGroupAlwaysNotify(bool newValue) = 0; }; diff --git a/src/persistence/inotificationsettings.h b/src/persistence/inotificationsettings.h new file mode 100644 index 000000000..666382950 --- /dev/null +++ b/src/persistence/inotificationsettings.h @@ -0,0 +1,50 @@ +/* + Copyright © 2014-2019 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#ifndef INOTIFICATION_SETTINGS_H +#define INOTIFICATION_SETTINGS_H + +#include + +class INotificationSettings +{ +public: + virtual bool getNotify() const = 0; + virtual void setNotify(bool newValue) = 0; + + virtual bool getShowWindow() const = 0; + virtual void setShowWindow(bool newValue) = 0; + + virtual bool getDesktopNotify() const = 0; + virtual void setDesktopNotify(bool enabled) = 0; + + virtual bool getNotifySound() const = 0; + virtual void setNotifySound(bool newValue) = 0; + + virtual bool getNotifyHide() const = 0; + virtual void setNotifyHide(bool newValue) = 0; + + virtual bool getBusySound() const = 0; + virtual void setBusySound(bool newValue) = 0; + + virtual bool getGroupAlwaysNotify() const = 0; + virtual void setGroupAlwaysNotify(bool newValue) = 0; +}; + +#endif /*INOTIFICATION_SETTINGS_H*/ diff --git a/src/persistence/settings.h b/src/persistence/settings.h index 08f833304..17fdfa4fe 100644 --- a/src/persistence/settings.h +++ b/src/persistence/settings.h @@ -27,6 +27,7 @@ #include "src/persistence/paths.h" #include "src/persistence/ifriendsettings.h" #include "src/persistence/igroupsettings.h" +#include "src/persistence/inotificationsettings.h" #include "src/video/ivideosettings.h" #include @@ -50,7 +51,8 @@ class Settings : public QObject, public IFriendSettings, public IGroupSettings, public IAudioSettings, - public IVideoSettings + public IVideoSettings, + public INotificationSettings { Q_OBJECT @@ -311,23 +313,23 @@ public: bool getCheckUpdates() const; void setCheckUpdates(bool newValue); - bool getNotify() const; - void setNotify(bool newValue); + bool getNotify() const override; + void setNotify(bool newValue) override; - bool getShowWindow() const; - void setShowWindow(bool newValue); + bool getShowWindow() const override; + void setShowWindow(bool newValue) override; - bool getDesktopNotify() const; - void setDesktopNotify(bool enabled); + bool getDesktopNotify() const override; + void setDesktopNotify(bool enabled) override; - bool getNotifySound() const; - void setNotifySound(bool newValue); + bool getNotifySound() const override; + void setNotifySound(bool newValue) override; - bool getNotifyHide() const; - void setNotifyHide(bool newValue); + bool getNotifyHide() const override; + void setNotifyHide(bool newValue) override; - bool getBusySound() const; - void setBusySound(bool newValue); + bool getBusySound() const override; + void setBusySound(bool newValue) override; bool getGroupAlwaysNotify() const override; void setGroupAlwaysNotify(bool newValue) override; diff --git a/test/mock/mockcoreidhandler.h b/test/mock/mockcoreidhandler.h new file mode 100644 index 000000000..ab25d7357 --- /dev/null +++ b/test/mock/mockcoreidhandler.h @@ -0,0 +1,26 @@ +#pragma once + +#include "src/core/icoreidhandler.h" + +#include + +class MockCoreIdHandler : public ICoreIdHandler +{ +public: + ToxId getSelfId() const override + { + std::terminate(); + return ToxId(); + } + + ToxPk getSelfPublicKey() const override + { + static uint8_t id[TOX_PUBLIC_KEY_SIZE] = {0}; + return ToxPk(id); + } + + QString getUsername() const override + { + return "me"; + } +}; diff --git a/test/mock/mockgroupquery.h b/test/mock/mockgroupquery.h new file mode 100644 index 000000000..013922a2b --- /dev/null +++ b/test/mock/mockgroupquery.h @@ -0,0 +1,63 @@ +#pragma once + +#include "src/core/icoregroupquery.h" + +#include + +/** + * Mock 1 peer at group number 0 + */ +class MockGroupQuery : public ICoreGroupQuery +{ +public: + GroupId getGroupPersistentId(uint32_t groupNumber) const override + { + return GroupId(0); + } + + uint32_t getGroupNumberPeers(int groupId) const override + { + if (emptyGroup) { + return 1; + } + + return 2; + } + + QString getGroupPeerName(int groupId, int peerId) const override + { + return QString("peer") + peerId; + } + + ToxPk getGroupPeerPk(int groupId, int peerId) const override + { + uint8_t id[TOX_PUBLIC_KEY_SIZE] = {static_cast(peerId)}; + return ToxPk(id); + } + + QStringList getGroupPeerNames(int groupId) const override + { + if (emptyGroup) { + return QStringList({QString("me")}); + } + return QStringList({QString("me"), QString("other")}); + } + + bool getGroupAvEnabled(int groupId) const override + { + return false; + } + + void setAsEmptyGroup() + { + emptyGroup = true; + } + + void setAsFunctionalGroup() + { + emptyGroup = false; + } + +private: + bool emptyGroup = false; +}; diff --git a/test/model/groupmessagedispatcher_test.cpp b/test/model/groupmessagedispatcher_test.cpp index e8d0372d4..cdebc64b1 100644 --- a/test/model/groupmessagedispatcher_test.cpp +++ b/test/model/groupmessagedispatcher_test.cpp @@ -23,6 +23,9 @@ #include "src/model/message.h" #include "src/persistence/settings.h" +#include "test/mock/mockcoreidhandler.h" +#include "test/mock/mockgroupquery.h" + #include #include @@ -47,85 +50,6 @@ public: size_t numSentMessages = 0; }; -/** - * Mock 1 peer at group number 0 - */ -class MockGroupQuery : public ICoreGroupQuery -{ -public: - GroupId getGroupPersistentId(uint32_t groupNumber) const override - { - return GroupId(); - } - - uint32_t getGroupNumberPeers(int groupId) const override - { - if (emptyGroup) { - return 1; - } - - return 2; - } - - QString getGroupPeerName(int groupId, int peerId) const override - { - return QString("peer") + peerId; - } - - ToxPk getGroupPeerPk(int groupId, int peerId) const override - { - uint8_t id[TOX_PUBLIC_KEY_SIZE] = {static_cast(peerId)}; - return ToxPk(id); - } - - QStringList getGroupPeerNames(int groupId) const override - { - if (emptyGroup) { - return QStringList({QString("me")}); - } - return QStringList({QString("me"), QString("other")}); - } - - bool getGroupAvEnabled(int groupId) const override - { - return false; - } - - void setAsEmptyGroup() - { - emptyGroup = true; - } - - void setAsFunctionalGroup() - { - emptyGroup = false; - } - -private: - bool emptyGroup = false; -}; - -class MockCoreIdHandler : public ICoreIdHandler -{ -public: - ToxId getSelfId() const override - { - std::terminate(); - return ToxId(); - } - - ToxPk getSelfPublicKey() const override - { - static uint8_t id[TOX_PUBLIC_KEY_SIZE] = {0}; - return ToxPk(id); - } - - QString getUsername() const override - { - return "me"; - } -}; - class MockGroupSettings : public IGroupSettings { public: @@ -139,13 +63,6 @@ public: blacklist = blist; } - bool getGroupAlwaysNotify() const override - { - return false; - } - - void setGroupAlwaysNotify(bool newValue) override {} - private: QStringList blacklist; }; diff --git a/test/model/notificationgenerator_test.cpp b/test/model/notificationgenerator_test.cpp new file mode 100644 index 000000000..e9d77f984 --- /dev/null +++ b/test/model/notificationgenerator_test.cpp @@ -0,0 +1,375 @@ + +/* + Copyright © 2019 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#include "src/model/notificationgenerator.h" + +#include "test/mock/mockcoreidhandler.h" +#include "test/mock/mockgroupquery.h" + +#include +#include + +namespace +{ + class MockNotificationSettings : public INotificationSettings + { + virtual bool getNotify() const override { return true; } + + virtual void setNotify(bool newValue) override {} + + virtual bool getShowWindow() const override { return true; } + virtual void setShowWindow(bool newValue) override {} + + virtual bool getDesktopNotify() const override { return true; } + virtual void setDesktopNotify(bool enabled) override {} + + virtual bool getNotifySound() const override { return true; } + virtual void setNotifySound(bool newValue) override {} + + virtual bool getNotifyHide() const override { return notifyHide; } + virtual void setNotifyHide(bool newValue) override { notifyHide = newValue; }; + + virtual bool getBusySound() const override { return true; } + virtual void setBusySound(bool newValue) override {} + + virtual bool getGroupAlwaysNotify() const override { return true; } + virtual void setGroupAlwaysNotify(bool newValue) override {} + private: + bool notifyHide = false; + }; + +} // namespace + +class TestNotificationGenerator : public QObject +{ + Q_OBJECT + +private slots: + void init(); + void testSingleFriendMessage(); + void testMultipleFriendMessages(); + void testNotificationClear(); + void testGroupMessage(); + void testMultipleGroupMessages(); + void testMultipleFriendSourceMessages(); + void testMultipleGroupSourceMessages(); + void testMixedSourceMessages(); + void testFileTransfer(); + void testFileTransferAfterMessage(); + void testGroupInvitation(); + void testGroupInviteUncounted(); + void testFriendRequest(); + void testFriendRequestUncounted(); + void testSimpleFriendMessage(); + void testSimpleFileTransfer(); + void testSimpleGroupMessage(); + void testSimpleFriendRequest(); + void testSimpleGroupInvite(); + void testSimpleMessageToggle(); + +private: + std::unique_ptr notificationSettings; + std::unique_ptr notificationGenerator; + std::unique_ptr groupQuery; + std::unique_ptr coreIdHandler; +}; + +void TestNotificationGenerator::init() +{ + notificationSettings.reset(new MockNotificationSettings()); + notificationGenerator.reset(new NotificationGenerator(*notificationSettings, nullptr)); + groupQuery.reset(new MockGroupQuery()); + coreIdHandler.reset(new MockCoreIdHandler()); +} + +void TestNotificationGenerator::testSingleFriendMessage() +{ + Friend f(0, ToxPk()); + f.setName("friendName"); + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test"); + QVERIFY(notificationData.title == "friendName"); + QVERIFY(notificationData.message == "test"); +} + +void TestNotificationGenerator::testMultipleFriendMessages() +{ + Friend f(0, ToxPk()); + f.setName("friendName"); + notificationGenerator->friendMessageNotification(&f, "test"); + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test2"); + QVERIFY(notificationData.title == "2 messages from friendName"); + QVERIFY(notificationData.message == "test2"); + + notificationData = notificationGenerator->friendMessageNotification(&f, "test3"); + QVERIFY(notificationData.title == "3 messages from friendName"); + QVERIFY(notificationData.message == "test3"); +} + +void TestNotificationGenerator::testNotificationClear() +{ + Friend f(0, ToxPk()); + f.setName("friendName"); + + notificationGenerator->friendMessageNotification(&f, "test"); + + // On notification clear we shouldn't see a notification count from the friend + notificationGenerator->onNotificationActivated(); + + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test2"); + QVERIFY(notificationData.title == "friendName"); + QVERIFY(notificationData.message == "test2"); +} + +void TestNotificationGenerator::testGroupMessage() +{ + Group g(0, GroupId(0), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("groupName"); + auto sender = groupQuery->getGroupPeerPk(0, 0); + g.updateUsername(sender, "sender1"); + + auto notificationData = notificationGenerator->groupMessageNotification(&g, sender, "test"); + QVERIFY(notificationData.title == "groupName"); + QVERIFY(notificationData.message == "sender1: test"); +} + +void TestNotificationGenerator::testMultipleGroupMessages() +{ + Group g(0, GroupId(0), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("groupName"); + auto sender = groupQuery->getGroupPeerPk(0, 0); + g.updateUsername(sender, "sender1"); + + auto sender2 = groupQuery->getGroupPeerPk(0, 1); + g.updateUsername(sender2, "sender2"); + + auto notificationData = notificationGenerator->groupMessageNotification(&g, sender2, "test2"); + QVERIFY(notificationData.title == "groupName"); + QVERIFY(notificationData.message == "sender2: test2"); +} + +void TestNotificationGenerator::testMultipleFriendSourceMessages() +{ + Friend f(0, ToxPk()); + f.setName("friend1"); + + Friend f2(1, ToxPk()); + f2.setName("friend2"); + + notificationGenerator->friendMessageNotification(&f, "test1"); + auto notificationData = notificationGenerator->friendMessageNotification(&f2, "test2"); + + QVERIFY(notificationData.title == "2 messages from 2 chats"); + QVERIFY(notificationData.message == "friend1, friend2"); +} + +void TestNotificationGenerator::testMultipleGroupSourceMessages() +{ + Group g(0, GroupId(QByteArray(32, 0)), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("groupName"); + + Group g2(1, GroupId(QByteArray(32, 1)), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("groupName2"); + + auto sender = groupQuery->getGroupPeerPk(0, 0); + g.updateUsername(sender, "sender1"); + + notificationGenerator->groupMessageNotification(&g, sender, "test1"); + auto notificationData = notificationGenerator->groupMessageNotification(&g2, sender, "test1"); + + QVERIFY(notificationData.title == "2 messages from 2 chats"); + QVERIFY(notificationData.message == "groupName, groupName2"); +} + +void TestNotificationGenerator::testMixedSourceMessages() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + Group g(0, GroupId(QByteArray(32, 0)), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("group"); + + auto sender = groupQuery->getGroupPeerPk(0, 0); + g.updateUsername(sender, "sender1"); + + notificationGenerator->friendMessageNotification(&f, "test1"); + auto notificationData = notificationGenerator->groupMessageNotification(&g, sender, "test2"); + + QVERIFY(notificationData.title == "2 messages from 2 chats"); + QVERIFY(notificationData.message == "friend, group"); + + notificationData = notificationGenerator->fileTransferNotification(&f, "file", 0); + QVERIFY(notificationData.title == "3 messages from 2 chats"); + QVERIFY(notificationData.message == "friend, group"); +} + +void TestNotificationGenerator::testFileTransfer() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + auto notificationData = notificationGenerator->fileTransferNotification(&f, "file", 5 * 1024 * 1024 /* 5MB */); + + QVERIFY(notificationData.title == "friend - File sent"); + QVERIFY(notificationData.message == "file (5.00MiB)"); +} + +void TestNotificationGenerator::testFileTransferAfterMessage() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationGenerator->friendMessageNotification(&f, "test1"); + auto notificationData = notificationGenerator->fileTransferNotification(&f, "file", 5 * 1024 * 1024 /* 5MB */); + + QVERIFY(notificationData.title == "2 messages from friend"); + QVERIFY(notificationData.message == "Incoming file transfer"); +} + +void TestNotificationGenerator::testGroupInvitation() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + auto notificationData = notificationGenerator->groupInvitationNotification(&f); + + QVERIFY(notificationData.title == "friend invites you to join a group."); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testGroupInviteUncounted() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationGenerator->friendMessageNotification(&f, "test"); + notificationGenerator->groupInvitationNotification(&f); + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test2"); + + QVERIFY(notificationData.title == "2 messages from friend"); + QVERIFY(notificationData.message == "test2"); +} + +void TestNotificationGenerator::testFriendRequest() +{ + ToxPk sender(QByteArray(32, 0)); + + auto notificationData = notificationGenerator->friendRequestNotification(sender, "request"); + + QVERIFY(notificationData.title == "0000000000000000000000000000000000000000000000000000000000000000 sent you a friend request."); + QVERIFY(notificationData.message == "request"); +} + +void TestNotificationGenerator::testFriendRequestUncounted() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + ToxPk sender(QByteArray(32, 0)); + + notificationGenerator->friendMessageNotification(&f, "test"); + notificationGenerator->friendRequestNotification(sender, "request"); + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test2"); + + QVERIFY(notificationData.title == "2 messages from friend"); + QVERIFY(notificationData.message == "test2"); +} + +void TestNotificationGenerator::testSimpleFriendMessage() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationSettings->setNotifyHide(true); + + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test"); + + QVERIFY(notificationData.title == "New message"); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testSimpleFileTransfer() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationSettings->setNotifyHide(true); + + auto notificationData = notificationGenerator->fileTransferNotification(&f, "file", 0); + + QVERIFY(notificationData.title == "Incoming file transfer"); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testSimpleGroupMessage() +{ + Group g(0, GroupId(0), "groupName", false, "selfName", *groupQuery, *coreIdHandler); + g.setName("groupName"); + auto sender = groupQuery->getGroupPeerPk(0, 0); + g.updateUsername(sender, "sender1"); + + notificationSettings->setNotifyHide(true); + + auto notificationData = notificationGenerator->groupMessageNotification(&g, sender, "test"); + QVERIFY(notificationData.title == "New group message"); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testSimpleFriendRequest() +{ + ToxPk sender(QByteArray(32, 0)); + + notificationSettings->setNotifyHide(true); + + auto notificationData = notificationGenerator->friendRequestNotification(sender, "request"); + + QVERIFY(notificationData.title == "Friend request received"); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testSimpleGroupInvite() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationSettings->setNotifyHide(true); + auto notificationData = notificationGenerator->groupInvitationNotification(&f); + + QVERIFY(notificationData.title == "Group invite received"); + QVERIFY(notificationData.message == ""); +} + +void TestNotificationGenerator::testSimpleMessageToggle() +{ + Friend f(0, ToxPk()); + f.setName("friend"); + + notificationSettings->setNotifyHide(true); + + notificationGenerator->friendMessageNotification(&f, "test"); + + notificationSettings->setNotifyHide(false); + + auto notificationData = notificationGenerator->friendMessageNotification(&f, "test2"); + + QVERIFY(notificationData.title == "2 messages from friend"); + QVERIFY(notificationData.message == "test2"); +} + +QTEST_GUILESS_MAIN(TestNotificationGenerator) +#include "notificationgenerator_test.moc"