mirror of
https://github.com/celisej567/abaddon.git
synced 2026-09-04 11:33:27 +03:00
rest of view threads window
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
107
windows/threadswindow.cpp
Normal 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
60
windows/threadswindow.hpp
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user