File indexing completed on 2024-04-28 08:51:49

0001 // SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
0002 // SPDX-License-Identifier: GPL-3.0-only
0003 
0004 #pragma once
0005 
0006 #include <QObject>
0007 #include <QQmlEngine>
0008 #include <QQuickItem>
0009 
0010 #include "neochatconnection.h"
0011 #include <Quotient/accountregistry.h>
0012 #include <Quotient/settings.h>
0013 
0014 #ifdef HAVE_KUNIFIEDPUSH
0015 #include <kunifiedpush/connector.h>
0016 #endif
0017 
0018 class TrayIcon;
0019 class QQuickTextDocument;
0020 
0021 namespace QKeychain
0022 {
0023 class ReadPasswordJob;
0024 }
0025 
0026 /**
0027  * @class Controller
0028  *
0029  * A singleton class designed to help manage the application.
0030  *
0031  * There are also a bunch of helper functions that currently don't fit anywhere
0032  * else.
0033  */
0034 class Controller : public QObject
0035 {
0036     Q_OBJECT
0037     QML_ELEMENT
0038     QML_SINGLETON
0039 
0040     /**
0041      * @brief The current connection for the rest of NeoChat to use.
0042      */
0043     Q_PROPERTY(NeoChatConnection *activeConnection READ activeConnection WRITE setActiveConnection NOTIFY activeConnectionChanged)
0044 
0045     /**
0046      * @brief Whether the OS NeoChat is running on supports sytem tray icons.
0047      */
0048     Q_PROPERTY(bool supportSystemTray READ supportSystemTray CONSTANT)
0049 
0050     /**
0051      * @brief Whether NeoChat is running as a flatpak.
0052      *
0053      * This is the only way to gate NeoChat features in flatpaks in QML.
0054      */
0055     Q_PROPERTY(bool isFlatpak READ isFlatpak CONSTANT)
0056 
0057     Q_PROPERTY(QStringList accountsLoading MEMBER m_accountsLoading NOTIFY accountsLoadingChanged)
0058 
0059 public:
0060     static Controller &instance();
0061     static Controller *create(QQmlEngine *engine, QJSEngine *)
0062     {
0063         engine->setObjectOwnership(&instance(), QQmlEngine::CppOwnership);
0064         return &instance();
0065     }
0066 
0067     void setActiveConnection(NeoChatConnection *connection);
0068     [[nodiscard]] NeoChatConnection *activeConnection() const;
0069 
0070     /**
0071      * @brief Add a new connection to the account registry.
0072      */
0073     void addConnection(NeoChatConnection *c);
0074 
0075     /**
0076      * @brief Drop a connection from the account registry.
0077      */
0078     void dropConnection(NeoChatConnection *c);
0079 
0080     /**
0081      * @brief Save an access token to the keychain for the given account.
0082      */
0083     bool saveAccessTokenToKeyChain(const Quotient::AccountSettings &account, const QByteArray &accessToken);
0084 
0085     [[nodiscard]] bool supportSystemTray() const;
0086 
0087     /**
0088      * @brief Sets the QNetworkProxy for the application.
0089      *
0090      * @sa QNetworkProxy::setApplicationProxy
0091      */
0092     Q_INVOKABLE void setApplicationProxy();
0093 
0094     bool isFlatpak() const;
0095 
0096     /**
0097      * @brief Force a QQuickTextDocument to refresh when images are loaded.
0098      *
0099      * HACK: This is a workaround for QTBUG 93281.
0100      */
0101     Q_INVOKABLE void forceRefreshTextDocument(QQuickTextDocument *textDocument, QQuickItem *item);
0102 
0103     /**
0104      * @brief Start listening for notifications in dbus-activated mode.
0105      * These notifications will quit the application when closed.
0106      */
0107     static void listenForNotifications();
0108 
0109     Quotient::AccountRegistry &accounts();
0110 
0111     static void setTestMode(bool testMode);
0112 
0113 private:
0114     explicit Controller(QObject *parent = nullptr);
0115 
0116     QPointer<NeoChatConnection> m_connection;
0117     TrayIcon *m_trayIcon = nullptr;
0118 
0119     QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const Quotient::AccountSettings &account);
0120 
0121     void loadSettings();
0122     void saveSettings() const;
0123 
0124     Quotient::AccountRegistry m_accountRegistry;
0125     QStringList m_accountsLoading;
0126     QString m_endpoint;
0127 
0128 private Q_SLOTS:
0129     void invokeLogin();
0130     void setQuitOnLastWindowClosed();
0131 
0132 Q_SIGNALS:
0133     void errorOccured(const QString &error, const QString &detail);
0134     void connectionAdded(NeoChatConnection *connection);
0135     void connectionDropped(NeoChatConnection *connection);
0136     void activeConnectionChanged();
0137     void accountsLoadingChanged();
0138 };