summaryrefslogtreecommitdiff
path: root/components/chatlist.hpp
blob: 45dc2eb0965f2518374c734db80e7f7b9e3f83bf (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
#pragma once
#include <gtkmm.h>
#include <map>
#include <vector>
#include "../discord/snowflake.hpp"

class ChatList : public Gtk::ScrolledWindow {
public:
    ChatList();
    void Clear();
    void SetActiveChannel(Snowflake id);
    template<typename Iter>
    void SetMessages(Iter begin, Iter end);
    template<typename Iter>
    void PrependMessages(Iter begin, Iter end);
    void ProcessNewMessage(Snowflake id, bool prepend);
    void DeleteMessage(Snowflake id);
    void RefetchMessage(Snowflake id);
    Snowflake GetOldestListedMessage();
    void UpdateMessageReactions(Snowflake id);
    void SetFailedByNonce(const std::string &nonce);
    std::vector<Snowflake> GetRecentAuthors();

private:
    void OnScrollEdgeOvershot(Gtk::PositionType pos);
    void ScrollToBottom();
    void RemoveMessageAndHeader(Gtk::Widget *widget);

    Snowflake m_active_channel;

    int m_num_messages = 0;
    int m_num_rows = 0;
    std::map<Snowflake, Gtk::Widget *> m_id_to_widget;

    bool m_should_scroll_to_bottom = true;
    Gtk::ListBox m_list;

public:
    // these are all forwarded by the parent
    using type_signal_action_message_delete = sigc::signal<void, Snowflake, Snowflake>;
    using type_signal_action_message_edit = sigc::signal<void, Snowflake, Snowflake>;
    using type_signal_action_chat_submit = sigc::signal<void, std::string, Snowflake, Snowflake>;
    using type_signal_action_chat_load_history = sigc::signal<void, Snowflake>;
    using type_signal_action_channel_click = sigc::signal<void, Snowflake>;
    using type_signal_action_insert_mention = sigc::signal<void, Snowflake>;
    using type_signal_action_open_user_menu = sigc::signal<void, const GdkEvent *, Snowflake, Snowflake>;
    using type_signal_action_reaction_add = sigc::signal<void, Snowflake, Glib::ustring>;
    using type_signal_action_reaction_remove = sigc::signal<void, Snowflake, Glib::ustring>;
    using type_signal_action_reply_to = sigc::signal<void, Snowflake>;

    type_signal_action_message_delete signal_action_message_delete();
    type_signal_action_message_edit signal_action_message_edit();
    type_signal_action_chat_submit signal_action_chat_submit();
    type_signal_action_chat_load_history signal_action_chat_load_history();
    type_signal_action_channel_click signal_action_channel_click();
    type_signal_action_insert_mention signal_action_insert_mention();
    type_signal_action_open_user_menu signal_action_open_user_menu();
    type_signal_action_reaction_add signal_action_reaction_add();
    type_signal_action_reaction_remove signal_action_reaction_remove();
    type_signal_action_reply_to signal_action_reply_to();

private:
    type_signal_action_message_delete m_signal_action_message_delete;
    type_signal_action_message_edit m_signal_action_message_edit;
    type_signal_action_chat_submit m_signal_action_chat_submit;
    type_signal_action_chat_load_history m_signal_action_chat_load_history;
    type_signal_action_channel_click m_signal_action_channel_click;
    type_signal_action_insert_mention m_signal_action_insert_mention;
    type_signal_action_open_user_menu m_signal_action_open_user_menu;
    type_signal_action_reaction_add m_signal_action_reaction_add;
    type_signal_action_reaction_remove m_signal_action_reaction_remove;
    type_signal_action_reply_to m_signal_action_reply_to;
};

template<typename Iter>
inline void ChatList::SetMessages(Iter begin, Iter end) {
    Clear();
    m_num_rows = 0;
    m_num_messages = 0;
    m_id_to_widget.clear();

    for (Iter it = begin; it != end; it++)
        ProcessNewMessage(*it, false);

    ScrollToBottom();
}

template<typename Iter>
inline void ChatList::PrependMessages(Iter begin, Iter end) {
    for (Iter it = begin; it != end; it++)
        ProcessNewMessage(*it, true);
}