summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/completer.cpp96
-rw-r--r--components/completer.hpp9
-rw-r--r--discord/discord.cpp7
-rw-r--r--discord/discord.hpp2
-rw-r--r--discord/user.hpp8
5 files changed, 85 insertions, 37 deletions
diff --git a/components/completer.cpp b/components/completer.cpp
index 3ecb972..9af4825 100644
--- a/components/completer.cpp
+++ b/components/completer.cpp
@@ -136,18 +136,8 @@ void Completer::CompleteMentions(const Glib::ustring &term) {
}
}
- auto &img = Abaddon::Get().GetImageManager();
- const auto placeholder = img.GetPlaceholder(24);
- if (author->HasAvatar()) {
- auto pb = img.GetFromURLIfCached(author->GetAvatarURL());
- if (pb) {
- entry->SetImage(pb);
- } else {
- entry->SetImage(placeholder);
- img.LoadFromURL(author->GetAvatarURL(), sigc::mem_fun(*entry, &CompleterEntry::SetImage));
- }
- } else
- entry->SetImage(placeholder);
+ if (author->HasAvatar())
+ entry->SetImage(author->GetAvatarURL());
}
}
@@ -159,38 +149,58 @@ void Completer::CompleteEmojis(const Glib::ustring &term) {
const auto channel_id = m_channel_id_cb();
const auto channel = discord.GetChannel(channel_id);
- const auto make_entry = [&](const Glib::ustring &name, const Glib::ustring &completion, const Glib::ustring &url = "") -> CompleterEntry * {
+ const auto make_entry = [&](const Glib::ustring &name, const Glib::ustring &completion, const Glib::ustring &url = "", bool animated = false) -> CompleterEntry * {
const auto entry = CreateEntry(completion);
entry->SetText(name);
if (url == "") return entry;
- auto &img = Abaddon::Get().GetImageManager();
- const auto placeholder = img.GetPlaceholder(24);
- const auto pb = img.GetFromURLIfCached(url);
- if (pb)
- entry->SetImage(pb);
- else {
- entry->SetImage(placeholder);
- img.LoadFromURL(url, sigc::mem_fun(*entry, &CompleterEntry::SetImage));
- }
+ if (animated)
+ entry->SetAnimation(url);
+ else
+ entry->SetImage(url);
return entry;
};
int i = 0;
- if (channel->GuildID.has_value()) {
- const auto guild = discord.GetGuild(*channel->GuildID);
-
- if (guild->Emojis.has_value())
+ if (discord.GetSelfPremiumType() == PremiumType::None) {
+ if (channel->GuildID.has_value()) {
+ const auto guild = discord.GetGuild(*channel->GuildID);
+
+ if (guild.has_value() && guild->Emojis.has_value())
+ for (const auto tmp : *guild->Emojis) {
+ const auto emoji = *discord.GetEmoji(tmp.ID);
+ if (emoji.IsAnimated.has_value() && *emoji.IsAnimated) continue;
+ if (emoji.IsAvailable.has_value() && !*emoji.IsAvailable) continue;
+ if (emoji.Roles.has_value() && emoji.Roles->size() > 0) continue;
+ if (term.size() > 0)
+ if (!StringContainsCaseless(emoji.Name, term)) continue;
+
+ if (i++ > MaxCompleterEntries) break;
+
+ make_entry(emoji.Name, "<:" + emoji.Name + ":" + std::to_string(emoji.ID) + ">", emoji.GetURL());
+ }
+ }
+ } else {
+ for (const auto guild_id : discord.GetGuilds()) {
+ const auto guild = discord.GetGuild(guild_id);
+ if (!guild.has_value()) continue;
for (const auto tmp : *guild->Emojis) {
- const auto emoji = discord.GetEmoji(tmp.ID);
- if (!emoji.has_value()) continue;
- if (emoji->IsAnimated.has_value() && *emoji->IsAnimated) continue;
+ const auto emoji = *discord.GetEmoji(tmp.ID);
+ const bool is_animated = emoji.IsAnimated.has_value() && *emoji.IsAnimated;
+ if (emoji.IsAvailable.has_value() && !*emoji.IsAvailable) continue;
+ if (emoji.Roles.has_value() && emoji.Roles->size() > 0) continue;
if (term.size() > 0)
- if (!StringContainsCaseless(emoji->Name, term)) continue;
- if (i++ > MaxCompleterEntries) break;
+ if (!StringContainsCaseless(emoji.Name, term)) continue;
+
+ if (i++ > MaxCompleterEntries) goto done;
- const auto entry = make_entry(emoji->Name, "<:" + emoji->Name + ":" + std::to_string(emoji->ID) + ">", emoji->GetURL());
+ if (is_animated)
+ make_entry(emoji.Name, "<a:" + emoji.Name + ":" + std::to_string(emoji.ID) + ">", emoji.GetURL("gif"), true);
+ else
+ make_entry(emoji.Name, "<:" + emoji.Name + ":" + std::to_string(emoji.ID) + ">", emoji.GetURL());
}
+ }
}
+done:
// if <15 guild emojis match then load up stock
if (i < 15) {
@@ -202,7 +212,7 @@ void Completer::CompleteEmojis(const Glib::ustring &term) {
const auto &pb = emojis.GetPixBuf(pattern);
if (!pb) continue;
const auto entry = make_entry(shortcode, pattern);
- entry->SetImage(pb);
+ entry->SetImage(pb->scale_simple(CompleterImageSize, CompleterImageSize, Gdk::INTERP_BILINEAR));
}
}
}
@@ -342,13 +352,29 @@ void CompleterEntry::SetText(const Glib::ustring &text) {
}
void CompleterEntry::SetImage(const Glib::RefPtr<Gdk::Pixbuf> &pb) {
+ CheckImage();
+ m_img->property_pixbuf() = pb;
+}
+
+void CompleterEntry::SetImage(const std::string &url) {
+ CheckImage();
+ m_img->SetAnimated(false);
+ m_img->SetURL(url);
+}
+
+void CompleterEntry::SetAnimation(const std::string &url) {
+ CheckImage();
+ m_img->SetAnimated(true);
+ m_img->SetURL(url);
+}
+
+void CompleterEntry::CheckImage() {
if (m_img == nullptr) {
- m_img = Gtk::manage(new Gtk::Image);
+ m_img = Gtk::manage(new LazyImage(CompleterImageSize, CompleterImageSize));
m_img->get_style_context()->add_class("completer-entry-image");
m_img->show();
m_box.pack_start(*m_img);
}
- m_img->property_pixbuf() = pb->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
}
int CompleterEntry::GetIndex() const {
diff --git a/components/completer.hpp b/components/completer.hpp
index 259fcdc..a669824 100644
--- a/components/completer.hpp
+++ b/components/completer.hpp
@@ -1,24 +1,31 @@
#pragma once
#include <gtkmm.h>
#include <functional>
+#include "lazyimage.hpp"
#include "../discord/snowflake.hpp"
+constexpr static int CompleterImageSize = 24;
+
class CompleterEntry : public Gtk::ListBoxRow {
public:
CompleterEntry(const Glib::ustring &completion, int index);
void SetTextColor(int color); // SetText will reset
void SetText(const Glib::ustring &text);
void SetImage(const Glib::RefPtr<Gdk::Pixbuf> &pb);
+ void SetImage(const std::string &url);
+ void SetAnimation(const std::string &url);
int GetIndex() const;
Glib::ustring GetCompletion() const;
private:
+ void CheckImage();
+
Glib::ustring m_completion;
int m_index;
Gtk::Box m_box;
Gtk::Label *m_text = nullptr;
- Gtk::Image *m_img = nullptr;
+ LazyImage *m_img = nullptr;
};
class Completer : public Gtk::Revealer {
diff --git a/discord/discord.cpp b/discord/discord.cpp
index 54a7b52..5c287d6 100644
--- a/discord/discord.cpp
+++ b/discord/discord.cpp
@@ -1617,6 +1617,13 @@ std::set<Snowflake> DiscordClient::GetPrivateChannels() const {
return ret;
}
+PremiumType DiscordClient::GetSelfPremiumType() const {
+ const auto &data = GetUserData();
+ if (data.PremiumType.has_value())
+ return *data.PremiumType;
+ return PremiumType::None;
+}
+
void DiscordClient::HeartbeatThread() {
while (m_client_connected) {
if (!m_heartbeat_acked) {
diff --git a/discord/discord.hpp b/discord/discord.hpp
index f085c7b..bb3d800 100644
--- a/discord/discord.hpp
+++ b/discord/discord.hpp
@@ -75,6 +75,8 @@ public:
std::set<Snowflake> GetMessagesForChannel(Snowflake id) const;
std::set<Snowflake> GetPrivateChannels() const;
+ PremiumType GetSelfPremiumType() const;
+
void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<Snowflake> &)> cb);
void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> cb);
std::optional<Message> GetMessage(Snowflake id) const;
diff --git a/discord/user.hpp b/discord/user.hpp
index 025139e..afb1149 100644
--- a/discord/user.hpp
+++ b/discord/user.hpp
@@ -3,6 +3,12 @@
#include "json.hpp"
#include <string>
+enum class PremiumType {
+ None = 0,
+ NitroClassic = 1,
+ Nitro = 2,
+};
+
struct UserData {
enum {
DiscordEmployee = 1 << 0,
@@ -36,7 +42,7 @@ struct UserData {
std::optional<bool> IsVerified;
std::optional<std::string> Email; // null
std::optional<uint64_t> Flags;
- std::optional<int> PremiumType; // null
+ std::optional<PremiumType> PremiumType; // null
std::optional<uint64_t> PublicFlags;
// undocumented (opt)