File indexing completed on 2024-12-01 04:37:05

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 "teamchannelswidget.h"
0008 #include "channels/createchanneljob.h"
0009 #include "connection.h"
0010 #include "dialogs/createnewchanneldialog.h"
0011 #include "groups/creategroupsjob.h"
0012 #include "model/teamroomsfilterproxymodel.h"
0013 #include "model/teamroomsmodel.h"
0014 #include "rocketchataccount.h"
0015 #include "ruqolawidgets_debug.h"
0016 #include "teams/teamaddroomsjob.h"
0017 #include "teams/teamchannelscombobox.h"
0018 #include "teams/teamremoveroomjob.h"
0019 #include "teams/teamroom.h"
0020 #include "teams/teamsearchroomdialog.h"
0021 #include "teams/teamslistroomsjob.h"
0022 #include "teams/teamupdateroomjob.h"
0023 #include <KLineEditEventHandler>
0024 
0025 #include <KLocalizedString>
0026 #include <KMessageBox>
0027 #include <QHBoxLayout>
0028 #include <QLineEdit>
0029 #include <QListView>
0030 #include <QMenu>
0031 #include <QVBoxLayout>
0032 
0033 TeamChannelsWidget::TeamChannelsWidget(RocketChatAccount *account, QWidget *parent)
0034     : QWidget(parent)
0035     , mListView(new QListView(this))
0036     , mSearchLineEdit(new QLineEdit(this))
0037     , mTeamChannelsCombobox(new TeamChannelsComboBox(this))
0038     , mTeamRoomsModel(new TeamRoomsModel(this))
0039     , mTeamRoomFilterProxyModel(new TeamRoomsFilterProxyModel(mTeamRoomsModel, this))
0040     , mRocketChatAccount(account)
0041 {
0042     auto mainLayout = new QVBoxLayout(this);
0043     mainLayout->setObjectName(QStringLiteral("mainLayout"));
0044     mainLayout->setContentsMargins({});
0045 
0046     auto hboxLayout = new QHBoxLayout;
0047     hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
0048     hboxLayout->setContentsMargins({});
0049 
0050     mSearchLineEdit->setObjectName(QStringLiteral("mSearchLineEdit"));
0051     hboxLayout->addWidget(mSearchLineEdit);
0052     connect(mSearchLineEdit, &QLineEdit::textChanged, this, &TeamChannelsWidget::slotTextChanged);
0053 
0054     mTeamChannelsCombobox->setObjectName(QStringLiteral("mTeamChannelsCombobox"));
0055     hboxLayout->addWidget(mTeamChannelsCombobox);
0056 
0057     mainLayout->addLayout(hboxLayout);
0058 
0059     mSearchLineEdit->setPlaceholderText(i18n("Search room..."));
0060     mSearchLineEdit->setClearButtonEnabled(true);
0061     KLineEditEventHandler::catchReturnKey(mSearchLineEdit);
0062 
0063     mListView->setObjectName(QStringLiteral("mListView"));
0064     mainLayout->addWidget(mListView);
0065 
0066     mListView->setModel(mTeamRoomFilterProxyModel);
0067     connect(mTeamChannelsCombobox, &TeamChannelsComboBox::currentIndexChanged, this, &TeamChannelsWidget::slotTypeTeamListChanged);
0068     mListView->setContextMenuPolicy(Qt::CustomContextMenu);
0069     connect(mListView, &QListView::customContextMenuRequested, this, &TeamChannelsWidget::slotCustomContextMenuRequested);
0070 }
0071 
0072 TeamChannelsWidget::~TeamChannelsWidget() = default;
0073 
0074 void TeamChannelsWidget::slotTypeTeamListChanged(int index)
0075 {
0076     mTeamRoomFilterProxyModel->setSortByAutoJoin(index == 1 ? true : false);
0077 }
0078 
0079 void TeamChannelsWidget::setRoom(Room *room)
0080 {
0081     mRoom = room;
0082     mTeamId = mRoom->teamInfo().teamId();
0083     initializeTeamRoomsList();
0084 }
0085 
0086 void TeamChannelsWidget::initializeTeamRoomsList()
0087 {
0088     auto job = new RocketChatRestApi::TeamsListRoomsJob(this);
0089     job->setTeamId(mTeamId);
0090     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0091     connect(job, &RocketChatRestApi::TeamsListRoomsJob::teamListRoomsDone, this, &TeamChannelsWidget::slotTeamListRoomsDone);
0092     if (!job->start()) {
0093         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamsListRoomsJob job";
0094     }
0095 }
0096 
0097 void TeamChannelsWidget::slotTeamListRoomsDone(const QJsonObject &obj)
0098 {
0099     const QVector<TeamRoom> teamRooms = TeamRoom::parseTeamRooms(obj);
0100     mTeamRoomsModel->setTeamRooms(std::move(teamRooms));
0101 }
0102 
0103 void TeamChannelsWidget::slotTextChanged(const QString &str)
0104 {
0105     mTeamRoomFilterProxyModel->setFilterString(str);
0106 }
0107 
0108 void TeamChannelsWidget::slotCustomContextMenuRequested(const QPoint &pos)
0109 {
0110     QMenu menu(this);
0111     QModelIndex index = mListView->indexAt(pos);
0112     if (mRoom->hasPermission(QStringLiteral("add-team-channel"))) {
0113         menu.addAction(i18n("Add Existing Room"), this, &TeamChannelsWidget::slotAddExistingRoom);
0114         menu.addSeparator();
0115         menu.addAction(QIcon::fromTheme(QStringLiteral("irc-join-channel")), i18n("Create Room"), this, &TeamChannelsWidget::slotCreateRoom);
0116     }
0117     if (index.isValid()) {
0118         if (mRoom->hasPermission(QStringLiteral("edit-team-channel"))) {
0119             menu.addSeparator();
0120             const bool autojoin = index.data(TeamRoomsModel::AutoJoin).toBool();
0121             menu.addAction(autojoin ? i18n("Remove Autojoin") : i18n("Add Autojoin"), this, [this, index, autojoin]() {
0122                 const QString roomId = index.data(TeamRoomsModel::Identifier).toString();
0123                 updateAutojoin(roomId, autojoin);
0124             });
0125         }
0126         if (mRoom->hasPermission(QStringLiteral("remove-team-channel"))) {
0127             menu.addSeparator();
0128             menu.addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("Remove from Team"), this, [this, index]() {
0129                 const QString roomId = index.data(TeamRoomsModel::Identifier).toString();
0130                 removeRoomFromTeam(roomId);
0131             });
0132         }
0133     }
0134     if (!menu.isEmpty()) {
0135         menu.exec(mListView->viewport()->mapToGlobal(pos));
0136     }
0137 }
0138 
0139 void TeamChannelsWidget::updateAutojoin(const QString &roomId, bool autojoin)
0140 {
0141     auto job = new RocketChatRestApi::TeamUpdateRoomJob(this);
0142     job->setIsDefault(!autojoin);
0143     job->setRoomId(roomId);
0144     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0145     connect(job, &RocketChatRestApi::TeamUpdateRoomJob::teamUpdateRoomDone, this, &TeamChannelsWidget::slotTeamUpdateRoomDone);
0146     if (!job->start()) {
0147         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamUpdateRoomJob job";
0148     }
0149 }
0150 
0151 void TeamChannelsWidget::slotTeamUpdateRoomDone(const QJsonObject &replyObject)
0152 {
0153     const QJsonObject room = replyObject.value(QLatin1String("room")).toObject();
0154     TeamRoom teamRoom;
0155     teamRoom.parse(room);
0156     mTeamRoomsModel->setRoomChanged(std::move(teamRoom));
0157 }
0158 
0159 void TeamChannelsWidget::removeRoomFromTeam(const QString &roomId)
0160 {
0161     if (KMessageBox::ButtonCode::PrimaryAction
0162         == KMessageBox::questionTwoActions(this,
0163                                            i18n("Would you like to remove this Channel from team?"),
0164                                            i18nc("@title", "Remove Channel from Team"),
0165                                            KStandardGuiItem::remove(),
0166                                            KStandardGuiItem::cancel())) {
0167         auto job = new RocketChatRestApi::TeamRemoveRoomJob(this);
0168         job->setTeamId(mTeamId);
0169         job->setRoomId(roomId);
0170         mRocketChatAccount->restApi()->initializeRestApiJob(job);
0171         connect(job, &RocketChatRestApi::TeamRemoveRoomJob::removeTeamRoomDone, this, &TeamChannelsWidget::slotRemoveTeamRoomDone);
0172         if (!job->start()) {
0173             qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamsListRoomsJob job";
0174         }
0175     }
0176 }
0177 
0178 void TeamChannelsWidget::slotRemoveTeamRoomDone()
0179 {
0180     // TODO try to remove item without sending new rest api call
0181     initializeTeamRoomsList();
0182 }
0183 
0184 void TeamChannelsWidget::slotAddExistingRoom()
0185 {
0186     QStringList roomIds;
0187     QPointer<TeamSearchRoomDialog> dlg = new TeamSearchRoomDialog(mRocketChatAccount, this);
0188     if (dlg->exec()) {
0189         roomIds = dlg->roomIds();
0190     }
0191     delete dlg;
0192     if (!roomIds.isEmpty()) {
0193         auto job = new RocketChatRestApi::TeamAddRoomsJob(this);
0194         job->setTeamId(mTeamId);
0195         job->setRoomIds(roomIds);
0196         mRocketChatAccount->restApi()->initializeRestApiJob(job);
0197         connect(job, &RocketChatRestApi::TeamAddRoomsJob::teamAddRoomsDone, this, &TeamChannelsWidget::slotTeamAddRoomsDone);
0198         if (!job->start()) {
0199             qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start TeamAddRoomsJob job";
0200         }
0201     }
0202 }
0203 
0204 void TeamChannelsWidget::slotTeamAddRoomsDone(const QJsonObject &obj)
0205 {
0206     // qDebug() << " obj " << obj;
0207     const QVector<TeamRoom> teamRooms = TeamRoom::parseTeamRooms(obj);
0208     if (!teamRooms.isEmpty()) {
0209         mTeamRoomsModel->insertRooms(teamRooms);
0210     }
0211 }
0212 
0213 void TeamChannelsWidget::slotCreateRoom()
0214 {
0215     QPointer<CreateNewChannelDialog> dlg = new CreateNewChannelDialog(mRocketChatAccount, this);
0216     CreateNewChannelWidget::Features flags;
0217     if (mRocketChatAccount->broadCastEnabled()) {
0218         flags |= CreateNewChannelWidget::Feature::BroadCast;
0219     }
0220     if (mRocketChatAccount->encryptionEnabled()) {
0221         flags |= CreateNewChannelWidget::Feature::Encrypted;
0222     }
0223     dlg->setFeatures(flags);
0224     if (dlg->exec()) {
0225         RocketChatRestApi::CreateChannelTeamInfo createRoominfo = dlg->channelInfo(false);
0226         createRoominfo.teamId = mTeamId;
0227         createRoominfo.infoType = RocketChatRestApi::CreateChannelTeamInfo::CreateInfoType::Channel;
0228         if (createRoominfo.privateChannel) {
0229             createGroups(createRoominfo);
0230         } else {
0231             createChannels(createRoominfo);
0232         }
0233     }
0234     delete dlg;
0235 }
0236 
0237 void TeamChannelsWidget::createChannels(const RocketChatRestApi::CreateChannelTeamInfo &info)
0238 {
0239     auto job = new RocketChatRestApi::CreateChannelJob(this);
0240     // TODO connect(job, &RocketChatRestApi::CreateChannelJob::addJoinCodeToChannel, this, &RestApiConnection::slotAddJoinCodeToChannel);
0241     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0242     connect(job, &RocketChatRestApi::CreateChannelJob::createChannelDone, this, [this](const QJsonObject &replyObject) {
0243         const QJsonObject obj = replyObject[QLatin1String("channel")].toObject();
0244         TeamRoom teamRoom;
0245         teamRoom.parse(obj);
0246         mTeamRoomsModel->insertRooms({teamRoom});
0247     });
0248     job->setCreateChannelInfo(info);
0249     if (!job->start()) {
0250         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start CreateChannelJob job";
0251     }
0252 }
0253 
0254 void TeamChannelsWidget::createGroups(const RocketChatRestApi::CreateChannelTeamInfo &info)
0255 {
0256     auto job = new RocketChatRestApi::CreateGroupsJob(this);
0257     mRocketChatAccount->restApi()->initializeRestApiJob(job);
0258     job->setCreateGroupsInfo(info);
0259     connect(job, &RocketChatRestApi::CreateGroupsJob::createGroupsDone, this, [this](const QJsonObject &replyObject) {
0260         const QJsonObject obj = replyObject[QLatin1String("group")].toObject();
0261         TeamRoom teamRoom;
0262         teamRoom.parse(obj);
0263         mTeamRoomsModel->insertRooms({teamRoom});
0264     });
0265     if (!job->start()) {
0266         qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start CreateGroupsJob job";
0267     }
0268 }
0269 
0270 #include "moc_teamchannelswidget.cpp"