Merge branch 'win-notification' into 'master'

Notification on Windows

See merge request b0/spectral!25
This commit is contained in:
Black Hat 2018-10-20 07:44:20 +00:00
commit 129a83d91f
9 changed files with 48 additions and 38 deletions

View File

@ -1,5 +1,5 @@
import QtQuick 2.9 import QtQuick 2.9
RoomForm { RoomForm {
roomListModel.onNewMessage: if (!window.visible) spectralController.postNotification(roomId, eventId, roomName, senderName, text, icon) roomListModel.onNewMessage: if (!window.visible) spectralController.postNotification(roomId, eventId, roomName, senderName, text, icon, iconPath)
} }

View File

@ -244,7 +244,8 @@ void Controller::setColor(QString userId, QColor newColor) {
void Controller::postNotification(const QString& roomId, const QString& eventId, void Controller::postNotification(const QString& roomId, const QString& eventId,
const QString& roomName, const QString& roomName,
const QString& senderName, const QString& senderName,
const QString& text, const QImage& icon) { const QString& text, const QImage& icon,
const QUrl& iconPath) {
notificationsManager.postNotification(roomId, eventId, roomName, senderName, notificationsManager.postNotification(roomId, eventId, roomName, senderName,
text, icon); text, icon, iconPath);
} }

View File

@ -73,7 +73,7 @@ class Controller : public QObject {
void playAudio(QUrl localFile); void playAudio(QUrl localFile);
void postNotification(const QString& roomId, const QString& eventId, void postNotification(const QString& roomId, const QString& eventId,
const QString& roomName, const QString& senderName, const QString& roomName, const QString& senderName,
const QString& text, const QImage& icon); const QString& text, const QImage& icon, const QUrl& iconPath);
static QImage safeImage(QImage image); static QImage safeImage(QImage image);
}; };

View File

@ -4,6 +4,7 @@
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QUrl>
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
#include <QtDBus/QDBusArgument> #include <QtDBus/QDBusArgument>
@ -22,7 +23,7 @@ class NotificationsManager : public QObject {
void postNotification(const QString &roomId, const QString &eventId, void postNotification(const QString &roomId, const QString &eventId,
const QString &roomName, const QString &senderName, const QString &roomName, const QString &senderName,
const QString &text, const QImage &icon); const QString &text, const QImage &icon, const QUrl &iconPath);
signals: signals:
void notificationClicked(const QString roomId, const QString eventId); void notificationClicked(const QString roomId, const QString eventId);
@ -39,7 +40,7 @@ class NotificationsManager : public QObject {
// these slots are platform specific (D-Bus only) // these slots are platform specific (D-Bus only)
// but Qt slot declarations can not be inside an ifdef! // but Qt slot declarations can not be inside an ifdef!
private slots: public slots:
void actionInvoked(uint id, QString action); void actionInvoked(uint id, QString action);
void notificationClosed(uint id, uint reason); void notificationClosed(uint id, uint reason);
}; };

View File

@ -25,7 +25,7 @@ NotificationsManager::NotificationsManager(QObject *parent)
void NotificationsManager::postNotification( void NotificationsManager::postNotification(
const QString &roomid, const QString &eventid, const QString &roomname, const QString &roomid, const QString &eventid, const QString &roomname,
const QString &sender, const QString &text, const QImage &icon) { const QString &sender, const QString &text, const QImage &icon, const QUrl &iconPath) {
uint id = showNotification(roomname, sender + ": " + text, icon); uint id = showNotification(roomname, sender + ": " + text, icon);
notificationIds[id] = roomEventId{roomid, eventid}; notificationIds[id] = roomEventId{roomid, eventid};
} }

View File

@ -19,11 +19,13 @@ NotificationsManager::postNotification(
const QString &roomName, const QString &roomName,
const QString &senderName, const QString &senderName,
const QString &text, const QString &text,
const QImage &icon) const QImage &icon,
const QUrl &iconPath)
{ {
Q_UNUSED(roomId); Q_UNUSED(roomId);
Q_UNUSED(eventId); Q_UNUSED(eventId);
Q_UNUSED(icon); Q_UNUSED(icon);
Q_UNUSED(iconPath);
NSUserNotification * notif = [[NSUserNotification alloc] init]; NSUserNotification * notif = [[NSUserNotification alloc] init];

View File

@ -1,25 +1,30 @@
#include "manager.h" #include "manager.h"
#include "wintoastlib.h" #include "wintoastlib.h"
#include <QDir>
using namespace WinToastLib; using namespace WinToastLib;
class CustomHandler : public QObject, public IWinToastHandler { class CustomHandler : public IWinToastHandler {
Q_OBJECT
public: public:
void toastActivated() { emit activated(notificationID); } CustomHandler(uint id, NotificationsManager *parent)
void toastActivated(int) { emit activated(notificationID); } : notificationID(id), notificationsManager(parent) {}
void toastActivated() {
notificationsManager->actionInvoked(notificationID, "");
}
void toastActivated(int) {
notificationsManager->actionInvoked(notificationID, "");
}
void toastFailed() { void toastFailed() {
std::wcout << L"Error showing current toast" << std::endl; std::wcout << L"Error showing current toast" << std::endl;
} }
void toastDismissed(WinToastDismissalReason) { void toastDismissed(WinToastDismissalReason) {
emit dismissed(notificationID); notificationsManager->notificationClosed(notificationID, 0);
} }
private:
uint notificationID; uint notificationID;
NotificationsManager *notificationsManager;
signals:
void activated(uint id);
void dismissed(uint id);
}; };
namespace { namespace {
@ -41,7 +46,8 @@ NotificationsManager::NotificationsManager(QObject *parent) : QObject(parent) {}
void NotificationsManager::postNotification( void NotificationsManager::postNotification(
const QString &room_id, const QString &event_id, const QString &room_name, const QString &room_id, const QString &event_id, const QString &room_name,
const QString &sender, const QString &text, const QImage &icon) { const QString &sender, const QString &text, const QImage &icon,
const QUrl &iconPath) {
Q_UNUSED(room_id) Q_UNUSED(room_id)
Q_UNUSED(event_id) Q_UNUSED(event_id)
Q_UNUSED(icon) Q_UNUSED(icon)
@ -58,17 +64,13 @@ void NotificationsManager::postNotification(
WinToastTemplate::FirstLine); WinToastTemplate::FirstLine);
templ.setTextField(QString("%1").arg(text).toStdWString(), templ.setTextField(QString("%1").arg(text).toStdWString(),
WinToastTemplate::SecondLine); WinToastTemplate::SecondLine);
// TODO: implement room or user avatar
// templ.setImagePath(L"C:/example.png");
CustomHandler *customHandler = new CustomHandler(); templ.setImagePath(
reinterpret_cast<const wchar_t *>(QDir::toNativeSeparators(iconPath.toLocalFile()).utf16()));
count++; count++;
customHandler->notificationID = count; CustomHandler *customHandler = new CustomHandler(count, this);
notificationIds[count] = roomEventId{room_id, event_id}; notificationIds[count] = roomEventId{room_id, event_id};
connect(customHandler, &CustomHandler::activated, this,
[=](uint id) { this->actionInvoked(id, ""); });
connect(customHandler, &CustomHandler::dismissed, this,
[=](uint id) { this->notificationClosed(id, 0); });
WinToast::instance()->showToast(templ, customHandler); WinToast::instance()->showToast(templ, customHandler);
} }

View File

@ -4,6 +4,7 @@
#include "events/roomevent.h" #include "events/roomevent.h"
#include <QStandardPaths>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtGui/QBrush> #include <QtGui/QBrush>
#include <QtGui/QColor> #include <QtGui/QColor>
@ -74,17 +75,20 @@ void RoomListModel::connectRoomSignals(SpectralRoom* room) {
[=] { refresh(room, {AvatarRole}); }); [=] { refresh(room, {AvatarRole}); });
connect(room, &Room::addedMessages, this, connect(room, &Room::addedMessages, this,
[=] { refresh(room, {LastEventRole}); }); [=] { refresh(room, {LastEventRole}); });
connect(room, &Room::aboutToAddNewMessages, this, connect(
[=](QMatrixClient::RoomEventsRange eventsRange) { room, &Room::aboutToAddNewMessages, this,
RoomEvent* event = (eventsRange.end() - 1)->get(); [=](QMatrixClient::RoomEventsRange eventsRange) {
if (event->isStateEvent()) return; RoomEvent* event = (eventsRange.end() - 1)->get();
User* sender = room->user(event->senderId()); if (event->isStateEvent()) return;
if (sender == room->localUser()) return; User* sender = room->user(event->senderId());
emit newMessage(room->id(), event->id(), room->displayName(), if (sender == room->localUser()) return;
sender->displayname(), QUrl _url = room->avatarUrl();
event->contentJson().value("body").toString(), emit newMessage(
room->avatar(128)); room->id(), event->id(), room->displayName(), sender->displayname(),
}); event->contentJson().value("body").toString(), room->avatar(128),
QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
"/avatar/" + _url.authority() + '_' + _url.fileName() + ".png"));
});
} }
void RoomListModel::updateRoom(Room* room, Room* prev) { void RoomListModel::updateRoom(Room* room, Room* prev) {

View File

@ -76,7 +76,7 @@ class RoomListModel : public QAbstractListModel {
void roomAdded(SpectralRoom* room); void roomAdded(SpectralRoom* room);
void newMessage(const QString& roomId, const QString& eventId, void newMessage(const QString& roomId, const QString& eventId,
const QString& roomName, const QString& senderName, const QString& roomName, const QString& senderName,
const QString& text, const QImage& icon); const QString& text, const QImage& icon, const QUrl& iconPath);
}; };
#endif // ROOMLISTMODEL_H #endif // ROOMLISTMODEL_H