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"