animated emojis
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
#include "../util.hpp"
|
#include "../util.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
constexpr const int EmojiSize = 24; // settings eventually
|
||||||
|
|
||||||
ChatMessageItemContainer::ChatMessageItemContainer() {
|
ChatMessageItemContainer::ChatMessageItemContainer() {
|
||||||
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
|
||||||
add(*m_main);
|
add(*m_main);
|
||||||
@@ -568,7 +570,7 @@ void ChatMessageItemContainer::HandleUserMentions(Gtk::TextView *tv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatMessageItemContainer::HandleStockEmojis(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) {
|
void ChatMessageItemContainer::HandleCustomEmojis(Gtk::TextView *tv) {
|
||||||
@@ -584,6 +586,8 @@ void ChatMessageItemContainer::HandleCustomEmojis(Gtk::TextView *tv) {
|
|||||||
while (rgx->match(text, startpos, match)) {
|
while (rgx->match(text, startpos, match)) {
|
||||||
int mstart, mend;
|
int mstart, mend;
|
||||||
if (!match.fetch_pos(0, mstart, mend)) break;
|
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_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);
|
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);
|
auto end_it = buf->get_iter_at_offset(chars_end);
|
||||||
|
|
||||||
startpos = mend;
|
startpos = mend;
|
||||||
auto pixbuf = img.GetFromURLIfCached(Emoji::URLFromID(match.fetch(2)));
|
if (is_animated && show_animations) {
|
||||||
if (pixbuf) {
|
auto pixbuf = img.GetAnimationFromURLIfCached(Emoji::URLFromID(match.fetch(2), "gif"), EmojiSize, EmojiSize);
|
||||||
auto it = buf->erase(start_it, end_it);
|
if (pixbuf) {
|
||||||
int alen = text.size();
|
const auto it = buf->erase(start_it, end_it);
|
||||||
text = GetText(buf);
|
const int alen = text.size();
|
||||||
int blen = text.size();
|
text = GetText(buf);
|
||||||
startpos -= (alen - blen);
|
const int blen = text.size();
|
||||||
buf->insert_pixbuf(it, pixbuf->scale_simple(24, 24, Gdk::INTERP_BILINEAR));
|
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 {
|
} else {
|
||||||
// clang-format off
|
auto pixbuf = img.GetFromURLIfCached(Emoji::URLFromID(match.fetch(2)));
|
||||||
// can't erase before pixbuf is ready or else marks that are in the same pos get mixed up
|
if (pixbuf) {
|
||||||
auto mark_start = buf->create_mark(start_it, false);
|
const auto it = buf->erase(start_it, end_it);
|
||||||
end_it.backward_char();
|
const int alen = text.size();
|
||||||
auto mark_end = buf->create_mark(end_it, false);
|
text = GetText(buf);
|
||||||
img.LoadFromURL(Emoji::URLFromID(match.fetch(2)), sigc::track_obj([this, buf, mark_start, mark_end](Glib::RefPtr<Gdk::Pixbuf> pixbuf) {
|
const int blen = text.size();
|
||||||
auto start_it = mark_start->get_iter();
|
startpos -= (alen - blen);
|
||||||
auto end_it = mark_end->get_iter();
|
buf->insert_pixbuf(it, pixbuf->scale_simple(EmojiSize, EmojiSize, Gdk::INTERP_BILINEAR));
|
||||||
end_it.forward_char();
|
} else {
|
||||||
buf->delete_mark(mark_start);
|
// can't erase before pixbuf is ready or else marks that are in the same pos get mixed up
|
||||||
buf->delete_mark(mark_end);
|
const auto mark_start = buf->create_mark(start_it, false);
|
||||||
auto it = buf->erase(start_it, end_it);
|
end_it.backward_char();
|
||||||
buf->insert_pixbuf(it, pixbuf->scale_simple(24, 24, Gdk::INTERP_BILINEAR));
|
const auto mark_end = buf->create_mark(end_it, false);
|
||||||
}, tv));
|
const auto cb = [this, buf, mark_start, mark_end](const Glib::RefPtr<Gdk::Pixbuf> &pixbuf) {
|
||||||
// clang-format on
|
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);
|
text = GetText(buf);
|
||||||
|
@@ -32,6 +32,6 @@ std::string Emoji::GetURL() const {
|
|||||||
return "https://cdn.discordapp.com/emojis/" + std::to_string(ID) + ".png";
|
return "https://cdn.discordapp.com/emojis/" + std::to_string(ID) + ".png";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Emoji::URLFromID(std::string emoji_id) {
|
std::string Emoji::URLFromID(std::string emoji_id, std::string ext) {
|
||||||
return "https://cdn.discordapp.com/emojis/" + emoji_id + ".png";
|
return "https://cdn.discordapp.com/emojis/" + emoji_id + "." + ext;
|
||||||
}
|
}
|
||||||
|
@@ -19,5 +19,5 @@ struct Emoji {
|
|||||||
friend void to_json(nlohmann::json &j, const Emoji &m);
|
friend void to_json(nlohmann::json &j, const Emoji &m);
|
||||||
|
|
||||||
std::string GetURL() const;
|
std::string GetURL() const;
|
||||||
static std::string URLFromID(std::string emoji_id);
|
static std::string URLFromID(std::string emoji_id, std::string ext = "png");
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user