Skip to content
Snippets Groups Projects
ChatPage.h 8.47 KiB
Newer Older
  • Learn to ignore specific revisions
  • // SPDX-FileCopyrightText: Nheko Contributors
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    #include <atomic>
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    #include <optional>
    #include <variant>
    
    
    #include <mtx/common.hpp>
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    #include <mtx/events.hpp>
    #include <mtx/events/encrypted.hpp>
    #include <mtx/events/member.hpp>
    
    #include <mtx/events/policy_rules.hpp>
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    #include <mtx/events/presence.hpp>
    
    #include <mtx/secret_storage.hpp>
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    #include <QMap>
    
    Joe Donofry's avatar
    Joe Donofry committed
    #include <QPoint>
    
    #include <QSharedPointer>
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    #include <QTimer>
    
    
    #include "CacheCryptoStructs.h"
    
    #include "ui/RoomSummary.h"
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    class TimelineViewManager;
    
    class UserSettings;
    
    class NotificationsManager;
    
    class TimelineModel;
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    class CallManager;
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    namespace mtx::requests {
    struct CreateRoom;
    }
    namespace mtx::responses {
    struct Notifications;
    struct Sync;
    struct Timeline;
    struct Rooms;
    
    using SecretsToDecrypt = std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData>;
    
    
    class ChatPage final : public QObject
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    {
    
        Q_OBJECT
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
    public:
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        ChatPage(QSharedPointer<UserSettings> userSettings, QObject *parent = nullptr);
    
        // Initialize all the components of the UI.
        void bootstrap(QString userid, QString homeserver, QString token);
    
        static ChatPage *instance() { return instance_; }
    
        QSharedPointer<UserSettings> userSettings() { return userSettings_; }
        CallManager *callManager() { return callManager_; }
        TimelineViewManager *timelineManager() { return view_manager_; }
        void deleteConfigs();
    
        void initiateLogout();
    
        QString status() const;
        void setStatus(const QString &status);
    
        mtx::presence::PresenceState currentPresence() const;
    
        void startChat(QString userid, std::optional<bool> encryptionEnabled);
    
        //! Check if the given room is currently open.
        bool isRoomActive(const QString &room_id);
    
    
        const std::unique_ptr<mtx::pushrules::PushRuleEvaluator> &pushruleEvaluator() const
        {
            return pushrules;
        }
    
    
        void removeAllNotifications();
    
    
        bool handleMatrixUri(QString uri);
    
        bool handleMatrixUri(const QUrl &uri);
    
    
        void startChat(QString userid) { startChat(userid, std::nullopt); }
    
        void leaveRoom(const QString &room_id, const QString &reason);
    
        void createRoom(const mtx::requests::CreateRoom &req);
    
        void joinRoom(const QString &room, const QString &reason = "");
    
        void knockRoom(const QString &room, QString reason = "") { knockRoom(room, {}, reason, false); }
        void knockRoom(const QString &room,
                       const std::vector<std::string> &via,
    
                       QString reason             = "",
                       bool failedJoin            = false,
                       bool promptForConfirmation = true);
    
        void joinRoomVia(const std::string &room_id,
                         const std::vector<std::string> &via,
    
                         bool promptForConfirmation = true,
                         const QString &reason      = "");
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        void inviteUser(const QString &room, QString userid, QString reason);
        void kickUser(const QString &room, QString userid, QString reason);
        void banUser(const QString &room, QString userid, QString reason);
        void unbanUser(const QString &room, QString userid, QString reason);
    
    
        void receivedSessionKey(const std::string &room_id, const std::string &session_id);
        void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
                                      const SecretsToDecrypt &secrets);
    
        void sendNotificationReply(const QString &roomid, const QString &eventid, const QString &body);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    signals:
    
        void connectionLost();
        void connectionRestored();
    
        void contentLoaded();
        void closing();
        void changeWindowTitle(const int);
        void unreadMessages(int count);
        void showNotification(const QString &msg);
        void showLoginPage(const QString &msg);
        void showUserSettingsPage();
    
        void ownProfileOk();
        void setUserDisplayName(const QString &name);
        void setUserAvatar(const QString &avatar);
        void loggedOut();
    
        void trySyncCb();
        void tryDelayedSyncCb();
        void tryInitialSyncCb();
        void newSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token);
        void leftRoom(const QString &room_id);
        void newRoom(const QString &room_id);
        void changeToRoom(const QString &room_id);
    
        void startRemoveFallbackKeyTimer();
    
        void initializeViews(const mtx::responses::Sync &rooms);
    
        void initializeEmptyViews();
    
        void syncUI(const mtx::responses::Sync &sync);
    
        void dropToLoginPageCb(const QString &msg);
    
        void notifyMessage(const QString &roomid,
                           const QString &eventid,
                           const QString &roomname,
                           const QString &sender,
                           const QString &message,
                           const QImage &icon);
    
        void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state);
        void themeChanged();
        void decryptSidebarChanged();
    
        //! Signals for device verificaiton
        void receivedDeviceVerificationAccept(const mtx::events::msg::KeyVerificationAccept &message);
        void receivedDeviceVerificationRequest(const mtx::events::msg::KeyVerificationRequest &message,
                                               std::string sender);
        void receivedRoomDeviceVerificationRequest(
          const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
          TimelineModel *model);
        void receivedDeviceVerificationCancel(const mtx::events::msg::KeyVerificationCancel &message);
        void receivedDeviceVerificationKey(const mtx::events::msg::KeyVerificationKey &message);
        void receivedDeviceVerificationMac(const mtx::events::msg::KeyVerificationMac &message);
        void receivedDeviceVerificationStart(const mtx::events::msg::KeyVerificationStart &message,
                                             std::string sender);
        void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
        void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
    
        void downloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
                               const SecretsToDecrypt &secrets);
    
        void showRoomJoinPrompt(RoomSummary *);
    
        void internalKnock(const QString &room,
                           const std::vector<std::string> &via,
    
                           QString reason             = "",
                           bool failedJoin            = false,
                           bool promptForConfirmation = true);
    
        void newOnlineKeyBackupAvailable();
    
        void callFunctionOnGuiThread(std::function<void()>);
    
    
        void logout();
        void removeRoom(const QString &room_id);
        void changeRoom(const QString &room_id);
        void dropToLoginPage(const QString &msg);
    
        void handleSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
    private:
    
        static ChatPage *instance_;
    
        void startInitialSync();
        void tryInitialSync();
        void trySync();
        void verifyOneTimeKeyCountAfterStartup();
    
        void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts,
                                   const std::optional<std::vector<std::string>> &fallback_keys);
        void removeOldFallbackKey();
    
        void getProfileInfo();
        void getBackupVersion();
    
        using UserID      = QString;
        using Membership  = mtx::events::StateEvent<mtx::events::state::Member>;
        using Memberships = std::map<std::string, Membership>;
    
        void loadStateFromCache();
        void resetUI();
    
        template<class Collection>
        Memberships getMemberships(const std::vector<Collection> &events) const;
    
        template<typename T>
        void connectCallMessage();
    
    trilene's avatar
    trilene committed
    
    
        TimelineViewManager *view_manager_;
    
        QTimer connectivityTimer_;
        std::atomic_bool isConnected_;
    
        // Global user settings.
        QSharedPointer<UserSettings> userSettings_;
    
        NotificationsManager *notificationsManager;
    
        CallManager *callManager_;
    
    
        std::unique_ptr<mtx::pushrules::PushRuleEvaluator> pushrules;
    
    
        QDateTime lastSpacesUpdate = QDateTime::currentDateTime();
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    };
    
    
    template<class Collection>
    std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>>
    ChatPage::getMemberships(const std::vector<Collection> &collection) const
    {
    
        std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>> memberships;
    
        using Member = mtx::events::StateEvent<mtx::events::state::Member>;
    
        for (const auto &event : collection) {
            if (auto member = std::get_if<Member>(event)) {
                memberships.emplace(member->state_key, *member);
    
        return memberships;