File indexing completed on 2024-04-28 04:59:37

0001 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
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 <QObject>
0007 #include <QQmlEngine>
0008 #include <QTextCursor>
0009 
0010 /**
0011  * @brief Defines a user mention in the current chat or edit text.
0012  */
0013 struct Mention {
0014     QTextCursor cursor; /**< Contains the mention's text and position in the text.  */
0015     QString text; /**< The inserted text of the mention. */
0016     int start = 0; /**< Start position of the mention. */
0017     int position = 0; /**< End position of the mention. */
0018     QString id; /**< The id the mention (used to create link when sending the message). */
0019 };
0020 
0021 /**
0022  * @class ChatBarCache
0023  *
0024  * A class to cache data from a chat bar.
0025  *
0026  * A chat bar can be anything that allows users to compose or edit message, it doesn't
0027  * necessarily have to use the ChatBar component, e.g. MessageEditComponent.
0028  *
0029  * This object is intended to allow the current contents of a chat bar to be cached
0030  * between different rooms, i.e. there is an expectation that each NeoChatRoom could
0031  * have a separate cache for each chat bar.
0032  *
0033  * @note The NeoChatRoom which this component is created in is expected to be set
0034  *       as it's parent. This is necessary for certain functions which need to get
0035  *       relevant room information.
0036  *
0037  * @sa ChatBar, MessageEditComponent, NeoChatRoom
0038  */
0039 class ChatBarCache : public QObject
0040 {
0041     Q_OBJECT
0042     QML_ELEMENT
0043     QML_UNCREATABLE("")
0044 
0045     /**
0046      * @brief The text in the chat bar.
0047      *
0048      * Due to problems with QTextDocument, unlike the other properties here,
0049      * text is *not* used to store the text when switching rooms.
0050      */
0051     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
0052 
0053     /**
0054      * @brief Whether the chat bar is currently replying to a message.
0055      */
0056     Q_PROPERTY(bool isReplying READ isReplying NOTIFY relationIdChanged)
0057 
0058     /**
0059      * @brief The Matrix message ID of an event being replied to, if any.
0060      *
0061      * Will return empty if the RelationType is currently set to None or Edit.
0062      *
0063      * @note Replying, editing and attachments are exclusive so setting this will
0064      *       clear an edit or attachment.
0065      *
0066      * @sa RelationType
0067      */
0068     Q_PROPERTY(QString replyId READ replyId WRITE setReplyId NOTIFY relationIdChanged)
0069 
0070     /**
0071      * @brief Whether the chat bar is currently editing a message.
0072      */
0073     Q_PROPERTY(bool isEditing READ isEditing NOTIFY relationIdChanged)
0074 
0075     /**
0076      * @brief The Matrix message ID of an event being edited, if any.
0077      *
0078      * Will return empty if the RelationType is currently set to None or Reply.
0079      *
0080      * @note Replying, editing and attachments are exclusive so setting this will
0081      *       clear an reply or attachment.
0082      *
0083      * @sa RelationType
0084      */
0085     Q_PROPERTY(QString editId READ editId WRITE setEditId NOTIFY relationIdChanged)
0086 
0087     /**
0088      * @brief Get the user for the message being replied to.
0089      *
0090      * This is different to getting a Quotient::User object
0091      * as neither of those can provide details like the displayName or avatarMediaId
0092      * without the room context as these can vary from room to room.
0093      *
0094      * Returns an empty user if not replying to a message.
0095      *
0096      * The user QVariantMap has the following properties:
0097      *  - isLocalUser - Whether the user is the local user.
0098      *  - id - The matrix ID of the user.
0099      *  - displayName - Display name in the context of this room.
0100      *  - avatarSource - The mxc URL for the user's avatar in the current room.
0101      *  - avatarMediaId - Avatar id in the context of this room.
0102      *  - color - Color for the user.
0103      *  - object - The Quotient::User object for the user.
0104      *
0105      * @sa getUser, Quotient::User
0106      */
0107     Q_PROPERTY(QVariantMap relationUser READ relationUser NOTIFY relationIdChanged)
0108 
0109     /**
0110      * @brief The content of the related message.
0111      *
0112      * Will be QString() if no related message.
0113      */
0114     Q_PROPERTY(QString relationMessage READ relationMessage NOTIFY relationIdChanged)
0115 
0116     /**
0117      * @brief Whether the chat bar is replying in a thread.
0118      */
0119     Q_PROPERTY(bool isThreaded READ isThreaded NOTIFY threadIdChanged)
0120 
0121     /**
0122      * @brief The Matrix message ID of thread root event, if any.
0123      */
0124     Q_PROPERTY(QString threadId READ threadId WRITE setThreadId NOTIFY threadIdChanged)
0125 
0126     /**
0127      * @brief The local path for a file to send, if any.
0128      *
0129      * @note Replying, editing and attachments are exclusive so setting this will
0130      *       clear an edit or reply.
0131      */
0132     Q_PROPERTY(QString attachmentPath READ attachmentPath WRITE setAttachmentPath NOTIFY attachmentPathChanged)
0133 
0134 public:
0135     /**
0136      * @brief Describes the type of relation which relationId can refer to.
0137      *
0138      * A chat bar can only be relating to a single message at a time making these
0139      * exclusive.
0140      */
0141     enum RelationType {
0142         Reply, /**< The current relation is a message being replied to. */
0143         Edit, /**< The current relation is a message being edited. */
0144         None, /**< There is currently no relation event */
0145     };
0146     Q_ENUM(RelationType)
0147 
0148     explicit ChatBarCache(QObject *parent = nullptr);
0149 
0150     QString text() const;
0151     void setText(const QString &text);
0152 
0153     bool isReplying() const;
0154     QString replyId() const;
0155     void setReplyId(const QString &replyId);
0156 
0157     bool isEditing() const;
0158     QString editId() const;
0159     void setEditId(const QString &editId);
0160 
0161     QVariantMap relationUser() const;
0162 
0163     QString relationMessage() const;
0164 
0165     bool isThreaded() const;
0166     QString threadId() const;
0167     void setThreadId(const QString &threadId);
0168 
0169     QString attachmentPath() const;
0170     void setAttachmentPath(const QString &attachmentPath);
0171 
0172     /**
0173      * @brief Retrieve the mentions for the current chat bar text.
0174      */
0175     QList<Mention> *mentions();
0176 
0177     /**
0178      * @brief Get the saved chat bar text.
0179      */
0180     QString savedText() const;
0181 
0182     /**
0183      * @brief Save the chat bar text.
0184      */
0185     void setSavedText(const QString &savedText);
0186 
0187 Q_SIGNALS:
0188     void textChanged();
0189     void relationIdChanged();
0190     void threadIdChanged();
0191     void attachmentPathChanged();
0192 
0193 private:
0194     QString m_text = QString();
0195     QString m_relationId = QString();
0196     RelationType m_relationType = RelationType::None;
0197     QString m_threadId = QString();
0198     QString m_attachmentPath = QString();
0199     QList<Mention> m_mentions;
0200     QString m_savedText;
0201 };