Merge pull request #184 from monich/notifications
Show notification popups except for the current chat
This commit is contained in:
commit
b7b9715969
8 changed files with 70 additions and 68 deletions
|
@ -14,7 +14,7 @@ TARGET = harbour-fernschreiber
|
||||||
|
|
||||||
CONFIG += sailfishapp sailfishapp_i18n
|
CONFIG += sailfishapp sailfishapp_i18n
|
||||||
|
|
||||||
PKGCONFIG += nemonotifications-qt5 ngf-qt5 zlib
|
PKGCONFIG += nemonotifications-qt5 zlib
|
||||||
|
|
||||||
QT += core dbus sql
|
QT += core dbus sql
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ Page {
|
||||||
property bool isInitialized: false;
|
property bool isInitialized: false;
|
||||||
readonly property int myUserId: tdLibWrapper.getUserInformation().id;
|
readonly property int myUserId: tdLibWrapper.getUserInformation().id;
|
||||||
property var chatInformation;
|
property var chatInformation;
|
||||||
|
property alias chatPicture: chatPictureThumbnail.photoData
|
||||||
property bool isPrivateChat: false;
|
property bool isPrivateChat: false;
|
||||||
property bool isBasicGroup: false;
|
property bool isBasicGroup: false;
|
||||||
property bool isSuperGroup: false;
|
property bool isSuperGroup: false;
|
||||||
|
@ -353,6 +354,9 @@ Page {
|
||||||
chatPage.isInitialized = true;
|
chatPage.isInitialized = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PageStatus.Inactive:
|
||||||
|
chatModel.clear();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,10 @@ Page {
|
||||||
ownUserId: overviewPage.ownUserId
|
ownUserId: overviewPage.ownUserId
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : display });
|
pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), {
|
||||||
|
chatInformation : display,
|
||||||
|
chatPicture: photo_small
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|
|
@ -85,6 +85,23 @@ bool ChatModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatModel::clear()
|
||||||
|
{
|
||||||
|
LOG("Clearing chat model");
|
||||||
|
chatId = 0;
|
||||||
|
inReload = false;
|
||||||
|
inIncrementalUpdate = false;
|
||||||
|
if (!messages.isEmpty()) {
|
||||||
|
beginResetModel();
|
||||||
|
messages.clear();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
if (!chatInformation.isEmpty()) {
|
||||||
|
chatInformation.clear();
|
||||||
|
emit smallPhotoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ChatModel::initialize(const QVariantMap &chatInformation)
|
void ChatModel::initialize(const QVariantMap &chatInformation)
|
||||||
{
|
{
|
||||||
LOG("Initializing chat model...");
|
LOG("Initializing chat model...");
|
||||||
|
@ -157,6 +174,11 @@ QVariantMap ChatModel::smallPhoto() const
|
||||||
return chatInformation.value(PHOTO).toMap().value(SMALL).toMap();
|
return chatInformation.value(PHOTO).toMap().value(SMALL).toMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qlonglong ChatModel::getChatId() const
|
||||||
|
{
|
||||||
|
return chatId;
|
||||||
|
}
|
||||||
|
|
||||||
static bool compareMessages(const QVariant &message1, const QVariant &message2)
|
static bool compareMessages(const QVariant &message1, const QVariant &message2)
|
||||||
{
|
{
|
||||||
const QVariantMap messageMap1 = message1.toMap();
|
const QVariantMap messageMap1 = message1.toMap();
|
||||||
|
|
|
@ -36,14 +36,16 @@ public:
|
||||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||||
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
|
||||||
|
Q_INVOKABLE void clear();
|
||||||
Q_INVOKABLE void initialize(const QVariantMap &chatInformation);
|
Q_INVOKABLE void initialize(const QVariantMap &chatInformation);
|
||||||
Q_INVOKABLE void triggerLoadMoreHistory();
|
Q_INVOKABLE void triggerLoadMoreHistory();
|
||||||
Q_INVOKABLE void triggerLoadMoreFuture();
|
Q_INVOKABLE void triggerLoadMoreFuture();
|
||||||
Q_INVOKABLE QVariantMap getChatInformation();
|
Q_INVOKABLE QVariantMap getChatInformation();
|
||||||
Q_INVOKABLE QVariantMap getMessage(int index);
|
Q_INVOKABLE QVariantMap getMessage(int index);
|
||||||
Q_INVOKABLE int getLastReadMessageIndex();
|
Q_INVOKABLE int getLastReadMessageIndex();
|
||||||
|
|
||||||
QVariantMap smallPhoto() const;
|
QVariantMap smallPhoto() const;
|
||||||
|
qlonglong getChatId() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void messagesReceived(int modelIndex, int lastReadSentIndex, int totalCount);
|
void messagesReceived(int modelIndex, int lastReadSentIndex, int totalCount);
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main(int argc, char *argv[])
|
||||||
ChatModel chatModel(tdLibWrapper);
|
ChatModel chatModel(tdLibWrapper);
|
||||||
context->setContextProperty("chatModel", &chatModel);
|
context->setContextProperty("chatModel", &chatModel);
|
||||||
|
|
||||||
NotificationManager notificationManager(tdLibWrapper, appSettings);
|
NotificationManager notificationManager(tdLibWrapper, appSettings, &chatModel);
|
||||||
context->setContextProperty("notificationManager", ¬ificationManager);
|
context->setContextProperty("notificationManager", ¬ificationManager);
|
||||||
|
|
||||||
ProcessLauncher processLauncher;
|
ProcessLauncher processLauncher;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "notificationmanager.h"
|
#include "notificationmanager.h"
|
||||||
#include "fernschreiberutils.h"
|
#include "fernschreiberutils.h"
|
||||||
|
#include "chatmodel.h"
|
||||||
#include <sailfishapp.h>
|
#include <sailfishapp.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QListIterator>
|
#include <QListIterator>
|
||||||
|
@ -50,15 +51,17 @@ namespace {
|
||||||
const QString CHAT_TYPE_BASIC_GROUP("chatTypeBasicGroup");
|
const QString CHAT_TYPE_BASIC_GROUP("chatTypeBasicGroup");
|
||||||
const QString CHAT_TYPE_SUPERGROUP("chatTypeSupergroup");
|
const QString CHAT_TYPE_SUPERGROUP("chatTypeSupergroup");
|
||||||
|
|
||||||
const QString NOTIFICATION_CATEGORY("x-nemo.messaging.im");
|
|
||||||
const QString NGF_EVENT("chat");
|
|
||||||
|
|
||||||
const QString APP_NAME("Fernschreiber");
|
const QString APP_NAME("Fernschreiber");
|
||||||
|
|
||||||
// Notification hints
|
// Notification hints
|
||||||
const QString HINT_GROUP_ID("x-fernschreiber.group_id"); // int
|
const QString HINT_GROUP_ID("x-fernschreiber.group_id"); // int
|
||||||
const QString HINT_CHAT_ID("x-fernschreiber.chat_id"); // qlonglong
|
const QString HINT_CHAT_ID("x-fernschreiber.chat_id"); // qlonglong
|
||||||
const QString HINT_TOTAL_COUNT("x-fernschreiber.total_count"); // int
|
const QString HINT_TOTAL_COUNT("x-fernschreiber.total_count"); // int
|
||||||
|
|
||||||
|
const QString HINT_VIBRA("x-nemo-vibrate"); // bool
|
||||||
|
const QString HINT_DISPLAY_ON("x-nemo-display-on"); // bool
|
||||||
|
const QString HINT_VISIBILITY("x-nemo-visibility"); // QString
|
||||||
|
const QString VISIBILITY_PUBLIC("public");
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationManager::ChatInfo
|
class NotificationManager::ChatInfo
|
||||||
|
@ -116,30 +119,21 @@ NotificationManager::NotificationGroup::~NotificationGroup()
|
||||||
delete nemoNotification;
|
delete nemoNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationManager::NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings) :
|
NotificationManager::NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings, ChatModel *chatModel) :
|
||||||
mceInterface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request", QDBusConnection::systemBus()),
|
mceInterface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request", QDBusConnection::systemBus()),
|
||||||
appIconFile(SailfishApp::pathTo("images/fernschreiber-notification.png").toLocalFile())
|
appIconFile(SailfishApp::pathTo("images/fernschreiber-notification.png").toLocalFile())
|
||||||
{
|
{
|
||||||
LOG("Initializing...");
|
LOG("Initializing...");
|
||||||
this->tdLibWrapper = tdLibWrapper;
|
this->tdLibWrapper = tdLibWrapper;
|
||||||
this->appSettings = appSettings;
|
this->appSettings = appSettings;
|
||||||
this->ngfClient = new Ngf::Client(this);
|
this->appSettings = appSettings;
|
||||||
|
this->chatModel = chatModel;
|
||||||
|
|
||||||
connect(this->tdLibWrapper, SIGNAL(activeNotificationsUpdated(QVariantList)), this, SLOT(handleUpdateActiveNotifications(QVariantList)));
|
connect(this->tdLibWrapper, SIGNAL(activeNotificationsUpdated(QVariantList)), this, SLOT(handleUpdateActiveNotifications(QVariantList)));
|
||||||
connect(this->tdLibWrapper, SIGNAL(notificationGroupUpdated(QVariantMap)), this, SLOT(handleUpdateNotificationGroup(QVariantMap)));
|
connect(this->tdLibWrapper, SIGNAL(notificationGroupUpdated(QVariantMap)), this, SLOT(handleUpdateNotificationGroup(QVariantMap)));
|
||||||
connect(this->tdLibWrapper, SIGNAL(notificationUpdated(QVariantMap)), this, SLOT(handleUpdateNotification(QVariantMap)));
|
connect(this->tdLibWrapper, SIGNAL(notificationUpdated(QVariantMap)), this, SLOT(handleUpdateNotification(QVariantMap)));
|
||||||
connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap)));
|
connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap)));
|
||||||
connect(this->tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString)));
|
connect(this->tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString)));
|
||||||
connect(this->ngfClient, SIGNAL(connectionStatus(bool)), this, SLOT(handleNgfConnectionStatus(bool)));
|
|
||||||
connect(this->ngfClient, SIGNAL(eventCompleted(quint32)), this, SLOT(handleNgfEventCompleted(quint32)));
|
|
||||||
connect(this->ngfClient, SIGNAL(eventFailed(quint32)), this, SLOT(handleNgfEventFailed(quint32)));
|
|
||||||
connect(this->ngfClient, SIGNAL(eventPlaying(quint32)), this, SLOT(handleNgfEventPlaying(quint32)));
|
|
||||||
|
|
||||||
if (this->ngfClient->connect()) {
|
|
||||||
LOG("NGF Client successfully initialized...");
|
|
||||||
} else {
|
|
||||||
LOG("Failed to initialize NGF Client...");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->controlLedNotification(false);
|
this->controlLedNotification(false);
|
||||||
|
|
||||||
|
@ -236,6 +230,12 @@ void NotificationManager::updateNotificationGroup(int groupId, qlonglong chatId,
|
||||||
notificationGroup->notificationOrder.removeOne(removedId);
|
notificationGroup->notificationOrder.removeOne(removedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure that if there's no notifications, order is empty too.
|
||||||
|
// That's usually already the case but double-check won't wort. It's cheap.
|
||||||
|
if (notificationGroup->activeNotifications.isEmpty()) {
|
||||||
|
notificationGroup->notificationOrder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Decide if we need a bzzz
|
// Decide if we need a bzzz
|
||||||
switch (feedback) {
|
switch (feedback) {
|
||||||
case AppSettings::NotificationFeedbackNone:
|
case AppSettings::NotificationFeedbackNone:
|
||||||
|
@ -251,6 +251,7 @@ void NotificationManager::updateNotificationGroup(int groupId, qlonglong chatId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish new or update the existing notification
|
// Publish new or update the existing notification
|
||||||
|
LOG("Feedback" << needFeedback);
|
||||||
publishNotification(notificationGroup, needFeedback);
|
publishNotification(notificationGroup, needFeedback);
|
||||||
} else if (notificationGroup) {
|
} else if (notificationGroup) {
|
||||||
// No active notifications left in this group
|
// No active notifications left in this group
|
||||||
|
@ -307,31 +308,6 @@ void NotificationManager::handleChatTitleUpdated(const QString &chatId, const QS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationManager::handleNgfConnectionStatus(bool connected)
|
|
||||||
{
|
|
||||||
LOG("NGF Daemon connection status changed" << connected);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::handleNgfEventFailed(quint32 eventId)
|
|
||||||
{
|
|
||||||
LOG("NGF event failed, id:" << eventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::handleNgfEventCompleted(quint32 eventId)
|
|
||||||
{
|
|
||||||
LOG("NGF event completed, id:" << eventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::handleNgfEventPlaying(quint32 eventId)
|
|
||||||
{
|
|
||||||
LOG("NGF event playing, id:" << eventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::handleNgfEventPaused(quint32 eventId)
|
|
||||||
{
|
|
||||||
LOG("NGF event paused, id:" << eventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::publishNotification(const NotificationGroup *notificationGroup, bool needFeedback)
|
void NotificationManager::publishNotification(const NotificationGroup *notificationGroup, bool needFeedback)
|
||||||
{
|
{
|
||||||
QVariantMap messageMap;
|
QVariantMap messageMap;
|
||||||
|
@ -374,25 +350,24 @@ void NotificationManager::publishNotification(const NotificationGroup *notificat
|
||||||
notificationBody = tr("%Ln unread messages", "", notificationGroup->totalCount);
|
notificationBody = tr("%Ln unread messages", "", notificationGroup->totalCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString summary(chatInformation ? chatInformation->title : QString());
|
||||||
nemoNotification->setBody(notificationBody);
|
nemoNotification->setBody(notificationBody);
|
||||||
nemoNotification->setSummary(chatInformation ? chatInformation->title : QString());
|
nemoNotification->setSummary(summary);
|
||||||
if (needFeedback) {
|
nemoNotification->setPreviewBody(notificationBody);
|
||||||
nemoNotification->setCategory(NOTIFICATION_CATEGORY);
|
nemoNotification->setPreviewSummary(summary);
|
||||||
|
nemoNotification->setHintValue(HINT_VIBRA, needFeedback);
|
||||||
|
|
||||||
// Setting preview body & summary to a non-empty string causes a notification popup,
|
// Don't show popup for the currently open chat
|
||||||
// no matter if we are in the current chat, in the app or not. That might be annoying
|
if (!needFeedback || (chatModel->getChatId() == notificationGroup->chatId &&
|
||||||
// In the future, we can show this popup depending if the app/chat is open or not
|
qGuiApp->applicationState() == Qt::ApplicationActive)) {
|
||||||
//
|
nemoNotification->setHintValue(HINT_DISPLAY_ON, false);
|
||||||
// nemoNotification->setPreviewBody(nemoNotification->body());
|
nemoNotification->setHintValue(HINT_VISIBILITY, QVariant());
|
||||||
// nemoNotification->setPreviewSummary(nemoNotification->summary());
|
nemoNotification->setUrgency(Notification::Low);
|
||||||
|
|
||||||
nemoNotification->setPreviewBody(QString());
|
|
||||||
nemoNotification->setPreviewSummary(QString());
|
|
||||||
ngfClient->play(NGF_EVENT);
|
|
||||||
} else {
|
} else {
|
||||||
nemoNotification->setCategory(QString());
|
// The "display on" option will be configurable
|
||||||
nemoNotification->setPreviewBody(QString());
|
nemoNotification->setHintValue(HINT_DISPLAY_ON, true);
|
||||||
nemoNotification->setPreviewSummary(QString());
|
nemoNotification->setHintValue(HINT_VISIBILITY, VISIBILITY_PUBLIC);
|
||||||
|
nemoNotification->setUrgency(Notification::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
nemoNotification->publish();
|
nemoNotification->publish();
|
||||||
|
|
|
@ -23,10 +23,11 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDBusInterface>
|
#include <QDBusInterface>
|
||||||
#include <nemonotifications-qt5/notification.h>
|
#include <nemonotifications-qt5/notification.h>
|
||||||
#include <ngf-qt5/NgfClient>
|
|
||||||
#include "tdlibwrapper.h"
|
#include "tdlibwrapper.h"
|
||||||
#include "appsettings.h"
|
#include "appsettings.h"
|
||||||
|
|
||||||
|
class ChatModel;
|
||||||
|
|
||||||
class NotificationManager : public QObject
|
class NotificationManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -35,7 +36,7 @@ class NotificationManager : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings);
|
NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings, ChatModel *chatModel);
|
||||||
~NotificationManager() override;
|
~NotificationManager() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -45,11 +46,6 @@ public slots:
|
||||||
void handleUpdateNotification(const QVariantMap &updatedNotification);
|
void handleUpdateNotification(const QVariantMap &updatedNotification);
|
||||||
void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
|
void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
|
||||||
void handleChatTitleUpdated(const QString &chatId, const QString &title);
|
void handleChatTitleUpdated(const QString &chatId, const QString &title);
|
||||||
void handleNgfConnectionStatus(bool connected);
|
|
||||||
void handleNgfEventFailed(quint32 eventId);
|
|
||||||
void handleNgfEventCompleted(quint32 eventId);
|
|
||||||
void handleNgfEventPlaying(quint32 eventId);
|
|
||||||
void handleNgfEventPaused(quint32 eventId);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -65,7 +61,7 @@ private:
|
||||||
|
|
||||||
TDLibWrapper *tdLibWrapper;
|
TDLibWrapper *tdLibWrapper;
|
||||||
AppSettings *appSettings;
|
AppSettings *appSettings;
|
||||||
Ngf::Client *ngfClient;
|
ChatModel *chatModel;
|
||||||
QMap<qlonglong,ChatInfo*> chatMap;
|
QMap<qlonglong,ChatInfo*> chatMap;
|
||||||
QMap<int,NotificationGroup*> notificationGroups;
|
QMap<int,NotificationGroup*> notificationGroups;
|
||||||
QDBusInterface mceInterface;
|
QDBusInterface mceInterface;
|
||||||
|
|
Loading…
Reference in a new issue