forked from OpenGamers/abaddon
Merge branch 'master' into member-list
This commit is contained in:
23
README.md
23
README.md
@@ -25,13 +25,15 @@ Current features:
|
||||
* Thread support<sup>3</sup>
|
||||
* Animated avatars, server icons, emojis (can be turned off)
|
||||
|
||||
1 - Abaddon tries its best (though is not perfect) to make Discord think it's a legitimate web client. Some of the things done to do this
|
||||
1 - Abaddon tries its best (though is not perfect) to make Discord think it's a legitimate web client. Some of the
|
||||
things done to do this
|
||||
include: using a browser user agent, sending the same IDENTIFY message that the official web client does, using API v9
|
||||
endpoints in all cases, and not using endpoints the web client does not normally use. There are still a few smaller
|
||||
inconsistencies, however. For example the web client sends lots of telemetry via the `/science` endpoint (uBlock origin
|
||||
stops this) as well as in the headers of all requests.<br>
|
||||
|
||||
**See [here](#the-spam-filter)** for things you might want to avoid if you are worried about being caught in the spam filter.
|
||||
**See [here](#the-spam-filter)** for things you might want to avoid if you are worried about being caught in the spam
|
||||
filter.
|
||||
|
||||
2 - Unicode emojis are substituted manually as opposed to rendered by GTK on non-Windows platforms. This can be changed
|
||||
with the `stock_emojis` setting as shown at the bottom of this README. A CBDT-based font using Twemoji is provided to
|
||||
@@ -68,8 +70,11 @@ the result of fundamental issues with Discord's thread implementation.
|
||||
|
||||
#### Linux:
|
||||
|
||||
1. Install dependencies: `libgtkmm-3.0-dev`, `libcurl4-gnutls-dev`,
|
||||
and [nlohmann-json](https://github.com/nlohmann/json)
|
||||
1. Install dependencies
|
||||
* On Ubuntu 20.04 (Focal) and newer:
|
||||
```Shell
|
||||
$ sudo apt install g++ cmake libgtkmm-3.0-dev libcurl4-gnutls-dev libsqlite3-dev libssl-dev nlohmann-json3-dev
|
||||
```
|
||||
2. `git clone https://github.com/uowuo/abaddon --recurse-submodules="subprojects" && cd abaddon`
|
||||
3. `mkdir build && cd build`
|
||||
4. `cmake ..`
|
||||
@@ -96,7 +101,12 @@ no `abaddon.ini` in the working directory
|
||||
|
||||
#### The Spam Filter
|
||||
|
||||
Discord likes disabling accounts/forcing them to reset their passwords if they think the user is a spam bot or potentially had their account compromised. While the official client still often gets users caught in the spam filter, third party clients tend to upset the spam filter more often. If you get caught by it, you can usually [appeal](https://support.discord.com/hc/en-us/requests/new?ticket_form_id=360000029731) it and get it restored. Here are some things you might want to do with the official client instead if you are particularly afraid of evoking the spam filter's wrath:
|
||||
Discord likes disabling accounts/forcing them to reset their passwords if they think the user is a spam bot or
|
||||
potentially had their account compromised. While the official client still often gets users caught in the spam filter,
|
||||
third party clients tend to upset the spam filter more often. If you get caught by it, you can
|
||||
usually [appeal](https://support.discord.com/hc/en-us/requests/new?ticket_form_id=360000029731) it and get it restored.
|
||||
Here are some things you might want to do with the official client instead if you are particularly afraid of evoking the
|
||||
spam filter's wrath:
|
||||
|
||||
* Joining or leaving servers (usually main cause of getting caught)
|
||||
* Frequently disconnecting and reconnecting
|
||||
@@ -249,6 +259,9 @@ For example, memory_db would be set by adding `memory_db = true` under the line
|
||||
over
|
||||
* owner_crown (true or false, default true) - show a crown next to the owner
|
||||
* unreads (true or false, default true) - show unread indicators and mention badges
|
||||
* save_state (true or false, default true) - save the state of the gui (active channels, tabs, expanded channels)
|
||||
* alt_menu (true or false, default false) - keep the menu hidden unless revealed with alt key
|
||||
* hide_to_tray (true or false, default false) - hide abaddon to the system tray on window close
|
||||
|
||||
#### style
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
/bin/libdeflate.dll
|
||||
/bin/libepoxy-0.dll
|
||||
/bin/libexpat-1.dll
|
||||
/bin/libffi-8.dll
|
||||
/bin/libfontconfig-1.dll
|
||||
/bin/libfreetype-6.dll
|
||||
/bin/libfribidi-0.dll
|
||||
@@ -41,7 +42,7 @@
|
||||
/bin/libpangoft2-1.0-0.dll
|
||||
/bin/libpangomm-1.4-1.dll
|
||||
/bin/libpangowin32-1.0-0.dll
|
||||
/bin/libpcre-1.dll
|
||||
/bin/libpcre2-8-0.dll
|
||||
/bin/libpixman-1-0.dll
|
||||
/bin/libpng16-16.dll
|
||||
/bin/libpsl-5.dll
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "discord/discord.hpp"
|
||||
#include "dialogs/token.hpp"
|
||||
#include "dialogs/editmessage.hpp"
|
||||
#include "dialogs/joinguild.hpp"
|
||||
#include "dialogs/confirm.hpp"
|
||||
#include "dialogs/setstatus.hpp"
|
||||
#include "dialogs/friendpicker.hpp"
|
||||
@@ -69,14 +68,13 @@ Abaddon &Abaddon::Get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
constexpr static guint BUTTON_BACK = 4;
|
||||
constexpr static guint BUTTON_FORWARD = 5;
|
||||
#else
|
||||
#else
|
||||
constexpr static guint BUTTON_BACK = 8;
|
||||
constexpr static guint BUTTON_FORWARD = 9;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static bool HandleButtonEvents(GdkEvent *event, MainWindow *main_window) {
|
||||
if (event->type != GDK_BUTTON_PRESS) return false;
|
||||
@@ -86,6 +84,7 @@ static bool HandleButtonEvents(GdkEvent *event, MainWindow *main_window) {
|
||||
auto *window = gtk_widget_get_toplevel(widget);
|
||||
if (static_cast<void *>(window) != static_cast<void *>(main_window->gobj())) return false; // is this the right way???
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
switch (event->button.button) {
|
||||
case BUTTON_BACK:
|
||||
main_window->GoBack();
|
||||
@@ -94,6 +93,7 @@ static bool HandleButtonEvents(GdkEvent *event, MainWindow *main_window) {
|
||||
main_window->GoForward();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -109,6 +109,15 @@ static bool HandleKeyEvents(GdkEvent *event, MainWindow *main_window) {
|
||||
const bool ctrl = (event->key.state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK;
|
||||
const bool shft = (event->key.state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK;
|
||||
|
||||
constexpr static guint EXCLUDE_STATES = GDK_CONTROL_MASK | GDK_SHIFT_MASK;
|
||||
|
||||
if (!(event->key.state & EXCLUDE_STATES) && event->key.keyval == GDK_KEY_Alt_L) {
|
||||
if (Abaddon::Get().GetSettings().AltMenu) {
|
||||
main_window->ToggleMenuVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
if (ctrl) {
|
||||
switch (event->key.keyval) {
|
||||
case GDK_KEY_Tab:
|
||||
@@ -135,6 +144,7 @@ static bool HandleKeyEvents(GdkEvent *event, MainWindow *main_window) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -144,7 +154,6 @@ static void MainEventHandler(GdkEvent *event, void *main_window) {
|
||||
if (HandleKeyEvents(event, static_cast<MainWindow *>(main_window))) return;
|
||||
gtk_main_do_event(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
int Abaddon::StartGTK() {
|
||||
m_gtk_app = Gtk::Application::create("com.github.uowuo.abaddon");
|
||||
@@ -229,7 +238,6 @@ int Abaddon::StartGTK() {
|
||||
m_main_window->signal_action_disconnect().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnect));
|
||||
m_main_window->signal_action_set_token().connect(sigc::mem_fun(*this, &Abaddon::ActionSetToken));
|
||||
m_main_window->signal_action_reload_css().connect(sigc::mem_fun(*this, &Abaddon::ActionReloadCSS));
|
||||
m_main_window->signal_action_join_guild().connect(sigc::mem_fun(*this, &Abaddon::ActionJoinGuildDialog));
|
||||
m_main_window->signal_action_set_status().connect(sigc::mem_fun(*this, &Abaddon::ActionSetStatus));
|
||||
m_main_window->signal_action_add_recipient().connect(sigc::mem_fun(*this, &Abaddon::ActionAddRecipient));
|
||||
m_main_window->signal_action_view_pins().connect(sigc::mem_fun(*this, &Abaddon::ActionViewPins));
|
||||
@@ -487,6 +495,11 @@ void Abaddon::RunFirstTimeDiscordStartup() {
|
||||
confirm.SetAcceptOnly(true);
|
||||
confirm.run();
|
||||
}
|
||||
|
||||
// autoconnect
|
||||
if (cookie.has_value() && build_number.has_value() && GetSettings().Autoconnect && !GetDiscordToken().empty()) {
|
||||
ActionConnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -693,15 +706,6 @@ void Abaddon::ActionSetToken() {
|
||||
m_main_window->UpdateMenus();
|
||||
}
|
||||
|
||||
void Abaddon::ActionJoinGuildDialog() {
|
||||
JoinGuildDialog dlg(*m_main_window);
|
||||
auto response = dlg.run();
|
||||
if (response == Gtk::RESPONSE_OK) {
|
||||
auto code = dlg.GetCode();
|
||||
m_discord.JoinGuild(code);
|
||||
}
|
||||
}
|
||||
|
||||
void Abaddon::ActionChannelOpened(Snowflake id, bool expand_to) {
|
||||
if (!id.IsValid()) {
|
||||
m_discord.SetReferringChannel(Snowflake::Invalid);
|
||||
|
||||
@@ -150,8 +150,8 @@ void ChatMessageItemContainer::UpdateAttributes() {
|
||||
|
||||
void ChatMessageItemContainer::AddClickHandler(Gtk::Widget *widget, const std::string &url) {
|
||||
// clang-format off
|
||||
widget->signal_button_press_event().connect([url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
widget->signal_button_release_event().connect([url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_RELEASE && event->button == GDK_BUTTON_PRIMARY) {
|
||||
LaunchBrowser(url);
|
||||
return true;
|
||||
}
|
||||
@@ -357,8 +357,8 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedComponent(const EmbedData &emb
|
||||
if (embed.URL.has_value()) {
|
||||
AddPointerCursor(*title_ev);
|
||||
auto url = *embed.URL;
|
||||
title_ev->signal_button_press_event().connect([url = std::move(url)](GdkEventButton *event) -> bool {
|
||||
if (event->button == GDK_BUTTON_PRIMARY) {
|
||||
title_ev->signal_button_release_event().connect([url = std::move(url)](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_RELEASE && event->button == GDK_BUTTON_PRIMARY) {
|
||||
LaunchBrowser(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#include "joinguild.hpp"
|
||||
#include "abaddon.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <regex>
|
||||
|
||||
JoinGuildDialog::JoinGuildDialog(Gtk::Window &parent)
|
||||
: Gtk::Dialog("Join Server", parent, true)
|
||||
, m_layout(Gtk::ORIENTATION_VERTICAL)
|
||||
, m_ok("OK")
|
||||
, m_cancel("Cancel")
|
||||
, m_info("Enter code") {
|
||||
set_default_size(300, 50);
|
||||
get_style_context()->add_class("app-window");
|
||||
get_style_context()->add_class("app-popup");
|
||||
|
||||
Glib::signal_idle().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_idle_slot));
|
||||
|
||||
m_entry.signal_changed().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_entry_changed));
|
||||
|
||||
m_ok.set_sensitive(false);
|
||||
|
||||
m_ok.signal_clicked().connect([&]() {
|
||||
response(Gtk::RESPONSE_OK);
|
||||
});
|
||||
|
||||
m_cancel.signal_clicked().connect([&]() {
|
||||
response(Gtk::RESPONSE_CANCEL);
|
||||
});
|
||||
|
||||
m_entry.set_hexpand(true);
|
||||
m_layout.add(m_entry);
|
||||
m_lower.set_hexpand(true);
|
||||
m_lower.pack_start(m_info);
|
||||
m_info.set_halign(Gtk::ALIGN_START);
|
||||
m_lower.pack_start(m_ok, Gtk::PACK_SHRINK);
|
||||
m_lower.pack_start(m_cancel, Gtk::PACK_SHRINK);
|
||||
m_ok.set_halign(Gtk::ALIGN_END);
|
||||
m_cancel.set_halign(Gtk::ALIGN_END);
|
||||
m_layout.add(m_lower);
|
||||
get_content_area()->add(m_layout);
|
||||
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void JoinGuildDialog::on_entry_changed() {
|
||||
std::string s = m_entry.get_text();
|
||||
std::regex invite_regex(R"((https?:\/\/)?discord\.(gg(\/invite)?\/|com\/invite\/)([A-Za-z0-9\-]+))", std::regex_constants::ECMAScript);
|
||||
std::smatch match;
|
||||
bool full_url = std::regex_search(s, match, invite_regex);
|
||||
if (full_url || IsCode(s)) {
|
||||
m_code = full_url ? match[4].str() : s;
|
||||
m_needs_request = true;
|
||||
m_ok.set_sensitive(false);
|
||||
} else {
|
||||
m_ok.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
|
||||
void JoinGuildDialog::CheckCode() {
|
||||
auto cb = [this](const std::optional<InviteData> &invite) {
|
||||
if (invite.has_value()) {
|
||||
m_ok.set_sensitive(true);
|
||||
if (invite->Guild.has_value()) {
|
||||
if (invite->MemberCount.has_value())
|
||||
m_info.set_text(invite->Guild->Name + " (" + std::to_string(*invite->MemberCount) + " members)");
|
||||
else
|
||||
m_info.set_text(invite->Guild->Name);
|
||||
} else {
|
||||
m_info.set_text("Group DM (" + std::to_string(*invite->MemberCount) + " members)");
|
||||
}
|
||||
} else {
|
||||
m_ok.set_sensitive(false);
|
||||
m_info.set_text("Invalid invite");
|
||||
}
|
||||
};
|
||||
Abaddon::Get().GetDiscordClient().FetchInvite(m_code, sigc::track_obj(cb, *this));
|
||||
}
|
||||
|
||||
bool JoinGuildDialog::IsCode(std::string str) {
|
||||
return str.length() >= 2 && std::all_of(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c) || c == '-'; });
|
||||
}
|
||||
|
||||
std::string JoinGuildDialog::GetCode() {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
static const constexpr int RateLimitMS = 1500;
|
||||
bool JoinGuildDialog::on_idle_slot() {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (m_needs_request && ((now - m_last_req_time) > std::chrono::milliseconds(RateLimitMS))) {
|
||||
m_needs_request = false;
|
||||
m_last_req_time = now;
|
||||
CheckCode();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
class JoinGuildDialog : public Gtk::Dialog {
|
||||
public:
|
||||
JoinGuildDialog(Gtk::Window &parent);
|
||||
std::string GetCode();
|
||||
|
||||
protected:
|
||||
void on_entry_changed();
|
||||
static bool IsCode(std::string str);
|
||||
|
||||
Gtk::Box m_layout;
|
||||
Gtk::Button m_ok;
|
||||
Gtk::Button m_cancel;
|
||||
Gtk::Box m_lower;
|
||||
Gtk::Label m_info;
|
||||
Gtk::Entry m_entry;
|
||||
|
||||
void CheckCode();
|
||||
|
||||
// needs a rate limit cuz if u hit it u get ip banned from /invites for a long time :(
|
||||
bool m_needs_request = false;
|
||||
std::chrono::time_point<std::chrono::steady_clock> m_last_req_time;
|
||||
bool on_idle_slot();
|
||||
|
||||
private:
|
||||
std::string m_code;
|
||||
};
|
||||
@@ -573,10 +573,6 @@ void DiscordClient::SendThreadLazyLoad(Snowflake id) {
|
||||
m_websocket.Send(msg);
|
||||
}
|
||||
|
||||
void DiscordClient::JoinGuild(const std::string &code) {
|
||||
m_http.MakePOST("/invites/" + code, "{}", [](auto) {});
|
||||
}
|
||||
|
||||
void DiscordClient::LeaveGuild(Snowflake id) {
|
||||
m_http.MakeDELETE("/users/@me/guilds/" + std::to_string(id), [](auto) {});
|
||||
}
|
||||
|
||||
@@ -113,7 +113,6 @@ public:
|
||||
void EditMessage(Snowflake channel_id, Snowflake id, std::string content);
|
||||
void SendLazyLoad(Snowflake id);
|
||||
void SendThreadLazyLoad(Snowflake id);
|
||||
void JoinGuild(const std::string &code);
|
||||
void LeaveGuild(Snowflake id);
|
||||
void KickUser(Snowflake user_id, Snowflake guild_id);
|
||||
void BanUser(Snowflake user_id, Snowflake guild_id); // todo: reason, delete messages
|
||||
|
||||
@@ -143,7 +143,7 @@ void HTTPClient::AddHeaders(http::request &r) {
|
||||
r.set_header(name, val);
|
||||
}
|
||||
curl_easy_setopt(r.get_curl(), CURLOPT_COOKIE, m_cookie.c_str());
|
||||
curl_easy_setopt(r.get_curl(), CURLOPT_ACCEPT_ENCODING, "gzip, deflate, br");
|
||||
curl_easy_setopt(r.get_curl(), CURLOPT_ACCEPT_ENCODING, "");
|
||||
}
|
||||
|
||||
void HTTPClient::OnResponse(const http::response_type &r, const std::function<void(http::response_type r)> &cb) {
|
||||
|
||||
@@ -8,33 +8,5 @@ void from_json(const nlohmann::json &j, UserSettingsGuildFoldersEntry &m) {
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, UserSettings &m) {
|
||||
JS_D("timezone_offset", m.TimezoneOffset);
|
||||
JS_D("theme", m.Theme);
|
||||
JS_D("stream_notifications_enabled", m.AreStreamNotificationsEnabled);
|
||||
JS_D("status", m.Status);
|
||||
JS_D("show_current_game", m.ShouldShowCurrentGame);
|
||||
// JS_D("restricted_guilds", m.RestrictedGuilds);
|
||||
JS_D("render_reactions", m.ShouldRenderReactions);
|
||||
JS_D("render_embeds", m.ShouldRenderEmbeds);
|
||||
JS_D("native_phone_integration_enabled", m.IsNativePhoneIntegrationEnabled);
|
||||
JS_D("message_display_compact", m.ShouldMessageDisplayCompact);
|
||||
JS_D("locale", m.Locale);
|
||||
JS_D("inline_embed_media", m.ShouldInlineEmbedMedia);
|
||||
JS_D("inline_attachment_media", m.ShouldInlineAttachmentMedia);
|
||||
JS_D("guild_positions", m.GuildPositions);
|
||||
JS_D("guild_folders", m.GuildFolders);
|
||||
JS_D("gif_auto_play", m.ShouldGIFAutoplay);
|
||||
// JS_D("friend_source_flags", m.FriendSourceFlags);
|
||||
JS_D("explicit_content_filter", m.ExplicitContentFilter);
|
||||
JS_D("enable_tts_command", m.IsTTSCommandEnabled);
|
||||
JS_D("disable_games_tab", m.ShouldDisableGamesTab);
|
||||
JS_D("developer_mode", m.DeveloperMode);
|
||||
JS_D("detect_platform_accounts", m.ShouldDetectPlatformAccounts);
|
||||
JS_D("default_guilds_restricted", m.AreDefaultGuildsRestricted);
|
||||
// JS_N("custom_status", m.CustomStatus);
|
||||
JS_D("convert_emoticons", m.ShouldConvertEmoticons);
|
||||
JS_D("contact_sync_enabled", m.IsContactSyncEnabled);
|
||||
JS_D("animate_emoji", m.ShouldAnimateEmojis);
|
||||
JS_D("allow_accessibility_detection", m.IsAccessibilityDetectionAllowed);
|
||||
JS_D("afk_timeout", m.AFKTimeout);
|
||||
}
|
||||
|
||||
@@ -13,35 +13,36 @@ struct UserSettingsGuildFoldersEntry {
|
||||
};
|
||||
|
||||
struct UserSettings {
|
||||
int TimezoneOffset; //
|
||||
std::string Theme; //
|
||||
bool AreStreamNotificationsEnabled; //
|
||||
std::string Status; //
|
||||
bool ShouldShowCurrentGame; //
|
||||
// std::vector<Unknown> RestrictedGuilds; //
|
||||
bool ShouldRenderReactions; //
|
||||
bool ShouldRenderEmbeds; //
|
||||
bool IsNativePhoneIntegrationEnabled; //
|
||||
bool ShouldMessageDisplayCompact; //
|
||||
std::string Locale; //
|
||||
bool ShouldInlineEmbedMedia; //
|
||||
bool ShouldInlineAttachmentMedia; //
|
||||
std::vector<Snowflake> GuildPositions; // deprecated?
|
||||
std::vector<UserSettingsGuildFoldersEntry> GuildFolders; //
|
||||
bool ShouldGIFAutoplay; //
|
||||
// Unknown FriendSourceFlags; //
|
||||
int ExplicitContentFilter; //
|
||||
bool IsTTSCommandEnabled; //
|
||||
bool ShouldDisableGamesTab; //
|
||||
bool DeveloperMode; //
|
||||
bool ShouldDetectPlatformAccounts; //
|
||||
bool AreDefaultGuildsRestricted; //
|
||||
std::vector<UserSettingsGuildFoldersEntry> GuildFolders;
|
||||
/*
|
||||
int TimezoneOffset;
|
||||
std::string Theme;
|
||||
bool AreStreamNotificationsEnabled;
|
||||
std::string Status;
|
||||
bool ShouldShowCurrentGame;
|
||||
// std::vector<Unknown> RestrictedGuilds;
|
||||
bool ShouldRenderReactions;
|
||||
bool ShouldRenderEmbeds;
|
||||
bool IsNativePhoneIntegrationEnabled;
|
||||
bool ShouldMessageDisplayCompact;
|
||||
std::string Locale;
|
||||
bool ShouldInlineEmbedMedia;
|
||||
bool ShouldInlineAttachmentMedia;
|
||||
std::vector<Snowflake> GuildPositions; // deprecated?
|
||||
bool ShouldGIFAutoplay;
|
||||
// Unknown FriendSourceFlags;
|
||||
int ExplicitContentFilter;
|
||||
bool IsTTSCommandEnabled;
|
||||
bool ShouldDisableGamesTab;
|
||||
bool DeveloperMode;
|
||||
bool ShouldDetectPlatformAccounts;
|
||||
bool AreDefaultGuildsRestricted;
|
||||
// Unknown CustomStatus; // null
|
||||
bool ShouldConvertEmoticons; //
|
||||
bool IsContactSyncEnabled; //
|
||||
bool ShouldAnimateEmojis; //
|
||||
bool IsAccessibilityDetectionAllowed; //
|
||||
int AFKTimeout;
|
||||
bool ShouldConvertEmoticons;
|
||||
bool IsContactSyncEnabled;
|
||||
bool ShouldAnimateEmojis;
|
||||
bool IsAccessibilityDetectionAllowed;
|
||||
int AFKTimeout;*/
|
||||
|
||||
friend void from_json(const nlohmann::json &j, UserSettings &m);
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@ void SettingsManager::ReadSettings() {
|
||||
SMSTR("discord", "token", DiscordToken);
|
||||
SMBOOL("discord", "memory_db", UseMemoryDB);
|
||||
SMBOOL("discord", "prefetch", Prefetch);
|
||||
SMBOOL("discord", "autoconnect", Autoconnect);
|
||||
SMSTR("gui", "css", MainCSS);
|
||||
SMBOOL("gui", "animated_guild_hover_only", AnimatedGuildHoverOnly);
|
||||
SMBOOL("gui", "animations", ShowAnimations);
|
||||
@@ -48,6 +49,7 @@ void SettingsManager::ReadSettings() {
|
||||
SMBOOL("gui", "save_state", SaveState);
|
||||
SMBOOL("gui", "stock_emojis", ShowStockEmojis);
|
||||
SMBOOL("gui", "unreads", Unreads);
|
||||
SMBOOL("gui", "alt_menu", AltMenu);
|
||||
SMBOOL("gui", "hide_to_tray", HideToTray);
|
||||
SMINT("http", "concurrent", CacheHTTPConcurrency);
|
||||
SMSTR("http", "user_agent", UserAgent);
|
||||
@@ -93,6 +95,7 @@ void SettingsManager::Close() {
|
||||
SMSTR("discord", "token", DiscordToken);
|
||||
SMBOOL("discord", "memory_db", UseMemoryDB);
|
||||
SMBOOL("discord", "prefetch", Prefetch);
|
||||
SMBOOL("discord", "autoconnect", Autoconnect);
|
||||
SMSTR("gui", "css", MainCSS);
|
||||
SMBOOL("gui", "animated_guild_hover_only", AnimatedGuildHoverOnly);
|
||||
SMBOOL("gui", "animations", ShowAnimations);
|
||||
@@ -102,6 +105,7 @@ void SettingsManager::Close() {
|
||||
SMBOOL("gui", "save_state", SaveState);
|
||||
SMBOOL("gui", "stock_emojis", ShowStockEmojis);
|
||||
SMBOOL("gui", "unreads", Unreads);
|
||||
SMBOOL("gui", "alt_menu", AltMenu);
|
||||
SMBOOL("gui", "hide_to_tray", HideToTray);
|
||||
SMINT("http", "concurrent", CacheHTTPConcurrency);
|
||||
SMSTR("http", "user_agent", UserAgent);
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
std::string DiscordToken;
|
||||
bool UseMemoryDB { false };
|
||||
bool Prefetch { false };
|
||||
bool Autoconnect { false };
|
||||
|
||||
// [gui]
|
||||
std::string MainCSS { "main.css" };
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
bool ShowStockEmojis { true };
|
||||
#endif
|
||||
bool Unreads { true };
|
||||
|
||||
bool AltMenu { false };
|
||||
bool HideToTray { false };
|
||||
|
||||
// [http]
|
||||
|
||||
@@ -56,10 +56,9 @@ GuildSettingsInfoPane::GuildSettingsInfoPane(Snowflake id)
|
||||
guild_icon_url = guild.GetIconURL("gif", "512");
|
||||
else
|
||||
guild_icon_url = guild.GetIconURL("png", "512");
|
||||
m_guild_icon_ev.signal_button_press_event().connect([guild_icon_url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
if (event->button == GDK_BUTTON_PRIMARY)
|
||||
LaunchBrowser(guild_icon_url);
|
||||
m_guild_icon_ev.signal_button_release_event().connect([guild_icon_url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_RELEASE && event->button == GDK_BUTTON_PRIMARY)
|
||||
LaunchBrowser(guild_icon_url);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -159,6 +159,10 @@ void MainWindow::UpdateMenus() {
|
||||
OnViewSubmenuPopup();
|
||||
}
|
||||
|
||||
void MainWindow::ToggleMenuVisibility() {
|
||||
m_menu_bar.set_visible(!m_menu_bar.get_visible());
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
void MainWindow::GoBack() {
|
||||
m_chat.GoBack();
|
||||
@@ -196,7 +200,6 @@ void MainWindow::OnDiscordSubmenuPopup() {
|
||||
std::string token = Abaddon::Get().GetDiscordToken();
|
||||
m_menu_discord_connect.set_sensitive(!token.empty() && !discord_active);
|
||||
m_menu_discord_disconnect.set_sensitive(discord_active);
|
||||
m_menu_discord_join_guild.set_sensitive(discord_active);
|
||||
m_menu_discord_set_token.set_sensitive(!discord_active);
|
||||
m_menu_discord_set_status.set_sensitive(discord_active);
|
||||
}
|
||||
@@ -239,15 +242,12 @@ void MainWindow::SetupMenu() {
|
||||
m_menu_discord_disconnect.set_label("Disconnect");
|
||||
m_menu_discord_disconnect.set_sensitive(false);
|
||||
m_menu_discord_set_token.set_label("Set Token");
|
||||
m_menu_discord_join_guild.set_label("Accept Invite");
|
||||
m_menu_discord_join_guild.set_sensitive(false);
|
||||
m_menu_discord_set_status.set_label("Set Status");
|
||||
m_menu_discord_set_status.set_sensitive(false);
|
||||
m_menu_discord_add_recipient.set_label("Add user to DM");
|
||||
m_menu_discord_sub.append(m_menu_discord_connect);
|
||||
m_menu_discord_sub.append(m_menu_discord_disconnect);
|
||||
m_menu_discord_sub.append(m_menu_discord_set_token);
|
||||
m_menu_discord_sub.append(m_menu_discord_join_guild);
|
||||
m_menu_discord_sub.append(m_menu_discord_set_status);
|
||||
m_menu_discord_sub.append(m_menu_discord_add_recipient);
|
||||
m_menu_discord.set_submenu(m_menu_discord_sub);
|
||||
@@ -266,6 +266,12 @@ void MainWindow::SetupMenu() {
|
||||
m_menu_view_threads.set_label("Threads");
|
||||
m_menu_view_mark_guild_as_read.set_label("Mark Server as Read");
|
||||
m_menu_view_mark_guild_as_read.add_accelerator("activate", m_accels, GDK_KEY_Escape, Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
|
||||
m_menu_view_channels.set_label("Channels");
|
||||
m_menu_view_channels.add_accelerator("activate", m_accels, GDK_KEY_L, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
m_menu_view_channels.set_active(true);
|
||||
m_menu_view_members.set_label("Members");
|
||||
m_menu_view_members.add_accelerator("activate", m_accels, GDK_KEY_M, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
m_menu_view_members.set_active(true);
|
||||
#ifdef WITH_LIBHANDY
|
||||
m_menu_view_go_back.set_label("Go Back");
|
||||
m_menu_view_go_forward.set_label("Go Forward");
|
||||
@@ -276,6 +282,8 @@ void MainWindow::SetupMenu() {
|
||||
m_menu_view_sub.append(m_menu_view_pins);
|
||||
m_menu_view_sub.append(m_menu_view_threads);
|
||||
m_menu_view_sub.append(m_menu_view_mark_guild_as_read);
|
||||
m_menu_view_sub.append(m_menu_view_channels);
|
||||
m_menu_view_sub.append(m_menu_view_members);
|
||||
#ifdef WITH_LIBHANDY
|
||||
m_menu_view_sub.append(m_menu_view_go_back);
|
||||
m_menu_view_sub.append(m_menu_view_go_forward);
|
||||
@@ -284,7 +292,25 @@ void MainWindow::SetupMenu() {
|
||||
m_menu_bar.append(m_menu_file);
|
||||
m_menu_bar.append(m_menu_discord);
|
||||
m_menu_bar.append(m_menu_view);
|
||||
m_menu_bar.show_all();
|
||||
|
||||
if (Abaddon::Get().GetSettings().AltMenu) {
|
||||
auto set_hide_cb = [this](Gtk::Menu &menu) {
|
||||
for (auto *child : menu.get_children()) {
|
||||
auto *item = dynamic_cast<Gtk::MenuItem *>(child);
|
||||
if (item != nullptr) {
|
||||
item->signal_activate().connect([this]() {
|
||||
m_menu_bar.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
set_hide_cb(m_menu_discord_sub);
|
||||
set_hide_cb(m_menu_file_sub);
|
||||
set_hide_cb(m_menu_view_sub);
|
||||
m_menu_bar.show_all_children();
|
||||
} else {
|
||||
m_menu_bar.show_all();
|
||||
}
|
||||
|
||||
m_menu_discord_connect.signal_activate().connect([this] {
|
||||
m_signal_action_connect.emit();
|
||||
@@ -298,10 +324,6 @@ void MainWindow::SetupMenu() {
|
||||
m_signal_action_set_token.emit();
|
||||
});
|
||||
|
||||
m_menu_discord_join_guild.signal_activate().connect([this] {
|
||||
m_signal_action_join_guild.emit();
|
||||
});
|
||||
|
||||
m_menu_file_reload_css.signal_activate().connect([this] {
|
||||
m_signal_action_reload_css.emit();
|
||||
});
|
||||
@@ -341,6 +363,14 @@ void MainWindow::SetupMenu() {
|
||||
}
|
||||
});
|
||||
|
||||
m_menu_view_channels.signal_activate().connect([this]() {
|
||||
m_channel_list.set_visible(m_menu_view_channels.get_active());
|
||||
});
|
||||
|
||||
m_menu_view_members.signal_activate().connect([this]() {
|
||||
m_members.GetRoot()->set_visible(m_menu_view_members.get_active());
|
||||
});
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
m_menu_view_go_back.signal_activate().connect([this] {
|
||||
GoBack();
|
||||
@@ -384,10 +414,6 @@ MainWindow::type_signal_action_reload_css MainWindow::signal_action_reload_css()
|
||||
return m_signal_action_reload_css;
|
||||
}
|
||||
|
||||
MainWindow::type_signal_action_join_guild MainWindow::signal_action_join_guild() {
|
||||
return m_signal_action_join_guild;
|
||||
}
|
||||
|
||||
MainWindow::type_signal_action_set_status MainWindow::signal_action_set_status() {
|
||||
return m_signal_action_set_status;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
void UpdateChatReactionAdd(Snowflake id, const Glib::ustring ¶m);
|
||||
void UpdateChatReactionRemove(Snowflake id, const Glib::ustring ¶m);
|
||||
void UpdateMenus();
|
||||
void ToggleMenuVisibility();
|
||||
|
||||
#ifdef WITH_LIBHANDY
|
||||
void GoBack();
|
||||
@@ -63,7 +64,6 @@ private:
|
||||
Gtk::MenuItem m_menu_discord_connect;
|
||||
Gtk::MenuItem m_menu_discord_disconnect;
|
||||
Gtk::MenuItem m_menu_discord_set_token;
|
||||
Gtk::MenuItem m_menu_discord_join_guild;
|
||||
Gtk::MenuItem m_menu_discord_set_status;
|
||||
Gtk::MenuItem m_menu_discord_add_recipient; // move me somewhere else some day
|
||||
void OnDiscordSubmenuPopup();
|
||||
@@ -79,6 +79,8 @@ private:
|
||||
Gtk::MenuItem m_menu_view_pins;
|
||||
Gtk::MenuItem m_menu_view_threads;
|
||||
Gtk::MenuItem m_menu_view_mark_guild_as_read;
|
||||
Gtk::CheckMenuItem m_menu_view_channels;
|
||||
Gtk::CheckMenuItem m_menu_view_members;
|
||||
#ifdef WITH_LIBHANDY
|
||||
Gtk::MenuItem m_menu_view_go_back;
|
||||
Gtk::MenuItem m_menu_view_go_forward;
|
||||
@@ -91,7 +93,6 @@ public:
|
||||
typedef sigc::signal<void> type_signal_action_disconnect;
|
||||
typedef sigc::signal<void> type_signal_action_set_token;
|
||||
typedef sigc::signal<void> type_signal_action_reload_css;
|
||||
typedef sigc::signal<void> type_signal_action_join_guild;
|
||||
typedef sigc::signal<void> type_signal_action_set_status;
|
||||
// this should probably be removed
|
||||
typedef sigc::signal<void, Snowflake> type_signal_action_add_recipient; // channel id
|
||||
@@ -102,7 +103,6 @@ public:
|
||||
type_signal_action_disconnect signal_action_disconnect();
|
||||
type_signal_action_set_token signal_action_set_token();
|
||||
type_signal_action_reload_css signal_action_reload_css();
|
||||
type_signal_action_join_guild signal_action_join_guild();
|
||||
type_signal_action_set_status signal_action_set_status();
|
||||
type_signal_action_add_recipient signal_action_add_recipient();
|
||||
type_signal_action_view_pins signal_action_view_pins();
|
||||
@@ -113,7 +113,6 @@ private:
|
||||
type_signal_action_disconnect m_signal_action_disconnect;
|
||||
type_signal_action_set_token m_signal_action_set_token;
|
||||
type_signal_action_reload_css m_signal_action_reload_css;
|
||||
type_signal_action_join_guild m_signal_action_join_guild;
|
||||
type_signal_action_set_status m_signal_action_set_status;
|
||||
type_signal_action_add_recipient m_signal_action_add_recipient;
|
||||
type_signal_action_view_pins m_signal_action_view_pins;
|
||||
|
||||
@@ -41,13 +41,13 @@ ConnectionItem::ConnectionItem(const ConnectionData &conn)
|
||||
m_box.add(m_name);
|
||||
if (!url.empty()) {
|
||||
auto cb = [url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
if (event->type == GDK_BUTTON_RELEASE && event->button == GDK_BUTTON_PRIMARY) {
|
||||
LaunchBrowser(url);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
signal_button_press_event().connect(sigc::track_obj(cb, *this));
|
||||
signal_button_release_event().connect(sigc::track_obj(cb, *this));
|
||||
AddPointerCursor(*this);
|
||||
}
|
||||
m_overlay.add(m_box);
|
||||
|
||||
@@ -34,8 +34,8 @@ ProfileWindow::ProfileWindow(Snowflake user_id)
|
||||
|
||||
if (user.HasAvatar())
|
||||
AddPointerCursor(m_avatar_ev);
|
||||
m_avatar_ev.signal_button_press_event().connect([user](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
m_avatar_ev.signal_button_release_event().connect([user](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_RELEASE && event->button == GDK_BUTTON_PRIMARY) {
|
||||
if (user.HasAnimatedAvatar())
|
||||
LaunchBrowser(user.GetAvatarURL("gif", "512"));
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user