rest of view threads window

This commit is contained in:
ouwou
2021-08-11 03:32:09 -04:00
parent e01110c739
commit 7ffded5b13
8 changed files with 223 additions and 8 deletions

View File

@@ -249,8 +249,22 @@ std::set<Snowflake> DiscordClient::GetChannelsInGuild(Snowflake id) const {
return {};
}
std::vector<ChannelData> DiscordClient::GetPublicThreads(Snowflake channel_id) const {
return m_store.GetThreads(channel_id);
// there is an endpoint for this but it should be synced before this is called anyways
std::vector<ChannelData> DiscordClient::GetActiveThreads(Snowflake channel_id) const {
return m_store.GetActiveThreads(channel_id);
}
void DiscordClient::GetArchivedPublicThreads(Snowflake channel_id, sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> callback) {
m_http.MakeGET("/channels/" + std::to_string(channel_id) + "/threads/archived/public", [this, callback](const http::response_type &r) {
if (CheckCode(r)) {
const auto data = nlohmann::json::parse(r.text).get<ArchivedThreadsResponseData>();
for (const auto &thread : data.Threads)
m_store.SetChannel(thread.ID, thread);
callback(DiscordError::NONE, data);
} else {
callback(GetCodeFromResponse(r), {});
}
});
}
bool DiscordClient::IsThreadJoined(Snowflake thread_id) const {

View File

@@ -86,7 +86,8 @@ public:
std::optional<RoleData> GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const;
std::set<Snowflake> GetUsersInGuild(Snowflake id) const;
std::set<Snowflake> GetChannelsInGuild(Snowflake id) const;
std::vector<ChannelData> GetPublicThreads(Snowflake channel_id) const;
std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const;
void GetArchivedPublicThreads(Snowflake channel_id, sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> callback);
bool IsThreadJoined(Snowflake thread_id) const;
bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const;

View File

@@ -497,3 +497,9 @@ void from_json(const nlohmann::json &j, ThreadMembersUpdateData &m) {
JS_O("added_members", m.AddedMembers);
JS_O("removed_member_ids", m.RemovedMemberIDs);
}
void from_json(const nlohmann::json &j, ArchivedThreadsResponseData &m) {
JS_D("threads", m.Threads);
JS_D("members", m.Members);
JS_D("has_more", m.HasMore);
}

View File

@@ -700,3 +700,11 @@ struct ThreadMembersUpdateData {
friend void from_json(const nlohmann::json &j, ThreadMembersUpdateData &m);
};
struct ArchivedThreadsResponseData {
std::vector<ChannelData> Threads;
std::vector<ThreadMemberObject> Members;
bool HasMore;
friend void from_json(const nlohmann::json &j, ArchivedThreadsResponseData &m);
};

View File

@@ -105,6 +105,16 @@ void Store::SetChannel(Snowflake id, const ChannelData &chan) {
Bind(m_set_chan_stmt, 17, chan.ParentID);
Bind(m_set_chan_stmt, 18, chan.LastPinTimestamp);
if (chan.ThreadMetadata.has_value()) {
Bind(m_set_chan_stmt, 19, chan.ThreadMetadata->IsArchived);
Bind(m_set_chan_stmt, 20, chan.ThreadMetadata->AutoArchiveDuration);
Bind(m_set_chan_stmt, 21, chan.ThreadMetadata->ArchiveTimestamp);
} else {
Bind(m_set_chan_stmt, 19, nullptr);
Bind(m_set_chan_stmt, 20, nullptr);
Bind(m_set_chan_stmt, 21, nullptr);
}
if (!RunInsert(m_set_chan_stmt))
fprintf(stderr, "channel insert failed: %s\n", sqlite3_errstr(m_db_err));
@@ -499,7 +509,7 @@ std::vector<Message> Store::GetPinnedMessages(Snowflake channel_id) const {
return ret;
}
std::vector<ChannelData> Store::GetThreads(Snowflake channel_id) const {
std::vector<ChannelData> Store::GetActiveThreads(Snowflake channel_id) const {
std::vector<ChannelData> ret;
Bind(m_get_threads_stmt, 1, channel_id);
@@ -552,6 +562,12 @@ std::optional<ChannelData> Store::GetChannel(Snowflake id) const {
Get(m_get_chan_stmt, 15, ret.ApplicationID);
Get(m_get_chan_stmt, 16, ret.ParentID);
Get(m_get_chan_stmt, 17, ret.LastPinTimestamp);
if (!IsNull(m_get_chan_stmt, 18)) {
ret.ThreadMetadata.emplace();
Get(m_get_chan_stmt, 18, ret.ThreadMetadata->IsArchived);
Get(m_get_chan_stmt, 19, ret.ThreadMetadata->AutoArchiveDuration);
Get(m_get_chan_stmt, 20, ret.ThreadMetadata->ArchiveTimestamp);
}
Reset(m_get_chan_stmt);
@@ -987,7 +1003,10 @@ bool Store::CreateTables() {
owner_id INTEGER,
application_id INTEGER,
parent_id INTEGER,
last_pin_timestamp TEXT
last_pin_timestamp TEXT,
archived BOOL, /* threads */
auto_archive INTEGER, /* threads */
archived_ts TEXT /* threads */
)
)";
@@ -1156,7 +1175,7 @@ bool Store::CreateStatements() {
const char *set_chan = R"(
REPLACE INTO channels VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
)";
@@ -1206,7 +1225,7 @@ bool Store::CreateStatements() {
)";
const char *get_threads = R"(
SELECT id FROM channels WHERE parent_id = ? AND type = 11
SELECT id FROM channels WHERE parent_id = ? AND (type = 10 OR type = 11 OR type = 12) AND archived = FALSE
)";
m_db_err = sqlite3_prepare_v2(m_db, set_user, -1, &m_set_user_stmt, nullptr);

View File

@@ -44,7 +44,7 @@ public:
std::vector<Message> GetLastMessages(Snowflake id, size_t num) const;
std::vector<Snowflake> GetChannelMessageIDs(Snowflake id) const;
std::vector<Message> GetPinnedMessages(Snowflake channel_id) const;
std::vector<ChannelData> GetThreads(Snowflake channel_id) const; // public
std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const; // public
void ClearGuild(Snowflake id);
void ClearChannel(Snowflake id);

107
windows/threadswindow.cpp Normal file
View File

@@ -0,0 +1,107 @@
#include "threadswindow.hpp"
#include "../abaddon.hpp"
ThreadsWindow::ThreadsWindow(const ChannelData &channel)
: m_channel_id(channel.ID)
, m_box(Gtk::ORIENTATION_VERTICAL)
, m_active(channel)
, m_archived(channel) {
set_name("threads-window");
set_default_size(450, 375);
set_title("#" + *channel.Name + " - Threads");
set_position(Gtk::WIN_POS_CENTER);
get_style_context()->add_class("app-window");
get_style_context()->add_class("app-popup");
get_style_context()->add_class("threads-window");
const auto cb = [this](Snowflake id) {
Abaddon::Get().ActionChannelOpened(id);
hide();
};
m_active.signal_thread_open().connect(cb);
m_archived.signal_thread_open().connect(cb);
m_switcher.set_halign(Gtk::ALIGN_CENTER);
m_switcher.set_stack(m_stack);
m_stack.add(m_active, "active", "Active Threads");
m_stack.add(m_archived, "archived", "Archived Threads");
m_active.show();
m_archived.show();
m_switcher.show();
m_stack.show();
m_box.show();
m_box.add(m_switcher);
m_box.add(m_stack);
add(m_box);
}
ThreadListRow::ThreadListRow(const ChannelData &channel)
: ID(channel.ID)
, m_label(*channel.Name, Gtk::ALIGN_START) {
m_label.show();
add(m_label);
}
ActiveThreadsList::ActiveThreadsList(const ChannelData &channel) {
set_vexpand(true);
m_list.set_selection_mode(Gtk::SELECTION_SINGLE);
m_list.set_hexpand(true);
m_list.show();
add(m_list);
m_list.signal_button_press_event().connect([this](GdkEventButton *ev) -> bool {
if (ev->button == GDK_BUTTON_PRIMARY && ev->type == GDK_2BUTTON_PRESS) {
if (auto row = dynamic_cast<ThreadListRow *>(m_list.get_selected_row()))
m_signal_thread_open.emit(row->ID);
}
return false;
});
const auto threads = Abaddon::Get().GetDiscordClient().GetActiveThreads(channel.ID);
for (const auto &thread : threads) {
auto row = Gtk::manage(new ThreadListRow(thread));
row->show();
m_list.add(*row);
}
}
ActiveThreadsList::type_signal_thread_open ActiveThreadsList::signal_thread_open() {
return m_signal_thread_open;
}
ArchivedThreadsList::ArchivedThreadsList(const ChannelData &channel) {
set_vexpand(true);
m_list.set_selection_mode(Gtk::SELECTION_SINGLE);
m_list.set_hexpand(true);
m_list.show();
add(m_list);
m_list.signal_button_press_event().connect([this](GdkEventButton *ev) -> bool {
if (ev->button == GDK_BUTTON_PRIMARY && ev->type == GDK_2BUTTON_PRESS) {
if (auto row = dynamic_cast<ThreadListRow *>(m_list.get_selected_row()))
m_signal_thread_open.emit(row->ID);
}
return false;
});
Abaddon::Get().GetDiscordClient().GetArchivedPublicThreads(channel.ID, sigc::mem_fun(*this, &ArchivedThreadsList::OnPublicFetched));
}
void ArchivedThreadsList::OnPublicFetched(DiscordError code, const ArchivedThreadsResponseData &data) {
for (const auto &thread : data.Threads) {
auto row = Gtk::manage(new ThreadListRow(thread));
row->show();
m_list.add(*row);
}
}
ArchivedThreadsList::type_signal_thread_open ArchivedThreadsList::signal_thread_open() {
return m_signal_thread_open;
}

60
windows/threadswindow.hpp Normal file
View File

@@ -0,0 +1,60 @@
#pragma once
#include <gtkmm.h>
#include "../discord/objects.hpp"
class ActiveThreadsList : public Gtk::ScrolledWindow {
public:
ActiveThreadsList(const ChannelData &channel);
private:
Gtk::ListBox m_list;
using type_signal_thread_open = sigc::signal<void, Snowflake>;
type_signal_thread_open m_signal_thread_open;
public:
type_signal_thread_open signal_thread_open();
};
class ArchivedThreadsList : public Gtk::ScrolledWindow {
public:
ArchivedThreadsList(const ChannelData &channel);
private:
Gtk::ListBox m_list;
void OnPublicFetched(DiscordError code, const ArchivedThreadsResponseData &data);
using type_signal_thread_open = sigc::signal<void, Snowflake>;
type_signal_thread_open m_signal_thread_open;
public:
type_signal_thread_open signal_thread_open();
};
// view all threads in a channel
class ThreadsWindow : public Gtk::Window {
public:
ThreadsWindow(const ChannelData &channel);
private:
Snowflake m_channel_id;
Gtk::StackSwitcher m_switcher;
Gtk::Stack m_stack;
Gtk::Box m_box;
ActiveThreadsList m_active;
ArchivedThreadsList m_archived;
};
class ThreadListRow : public Gtk::ListBoxRow {
public:
ThreadListRow(const ChannelData &channel);
Snowflake ID;
private:
Gtk::Label m_label;
};