File indexing completed on 2024-12-08 04:34:37

0001 /*
0002    SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "threadmessagewidget.h"
0008 #include "chat/followmessagejob.h"
0009 #include "chat/unfollowmessagejob.h"
0010 #include "connection.h"
0011 #include "rocketchataccount.h"
0012 #include "room.h"
0013 #include "room/messagelinewidget.h"
0014 #include "room/messagelistview.h"
0015 #include "room/roomwidgetbase.h"
0016 #include "ruqolawidgets_debug.h"
0017 
0018 #include <KLocalizedString>
0019 
0020 #include <QDragEnterEvent>
0021 #include <QDropEvent>
0022 #include <QLabel>
0023 #include <QMimeData>
0024 #include <QToolButton>
0025 #include <QVBoxLayout>
0026 
0027 #include "config-ruqola.h"
0028 
0029 #if HAVE_TEXT_TO_SPEECH
0030 #include <TextEditTextToSpeech/TextToSpeechContainerWidget>
0031 #endif
0032 
0033 ThreadMessageWidget::ThreadMessageWidget(RocketChatAccount *account, QWidget *parent)
0034     : QWidget(parent)
0035     , mThreadPreview(new QLabel(this))
0036     , mRoomWidgetBase(new RoomWidgetBase(MessageListView::Mode::ThreadEditing, this))
0037     , mRocketChatAccount(account)
0038     , mFollowButton(new QToolButton(this))
0039 #if HAVE_TEXT_TO_SPEECH
0040     , mTextToSpeechWidget(new TextEditTextToSpeech::TextToSpeechContainerWidget(this))
0041 #endif
0042 {
0043     auto mainLayout = new QVBoxLayout(this);
0044     mainLayout->setObjectName(QStringLiteral("mainLayout"));
0045     mainLayout->setContentsMargins({});
0046     mainLayout->setSpacing(0);
0047 
0048     auto hboxLayout = new QHBoxLayout;
0049     hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
0050     hboxLayout->setContentsMargins(QMargins());
0051 
0052     mainLayout->addLayout(hboxLayout);
0053 
0054     mFollowButton->setObjectName(QStringLiteral("mFollowButton"));
0055     mFollowButton->setCheckable(true);
0056     mFollowButton->setAutoRaise(true);
0057     hboxLayout->addWidget(mFollowButton);
0058     connect(mFollowButton, &QToolButton::clicked, this, &ThreadMessageWidget::slotFollowThreadChanged);
0059 
0060     mThreadPreview->setObjectName(QStringLiteral("mThreadPreview"));
0061     mThreadPreview->setContextMenuPolicy(Qt::NoContextMenu);
0062     mThreadPreview->setWordWrap(true);
0063     mThreadPreview->setTextInteractionFlags(Qt::TextBrowserInteraction);
0064     hboxLayout->addWidget(mThreadPreview);
0065 
0066 #if HAVE_TEXT_TO_SPEECH
0067     mTextToSpeechWidget->setObjectName(QStringLiteral("mTextToSpeechWidget"));
0068     mainLayout->addWidget(mTextToSpeechWidget);
0069     connect(mRoomWidgetBase, &RoomWidgetBase::textToSpeech, mTextToSpeechWidget, &TextEditTextToSpeech::TextToSpeechContainerWidget::say);
0070 #endif
0071 
0072     mRoomWidgetBase->setObjectName(QStringLiteral("mRoomWidgetBase"));
0073     mainLayout->addWidget(mRoomWidgetBase);
0074     connect(mRoomWidgetBase, &RoomWidgetBase::createNewDiscussion, this, &ThreadMessageWidget::slotCreateNewDiscussion);
0075     setAcceptDrops(true);
0076     if (mRocketChatAccount) {
0077         initialize();
0078     }
0079 }
0080 
0081 ThreadMessageWidget::~ThreadMessageWidget() = default;
0082 
0083 void ThreadMessageWidget::slotCreateNewDiscussion(const QString &messageId, const QString &originalMessage)
0084 {
0085     mRoomWidgetBase->slotCreateNewDiscussion(messageId, originalMessage, QString());
0086 }
0087 
0088 void ThreadMessageWidget::slotFollowThreadChanged(bool clicked)
0089 {
0090     if (clicked) {
0091         auto job = new RocketChatRestApi::UnFollowMessageJob(this);
0092         job->setMessageId(mThreadMessageId);
0093         mRocketChatAccount->restApi()->initializeRestApiJob(job);
0094         connect(job, &RocketChatRestApi::UnFollowMessageJob::unFollowMessageDone, this, [this]() {
0095             updateFollowThreadIcon(false); // TODO verify it
0096         });
0097         if (!job->start()) {
0098             qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start UnFollowMessageJob job";
0099         }
0100     } else {
0101         auto job = new RocketChatRestApi::FollowMessageJob(this);
0102         job->setMessageId(mThreadMessageId);
0103         mRocketChatAccount->restApi()->initializeRestApiJob(job);
0104         connect(job, &RocketChatRestApi::FollowMessageJob::followMessageDone, this, [this]() {
0105             updateFollowThreadIcon(true); // TODO verify it
0106         });
0107         if (!job->start()) {
0108             qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start FollowMessageJob job";
0109         }
0110     }
0111 }
0112 
0113 void ThreadMessageWidget::updateFollowThreadIcon(bool followThread)
0114 {
0115     mFollowButton->setIcon(followThread ? QIcon::fromTheme(QStringLiteral("notifications")) : QIcon::fromTheme(QStringLiteral("notifications-disabled")));
0116     mFollowButton->setToolTip(followThread ? i18n("Follow Message") : i18n("Unfollow Message"));
0117 }
0118 
0119 void ThreadMessageWidget::setThreadMessageInfo(const ThreadMessageWidget::ThreadMessageInfo &info)
0120 {
0121     updateFollowThreadIcon(info.threadIsFollowing);
0122     mFollowButton->setChecked(!info.threadIsFollowing);
0123 
0124     mRoom = info.room;
0125     if (mRoom) {
0126         mRoomWidgetBase->messageLineWidget()->setRoomId(mRoom->roomId());
0127         mRoomWidgetBase->messageListView()->setRoom(mRoom);
0128         mRoomWidgetBase->updateRoomReadOnly(mRoom);
0129     }
0130     mThreadPreview->setText(info.threadMessagePreview);
0131     if (mThreadMessageId != info.threadMessageId) {
0132         mThreadMessageId = info.threadMessageId;
0133         mRocketChatAccount->getThreadMessages(mThreadMessageId, info.messageThread);
0134         mRoomWidgetBase->messageListView()->setModel(mRocketChatAccount->threadMessageModel());
0135         mRoomWidgetBase->messageLineWidget()->setThreadMessageId(mThreadMessageId, {}, true);
0136     }
0137 }
0138 
0139 void ThreadMessageWidget::initialize()
0140 {
0141     mRoomWidgetBase->setCurrentRocketChatAccount(mRocketChatAccount);
0142     mRoomWidgetBase->messageLineWidget()->setCurrentRocketChatAccount(mRocketChatAccount, true);
0143     mRoomWidgetBase->messageListView()->setCurrentRocketChatAccount(mRocketChatAccount);
0144     // When we switch we need to update it.
0145     mRoomWidgetBase->messageLineWidget()->slotPublicSettingChanged();
0146     mRoomWidgetBase->messageLineWidget()->slotOwnUserPreferencesChanged();
0147 }
0148 
0149 void ThreadMessageWidget::dragEnterEvent(QDragEnterEvent *event)
0150 {
0151     const QMimeData *mimeData = event->mimeData();
0152     if (mimeData->hasUrls()) {
0153         event->accept();
0154     }
0155 }
0156 
0157 void ThreadMessageWidget::dropEvent(QDropEvent *event)
0158 {
0159     // Don't allow to drop element when it's blocked
0160     if (mRoom && mRoom->roomIsBlocked()) {
0161         return;
0162     }
0163     const QMimeData *mimeData = event->mimeData();
0164     if (mimeData->hasUrls()) {
0165         mRoomWidgetBase->messageLineWidget()->handleMimeData(mimeData);
0166     }
0167 }
0168 
0169 #include "moc_threadmessagewidget.cpp"