File indexing completed on 2024-05-12 05:04:09
0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu> 0002 // SPDX-License-Identifier: GPL-3.0-or-later 0003 0004 #include "notificationhandler.h" 0005 0006 #include "account.h" 0007 #include "networkcontroller.h" 0008 0009 #include <QPainter> 0010 0011 #include <KLocalizedString> 0012 #include <KNotification> 0013 0014 #ifdef HAVE_KIO 0015 #include <KIO/ApplicationLauncherJob> 0016 #endif 0017 0018 NotificationHandler::NotificationHandler(QNetworkAccessManager *nam, QObject *parent) 0019 : QObject(parent) 0020 , m_nam(nam) 0021 { 0022 } 0023 0024 void NotificationHandler::handle(std::shared_ptr<Notification> notification, AbstractAccount *account) 0025 { 0026 KNotification *knotification; 0027 0028 const auto addViewPostAction = [this, &knotification, notification] { 0029 #ifdef HAVE_KIO 0030 auto viewPostAction = knotification->addAction(i18n("View Post")); 0031 auto defaultAction = knotification->addDefaultAction(i18n("View Post")); 0032 0033 auto openPost = [=] { 0034 if (auto post = notification->post(); post != nullptr) { 0035 auto url = post->url(); 0036 url.setScheme(QStringLiteral("web+ap")); 0037 0038 auto *job = new KIO::ApplicationLauncherJob(KService::serviceByDesktopName(QStringLiteral("org.kde.tokodon"))); 0039 job->setUrls({url}); 0040 job->start(); 0041 } 0042 }; 0043 0044 connect(viewPostAction, &KNotificationAction::activated, this, openPost); 0045 connect(defaultAction, &KNotificationAction::activated, this, openPost); 0046 #endif 0047 }; 0048 0049 const auto addViewUserAction = [this, &knotification, notification] { 0050 #ifdef HAVE_KIO 0051 auto viewProfileActions = knotification->addAction(i18n("View Profile")); 0052 auto defaultAction = knotification->addDefaultAction(i18n("View Profile")); 0053 0054 auto viewProfile = [=] { 0055 auto url = notification->identity()->url(); 0056 url.setScheme(QStringLiteral("web+ap")); 0057 0058 auto *job = new KIO::ApplicationLauncherJob(KService::serviceByDesktopName(QStringLiteral("org.kde.tokodon"))); 0059 job->setUrls({url}); 0060 job->start(); 0061 }; 0062 0063 connect(viewProfileActions, &KNotificationAction::activated, this, viewProfile); 0064 connect(defaultAction, &KNotificationAction::activated, this, viewProfile); 0065 #endif 0066 }; 0067 0068 switch (notification->type()) { 0069 case Notification::Mention: 0070 if (!account->config()->notifyMention()) { 0071 return; 0072 } 0073 knotification = new KNotification(QStringLiteral("mention")); 0074 knotification->setTitle(i18n("%1 mentioned you", notification->identity()->displayName())); 0075 addViewPostAction(); 0076 break; 0077 case Notification::Status: 0078 if (!account->config()->notifyStatus()) { 0079 return; 0080 } 0081 knotification = new KNotification(QStringLiteral("status")); 0082 knotification->setTitle(i18n("%1 wrote a new post", notification->identity()->displayName())); 0083 addViewPostAction(); 0084 break; 0085 case Notification::Repeat: 0086 if (!account->config()->notifyBoost()) { 0087 return; 0088 } 0089 knotification = new KNotification(QStringLiteral("boost")); 0090 knotification->setTitle(i18n("%1 boosted your post", notification->identity()->displayName())); 0091 addViewPostAction(); 0092 break; 0093 case Notification::Follow: 0094 if (!account->config()->notifyFollow()) { 0095 return; 0096 } 0097 knotification = new KNotification(QStringLiteral("follow")); 0098 knotification->setTitle(i18n("%1 followed you", notification->identity()->displayName())); 0099 addViewUserAction(); 0100 break; 0101 case Notification::FollowRequest: 0102 if (!account->config()->notifyFollowRequest()) { 0103 return; 0104 } 0105 knotification = new KNotification(QStringLiteral("follow-request")); 0106 knotification->setTitle(i18n("%1 requested to follow you", notification->identity()->displayName())); 0107 addViewUserAction(); 0108 break; 0109 case Notification::Favorite: 0110 if (!account->config()->notifyFavorite()) { 0111 return; 0112 } 0113 knotification = new KNotification(QStringLiteral("favorite")); 0114 knotification->setTitle(i18n("%1 favorited your post", notification->identity()->displayName())); 0115 addViewPostAction(); 0116 break; 0117 case Notification::Poll: 0118 if (!account->config()->notifyPoll()) { 0119 return; 0120 } 0121 knotification = new KNotification(QStringLiteral("poll")); 0122 knotification->setTitle(i18n("Poll by %1 has ended", notification->identity()->displayName())); 0123 addViewPostAction(); 0124 break; 0125 case Notification::Update: 0126 if (!account->config()->notifyUpdate()) { 0127 return; 0128 } 0129 knotification = new KNotification(QStringLiteral("update")); 0130 knotification->setTitle(i18n("%1 edited a post", notification->identity()->displayName())); 0131 addViewPostAction(); 0132 break; 0133 0134 default: 0135 Q_UNREACHABLE(); 0136 } 0137 0138 if (notification->post() != nullptr) { 0139 knotification->setText(notification->post()->content()); 0140 } 0141 knotification->setHint(QStringLiteral("x-kde-origin-name"), account->identity()->displayName()); 0142 0143 if (!notification->identity()->avatarUrl().isEmpty()) { 0144 const auto avatarUrl = notification->identity()->avatarUrl(); 0145 auto request = QNetworkRequest(avatarUrl); 0146 auto reply = m_nam->get(request); 0147 connect(reply, &QNetworkReply::finished, this, [reply, knotification]() { 0148 reply->deleteLater(); 0149 if (reply->error() != QNetworkReply::NoError) { 0150 knotification->sendEvent(); 0151 return; 0152 } 0153 QPixmap img; 0154 img.loadFromData(reply->readAll()); 0155 0156 // Handle avatars that are lopsided in one dimension 0157 const int biggestDimension = std::max(img.width(), img.height()); 0158 const QRect imageRect{0, 0, biggestDimension, biggestDimension}; 0159 0160 QImage roundedImage(imageRect.size(), QImage::Format_ARGB32); 0161 roundedImage.fill(Qt::transparent); 0162 0163 QPainter painter(&roundedImage); 0164 painter.setRenderHint(QPainter::SmoothPixmapTransform); 0165 painter.setPen(Qt::NoPen); 0166 0167 // Fill background for transparent avatars 0168 painter.setBrush(Qt::white); 0169 painter.drawRoundedRect(imageRect, imageRect.width(), imageRect.height()); 0170 0171 QBrush brush(img.scaledToHeight(biggestDimension)); 0172 painter.setBrush(brush); 0173 painter.drawRoundedRect(imageRect, imageRect.width(), 0174 imageRect.height()); 0175 painter.end(); 0176 0177 knotification->setPixmap( 0178 QPixmap::fromImage(std::move(roundedImage))); 0179 knotification->sendEvent(); 0180 }); 0181 } else { 0182 knotification->sendEvent(); 0183 } 0184 } 0185 0186 #include "moc_notificationhandler.cpp"