1 // SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
2 // SPDX-License-Identifier: GPL-3.0-only
3 
4 #pragma once
5 
6 #include <events/encryptionevent.h>
7 #include <events/redactionevent.h>
8 #include <events/roomavatarevent.h>
9 #include <events/roomcreateevent.h>
10 #include <events/roommemberevent.h>
11 #include <events/roommessageevent.h>
12 #include <events/simplestateevents.h>
13 
14 #include <QObject>
15 #include <QPointer>
16 #include <QTimer>
17 
18 #include "neochatuser.h"
19 #include "room.h"
20 
21 using namespace Quotient;
22 
23 class NeoChatRoom : public Room
24 {
25     Q_OBJECT
26     Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
27     Q_PROPERTY(QString cachedInput MEMBER m_cachedInput NOTIFY cachedInputChanged)
28     Q_PROPERTY(bool hasFileUploading READ hasFileUploading WRITE setHasFileUploading NOTIFY hasFileUploadingChanged)
29     Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY fileUploadingProgressChanged)
30     Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false)
31     Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged)
32     Q_PROPERTY(QDateTime lastActiveTime READ lastActiveTime NOTIFY lastActiveTimeChanged)
33     Q_PROPERTY(bool isInvite READ isInvite NOTIFY isInviteChanged)
34 
35 public:
36     explicit NeoChatRoom(Connection *connection, QString roomId, JoinState joinState = {});
37 
38     [[nodiscard]] QVariantList getUsersTyping() const;
39 
40     /// Get the interesting last event.
41     ///
42     /// This function respect the showLeaveJoinEvent setting and discard
43     /// other not interesting events. This function can return an empty pointer
44     /// when the room is empty of RoomMessageEvent.
45     [[nodiscard]] const RoomMessageEvent *lastEvent(bool ignoreStateEvent = false) const;
46 
47     /// Convenient way to get the last event but in a string format.
48     ///
49     /// \see lastEvent
50     [[nodiscard]] QString lastEventToString() const;
51 
52     /// Convenient way to get the QDateTime of the last event.
53     ///
54     /// \see lastEvent
55     [[nodiscard]] QDateTime lastActiveTime();
56 
57     bool isEventHighlighted(const Quotient::RoomEvent *e) const;
58 
hasFileUploading()59     [[nodiscard]] bool hasFileUploading() const
60     {
61         return m_hasFileUploading;
62     }
setHasFileUploading(bool value)63     void setHasFileUploading(bool value)
64     {
65         if (value == m_hasFileUploading) {
66             return;
67         }
68         m_hasFileUploading = value;
69         Q_EMIT hasFileUploadingChanged();
70     }
71 
fileUploadingProgress()72     [[nodiscard]] int fileUploadingProgress() const
73     {
74         return m_fileUploadingProgress;
75     }
setFileUploadingProgress(int value)76     void setFileUploadingProgress(int value)
77     {
78         if (m_fileUploadingProgress == value) {
79             return;
80         }
81         m_fileUploadingProgress = value;
82         Q_EMIT fileUploadingProgressChanged();
83     }
84 
85     [[nodiscard]] bool readMarkerLoaded() const;
86 
87     Q_INVOKABLE [[nodiscard]] int savedTopVisibleIndex() const;
88     Q_INVOKABLE [[nodiscard]] int savedBottomVisibleIndex() const;
89     Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex);
90 
91     Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword) const;
92     Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
93 
94     Q_INVOKABLE QUrl urlToMxcUrl(const QUrl &mxcUrl);
95 
96     [[nodiscard]] QString avatarMediaId() const;
97 
98     [[nodiscard]] QString eventToString(const RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const;
99 
100     Q_INVOKABLE [[nodiscard]] bool containsUser(const QString &userID) const;
101     Q_INVOKABLE [[nodiscard]] bool isUserBanned(const QString &user) const;
102 
103     Q_INVOKABLE [[nodiscard]] bool canSendEvent(const QString &eventType) const;
104     Q_INVOKABLE [[nodiscard]] bool canSendState(const QString &eventType) const;
105 
106     bool isInvite() const;
107 
108 private:
109     QString m_cachedInput;
110     QSet<const Quotient::RoomEvent *> highlights;
111 
112     bool m_hasFileUploading = false;
113     int m_fileUploadingProgress = 0;
114 
115     void checkForHighlights(const Quotient::TimelineItem &ti);
116 
117     void onAddNewTimelineEvents(timeline_iter_t from) override;
118     void onAddHistoricalTimelineEvents(rev_iter_t from) override;
119     void onRedaction(const RoomEvent &prevEvent, const RoomEvent &after) override;
120 
121     static QString markdownToHTML(const QString &markdown);
122 
123 private Q_SLOTS:
124     void countChanged();
125 
126 Q_SIGNALS:
127     void cachedInputChanged();
128     void busyChanged();
129     void hasFileUploadingChanged();
130     void fileUploadingProgressChanged();
131     void backgroundChanged();
132     void readMarkerLoadedChanged();
133     void lastActiveTimeChanged();
134     void isInviteChanged();
135 
136 public Q_SLOTS:
137     void uploadFile(const QUrl &url, const QString &body = QString());
138     void acceptInvitation();
139     void forget();
140     void sendTypingNotification(bool isTyping);
141     /// @param rawText The text as it was typed.
142     /// @param cleanedText The text with link to the users.
143     void postMessage(const QString &rawText,
144                      const QString &cleanedText,
145                      Quotient::MessageEventType type = Quotient::MessageEventType::Text,
146                      const QString &replyEventId = QString(),
147                      const QString &relateToEventId = QString());
148     void postHtmlMessage(const QString &text,
149                          const QString &html,
150                          Quotient::MessageEventType type = Quotient::MessageEventType::Text,
151                          const QString &replyEventId = QString(),
152                          const QString &relateToEventId = QString());
153     void changeAvatar(const QUrl &localFile);
154     void addLocalAlias(const QString &alias);
155     void removeLocalAlias(const QString &alias);
156     void toggleReaction(const QString &eventId, const QString &reaction);
157 };
158