aboutsummaryrefslogtreecommitdiff
path: root/lib/eventitem.h
blob: ae3d5762a78e298c9571259fa9b424f3d2218603 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/******************************************************************************
 * SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#pragma once

#include "events/stateevent.h"

#include <utility>

namespace Quotient {
class StateEventBase;

class EventStatus {
    Q_GADGET
public:
    /** Special marks an event can assume
     *
     * This is used to hint at a special status of some events in UI.
     * All values except Redacted and Hidden are mutually exclusive.
     */
    enum Code {
        Normal = 0x0, //< No special designation
        Submitted = 0x01, //< The event has just been submitted for sending
        FileUploaded = 0x02, //< The file attached to the event has been
                             // uploaded to the server
        Departed = 0x03, //< The event has left the client
        ReachedServer = 0x04, //< The server has received the event
        SendingFailed = 0x05, //< The server could not receive the event
        Redacted = 0x08, //< The event has been redacted
        Replaced = 0x10, //< The event has been replaced
        Hidden = 0x100, //< The event should not be shown in the timeline
    };
    Q_DECLARE_FLAGS(Status, Code)
    Q_FLAG(Status)
};

class EventItemBase {
public:
    explicit EventItemBase(RoomEventPtr&& e) : evt(std::move(e))
    {
        Q_ASSERT(evt);
    }

    const RoomEvent* event() const { return rawPtr(evt); }
    const RoomEvent* get() const { return event(); }
    template <typename EventT>
    const EventT* viewAs() const
    {
        return eventCast<const EventT>(evt);
    }
    const RoomEventPtr& operator->() const { return evt; }
    const RoomEvent& operator*() const { return *evt; }

    // Used for event redaction
    RoomEventPtr replaceEvent(RoomEventPtr&& other)
    {
        return std::exchange(evt, move(other));
    }

protected:
    template <typename EventT>
    EventT* getAs()
    {
        return eventCast<EventT>(evt);
    }

private:
    RoomEventPtr evt;
};

class TimelineItem : public EventItemBase {
public:
    // For compatibility with Qt containers, even though we use
    // a std:: container now for the room timeline
    using index_t = int;

    TimelineItem(RoomEventPtr&& e, index_t number)
        : EventItemBase(std::move(e)), idx(number)
    {}

    index_t index() const { return idx; }

private:
    index_t idx;
};

template <>
inline const StateEventBase* EventItemBase::viewAs<StateEventBase>() const
{
    return evt->isStateEvent() ? weakPtrCast<const StateEventBase>(evt)
                               : nullptr;
}

template <>
inline const CallEventBase* EventItemBase::viewAs<CallEventBase>() const
{
    return evt->isCallEvent() ? weakPtrCast<const CallEventBase>(evt) : nullptr;
}

class PendingEventItem : public EventItemBase {
    Q_GADGET
public:
    using EventItemBase::EventItemBase;

    EventStatus::Code deliveryStatus() const { return _status; }
    QDateTime lastUpdated() const { return _lastUpdated; }
    QString annotation() const { return _annotation; }

    void setDeparted() { setStatus(EventStatus::Departed); }
    void setFileUploaded(const QUrl& remoteUrl);
    void setReachedServer(const QString& eventId)
    {
        setStatus(EventStatus::ReachedServer);
        (*this)->addId(eventId);
    }
    void setSendingFailed(QString errorText)
    {
        setStatus(EventStatus::SendingFailed);
        _annotation = std::move(errorText);
    }
    void resetStatus() { setStatus(EventStatus::Submitted); }

private:
    EventStatus::Code _status = EventStatus::Submitted;
    QDateTime _lastUpdated = QDateTime::currentDateTimeUtc();
    QString _annotation;

    void setStatus(EventStatus::Code status)
    {
        _status = status;
        _lastUpdated = QDateTime::currentDateTimeUtc();
        _annotation.clear();
    }
};

inline QDebug& operator<<(QDebug& d, const TimelineItem& ti)
{
    QDebugStateSaver dss(d);
    d.nospace() << "(" << ti.index() << "|" << ti->id() << ")";
    return d;
}
} // namespace Quotient
Q_DECLARE_METATYPE(Quotient::EventStatus)