mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-21 15:24:01 +02:00
notifications: add avatars to gnu/linux notifications
Gitlab: #320 Change-Id: Ib2121257af2704dd2a246b499961657b66ae944d
This commit is contained in:
parent
2cc82053c9
commit
7f28ac65df
7 changed files with 57 additions and 14 deletions
|
@ -140,6 +140,8 @@ pkg_check_modules(LIBNOTIFY libnotify>=0.7.6)
|
||||||
if(LIBNOTIFY_FOUND)
|
if(LIBNOTIFY_FOUND)
|
||||||
add_definitions(-DUSE_LIBNOTIFY)
|
add_definitions(-DUSE_LIBNOTIFY)
|
||||||
add_definitions(${LIBNOTIFY_CFLAGS})
|
add_definitions(${LIBNOTIFY_CFLAGS})
|
||||||
|
pkg_check_modules(LIBGDKPIXBUF gdk-pixbuf-2.0>=2.40.0)
|
||||||
|
add_definitions(${LIBGDKPIXBUF_CFLAGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(QT5_VER AND QT5_PATH)
|
if(QT5_VER AND QT5_PATH)
|
||||||
|
@ -217,7 +219,8 @@ include_directories(${PROJECT_SOURCE_DIR}
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
${LRC_SRC_PATH}
|
${LRC_SRC_PATH}
|
||||||
${LIBNM_INCLUDE_DIRS}
|
${LIBNM_INCLUDE_DIRS}
|
||||||
${LIBNOTIFY_INCLUDE_DIRS})
|
${LIBNOTIFY_INCLUDE_DIRS}
|
||||||
|
${LIBGDKPIXBUF_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME}
|
add_executable(${PROJECT_NAME}
|
||||||
${SRC_DIR}/main.cpp
|
${SRC_DIR}/main.cpp
|
||||||
|
@ -239,7 +242,8 @@ target_link_libraries(jami-qt
|
||||||
${qrencode}
|
${qrencode}
|
||||||
${X11}
|
${X11}
|
||||||
${LIBNM_LIBRARIES}
|
${LIBNM_LIBRARIES}
|
||||||
${LIBNOTIFY_LIBRARIES})
|
${LIBNOTIFY_LIBRARIES}
|
||||||
|
${LIBGDKPIXBUF_LIBRARIES})
|
||||||
|
|
||||||
if(ENABLE_TESTS)
|
if(ENABLE_TESTS)
|
||||||
message("Add Jami tests")
|
message("Add Jami tests")
|
||||||
|
|
|
@ -102,13 +102,19 @@ CallAdapter::onCallStatusChanged(const QString& accountId, const QString& callId
|
||||||
if (systemTray_->hideNotification(QString("%1;%2").arg(accountId).arg(convInfo.uid))
|
if (systemTray_->hideNotification(QString("%1;%2").arg(accountId).arg(convInfo.uid))
|
||||||
&& call.startTime.time_since_epoch().count() == 0) {
|
&& call.startTime.time_since_epoch().count() == 0) {
|
||||||
// This was a missed call; show a missed call notification
|
// This was a missed call; show a missed call notification
|
||||||
|
// TODO: swarmify(avoid using convInfo.participants[0])
|
||||||
|
auto contactPhoto = Utils::contactPhoto(lrcInstance_,
|
||||||
|
convInfo.participants[0],
|
||||||
|
QSize(50, 50),
|
||||||
|
accountId);
|
||||||
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
||||||
auto from = accInfo.contactModel->bestNameForContact(convInfo.participants[0]);
|
auto from = accInfo.contactModel->bestNameForContact(convInfo.participants[0]);
|
||||||
auto notifId = QString("%1;%2").arg(accountId).arg(convInfo.uid);
|
auto notifId = QString("%1;%2").arg(accountId).arg(convInfo.uid);
|
||||||
systemTray_->showNotification(notifId,
|
systemTray_->showNotification(notifId,
|
||||||
tr("Missed call"),
|
tr("Missed call"),
|
||||||
tr("Missed call from %1").arg(from),
|
tr("Missed call from %1").arg(from),
|
||||||
NotificationType::CHAT);
|
NotificationType::CHAT,
|
||||||
|
Utils::QImageToByteArray(contactPhoto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -384,11 +390,16 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid)
|
||||||
Q_EMIT lrcInstance_->updateSmartList();
|
Q_EMIT lrcInstance_->updateSmartList();
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
auto contactPhoto = Utils::contactPhoto(lrcInstance_,
|
||||||
|
convInfo.participants[0],
|
||||||
|
QSize(50, 50),
|
||||||
|
accountId);
|
||||||
auto notifId = QString("%1;%2").arg(accountId).arg(convUid);
|
auto notifId = QString("%1;%2").arg(accountId).arg(convUid);
|
||||||
systemTray_->showNotification(notifId,
|
systemTray_->showNotification(notifId,
|
||||||
tr("Incoming call"),
|
tr("Incoming call"),
|
||||||
tr("%1 is calling you").arg(from),
|
tr("%1 is calling you").arg(from),
|
||||||
NotificationType::CALL);
|
NotificationType::CALL,
|
||||||
|
Utils::QImageToByteArray(contactPhoto));
|
||||||
#else
|
#else
|
||||||
auto onClicked = [this, accountId, convUid = convInfo.uid]() {
|
auto onClicked = [this, accountId, convUid = convInfo.uid]() {
|
||||||
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
|
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
|
||||||
|
|
|
@ -171,14 +171,19 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
|
||||||
if (!interaction.authorUri.isEmpty()
|
if (!interaction.authorUri.isEmpty()
|
||||||
&& (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()
|
&& (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()
|
||||||
|| convUid != lrcInstance_->getCurrentConvUid())) {
|
|| convUid != lrcInstance_->getCurrentConvUid())) {
|
||||||
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
auto& accountInfo = lrcInstance_->getAccountInfo(accountId);
|
||||||
auto from = accInfo.contactModel->bestNameForContact(interaction.authorUri);
|
auto from = accountInfo.contactModel->bestNameForContact(interaction.authorUri);
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
auto contactPhoto = Utils::contactPhoto(lrcInstance_,
|
||||||
|
interaction.authorUri,
|
||||||
|
QSize(50, 50),
|
||||||
|
accountId);
|
||||||
auto notifId = QString("%1;%2;%3").arg(accountId).arg(convUid).arg(interactionId);
|
auto notifId = QString("%1;%2;%3").arg(accountId).arg(convUid).arg(interactionId);
|
||||||
systemTray_->showNotification(notifId,
|
systemTray_->showNotification(notifId,
|
||||||
tr("New message"),
|
tr("New message"),
|
||||||
from + ": " + interaction.body,
|
from + ": " + interaction.body,
|
||||||
NotificationType::CHAT);
|
NotificationType::CHAT,
|
||||||
|
Utils::QImageToByteArray(contactPhoto));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(interactionId)
|
Q_UNUSED(interactionId)
|
||||||
|
@ -215,11 +220,13 @@ ConversationsAdapter::onNewTrustRequest(const QString& accountId, const QString&
|
||||||
if (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()) {
|
if (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()) {
|
||||||
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
||||||
auto from = accInfo.contactModel->bestNameForContact(peerUri);
|
auto from = accInfo.contactModel->bestNameForContact(peerUri);
|
||||||
|
auto contactPhoto = Utils::contactPhoto(lrcInstance_, peerUri, QSize(50, 50), accountId);
|
||||||
auto notifId = QString("%1;%2").arg(accountId).arg(peerUri);
|
auto notifId = QString("%1;%2").arg(accountId).arg(peerUri);
|
||||||
systemTray_->showNotification(notifId,
|
systemTray_->showNotification(notifId,
|
||||||
tr("Trust request"),
|
tr("Trust request"),
|
||||||
"New request from " + from,
|
"New request from " + from,
|
||||||
NotificationType::REQUEST);
|
NotificationType::REQUEST,
|
||||||
|
Utils::QImageToByteArray(contactPhoto));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,8 @@ void
|
||||||
SystemTray::showNotification(const QString& id,
|
SystemTray::showNotification(const QString& id,
|
||||||
const QString& title,
|
const QString& title,
|
||||||
const QString& body,
|
const QString& body,
|
||||||
NotificationType type)
|
NotificationType type,
|
||||||
|
const QByteArray& avatar)
|
||||||
{
|
{
|
||||||
if (!settingsManager_->getValue(Settings::Key::EnableNotifications).toBool())
|
if (!settingsManager_->getValue(Settings::Key::EnableNotifications).toBool())
|
||||||
return;
|
return;
|
||||||
|
@ -184,7 +185,16 @@ SystemTray::showNotification(const QString& id,
|
||||||
|
|
||||||
pimpl_->notifications.emplace(id, n);
|
pimpl_->notifications.emplace(id, n);
|
||||||
|
|
||||||
// TODO: notify_notification_set_image_from_pixbuf <- GdkPixbuf
|
if (!avatar.isEmpty()) {
|
||||||
|
GError* error = nullptr;
|
||||||
|
GdkPixbuf* pixbuf = nullptr;
|
||||||
|
GInputStream* stream = nullptr;
|
||||||
|
stream = g_memory_input_stream_new_from_data(avatar.constData(), avatar.size(), NULL);
|
||||||
|
pixbuf = gdk_pixbuf_new_from_stream(stream, nullptr, &error);
|
||||||
|
g_input_stream_close(stream, nullptr, nullptr);
|
||||||
|
g_object_unref(stream);
|
||||||
|
notify_notification_set_image_from_pixbuf(notification.get(), pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
if (type != NotificationType::CHAT) {
|
if (type != NotificationType::CHAT) {
|
||||||
notify_notification_set_urgency(notification.get(), NOTIFY_URGENCY_CRITICAL);
|
notify_notification_set_urgency(notification.get(), NOTIFY_URGENCY_CRITICAL);
|
||||||
|
|
|
@ -42,7 +42,8 @@ public:
|
||||||
void showNotification(const QString& id,
|
void showNotification(const QString& id,
|
||||||
const QString& title,
|
const QString& title,
|
||||||
const QString& body,
|
const QString& body,
|
||||||
NotificationType type);
|
NotificationType type,
|
||||||
|
const QByteArray& avatar = {});
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void openConversationActivated(const QString& accountId, const QString& convUid);
|
void openConversationActivated(const QString& accountId, const QString& convUid);
|
||||||
|
|
|
@ -68,6 +68,7 @@ Utils::CreateStartupLink(const std::wstring& wstrAppName)
|
||||||
|
|
||||||
return Utils::CreateLink(programPath.c_str(), linkPath.c_str());
|
return Utils::CreateLink(programPath.c_str(), linkPath.c_str());
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED(wstrAppName)
|
||||||
QString desktopPath;
|
QString desktopPath;
|
||||||
/* cmake should set JAMI_INSTALL_PREFIX, otherwise it checks the following dirs
|
/* cmake should set JAMI_INSTALL_PREFIX, otherwise it checks the following dirs
|
||||||
* - /usr/<data dir>
|
* - /usr/<data dir>
|
||||||
|
@ -179,6 +180,7 @@ Utils::DeleteStartupLink(const std::wstring& wstrAppName)
|
||||||
DeleteFile(linkPath.c_str());
|
DeleteFile(linkPath.c_str());
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED(wstrAppName)
|
||||||
QString desktopFile = QStandardPaths::locate(QStandardPaths::ConfigLocation,
|
QString desktopFile = QStandardPaths::locate(QStandardPaths::ConfigLocation,
|
||||||
"autostart/jami-qt.desktop");
|
"autostart/jami-qt.desktop");
|
||||||
if (!desktopFile.isEmpty()) {
|
if (!desktopFile.isEmpty()) {
|
||||||
|
@ -205,6 +207,7 @@ Utils::CheckStartupLink(const std::wstring& wstrAppName)
|
||||||
linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk"));
|
linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk"));
|
||||||
return PathFileExists(linkPath.c_str());
|
return PathFileExists(linkPath.c_str());
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED(wstrAppName)
|
||||||
return (!QStandardPaths::locate(QStandardPaths::ConfigLocation, "autostart/jami-qt.desktop")
|
return (!QStandardPaths::locate(QStandardPaths::ConfigLocation, "autostart/jami-qt.desktop")
|
||||||
.isEmpty());
|
.isEmpty());
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,6 +225,7 @@ Utils::WinGetEnv(const char* name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED(name)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -321,7 +325,10 @@ Utils::GetISODate()
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage
|
QImage
|
||||||
Utils::contactPhoto(LRCInstance* instance, const QString& contactUri, const QSize& size)
|
Utils::contactPhoto(LRCInstance* instance,
|
||||||
|
const QString& contactUri,
|
||||||
|
const QSize& size,
|
||||||
|
const QString& accountId)
|
||||||
{
|
{
|
||||||
QImage photo;
|
QImage photo;
|
||||||
|
|
||||||
|
@ -329,7 +336,8 @@ Utils::contactPhoto(LRCInstance* instance, const QString& contactUri, const QSiz
|
||||||
/*
|
/*
|
||||||
* Get first contact photo.
|
* Get first contact photo.
|
||||||
*/
|
*/
|
||||||
auto& accountInfo = instance->accountModel().getAccountInfo(instance->getCurrAccId());
|
auto& accountInfo = instance->accountModel().getAccountInfo(
|
||||||
|
accountId.isEmpty() ? instance->getCurrAccId() : accountId);
|
||||||
auto contactInfo = accountInfo.contactModel->getContact(contactUri);
|
auto contactInfo = accountInfo.contactModel->getContact(contactUri);
|
||||||
auto contactPhoto = contactInfo.profileInfo.avatar;
|
auto contactPhoto = contactInfo.profileInfo.avatar;
|
||||||
auto bestName = accountInfo.contactModel->bestNameForContact(contactUri);
|
auto bestName = accountInfo.contactModel->bestNameForContact(contactUri);
|
||||||
|
@ -405,6 +413,7 @@ Utils::getRealSize(QScreen* screen)
|
||||||
(DEVMODE*) &dmThisScreen);
|
(DEVMODE*) &dmThisScreen);
|
||||||
return QSize(dmThisScreen.dmPelsWidth, dmThisScreen.dmPelsHeight);
|
return QSize(dmThisScreen.dmPelsWidth, dmThisScreen.dmPelsHeight);
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED(screen)
|
||||||
return {};
|
return {};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,8 @@ static const QSize defaultAvatarSize {128, 128};
|
||||||
QImage contactPhotoFromBase64(const QByteArray& data, const QString& type);
|
QImage contactPhotoFromBase64(const QByteArray& data, const QString& type);
|
||||||
QImage contactPhoto(LRCInstance* instance,
|
QImage contactPhoto(LRCInstance* instance,
|
||||||
const QString& contactUri,
|
const QString& contactUri,
|
||||||
const QSize& size = defaultAvatarSize);
|
const QSize& size = defaultAvatarSize,
|
||||||
|
const QString& accountId = {});
|
||||||
QImage getCirclePhoto(const QImage original, int sizePhoto);
|
QImage getCirclePhoto(const QImage original, int sizePhoto);
|
||||||
QColor getAvatarColor(const QString& canonicalUri);
|
QColor getAvatarColor(const QString& canonicalUri);
|
||||||
QImage fallbackAvatar(const QString& canonicalUriStr,
|
QImage fallbackAvatar(const QString& canonicalUriStr,
|
||||||
|
|
Loading…
Add table
Reference in a new issue