Show notification popups except for the current chat

And drop dependency on Ngf. Also, pre-initialize the chat photo when
pushing the chat page.
This commit is contained in:
Slava Monich 2020-11-20 21:39:23 +02:00
parent dd6239c119
commit d1ccf9f796
8 changed files with 70 additions and 68 deletions

View file

@ -14,7 +14,7 @@ TARGET = harbour-fernschreiber
CONFIG += sailfishapp sailfishapp_i18n
PKGCONFIG += nemonotifications-qt5 ngf-qt5 zlib
PKGCONFIG += nemonotifications-qt5 zlib
QT += core dbus sql

View file

@ -35,6 +35,7 @@ Page {
property bool isInitialized: false;
readonly property int myUserId: tdLibWrapper.getUserInformation().id;
property var chatInformation;
property alias chatPicture: chatPictureThumbnail.photoData
property bool isPrivateChat: false;
property bool isBasicGroup: false;
property bool isSuperGroup: false;
@ -353,6 +354,9 @@ Page {
chatPage.isInitialized = true;
}
break;
case PageStatus.Inactive:
chatModel.clear();
break;
}
}

View file

@ -237,7 +237,10 @@ Page {
ownUserId: overviewPage.ownUserId
onClicked: {
pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : display });
pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), {
chatInformation : display,
chatPicture: photo_small
})
}
Connections {

View file

@ -85,6 +85,23 @@ bool ChatModel::insertRows(int row, int count, const QModelIndex &parent)
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)
{
LOG("Initializing chat model...");
@ -157,6 +174,11 @@ QVariantMap ChatModel::smallPhoto() const
return chatInformation.value(PHOTO).toMap().value(SMALL).toMap();
}
qlonglong ChatModel::getChatId() const
{
return chatId;
}
static bool compareMessages(const QVariant &message1, const QVariant &message2)
{
const QVariantMap messageMap1 = message1.toMap();

View file

@ -36,14 +36,16 @@ public:
virtual QVariant data(const QModelIndex &index, int role) const 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 triggerLoadMoreHistory();
Q_INVOKABLE void triggerLoadMoreFuture();
Q_INVOKABLE QVariantMap getChatInformation();
Q_INVOKABLE QVariantMap getMessage(int index);
Q_INVOKABLE int getLastReadMessageIndex();
QVariantMap smallPhoto() const;
qlonglong getChatId() const;
signals:
void messagesReceived(int modelIndex, int lastReadSentIndex, int totalCount);

View file

@ -73,7 +73,7 @@ int main(int argc, char *argv[])
ChatModel chatModel(tdLibWrapper);
context->setContextProperty("chatModel", &chatModel);
NotificationManager notificationManager(tdLibWrapper, appSettings);
NotificationManager notificationManager(tdLibWrapper, appSettings, &chatModel);
context->setContextProperty("notificationManager", &notificationManager);
ProcessLauncher processLauncher;

View file

@ -19,6 +19,7 @@
#include "notificationmanager.h"
#include "fernschreiberutils.h"
#include "chatmodel.h"
#include <sailfishapp.h>
#include <QDebug>
#include <QListIterator>
@ -50,15 +51,17 @@ namespace {
const QString CHAT_TYPE_BASIC_GROUP("chatTypeBasicGroup");
const QString CHAT_TYPE_SUPERGROUP("chatTypeSupergroup");
const QString NOTIFICATION_CATEGORY("x-nemo.messaging.im");
const QString NGF_EVENT("chat");
const QString APP_NAME("Fernschreiber");
// Notification hints
const QString HINT_GROUP_ID("x-fernschreiber.group_id"); // int
const QString HINT_CHAT_ID("x-fernschreiber.chat_id"); // qlonglong
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
@ -116,30 +119,21 @@ NotificationManager::NotificationGroup::~NotificationGroup()
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()),
appIconFile(SailfishApp::pathTo("images/fernschreiber-notification.png").toLocalFile())
{
LOG("Initializing...");
this->tdLibWrapper = tdLibWrapper;
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(notificationGroupUpdated(QVariantMap)), this, SLOT(handleUpdateNotificationGroup(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(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);
@ -236,6 +230,12 @@ void NotificationManager::updateNotificationGroup(int groupId, qlonglong chatId,
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
switch (feedback) {
case AppSettings::NotificationFeedbackNone:
@ -251,6 +251,7 @@ void NotificationManager::updateNotificationGroup(int groupId, qlonglong chatId,
}
// Publish new or update the existing notification
LOG("Feedback" << needFeedback);
publishNotification(notificationGroup, needFeedback);
} else if (notificationGroup) {
// 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)
{
QVariantMap messageMap;
@ -374,25 +350,24 @@ void NotificationManager::publishNotification(const NotificationGroup *notificat
notificationBody = tr("%Ln unread messages", "", notificationGroup->totalCount);
}
const QString summary(chatInformation ? chatInformation->title : QString());
nemoNotification->setBody(notificationBody);
nemoNotification->setSummary(chatInformation ? chatInformation->title : QString());
if (needFeedback) {
nemoNotification->setCategory(NOTIFICATION_CATEGORY);
nemoNotification->setSummary(summary);
nemoNotification->setPreviewBody(notificationBody);
nemoNotification->setPreviewSummary(summary);
nemoNotification->setHintValue(HINT_VIBRA, needFeedback);
// Setting preview body & summary to a non-empty string causes a notification popup,
// no matter if we are in the current chat, in the app or not. That might be annoying
// In the future, we can show this popup depending if the app/chat is open or not
//
// nemoNotification->setPreviewBody(nemoNotification->body());
// nemoNotification->setPreviewSummary(nemoNotification->summary());
nemoNotification->setPreviewBody(QString());
nemoNotification->setPreviewSummary(QString());
ngfClient->play(NGF_EVENT);
// Don't show popup for the currently open chat
if (!needFeedback || (chatModel->getChatId() == notificationGroup->chatId &&
qGuiApp->applicationState() == Qt::ApplicationActive)) {
nemoNotification->setHintValue(HINT_DISPLAY_ON, false);
nemoNotification->setHintValue(HINT_VISIBILITY, QVariant());
nemoNotification->setUrgency(Notification::Low);
} else {
nemoNotification->setCategory(QString());
nemoNotification->setPreviewBody(QString());
nemoNotification->setPreviewSummary(QString());
// The "display on" option will be configurable
nemoNotification->setHintValue(HINT_DISPLAY_ON, true);
nemoNotification->setHintValue(HINT_VISIBILITY, VISIBILITY_PUBLIC);
nemoNotification->setUrgency(Notification::Normal);
}
nemoNotification->publish();

View file

@ -23,10 +23,11 @@
#include <QObject>
#include <QDBusInterface>
#include <nemonotifications-qt5/notification.h>
#include <ngf-qt5/NgfClient>
#include "tdlibwrapper.h"
#include "appsettings.h"
class ChatModel;
class NotificationManager : public QObject
{
Q_OBJECT
@ -35,7 +36,7 @@ class NotificationManager : public QObject
public:
NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings);
NotificationManager(TDLibWrapper *tdLibWrapper, AppSettings *appSettings, ChatModel *chatModel);
~NotificationManager() override;
public slots:
@ -45,11 +46,6 @@ public slots:
void handleUpdateNotification(const QVariantMap &updatedNotification);
void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation);
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:
@ -65,7 +61,7 @@ private:
TDLibWrapper *tdLibWrapper;
AppSettings *appSettings;
Ngf::Client *ngfClient;
ChatModel *chatModel;
QMap<qlonglong,ChatInfo*> chatMap;
QMap<int,NotificationGroup*> notificationGroups;
QDBusInterface mceInterface;