summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2020-12-21 19:08:44 -0500
committerouwou <26526779+ouwou@users.noreply.github.com>2020-12-21 19:08:44 -0500
commitd8ff05ddf898dfcd6fa0e3398cc38abcab07e2fe (patch)
tree667eb93e54d0698b62f098e911a24e70fb0448be
parent486d184c8306d3e8a4889a5b079cd9b3003896c2 (diff)
downloadabaddon-portaudio-d8ff05ddf898dfcd6fa0e3398cc38abcab07e2fe.tar.gz
abaddon-portaudio-d8ff05ddf898dfcd6fa0e3398cc38abcab07e2fe.zip
support animated guild icon
-rw-r--r--components/channels.cpp30
-rw-r--r--components/channels.hpp3
-rw-r--r--discord/guild.cpp4
-rw-r--r--discord/guild.hpp1
-rw-r--r--imgmanager.cpp40
-rw-r--r--imgmanager.hpp5
-rw-r--r--settings.cpp4
-rw-r--r--settings.hpp1
8 files changed, 77 insertions, 11 deletions
diff --git a/components/channels.cpp b/components/channels.cpp
index 172286b..38b1e1f 100644
--- a/components/channels.cpp
+++ b/components/channels.cpp
@@ -119,13 +119,25 @@ ChannelListRowGuild::ChannelListRowGuild(const Guild *data) {
m_menu.show_all();
+ const auto show_animations = Abaddon::Get().GetSettings().GetShowAnimations();
+ auto &img = Abaddon::Get().GetImageManager();
if (data->HasIcon()) {
- auto buf = Abaddon::Get().GetImageManager().GetFromURLIfCached(data->GetIconURL("png", "32"));
- if (buf)
- m_icon = Gtk::manage(new Gtk::Image(buf->scale_simple(24, 24, Gdk::INTERP_BILINEAR)));
- else {
- m_icon = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(24)));
- Abaddon::Get().GetImageManager().LoadFromURL(data->GetIconURL("png", "32"), sigc::mem_fun(*this, &ChannelListRowGuild::OnImageLoad));
+ if (data->HasAnimatedIcon() && show_animations) {
+ auto buf = img.GetAnimationFromURLIfCached(data->GetIconURL("gif", "32"), 24, 24);
+ if (buf)
+ m_icon = Gtk::manage(new Gtk::Image(buf));
+ else {
+ m_icon = Gtk::manage(new Gtk::Image(img.GetPlaceholder(24)));
+ img.LoadAnimationFromURL(data->GetIconURL("gif", "32"), 24, 24, sigc::mem_fun(*this, &ChannelListRowGuild::OnAnimatedImageLoad));
+ }
+ } else {
+ auto buf = img.GetFromURLIfCached(data->GetIconURL("png", "32"));
+ if (buf)
+ m_icon = Gtk::manage(new Gtk::Image(buf->scale_simple(24, 24, Gdk::INTERP_BILINEAR)));
+ else {
+ m_icon = Gtk::manage(new Gtk::Image(img.GetPlaceholder(24)));
+ img.LoadFromURL(data->GetIconURL("png", "32"), sigc::mem_fun(*this, &ChannelListRowGuild::OnImageLoad));
+ }
}
} else {
m_icon = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(24)));
@@ -148,10 +160,14 @@ ChannelListRowGuild::ChannelListRowGuild(const Guild *data) {
show_all_children();
}
-void ChannelListRowGuild::OnImageLoad(Glib::RefPtr<Gdk::Pixbuf> buf) {
+void ChannelListRowGuild::OnImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &buf) {
m_icon->property_pixbuf() = buf->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
}
+void ChannelListRowGuild::OnAnimatedImageLoad(const Glib::RefPtr<Gdk::PixbufAnimation> &buf) {
+ m_icon->property_pixbuf_animation() = buf;
+}
+
ChannelListRowGuild::type_signal_copy_id ChannelListRowGuild::signal_copy_id() {
return m_signal_copy_id;
}
diff --git a/components/channels.hpp b/components/channels.hpp
index d481b13..f259266 100644
--- a/components/channels.hpp
+++ b/components/channels.hpp
@@ -53,7 +53,8 @@ public:
int GuildIndex;
protected:
- void OnImageLoad(Glib::RefPtr<Gdk::Pixbuf> buf);
+ void OnImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &buf);
+ void OnAnimatedImageLoad(const Glib::RefPtr<Gdk::PixbufAnimation> &buf);
Gtk::EventBox *m_ev;
Gtk::Box *m_box;
diff --git a/discord/guild.cpp b/discord/guild.cpp
index 13e20bf..c3c35b9 100644
--- a/discord/guild.cpp
+++ b/discord/guild.cpp
@@ -122,6 +122,10 @@ bool Guild::HasIcon() const {
return Icon != "";
}
+bool Guild::HasAnimatedIcon() const {
+ return HasIcon() && Icon[0] == 'a' && Icon[1] == '_';
+}
+
std::string Guild::GetIconURL(std::string ext, std::string size) const {
return "https://cdn.discordapp.com/icons/" + std::to_string(ID) + "/" + Icon + "." + ext + "?size=" + size;
}
diff --git a/discord/guild.hpp b/discord/guild.hpp
index d0863d5..ba46d75 100644
--- a/discord/guild.hpp
+++ b/discord/guild.hpp
@@ -68,6 +68,7 @@ struct Guild {
void update_from_json(const nlohmann::json &j);
bool HasIcon() const;
+ bool HasAnimatedIcon() const;
std::string GetIconURL(std::string ext = "png", std::string size = "32") const;
std::vector<Snowflake> GetSortedChannels(Snowflake ignore = Snowflake::Invalid) const;
};
diff --git a/imgmanager.cpp b/imgmanager.cpp
index 218c9ca..c1c67fd 100644
--- a/imgmanager.cpp
+++ b/imgmanager.cpp
@@ -20,9 +20,19 @@ Glib::RefPtr<Gdk::Pixbuf> ImageManager::ReadFileToPixbuf(std::string path) {
});
loader->write(static_cast<const guint8 *>(data.data()), data.size());
loader->close();
- auto buf = loader->get_pixbuf();
+ return loader->get_pixbuf();
+}
- return buf;
+Glib::RefPtr<Gdk::PixbufAnimation> ImageManager::ReadFileToPixbufAnimation(std::string path, int w, int h) {
+ const auto &data = ReadWholeFile(path);
+ if (data.size() == 0) return Glib::RefPtr<Gdk::PixbufAnimation>(nullptr);
+ auto loader = Gdk::PixbufLoader::create();
+ loader->signal_size_prepared().connect([&loader, w, h](int, int) {
+ loader->set_size(w, h);
+ });
+ loader->write(static_cast<const guint8 *>(data.data()), data.size());
+ loader->close();
+ return loader->get_animation();
}
void ImageManager::LoadFromURL(std::string url, callback_type cb) {
@@ -35,12 +45,28 @@ void ImageManager::LoadFromURL(std::string url, callback_type cb) {
m_cb_queue.push([signal, buf]() { signal.emit(buf); });
m_cb_dispatcher.emit();
m_cb_mutex.unlock();
- } catch (std::exception &e) {
+ } catch (const std::exception &e) {
fprintf(stderr, "err loading pixbuf from %s: %s\n", path.c_str(), e.what());
}
});
}
+void ImageManager::LoadAnimationFromURL(std::string url, int w, int h, callback_anim_type cb) {
+ sigc::signal<void(Glib::RefPtr<Gdk::PixbufAnimation>)> signal;
+ signal.connect(cb);
+ m_cache.GetFileFromURL(url, [this, url, signal, w, h](std::string path) {
+ try {
+ auto buf = ReadFileToPixbufAnimation(path, w, h);
+ m_cb_mutex.lock();
+ m_cb_queue.push([signal, buf]() { signal.emit(buf); });
+ m_cb_dispatcher.emit();
+ m_cb_mutex.unlock();
+ } catch (const std::exception &e) {
+ fprintf(stderr, "err loading pixbuf animation from %s: %s\n", path.c_str(), e.what());
+ }
+ });
+}
+
void ImageManager::Prefetch(std::string url) {
m_cache.GetFileFromURL(url, [](const auto &) {});
}
@@ -60,6 +86,14 @@ Glib::RefPtr<Gdk::Pixbuf> ImageManager::GetFromURLIfCached(std::string url) {
return Glib::RefPtr<Gdk::Pixbuf>(nullptr);
}
+Glib::RefPtr<Gdk::PixbufAnimation> ImageManager::GetAnimationFromURLIfCached(std::string url, int w, int h) {
+ std::string path = m_cache.GetPathIfCached(url);
+ if (path != "")
+ return ReadFileToPixbufAnimation(path, w, h);
+
+ return Glib::RefPtr<Gdk::PixbufAnimation>(nullptr);
+}
+
Glib::RefPtr<Gdk::Pixbuf> ImageManager::GetPlaceholder(int size) {
std::string name = "/placeholder" + std::to_string(size);
if (m_pixs.find(name) != m_pixs.end())
diff --git a/imgmanager.hpp b/imgmanager.hpp
index 46d8ab3..f665a7b 100644
--- a/imgmanager.hpp
+++ b/imgmanager.hpp
@@ -10,16 +10,21 @@ class ImageManager {
public:
ImageManager();
+ using callback_anim_type = sigc::slot<void(Glib::RefPtr<Gdk::PixbufAnimation>)>;
using callback_type = sigc::slot<void(Glib::RefPtr<Gdk::Pixbuf>)>;
Cache &GetCache();
void LoadFromURL(std::string url, callback_type cb);
+ // animations need dimensions before loading since there is no (easy) way to scale a PixbufAnimation
+ void LoadAnimationFromURL(std::string url, int w, int h, callback_anim_type cb);
void Prefetch(std::string url);
Glib::RefPtr<Gdk::Pixbuf> GetFromURLIfCached(std::string url);
+ Glib::RefPtr<Gdk::PixbufAnimation> GetAnimationFromURLIfCached(std::string url, int w, int h);
Glib::RefPtr<Gdk::Pixbuf> GetPlaceholder(int size);
private:
Glib::RefPtr<Gdk::Pixbuf> ReadFileToPixbuf(std::string path);
+ Glib::RefPtr<Gdk::PixbufAnimation> ReadFileToPixbufAnimation(std::string path, int w, int h);
mutable std::mutex m_load_mutex;
void RunCallbacks();
diff --git a/settings.cpp b/settings.cpp
index ce7d94e..7790e36 100644
--- a/settings.cpp
+++ b/settings.cpp
@@ -73,3 +73,7 @@ bool SettingsManager::GetPrefetch() const {
std::string SettingsManager::GetMainCSS() const {
return GetSettingString("gui", "css", "./css/main.css");
}
+
+bool SettingsManager::GetShowAnimations() const {
+ return GetSettingBool("gui", "animations", true);
+}
diff --git a/settings.hpp b/settings.hpp
index 30ce975..7bb022e 100644
--- a/settings.hpp
+++ b/settings.hpp
@@ -18,6 +18,7 @@ public:
int GetCacheHTTPConcurrency() const;
bool GetPrefetch() const;
std::string GetMainCSS() const;
+ bool GetShowAnimations() const;
bool IsValid() const;