diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-12-22 01:23:56 -0500 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-12-22 01:23:56 -0500 |
commit | 8a2f13795ddb13f6a6bb6d67ea409a628fe1d03b (patch) | |
tree | fd1c691653504c7f63f21b7d9e8ef543f3b73b33 /components | |
parent | d8ff05ddf898dfcd6fa0e3398cc38abcab07e2fe (diff) | |
download | abaddon-portaudio-8a2f13795ddb13f6a6bb6d67ea409a628fe1d03b.tar.gz abaddon-portaudio-8a2f13795ddb13f6a6bb6d67ea409a628fe1d03b.zip |
animated emojis
Diffstat (limited to 'components')
-rw-r--r-- | components/chatmessage.cpp | 83 |
1 files changed, 59 insertions, 24 deletions
diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index 85d8f16..f0df016 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -3,6 +3,8 @@ #include "../util.hpp" #include <unordered_map> +constexpr const int EmojiSize = 24; // settings eventually + ChatMessageItemContainer::ChatMessageItemContainer() { m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); add(*m_main); @@ -568,7 +570,7 @@ void ChatMessageItemContainer::HandleUserMentions(Gtk::TextView *tv) { } void ChatMessageItemContainer::HandleStockEmojis(Gtk::TextView *tv) { - Abaddon::Get().GetEmojis().ReplaceEmojis(tv->get_buffer()); + Abaddon::Get().GetEmojis().ReplaceEmojis(tv->get_buffer(), EmojiSize); } void ChatMessageItemContainer::HandleCustomEmojis(Gtk::TextView *tv) { @@ -584,6 +586,8 @@ void ChatMessageItemContainer::HandleCustomEmojis(Gtk::TextView *tv) { while (rgx->match(text, startpos, match)) { int mstart, mend; if (!match.fetch_pos(0, mstart, mend)) break; + const bool is_animated = match.fetch(0)[1] == 'a'; + const bool show_animations = Abaddon::Get().GetSettings().GetShowAnimations(); const auto chars_start = g_utf8_pointer_to_offset(text.c_str(), text.c_str() + mstart); const auto chars_end = g_utf8_pointer_to_offset(text.c_str(), text.c_str() + mend); @@ -591,30 +595,61 @@ void ChatMessageItemContainer::HandleCustomEmojis(Gtk::TextView *tv) { auto end_it = buf->get_iter_at_offset(chars_end); startpos = mend; - auto pixbuf = img.GetFromURLIfCached(Emoji::URLFromID(match.fetch(2))); - if (pixbuf) { - auto it = buf->erase(start_it, end_it); - int alen = text.size(); - text = GetText(buf); - int blen = text.size(); - startpos -= (alen - blen); - buf->insert_pixbuf(it, pixbuf->scale_simple(24, 24, Gdk::INTERP_BILINEAR)); + if (is_animated && show_animations) { + auto pixbuf = img.GetAnimationFromURLIfCached(Emoji::URLFromID(match.fetch(2), "gif"), EmojiSize, EmojiSize); + if (pixbuf) { + const auto it = buf->erase(start_it, end_it); + const int alen = text.size(); + text = GetText(buf); + const int blen = text.size(); + startpos -= (alen - blen); + const auto anchor = buf->create_child_anchor(it); + auto img = Gtk::manage(new Gtk::Image(pixbuf)); + img->show(); + tv->add_child_at_anchor(*img, anchor); + } else { + const auto mark_start = buf->create_mark(start_it, false); + end_it.backward_char(); + const auto mark_end = buf->create_mark(end_it, false); + const auto cb = [this, tv, buf, mark_start, mark_end](const Glib::RefPtr<Gdk::PixbufAnimation> &pixbuf) { + auto start_it = mark_start->get_iter(); + auto end_it = mark_end->get_iter(); + end_it.forward_char(); + buf->delete_mark(mark_start); + buf->delete_mark(mark_end); + auto it = buf->erase(start_it, end_it); + const auto anchor = buf->create_child_anchor(it); + auto img = Gtk::manage(new Gtk::Image(pixbuf)); + img->show(); + tv->add_child_at_anchor(*img, anchor); + }; + img.LoadAnimationFromURL(Emoji::URLFromID(match.fetch(2), "gif"), EmojiSize, EmojiSize, sigc::track_obj(cb, tv)); + } } else { - // clang-format off - // can't erase before pixbuf is ready or else marks that are in the same pos get mixed up - auto mark_start = buf->create_mark(start_it, false); - end_it.backward_char(); - auto mark_end = buf->create_mark(end_it, false); - img.LoadFromURL(Emoji::URLFromID(match.fetch(2)), sigc::track_obj([this, buf, mark_start, mark_end](Glib::RefPtr<Gdk::Pixbuf> pixbuf) { - auto start_it = mark_start->get_iter(); - auto end_it = mark_end->get_iter(); - end_it.forward_char(); - buf->delete_mark(mark_start); - buf->delete_mark(mark_end); - auto it = buf->erase(start_it, end_it); - buf->insert_pixbuf(it, pixbuf->scale_simple(24, 24, Gdk::INTERP_BILINEAR)); - }, tv)); - // clang-format on + auto pixbuf = img.GetFromURLIfCached(Emoji::URLFromID(match.fetch(2))); + if (pixbuf) { + const auto it = buf->erase(start_it, end_it); + const int alen = text.size(); + text = GetText(buf); + const int blen = text.size(); + startpos -= (alen - blen); + buf->insert_pixbuf(it, pixbuf->scale_simple(EmojiSize, EmojiSize, Gdk::INTERP_BILINEAR)); + } else { + // can't erase before pixbuf is ready or else marks that are in the same pos get mixed up + const auto mark_start = buf->create_mark(start_it, false); + end_it.backward_char(); + const auto mark_end = buf->create_mark(end_it, false); + const auto cb = [this, buf, mark_start, mark_end](const Glib::RefPtr<Gdk::Pixbuf> &pixbuf) { + auto start_it = mark_start->get_iter(); + auto end_it = mark_end->get_iter(); + end_it.forward_char(); + buf->delete_mark(mark_start); + buf->delete_mark(mark_end); + auto it = buf->erase(start_it, end_it); + buf->insert_pixbuf(it, pixbuf->scale_simple(EmojiSize, EmojiSize, Gdk::INTERP_BILINEAR)); + }; + img.LoadFromURL(Emoji::URLFromID(match.fetch(2)), sigc::track_obj(cb, tv)); + } } text = GetText(buf); |