File indexing completed on 2024-05-12 16:27:12

0001 /*
0002    SPDX-FileCopyrightText: 2021-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "channelinfoeditablewidget.h"
0008 #include "channelinfoprunewidget.h"
0009 #include "connection.h"
0010 #include "messagetexteditor.h"
0011 #include "misc/systemmessagescombobox.h"
0012 #include "rocketchataccount.h"
0013 #include "roomavatarwidget.h"
0014 #include "ruqolawidgets_debug.h"
0015 #include "teams/teamdeletejob.h"
0016 #include "teams/teamroom.h"
0017 #include "teams/teamselectdeletedroomdialog.h"
0018 #include "teams/teamslistroomsjob.h"
0019 #include <KAuthorized>
0020 #include <KLocalizedString>
0021 #include <KMessageBox>
0022 #include <KPasswordLineEdit>
0023 #include <KSeparator>
0024 #include <QCheckBox>
0025 #include <QFormLayout>
0026 #include <QPointer>
0027 #include <QPushButton>
0028 
0029 ChannelInfoEditableWidget::ChannelInfoEditableWidget(Room *room, RocketChatAccount *account, QWidget *parent)
0030     : QWidget(parent)
0031     , mRoom(room)
0032     , mName(new QLineEdit(this))
0033     , mComment(new MessageTextEditor(this))
0034     , mAnnouncement(new MessageTextEditor(this))
0035     , mDescription(new MessageTextEditor(this))
0036     , mPasswordLineEdit(new KPasswordLineEdit(this))
0037     , mReadOnly(new QCheckBox(this))
0038     , mArchive(new QCheckBox(this))
0039     , mPrivate(new QCheckBox(this))
0040     , mEncrypted(new QCheckBox(this))
0041     , mDeleteChannel(new QPushButton(QIcon::fromTheme(QStringLiteral("edit-delete-shred")), i18n("Delete"), this))
0042     , mChannelInfoPruneWidget(new ChannelInfoPruneWidget(this))
0043     , mSystemMessageCombox(new SystemMessagesComboBox(this))
0044     , mRoomAvatarWidget(new RoomAvatarWidget(this))
0045     , mRocketChatAccount(account)
0046 {
0047     auto layout = new QFormLayout(this);
0048     layout->setObjectName(QStringLiteral("layout"));
0049     layout->setContentsMargins({});
0050 
0051     mRoomAvatarWidget->setObjectName(QStringLiteral("mRoomAvatarWidget"));
0052     layout->addRow(QStringLiteral(" "), mRoomAvatarWidget);
0053     QString str = i18n("Name:");
0054     mName->setObjectName(QStringLiteral("mName"));
0055     layout->addRow(str, mName);
0056     connect(mName, &QLineEdit::textChanged, this, [this](const QString &str) {
0057         Q_EMIT roomNameValid(!str.trimmed().isEmpty());
0058     });
0059 
0060     mComment->setObjectName(QStringLiteral("mComment"));
0061     str = i18n("Comment:");
0062     layout->addRow(str, mComment);
0063 
0064     mAnnouncement->setObjectName(QStringLiteral("mAnnouncement"));
0065     str = i18n("Announcement:");
0066     layout->addRow(str, mAnnouncement);
0067 
0068     mDescription->setObjectName(QStringLiteral("mDescription"));
0069     str = i18n("Description:");
0070 
0071     layout->addRow(str, mDescription);
0072 
0073     // Show it if room is not private
0074     mPasswordLineEdit->setObjectName(QStringLiteral("mPasswordLineEdit"));
0075     mPasswordLineEdit->setRevealPasswordAvailable(KAuthorized::authorize(QStringLiteral("lineedit_reveal_password")));
0076     layout->addRow(i18n("Password:"), mPasswordLineEdit);
0077 
0078     mReadOnly->setObjectName(QStringLiteral("mReadOnly"));
0079     layout->addRow(i18n("ReadOnly:"), mReadOnly);
0080 
0081     mArchive->setObjectName(QStringLiteral("mArchive"));
0082     layout->addRow(i18n("Archive:"), mArchive);
0083     const bool canArchiveOrUnarchive = mRocketChatAccount
0084         && (mRocketChatAccount->hasPermission(QStringLiteral("archive-room")) || mRocketChatAccount->hasPermission(QStringLiteral("unarchive-room")));
0085     mArchive->setEnabled(canArchiveOrUnarchive);
0086     connect(mArchive, &QCheckBox::clicked, this, [this](bool checked) {
0087         const QString text = checked ? i18n("Do you want to archive this room?") : i18n("Do you want to unarchive this room?");
0088         const QString title = checked ? i18n("Archive Channel") : i18n("Unarchive Channel");
0089         if (KMessageBox::ButtonCode::PrimaryAction == KMessageBox::questionTwoActions(this, text, title, KStandardGuiItem::ok(), KStandardGuiItem::cancel())) {
0090             // mRocketChatAccount->changeChannelSettings(mRoom->roomId(), RocketChatAccount::Archive, checked, mRoom->channelType());
0091         }
0092     });
0093 
0094     mPrivate->setObjectName(QStringLiteral("mPrivate"));
0095     layout->addRow(i18n("Private:"), mPrivate);
0096 
0097     mEncrypted->setObjectName(QStringLiteral("mEncrypted"));
0098     layout->addRow(i18n("Encrypted:"), mEncrypted);
0099     mEncryptedLabel = layout->labelForField(mEncrypted);
0100 
0101     mSystemMessageCombox->setObjectName(QStringLiteral("mSystemMessageCombox"));
0102     layout->addRow(i18n("Hide System Messages:"), mSystemMessageCombox);
0103 
0104     mChannelInfoPruneWidget->setObjectName(QStringLiteral("mChannelInfoPruneWidget"));
0105     layout->addRow(mChannelInfoPruneWidget);
0106     auto separator = new KSeparator(this);
0107     separator->setObjectName(QStringLiteral("separator"));
0108     layout->addWidget(separator);
0109 
0110     mDeleteChannel->setObjectName(QStringLiteral("mDeleteChannel"));
0111     layout->addRow(QStringLiteral(" "), mDeleteChannel);
0112     connect(mDeleteChannel, &QPushButton::clicked, this, [this]() {
0113         if (mRoom->teamInfo().mainTeam()) {
0114             if (KMessageBox::ButtonCode::PrimaryAction
0115                 == KMessageBox::questionTwoActions(this,
0116                                                    i18n("Do you want to delete this Team?"),
0117                                                    i18nc("@title", "Delete Team"),
0118                                                    KStandardGuiItem::del(),
0119                                                    KStandardGuiItem::cancel())) {
0120                 selectRoomToDelete(mRoom->teamInfo().teamId());
0121             }
0122         } else {
0123             if (KMessageBox::ButtonCode::PrimaryAction
0124                 == KMessageBox::questionTwoActions(this,
0125                                                    i18n("Do you want to delete this room?"),
0126                                                    i18nc("@title", "Delete Room"),
0127                                                    KStandardGuiItem::del(),
0128                                                    KStandardGuiItem::cancel())) {
0129                 mRocketChatAccount->eraseRoom(mRoom->roomId(), mRoom->channelType());
0130                 Q_EMIT channelDeleted();
0131             }
0132         }
0133     });
0134 }
0135 
0136 ChannelInfoEditableWidget::~ChannelInfoEditableWidget() = default;
0137 
0138 void ChannelInfoEditableWidget::selectRoomToDelete(const QString &teamId)
0139 {
0140     auto job = new RocketChatRestApi::TeamsListRoomsJob(this);
0141     job->setTeamId(teamId);
0142     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0143     connect(job, &RocketChatRestApi::TeamsListRoomsJob::teamListRoomsDone, this, &ChannelInfoEditableWidget::slotTeamListRoomsDone);
0144     if (!job->start()) {
0145         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamsListRoomsJob job";
0146     }
0147 }
0148 
0149 void ChannelInfoEditableWidget::deleteTeam(const QString &teamId, const QStringList &roomIds)
0150 {
0151     auto job = new RocketChatRestApi::TeamDeleteJob(this);
0152     job->setTeamId(teamId);
0153     job->setRoomsId(roomIds);
0154     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0155     connect(job, &RocketChatRestApi::TeamDeleteJob::deleteTeamDone, this, &ChannelInfoEditableWidget::slotTeamDeleteDone);
0156     if (!job->start()) {
0157         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamsListRoomsJob job";
0158     }
0159 }
0160 
0161 void ChannelInfoEditableWidget::slotTeamListRoomsDone(const QJsonObject &obj)
0162 {
0163     QVector<TeamRoom> teamRooms = TeamRoom::parseTeamRooms(obj);
0164     const QString teamId = mRoom->teamInfo().teamId();
0165     if (teamRooms.isEmpty()) {
0166         deleteTeam(teamId, {});
0167     } else {
0168         QPointer<TeamSelectDeletedRoomDialog> dlg = new TeamSelectDeletedRoomDialog(this);
0169         dlg->setTeamRooms(teamRooms);
0170         if (dlg->exec()) {
0171             const QStringList roomIds = dlg->roomsId();
0172             auto job = new RocketChatRestApi::TeamDeleteJob(this);
0173             job->setRoomsId(roomIds);
0174             job->setTeamId(teamId);
0175             mRocketChatAccount->restApi()->initializeRestApiJob(job);
0176             connect(job, &RocketChatRestApi::TeamDeleteJob::deleteTeamDone, this, &ChannelInfoEditableWidget::slotTeamDeleteDone);
0177             if (!job->start()) {
0178                 qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamsListRoomsJob job";
0179             }
0180         }
0181         delete dlg;
0182     }
0183 }
0184 
0185 void ChannelInfoEditableWidget::slotTeamDeleteDone()
0186 {
0187     Q_EMIT channelDeleted();
0188 }
0189 
0190 RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo ChannelInfoEditableWidget::saveRoomSettingsInfo() const
0191 {
0192     RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo info;
0193     if (mName->text().isEmpty()) {
0194         return info;
0195     }
0196 
0197     info.roomId = mRoom->roomId();
0198     info.joinCode = mPasswordLineEdit->password();
0199     if (mRoom->name() != mName->text()) {
0200         info.roomName = mName->text();
0201         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomName;
0202     }
0203     if (mRoom->announcement() != mAnnouncement->toPlainText()) {
0204         info.roomAnnouncement = mAnnouncement->toPlainText();
0205         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomAnnouncement;
0206     }
0207     if (mRoom->description() != mDescription->toPlainText()) {
0208         info.roomDescription = mDescription->toPlainText();
0209         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomDescription;
0210     }
0211     if (mRoom->topic() != mComment->toPlainText()) {
0212         info.roomTopic = mComment->toPlainText();
0213         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomTopic;
0214     }
0215     if (mRoom->readOnly() != mReadOnly->isChecked()) {
0216         info.readOnly = mReadOnly->isChecked();
0217         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::ReadOnly;
0218     }
0219     if (mRoom->displaySystemMessageTypes() != mSystemMessageCombox->systemMessagesSelected()) {
0220         info.systemMessages = mSystemMessageCombox->systemMessagesSelected();
0221         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::SystemMessages;
0222     }
0223     if (mRoom->encrypted() != mEncrypted->isChecked()) {
0224         info.encrypted = mEncrypted->isChecked();
0225         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::Encrypted;
0226     }
0227 
0228     if (/*(mRoom->channelType() == Room::RoomType::Private) != mPrivate->isChecked()*/ 1) { // TODO verify
0229         info.roomType = mPrivate->isChecked() ? QStringLiteral("p") : QStringLiteral("c");
0230         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomType;
0231     }
0232 
0233     if (hasRetentionPermission()) {
0234         mChannelInfoPruneWidget->saveRoomSettingsInfo(info, mRoom);
0235     }
0236     if (mRoomAvatarWidget->wasChanged()) {
0237         info.roomAvatar = mRoomAvatarWidget->roomAvatar();
0238         info.mSettingsWillBeChanged |= RocketChatRestApi::SaveRoomSettingsJob::SaveRoomSettingsInfo::RoomAvatar;
0239     }
0240     // qDebug() << " info " << info;
0241     //    mArchive->setChecked(mRoom->archived());
0242     return info;
0243 }
0244 
0245 void ChannelInfoEditableWidget::updateEditableChannelInfo()
0246 {
0247     mName->setText(mRoom->displayFName());
0248     mComment->setText(mRoom->topic());
0249     mAnnouncement->setText(mRoom->announcement());
0250     mDescription->setText(mRoom->description());
0251     mReadOnly->setChecked(mRoom->readOnly());
0252     mArchive->setChecked(mRoom->archived());
0253     mPrivate->setChecked(mRoom->channelType() == Room::RoomType::Private);
0254     mEncrypted->setVisible(mRoom->encryptedEnabled());
0255     mEncrypted->setChecked(mRoom->encrypted());
0256     mEncryptedLabel->setVisible(mRoom->encryptedEnabled());
0257     mSystemMessageCombox->setMessagesSystem(mRoom->displaySystemMessageTypes());
0258     joinCodeChanged();
0259 }
0260 
0261 void ChannelInfoEditableWidget::joinCodeChanged()
0262 {
0263     mPasswordLineEdit->lineEdit()->setPlaceholderText(mRoom->joinCodeRequired() ? i18n("This room has a password") : i18n("Add password"));
0264 }
0265 
0266 void ChannelInfoEditableWidget::connectEditableWidget()
0267 {
0268     connect(mRoom, &Room::announcementChanged, this, [this]() {
0269         mAnnouncement->setText(mRoom->announcement());
0270     });
0271     connect(mRoom, &Room::topicChanged, this, [this]() {
0272         mComment->setText(mRoom->topic());
0273     });
0274     connect(mRoom, &Room::fnameChanged, this, [this]() {
0275         mName->setText(mRoom->fName());
0276         Q_EMIT fnameChanged(mRoom->fName());
0277     });
0278     connect(mRoom, &Room::descriptionChanged, this, [this]() {
0279         mDescription->setText(mRoom->description());
0280     });
0281     connect(mRoom, &Room::readOnlyChanged, this, [this]() {
0282         mReadOnly->setChecked(mRoom->readOnly());
0283     });
0284     connect(mRoom, &Room::archivedChanged, this, [this]() {
0285         mArchive->setChecked(mRoom->archived());
0286     });
0287     connect(mRoom, &Room::joinCodeRequiredChanged, this, [this]() {
0288         joinCodeChanged();
0289     });
0290     connect(mRoom, &Room::channelTypeChanged, this, [this]() {
0291         mPrivate->setChecked(mRoom->channelType() == Room::RoomType::Private);
0292     });
0293 
0294     const Utils::AvatarInfo avatarInfo = mRoom->avatarInfo();
0295     const QString iconUrlStr = mRocketChatAccount->avatarUrl(avatarInfo);
0296     if (!iconUrlStr.isEmpty()) {
0297         const QString iconPath{QUrl(iconUrlStr).toLocalFile()};
0298         mRoomAvatarWidget->setCurrentIconPath(iconPath);
0299     }
0300 }
0301 
0302 void ChannelInfoEditableWidget::updateRetentionValue()
0303 {
0304     if (!mChannelInfoPruneWidget->isHidden()) {
0305         mChannelInfoPruneWidget->setRetentionInfo(mRoom->retentionInfo());
0306     }
0307 }
0308 
0309 void ChannelInfoEditableWidget::updateUiFromPermission()
0310 {
0311     mChannelInfoPruneWidget->setHidden(!hasRetentionPermission());
0312 }
0313 
0314 bool ChannelInfoEditableWidget::hasRetentionPermission() const
0315 {
0316     return mRoom->hasPermission(QStringLiteral("edit-room-retention-policy"));
0317 }
0318 
0319 #include "moc_channelinfoeditablewidget.cpp"