Skip to content
Snippets Groups Projects
Commit 7f28ac65 authored by Andreas Traczyk's avatar Andreas Traczyk Committed by Sébastien Blin
Browse files

notifications: add avatars to gnu/linux notifications

Gitlab: #320
Change-Id: Ib2121257af2704dd2a246b499961657b66ae944d
parent 2cc82053
No related branches found
No related tags found
No related merge requests found
......@@ -140,6 +140,8 @@ pkg_check_modules(LIBNOTIFY libnotify>=0.7.6)
if(LIBNOTIFY_FOUND)
add_definitions(-DUSE_LIBNOTIFY)
add_definitions(${LIBNOTIFY_CFLAGS})
pkg_check_modules(LIBGDKPIXBUF gdk-pixbuf-2.0>=2.40.0)
add_definitions(${LIBGDKPIXBUF_CFLAGS})
endif()
if(QT5_VER AND QT5_PATH)
......@@ -217,7 +219,8 @@ include_directories(${PROJECT_SOURCE_DIR}
${SRC_DIR}
${LRC_SRC_PATH}
${LIBNM_INCLUDE_DIRS}
${LIBNOTIFY_INCLUDE_DIRS})
${LIBNOTIFY_INCLUDE_DIRS}
${LIBGDKPIXBUF_INCLUDE_DIRS})
add_executable(${PROJECT_NAME}
${SRC_DIR}/main.cpp
......@@ -239,7 +242,8 @@ target_link_libraries(jami-qt
${qrencode}
${X11}
${LIBNM_LIBRARIES}
${LIBNOTIFY_LIBRARIES})
${LIBNOTIFY_LIBRARIES}
${LIBGDKPIXBUF_LIBRARIES})
if(ENABLE_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))
&& call.startTime.time_since_epoch().count() == 0) {
// 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 from = accInfo.contactModel->bestNameForContact(convInfo.participants[0]);
auto notifId = QString("%1;%2").arg(accountId).arg(convInfo.uid);
systemTray_->showNotification(notifId,
tr("Missed call"),
tr("Missed call from %1").arg(from),
NotificationType::CHAT);
NotificationType::CHAT,
Utils::QImageToByteArray(contactPhoto));
}
}
#endif
......@@ -384,11 +390,16 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid)
Q_EMIT lrcInstance_->updateSmartList();
#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);
systemTray_->showNotification(notifId,
tr("Incoming call"),
tr("%1 is calling you").arg(from),
NotificationType::CALL);
NotificationType::CALL,
Utils::QImageToByteArray(contactPhoto));
#else
auto onClicked = [this, accountId, convUid = convInfo.uid]() {
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
......
......@@ -171,14 +171,19 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
if (!interaction.authorUri.isEmpty()
&& (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()
|| convUid != lrcInstance_->getCurrentConvUid())) {
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
auto from = accInfo.contactModel->bestNameForContact(interaction.authorUri);
auto& accountInfo = lrcInstance_->getAccountInfo(accountId);
auto from = accountInfo.contactModel->bestNameForContact(interaction.authorUri);
#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);
systemTray_->showNotification(notifId,
tr("New message"),
from + ": " + interaction.body,
NotificationType::CHAT);
NotificationType::CHAT,
Utils::QImageToByteArray(contactPhoto));
#else
Q_UNUSED(interactionId)
......@@ -215,11 +220,13 @@ ConversationsAdapter::onNewTrustRequest(const QString& accountId, const QString&
if (!QApplication::focusWindow() || accountId != lrcInstance_->getCurrAccId()) {
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
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);
systemTray_->showNotification(notifId,
tr("Trust request"),
"New request from " + from,
NotificationType::REQUEST);
NotificationType::REQUEST,
Utils::QImageToByteArray(contactPhoto));
}
#endif
}
......
......@@ -167,7 +167,8 @@ void
SystemTray::showNotification(const QString& id,
const QString& title,
const QString& body,
NotificationType type)
NotificationType type,
const QByteArray& avatar)
{
if (!settingsManager_->getValue(Settings::Key::EnableNotifications).toBool())
return;
......@@ -184,7 +185,16 @@ SystemTray::showNotification(const QString& id,
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) {
notify_notification_set_urgency(notification.get(), NOTIFY_URGENCY_CRITICAL);
......
......@@ -42,7 +42,8 @@ public:
void showNotification(const QString& id,
const QString& title,
const QString& body,
NotificationType type);
NotificationType type,
const QByteArray& avatar = {});
Q_SIGNALS:
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());
#else
Q_UNUSED(wstrAppName)
QString desktopPath;
/* cmake should set JAMI_INSTALL_PREFIX, otherwise it checks the following dirs
* - /usr/<data dir>
......@@ -179,6 +180,7 @@ Utils::DeleteStartupLink(const std::wstring& wstrAppName)
DeleteFile(linkPath.c_str());
#else
Q_UNUSED(wstrAppName)
QString desktopFile = QStandardPaths::locate(QStandardPaths::ConfigLocation,
"autostart/jami-qt.desktop");
if (!desktopFile.isEmpty()) {
......@@ -205,6 +207,7 @@ Utils::CheckStartupLink(const std::wstring& wstrAppName)
linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk"));
return PathFileExists(linkPath.c_str());
#else
Q_UNUSED(wstrAppName)
return (!QStandardPaths::locate(QStandardPaths::ConfigLocation, "autostart/jami-qt.desktop")
.isEmpty());
#endif
......@@ -222,6 +225,7 @@ Utils::WinGetEnv(const char* name)
return 0;
}
#else
Q_UNUSED(name)
return 0;
#endif
}
......@@ -321,7 +325,10 @@ Utils::GetISODate()
}
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;
......@@ -329,7 +336,8 @@ Utils::contactPhoto(LRCInstance* instance, const QString& contactUri, const QSiz
/*
* 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 contactPhoto = contactInfo.profileInfo.avatar;
auto bestName = accountInfo.contactModel->bestNameForContact(contactUri);
......@@ -405,6 +413,7 @@ Utils::getRealSize(QScreen* screen)
(DEVMODE*) &dmThisScreen);
return QSize(dmThisScreen.dmPelsWidth, dmThisScreen.dmPelsHeight);
#else
Q_UNUSED(screen)
return {};
#endif
}
......
......@@ -84,7 +84,8 @@ static const QSize defaultAvatarSize {128, 128};
QImage contactPhotoFromBase64(const QByteArray& data, const QString& type);
QImage contactPhoto(LRCInstance* instance,
const QString& contactUri,
const QSize& size = defaultAvatarSize);
const QSize& size = defaultAvatarSize,
const QString& accountId = {});
QImage getCirclePhoto(const QImage original, int sizePhoto);
QColor getAvatarColor(const QString& canonicalUri);
QImage fallbackAvatar(const QString& canonicalUriStr,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment