diff options
-rw-r--r-- | src/components/chatmessage.cpp | 43 | ||||
-rw-r--r-- | src/components/chatmessage.hpp | 3 | ||||
-rw-r--r-- | src/discord/role.cpp | 8 | ||||
-rw-r--r-- | src/discord/role.hpp | 3 |
4 files changed, 55 insertions, 2 deletions
diff --git a/src/components/chatmessage.cpp b/src/components/chatmessage.cpp index d34730b..69e46a6 100644 --- a/src/components/chatmessage.cpp +++ b/src/components/chatmessage.cpp @@ -203,6 +203,7 @@ void ChatMessageItemContainer::UpdateTextComponent(Gtk::TextView *tv) { case MessageType::DEFAULT: case MessageType::INLINE_REPLY: b->insert(s, data->Content); + HandleRoleMentions(b); HandleUserMentions(b); HandleLinks(*tv); HandleChannelMentions(tv); @@ -736,7 +737,47 @@ bool ChatMessageItemContainer::IsEmbedImageOnly(const EmbedData &data) { return data.Thumbnail->ProxyURL.has_value() && data.Thumbnail->URL.has_value() && data.Thumbnail->Width.has_value() && data.Thumbnail->Height.has_value(); } -void ChatMessageItemContainer::HandleUserMentions(Glib::RefPtr<Gtk::TextBuffer> buf) { +void ChatMessageItemContainer::HandleRoleMentions(const Glib::RefPtr<Gtk::TextBuffer> &buf) { + constexpr static const auto mentions_regex = R"(<@&(\d+)>)"; + + static auto rgx = Glib::Regex::create(mentions_regex); + + Glib::ustring text = GetText(buf); + const auto &discord = Abaddon::Get().GetDiscordClient(); + + int startpos = 0; + Glib::MatchInfo match; + while (rgx->match(text, startpos, match)) { + int mstart, mend; + if (!match.fetch_pos(0, mstart, mend)) break; + const Glib::ustring role_id = match.fetch(1); + const auto role = discord.GetRole(role_id); + if (!role.has_value()) { + startpos = mend; + continue; + } + + Glib::ustring replacement; + if (role->HasColor()) { + replacement = "<b><span color=\"#" + IntToCSSColor(role->Color) + "\">@" + role->GetEscapedName() + "</span></b>"; + } else { + replacement = "<b>@" + role->GetEscapedName() + "</b>"; + } + + 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 start_it = buf->get_iter_at_offset(chars_start); + const auto end_it = buf->get_iter_at_offset(chars_end); + + auto it = buf->erase(start_it, end_it); + buf->insert_markup(it, replacement); + + text = GetText(buf); + startpos = 0; + } +} + +void ChatMessageItemContainer::HandleUserMentions(const Glib::RefPtr<Gtk::TextBuffer> &buf) { constexpr static const auto mentions_regex = R"(<@!?(\d+)>)"; static auto rgx = Glib::Regex::create(mentions_regex); diff --git a/src/components/chatmessage.hpp b/src/components/chatmessage.hpp index 8b69117..bd99275 100644 --- a/src/components/chatmessage.hpp +++ b/src/components/chatmessage.hpp @@ -34,7 +34,8 @@ protected: static bool IsEmbedImageOnly(const EmbedData &data); - void HandleUserMentions(Glib::RefPtr<Gtk::TextBuffer> buf); + void HandleRoleMentions(const Glib::RefPtr<Gtk::TextBuffer> &buf); + void HandleUserMentions(const Glib::RefPtr<Gtk::TextBuffer> &buf); void HandleStockEmojis(Gtk::TextView &tv); void HandleCustomEmojis(Gtk::TextView &tv); void HandleEmojis(Gtk::TextView &tv); diff --git a/src/discord/role.cpp b/src/discord/role.cpp index 07a912e..8a9ed50 100644 --- a/src/discord/role.cpp +++ b/src/discord/role.cpp @@ -12,3 +12,11 @@ void from_json(const nlohmann::json &j, RoleData &m) { JS_D("managed", m.IsManaged); JS_D("mentionable", m.IsMentionable); } + +bool RoleData::HasColor() const noexcept { + return Color != 0; +} + +Glib::ustring RoleData::GetEscapedName() const { + return Glib::Markup::escape_text(Name); +} diff --git a/src/discord/role.hpp b/src/discord/role.hpp index f638b65..a526f4e 100644 --- a/src/discord/role.hpp +++ b/src/discord/role.hpp @@ -16,5 +16,8 @@ struct RoleData { bool IsManaged; bool IsMentionable; + bool HasColor() const noexcept; + Glib::ustring GetEscapedName() const; + friend void from_json(const nlohmann::json &j, RoleData &m); }; |