File indexing completed on 2024-09-15 04:28:35
0001 // SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> 0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 0004 #pragma once 0005 0006 #include <KConfigGroup> 0007 #include <KSharedConfig> 0008 #include <QObject> 0009 #include <QQmlEngine> 0010 #include <Quotient/room.h> 0011 #include <Quotient/uriresolver.h> 0012 #include <KConfigGroup> 0013 0014 #include "chatdocumenthandler.h" 0015 #include "enums/delegatetype.h" 0016 #include "models/mediamessagefiltermodel.h" 0017 #include "models/messagefiltermodel.h" 0018 #include "models/timelinemodel.h" 0019 0020 class NeoChatRoom; 0021 class NeoChatConnection; 0022 0023 namespace Quotient 0024 { 0025 class Room; 0026 class User; 0027 } 0028 0029 using namespace Quotient; 0030 0031 /** 0032 * @class RoomManager 0033 * 0034 * A singleton class to help manage which room is open in NeoChat. 0035 * 0036 * This class also inherits UriResolverBase and overrides the relevant functions to 0037 * resolve various URIs. The base functions visitUser(), visitRoom(), etc are held 0038 * private intentionally and instead resolveResource() should be called with either 0039 * an appropriate URI or a Matrix ID and action. 0040 */ 0041 class RoomManager : public QObject, public UriResolverBase 0042 { 0043 Q_OBJECT 0044 QML_ELEMENT 0045 QML_SINGLETON 0046 0047 Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) 0048 0049 /** 0050 * @brief The current open room in NeoChat, if any. 0051 * 0052 * @sa hasOpenRoom 0053 */ 0054 Q_PROPERTY(NeoChatRoom *currentRoom READ currentRoom NOTIFY currentRoomChanged) 0055 0056 /** 0057 * @brief The TimelineModel that should be used for room message visualisation. 0058 * 0059 * The room object the model uses to get the data will be updated by this class 0060 * so there is no need to do this manually or replace the model when a room 0061 * changes. 0062 * 0063 * @note Available here so that the room page and drawer both have access to the 0064 * same model. 0065 */ 0066 Q_PROPERTY(TimelineModel *timelineModel READ timelineModel CONSTANT) 0067 0068 /** 0069 * @brief The MessageFilterModel that should be used for room message visualisation. 0070 * 0071 * @note Available here so that the room page and drawer both have access to the 0072 * same model. 0073 */ 0074 Q_PROPERTY(MessageFilterModel *messageFilterModel READ messageFilterModel CONSTANT) 0075 0076 /** 0077 * @brief The MediaMessageFilterModel that should be used for room media message visualisation. 0078 * 0079 * @note Available here so that the room page and drawer both have access to the 0080 * same model. 0081 */ 0082 Q_PROPERTY(MediaMessageFilterModel *mediaMessageFilterModel READ mediaMessageFilterModel CONSTANT) 0083 0084 /** 0085 * @brief Whether a room is currently open in NeoChat. 0086 * 0087 * @sa room 0088 */ 0089 Q_PROPERTY(bool hasOpenRoom READ hasOpenRoom NOTIFY currentRoomChanged) 0090 0091 /** 0092 * @brief The room ID of the last space entered. 0093 */ 0094 Q_PROPERTY(QString lastSpaceId READ lastSpaceId CONSTANT) 0095 0096 /** 0097 * @brief The ChatDocumentHandler for the open room. 0098 * 0099 * @sa ChatDocumentHandler 0100 */ 0101 Q_PROPERTY(ChatDocumentHandler *chatDocumentHandler READ chatDocumentHandler WRITE setChatDocumentHandler NOTIFY chatDocumentHandlerChanged) 0102 0103 public: 0104 virtual ~RoomManager(); 0105 static RoomManager &instance(); 0106 static RoomManager *create(QQmlEngine *engine, QJSEngine *) 0107 { 0108 engine->setObjectOwnership(&instance(), QQmlEngine::CppOwnership); 0109 return &instance(); 0110 } 0111 0112 NeoChatRoom *currentRoom() const; 0113 0114 TimelineModel *timelineModel() const; 0115 MessageFilterModel *messageFilterModel() const; 0116 MediaMessageFilterModel *mediaMessageFilterModel() const; 0117 0118 /** 0119 * @brief Resolve the given URI resource. 0120 * 0121 * @note It's actually Quotient::UriResolverBase::visitResource() but with Q_INVOKABLE 0122 * and the connection grabbed from RoomManager. 0123 * 0124 * @sa Quotient::UriResolverBase::visitResource() 0125 */ 0126 Q_INVOKABLE UriResolveResult resolveResource(const Uri &uri); 0127 0128 /** 0129 * @brief Resolve the given resource. 0130 * 0131 * @note It's actually Quotient::UriResolverBase::visitResource() but with Q_INVOKABLE 0132 * and the connection grabbed from RoomManager. 0133 * 0134 * @sa Quotient::UriResolverBase::visitResource() 0135 */ 0136 Q_INVOKABLE void resolveResource(const QString &idOrUri, const QString &action = {}); 0137 0138 bool hasOpenRoom() const; 0139 0140 /** 0141 * @brief Load the last opened room or the welcome page. 0142 */ 0143 Q_INVOKABLE void loadInitialRoom(); 0144 0145 /** 0146 * @brief Open a new window with the given room. 0147 * 0148 * The open window will have its own message list for the given room. 0149 */ 0150 Q_INVOKABLE void openWindow(NeoChatRoom *room); 0151 0152 /** 0153 * @brief Leave the room and close it if it is open. 0154 */ 0155 Q_INVOKABLE void leaveRoom(NeoChatRoom *room); 0156 0157 /** 0158 * @brief Knock a room. 0159 * 0160 * See https://spec.matrix.org/latest/client-server-api/#knocking-on-rooms for 0161 * knocking on rooms. 0162 */ 0163 void knockRoom(Quotient::Connection *account, const QString &roomAliasOrId, const QString &reason, const QStringList &viaServers); 0164 0165 /** 0166 * @brief Show a media item maximized. 0167 * 0168 * @param index the index to open the maximize delegate model at. This is the 0169 * index in the MediaMessageFilterModel owned by this RoomManager. A value 0170 * of -1 opens a the default item. 0171 */ 0172 Q_INVOKABLE void maximizeMedia(int index); 0173 0174 /** 0175 * @brief Request that any full screen overlay currently open closes. 0176 */ 0177 Q_INVOKABLE void requestFullScreenClose(); 0178 0179 /** 0180 * @brief Show the JSON source for the given event Matrix ID 0181 */ 0182 Q_INVOKABLE void viewEventSource(const QString &eventId); 0183 0184 /** 0185 * @brief Show a conterxt menu for the given event. 0186 */ 0187 Q_INVOKABLE void viewEventMenu(const QString &eventId, 0188 const QVariantMap &author, 0189 DelegateType::Type delegateType, 0190 const QString &plainText, 0191 const QString &htmlText = {}, 0192 const QString &selectedText = {}, 0193 const QString &mimeType = {}, 0194 const FileTransferInfo &progressInfo = {}); 0195 0196 /** 0197 * @brief Call this when the current used connection is dropped. 0198 */ 0199 Q_INVOKABLE void reset(); 0200 0201 ChatDocumentHandler *chatDocumentHandler() const; 0202 void setChatDocumentHandler(ChatDocumentHandler *handler); 0203 0204 /** 0205 * @brief Set a URL to be loaded as the initial room. 0206 */ 0207 void setUrlArgument(const QString &arg); 0208 0209 QString lastSpaceId(); 0210 0211 NeoChatConnection *connection() const; 0212 void setConnection(NeoChatConnection *connection); 0213 0214 Q_SIGNALS: 0215 void currentRoomChanged(); 0216 0217 /** 0218 * @brief Push a new room page. 0219 * 0220 * Signal triggered when the main window pageStack should push a new page with 0221 * the message list for the given room. 0222 * 0223 * @param room the room to be shown on the new page. 0224 * @param event the event to got to if available. 0225 */ 0226 void pushRoom(NeoChatRoom *room, const QString &event); 0227 0228 /** 0229 * @brief Replace the existing room. 0230 * 0231 * Signal triggered when the room displayed by the message list should be changed. 0232 * 0233 * @param room the room to be shown on the new page. 0234 * @param event the event to got to if available. 0235 */ 0236 void replaceRoom(NeoChatRoom *room, const QString &event); 0237 0238 /** 0239 * @brief Push a new space home page. 0240 * 0241 * Signal triggered when the main window pageStack should push a new page with 0242 * the space home for the given space room. 0243 * 0244 * @param spaceRoom the space room to be shown on the new page. 0245 */ 0246 void pushSpaceHome(NeoChatRoom *spaceRoom); 0247 0248 /** 0249 * @brief Replace the existing space home. 0250 * 0251 * Signal triggered when the currently displayed room page should be changed 0252 * to the space home for the given space room. 0253 * 0254 * @param spaceRoom the space room to be shown on the new page. 0255 */ 0256 void replaceSpaceHome(NeoChatRoom *spaceRoom); 0257 0258 /** 0259 * @brief Go to the specified event in the current room. 0260 */ 0261 void goToEvent(const QString &event); 0262 0263 /** 0264 * @brief Open room in a new window. 0265 * 0266 * Signal triggered when a room needs to be opened in a new window. 0267 */ 0268 void openRoomInNewWindow(NeoChatRoom *room); 0269 0270 /** 0271 * @brief Show details for the given user. 0272 * 0273 * Ask current room to open the user's details for the give user. 0274 * This assumes the user is loaded. 0275 */ 0276 void showUserDetail(const Quotient::User *user); 0277 0278 /** 0279 * @brief Request a media item is shown maximized. 0280 * 0281 * @param index the index to open the maximize delegate model at. This is the 0282 * index in the MediaMessageFilterModel owned by this RoomManager. A value 0283 * of -1 opens a the default item. 0284 */ 0285 void showMaximizedMedia(int index); 0286 0287 /** 0288 * @brief Request that any full screen overlay closes. 0289 */ 0290 void closeFullScreen(); 0291 0292 /** 0293 * @brief Request the JSON source for the given event ID is shown. 0294 */ 0295 void showEventSource(const QString &eventId); 0296 0297 /** 0298 * @brief Request to show a menu for the given event. 0299 */ 0300 void showMessageMenu(const QString &eventId, 0301 const QVariantMap &author, 0302 DelegateType::Type delegateType, 0303 const QString &plainText, 0304 const QString &htmlText, 0305 const QString &selectedText); 0306 0307 /** 0308 * @brief Request to show a menu for the given media event. 0309 */ 0310 void showFileMenu(const QString &eventId, 0311 const QVariantMap &author, 0312 DelegateType::Type delegateType, 0313 const QString &plainText, 0314 const QString &mimeType, 0315 const FileTransferInfo &progressInfo); 0316 0317 /** 0318 * @brief Show the direct chat confirmation dialog. 0319 * 0320 * Ask current room to show confirmation dialog to open direct chat. 0321 * This assumes the user is loaded. 0322 */ 0323 void askDirectChatConfirmation(const Quotient::User *user); 0324 0325 /** 0326 * @brief Displays warning to the user. 0327 */ 0328 void warning(const QString &title, const QString &message); 0329 0330 void chatDocumentHandlerChanged(); 0331 0332 void connectionChanged(); 0333 0334 private: 0335 void openRoomForActiveConnection(); 0336 0337 NeoChatRoom *m_currentRoom; 0338 NeoChatRoom *m_lastCurrentRoom; 0339 QString m_arg; 0340 KSharedConfig::Ptr m_config; 0341 KConfigGroup m_lastRoomConfig; 0342 KConfigGroup m_lastSpaceConfig; 0343 QPointer<ChatDocumentHandler> m_chatDocumentHandler; 0344 0345 TimelineModel *m_timelineModel; 0346 MessageFilterModel *m_messageFilterModel; 0347 MediaMessageFilterModel *m_mediaMessageFilterModel; 0348 NeoChatConnection *m_connection; 0349 0350 /** 0351 * @brief Resolve a user URI. 0352 * 0353 * This overloads Quotient::UriResolverBase::visitUser(). 0354 * 0355 * Called by Quotient::UriResolverBase::visitResource() when the passed URI 0356 * identifies a Matrix user. 0357 * 0358 * @note This is private as resolveResource() should always be called, which 0359 * will in turn call Quotient::UriResolverBase::visitResource() and this 0360 * function if appropriate for the URI. 0361 * 0362 * @sa resolveResource(), Quotient::UriResolverBase::visitUser(), Quotient::UriResolverBase::visitResource() 0363 */ 0364 UriResolveResult visitUser(User *user, const QString &action) override; 0365 0366 /** 0367 * @brief Visit a room. 0368 * 0369 * This overloads Quotient::UriResolverBase::visitRoom(). 0370 * 0371 * Called by Quotient::UriResolverBase::visitResource() when the passed URI 0372 * identifies a room or an event in a room. 0373 * 0374 * @note This is private as resolveResource() should always be called, which 0375 * will in turn call Quotient::UriResolverBase::visitResource() and this 0376 * function if appropriate for the URI. 0377 * 0378 * @sa resolveResource(), Quotient::UriResolverBase::visitUser(), Quotient::UriResolverBase::visitResource() 0379 */ 0380 Q_INVOKABLE void visitRoom(Quotient::Room *room, const QString &eventId) override; 0381 0382 /** 0383 * @brief Join a room. 0384 * 0385 * This overloads Quotient::UriResolverBase::joinRoom(). 0386 * 0387 * Called by Quotient::UriResolverBase::visitResource() when the passed URI has 0388 * `action() == "join"` and identifies a room that the user defined by the 0389 * Connection argument is not a member of. 0390 * 0391 * @note This is private as resolveResource() should always be called, which 0392 * will in turn call Quotient::UriResolverBase::visitResource() and this 0393 * function if appropriate for the URI. 0394 * 0395 * @sa resolveResource(), Quotient::UriResolverBase::visitUser(), Quotient::UriResolverBase::visitResource() 0396 */ 0397 void joinRoom(Quotient::Connection *account, const QString &roomAliasOrId, const QStringList &viaServers) override; 0398 0399 /** 0400 * @brief Visit a non-matrix resource. 0401 * 0402 * This overloads Quotient::UriResolverBase::visitNonMatrix(). 0403 * 0404 * Called by Quotient::UriResolverBase::visitResource() when the passed URI 0405 * has `type() == NonMatrix` 0406 * 0407 * @note This is private as resolveResource() should always be called, which 0408 * will in turn call Quotient::UriResolverBase::visitResource() and this 0409 * function if appropriate for the URI. 0410 * 0411 * @sa resolveResource(), Quotient::UriResolverBase::visitUser(), Quotient::UriResolverBase::visitResource() 0412 */ 0413 Q_INVOKABLE bool visitNonMatrix(const QUrl &url) override; 0414 0415 private: 0416 explicit RoomManager(QObject *parent = nullptr); 0417 };