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
15namespace Quotient {
16
17namespace 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
40class QUOTIENT_API EventItemBase {
41public:
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
69protected:
70 template <EventClass<RoomEvent> EventT>
71 EventT* getAs()
72 {
73 return eventCast<EventT>(evt);
74 }
75
76private:
77 RoomEventPtr evt;
78 std::any data;
79};
80
81class QUOTIENT_API TimelineItem : public EventItemBase {
82public:
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
93private:
94 index_t idx;
95};
96
97template <>
98inline const StateEvent* EventItemBase::viewAs<StateEvent>() const
99{
100 return evt->isStateEvent() ? weakPtrCast<const StateEvent>(ptr: evt) : nullptr;
101}
102
103template <>
104inline const CallEvent* EventItemBase::viewAs<CallEvent>() const
105{
106 return evt->is<CallEvent>() ? weakPtrCast<const CallEvent>(ptr: evt) : nullptr;
107}
108
109class QUOTIENT_API PendingEventItem : public EventItemBase {
110public:
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
131private:
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
144inline 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