1 | // SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net> |
2 | // SPDX-License-Identifier: LGPL-2.1-or-later |
3 | |
4 | #pragma once |
5 | |
6 | #include "quotient_common.h" |
7 | |
8 | #include "events/callevents.h" |
9 | #include "events/filesourceinfo.h" |
10 | #include "events/stateevent.h" |
11 | |
12 | #include <any> |
13 | #include <utility> |
14 | |
15 | namespace Quotient { |
16 | |
17 | namespace EventStatus { |
18 | Q_NAMESPACE_EXPORT(QUOTIENT_API) |
19 | |
20 | /** Special marks an event can assume |
21 | * |
22 | * This is used to hint at a special status of some events in UI. |
23 | * All values except Redacted and Hidden are mutually exclusive. |
24 | */ |
25 | enum Code { |
26 | Normal = 0x0, ///< No special designation |
27 | Submitted = 0x01, ///< The event has just been submitted for sending |
28 | FileUploaded = 0x02, ///< The file attached to the event has been |
29 | /// uploaded to the server |
30 | Departed = 0x03, ///< The event has left the client |
31 | ReachedServer = 0x04, ///< The server has received the event |
32 | SendingFailed = 0x05, ///< The server could not receive the event |
33 | Redacted = 0x08, ///< The event has been redacted |
34 | Replaced = 0x10, ///< The event has been replaced |
35 | Hidden = 0x100, ///< The event should not be shown in the timeline |
36 | }; |
37 | Q_ENUM_NS(Code) |
38 | } // namespace EventStatus |
39 | |
40 | class QUOTIENT_API EventItemBase { |
41 | public: |
42 | explicit EventItemBase(RoomEventPtr&& e) : evt(std::move(e)) |
43 | { |
44 | Q_ASSERT(evt); |
45 | } |
46 | |
47 | const RoomEvent* event() const { return std::to_address(ptr: evt); } |
48 | const RoomEvent* get() const { return event(); } |
49 | template <EventClass<RoomEvent> EventT> |
50 | const EventT* viewAs() const |
51 | { |
52 | return eventCast<const EventT>(evt); |
53 | } |
54 | const RoomEventPtr& operator->() const { return evt; } |
55 | const RoomEvent& operator*() const { return *evt; } |
56 | |
57 | // Used for event redaction |
58 | RoomEventPtr replaceEvent(RoomEventPtr&& other) |
59 | { |
60 | return std::exchange(obj&: evt, new_val: std::move(other)); |
61 | } |
62 | |
63 | /// Store arbitrary data with the event item |
64 | void setUserData(std::any userData) { data = std::move(userData); } |
65 | /// Obtain custom data previously stored with the event item |
66 | const std::any& userdata() const { return data; } |
67 | std::any& userData() { return data; } |
68 | |
69 | protected: |
70 | template <EventClass<RoomEvent> EventT> |
71 | EventT* getAs() |
72 | { |
73 | return eventCast<EventT>(evt); |
74 | } |
75 | |
76 | private: |
77 | RoomEventPtr evt; |
78 | std::any data; |
79 | }; |
80 | |
81 | class QUOTIENT_API TimelineItem : public EventItemBase { |
82 | public: |
83 | // For compatibility with Qt containers, even though we use |
84 | // a std:: container now for the room timeline |
85 | using index_t = int; |
86 | |
87 | TimelineItem(RoomEventPtr&& e, index_t number) |
88 | : EventItemBase(std::move(e)), idx(number) |
89 | {} |
90 | |
91 | index_t index() const { return idx; } |
92 | |
93 | private: |
94 | index_t idx; |
95 | }; |
96 | |
97 | template <> |
98 | inline const StateEvent* EventItemBase::viewAs<StateEvent>() const |
99 | { |
100 | return evt->isStateEvent() ? weakPtrCast<const StateEvent>(ptr: evt) : nullptr; |
101 | } |
102 | |
103 | template <> |
104 | inline const CallEvent* EventItemBase::viewAs<CallEvent>() const |
105 | { |
106 | return evt->is<CallEvent>() ? weakPtrCast<const CallEvent>(ptr: evt) : nullptr; |
107 | } |
108 | |
109 | class QUOTIENT_API PendingEventItem : public EventItemBase { |
110 | public: |
111 | using EventItemBase::EventItemBase; |
112 | |
113 | EventStatus::Code deliveryStatus() const { return _status; } |
114 | QDateTime lastUpdated() const { return _lastUpdated; } |
115 | QString annotation() const { return _annotation; } |
116 | |
117 | void setDeparted() { setStatus(EventStatus::Departed); } |
118 | void setFileUploaded(const FileSourceInfo &uploadedFileData); |
119 | void setReachedServer(const QString& eventId) |
120 | { |
121 | setStatus(EventStatus::ReachedServer); |
122 | (*this)->addId(newId: eventId); |
123 | } |
124 | void setSendingFailed(QString errorText) |
125 | { |
126 | setStatus(EventStatus::SendingFailed); |
127 | _annotation = std::move(errorText); |
128 | } |
129 | void resetStatus() { setStatus(EventStatus::Submitted); } |
130 | |
131 | private: |
132 | EventStatus::Code _status = EventStatus::Submitted; |
133 | QDateTime _lastUpdated = QDateTime::currentDateTimeUtc(); |
134 | QString _annotation; |
135 | |
136 | void setStatus(EventStatus::Code status) |
137 | { |
138 | _status = status; |
139 | _lastUpdated = QDateTime::currentDateTimeUtc(); |
140 | _annotation.clear(); |
141 | } |
142 | }; |
143 | |
144 | inline QDebug& operator<<(QDebug& d, const TimelineItem& ti) |
145 | { |
146 | QDebugStateSaver dss(d); |
147 | d.nospace() << "(" << ti.index() << "|" << ti->id() << ")" ; |
148 | return d; |
149 | } |
150 | } // namespace Quotient |
151 | |