diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | abaddon.cpp | 6 | ||||
-rw-r--r-- | abaddon.hpp | 6 | ||||
-rw-r--r-- | components/chatmessage.cpp | 20 | ||||
-rw-r--r-- | components/chatmessage.hpp | 1 | ||||
-rw-r--r-- | components/chatwindow.cpp | 19 | ||||
-rw-r--r-- | discord/user.hpp | 2 | ||||
-rw-r--r-- | imgmanager.cpp | 29 | ||||
-rw-r--r-- | imgmanager.hpp | 17 |
9 files changed, 87 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 33e5c0a..792e373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,8 @@ add_executable(abaddon abaddon.cpp filecache.hpp filecache.cpp + "imgmanager.hpp" + "imgmanager.cpp" components/channels.hpp components/channels.cpp components/chatmessage.hpp diff --git a/abaddon.cpp b/abaddon.cpp index e241ca7..2b8ea4e 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -199,6 +199,8 @@ void Abaddon::ActionCopyGuildID(Snowflake id) { } void Abaddon::ActionListChannelItemClick(Snowflake id) { + if (id == m_main_window->GetChatActiveChannel()) return; + auto *channel = m_discord.GetChannel(id); if (channel->Type != ChannelType::DM && channel->Type != ChannelType::GROUP_DM) m_discord.SendLazyLoad(id); @@ -283,8 +285,8 @@ void Abaddon::ActionReloadCSS() { } } -Cache &Abaddon::GetCache() { - return m_cache; +ImageManager &Abaddon::GetImageManager() { + return m_img_mgr; } int main(int argc, char **argv) { diff --git a/abaddon.hpp b/abaddon.hpp index a52e759..9b4bf81 100644 --- a/abaddon.hpp +++ b/abaddon.hpp @@ -6,7 +6,7 @@ #include "discord/discord.hpp" #include "windows/mainwindow.hpp" #include "settings.hpp" -#include "filecache.hpp" +#include "imgmanager.hpp" #define APP_TITLE "Abaddon" @@ -43,7 +43,7 @@ public: void ActionReloadCSS(); - Cache &GetCache(); + ImageManager &GetImageManager(); std::string GetDiscordToken() const; bool IsDiscordActive() const; @@ -65,7 +65,7 @@ private: std::unordered_map<Snowflake, Snowflake> m_oldest_listed_message; std::unordered_set<Snowflake> m_channels_history_loading; - Cache m_cache; + ImageManager m_img_mgr; mutable std::mutex m_mutex; Glib::RefPtr<Gtk::Application> m_gtk_app; diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index c3f4dae..cdb1b28 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -14,18 +14,16 @@ ChatMessageContainer::ChatMessageContainer(const Message *data) { m_author = Gtk::manage(new Gtk::Label); m_timestamp = Gtk::manage(new Gtk::Label); - static Glib::RefPtr<Gdk::Pixbuf> test = Gdk::Pixbuf::create_from_file("res/decamarks.png", 32, 32); - m_avatar = Gtk::manage(new Gtk::Image(test)); + static auto placeholder = Gdk::Pixbuf::create_from_file("res/decamarks.png", 32, 32); + auto buf = Abaddon::Get().GetImageManager().GetFromURLIfCached(data->Author.GetAvatarURL()); + if (buf) + m_avatar = Gtk::manage(new Gtk::Image(buf)); + else + m_avatar = Gtk::manage(new Gtk::Image(placeholder)); + m_avatar->set_valign(Gtk::ALIGN_START); m_avatar->set_margin_right(10); - if (data->Author.HasAvatar()) { - Abaddon::Get().GetCache().GetFileFromURL(data->Author.GetAvatarURL(), [this](std::string filepath) { - auto buf = Gdk::Pixbuf::create_from_file(filepath, 32, 32); - m_avatar->property_pixbuf() = buf; - }); - } - get_style_context()->add_class("message-container"); m_author->get_style_context()->add_class("message-container-author"); m_timestamp->get_style_context()->add_class("message-container-timestamp"); @@ -67,6 +65,10 @@ ChatMessageContainer::ChatMessageContainer(const Message *data) { show(); } +void ChatMessageContainer::SetAvatarFromPixbuf(Glib::RefPtr<Gdk::Pixbuf> pixbuf) { + m_avatar->property_pixbuf() = pixbuf; +} + void ChatMessageContainer::Update() { auto &discord = Abaddon::Get().GetDiscordClient(); auto guild_id = discord.GetChannel(ChannelID)->GuildID; diff --git a/components/chatmessage.hpp b/components/chatmessage.hpp index e7202a5..9365dd5 100644 --- a/components/chatmessage.hpp +++ b/components/chatmessage.hpp @@ -19,6 +19,7 @@ public: ChatMessageContainer(const Message *data); void AddNewContent(Gtk::Widget *widget, bool prepend = false); + void SetAvatarFromPixbuf(Glib::RefPtr<Gdk::Pixbuf> pixbuf); void Update(); protected: diff --git a/components/chatwindow.cpp b/components/chatwindow.cpp index d8ae2b7..b7da92d 100644 --- a/components/chatwindow.cpp +++ b/components/chatwindow.cpp @@ -115,6 +115,25 @@ void ChatWindow::ProcessMessage(const Message *data, bool prepend) { } else { container = Gtk::manage(new ChatMessageContainer(data)); // only accesses timestamp and user container->Update(); + + auto user_id = data->Author.ID; + const auto *user = Abaddon::Get().GetDiscordClient().GetUser(user_id); + if (user == nullptr) return; + Abaddon::Get().GetImageManager().LoadFromURL(user->GetAvatarURL(), [this, user_id](Glib::RefPtr<Gdk::Pixbuf> buf) { + // am i retarded? + Glib::signal_idle().connect([this, buf, user_id]() -> bool { + auto children = m_listbox->get_children(); + for (auto child : children) { + auto *row = dynamic_cast<ChatMessageContainer *>(child); + if (row == nullptr) continue; + if (row->UserID == user_id) { + row->SetAvatarFromPixbuf(buf); + } + } + + return false; + }); + }); m_num_rows++; } diff --git a/discord/user.hpp b/discord/user.hpp index e495b21..ff809a6 100644 --- a/discord/user.hpp +++ b/discord/user.hpp @@ -27,5 +27,5 @@ struct User { friend void from_json(const nlohmann::json &j, User &m); bool HasAvatar() const; - std::string GetAvatarURL(std::string ext = "png", std::string size = "64") const; + std::string GetAvatarURL(std::string ext = "png", std::string size = "32") const; }; diff --git a/imgmanager.cpp b/imgmanager.cpp new file mode 100644 index 0000000..2d9c0aa --- /dev/null +++ b/imgmanager.cpp @@ -0,0 +1,29 @@ +#include "imgmanager.hpp" + +Cache &ImageManager::GetCache() { + return m_cache; +} + +void ImageManager::LoadFromURL(std::string url, std::function<void(Glib::RefPtr<Gdk::Pixbuf>)> cb) { + if (m_pixs.find(url) != m_pixs.end()) { + cb(m_pixs.at(url)); + return; + } + + m_cache.GetFileFromURL(url, [this, url, cb](std::string path) { + try { + auto buf = Gdk::Pixbuf::create_from_file(path); + m_pixs[url] = buf; + cb(buf); + } catch (std::exception &e) { + fprintf(stderr, "err loading pixbuf from %s: %s\n", path.c_str(), e.what()); + } + }); +} + +Glib::RefPtr<Gdk::Pixbuf> ImageManager::GetFromURLIfCached(std::string url) { + if (m_pixs.find(url) != m_pixs.end()) + return m_pixs.at(url); + + return Glib::RefPtr<Gdk::Pixbuf>(nullptr); +} diff --git a/imgmanager.hpp b/imgmanager.hpp new file mode 100644 index 0000000..80262a8 --- /dev/null +++ b/imgmanager.hpp @@ -0,0 +1,17 @@ +#pragma once +#include <string> +#include <unordered_map> +#include <functional> +#include <gtkmm.h> +#include "filecache.hpp" + +class ImageManager { +public: + Cache &GetCache(); + void LoadFromURL(std::string url, std::function<void(Glib::RefPtr<Gdk::Pixbuf>)> cb); + Glib::RefPtr<Gdk::Pixbuf> GetFromURLIfCached(std::string url); + +private: + std::unordered_map<std::string, Glib::RefPtr<Gdk::Pixbuf>> m_pixs; + Cache m_cache; +}; |