diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-09 23:14:57 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-09 23:14:57 -0400 |
commit | a93230e6926b6a1b5aae77d5e98c36af57cb43fa (patch) | |
tree | 71054174f1cb6afd5ddc76ac3cb92aa888b79f77 /components | |
parent | 2798bf96d5ec788cf7ecbcb7fbc53198ce2e5569 (diff) | |
download | abaddon-portaudio-a93230e6926b6a1b5aae77d5e98c36af57cb43fa.tar.gz abaddon-portaudio-a93230e6926b6a1b5aae77d5e98c36af57cb43fa.zip |
make links clickable
Diffstat (limited to 'components')
-rw-r--r-- | components/chatmessage.cpp | 77 | ||||
-rw-r--r-- | components/chatmessage.hpp | 4 |
2 files changed, 81 insertions, 0 deletions
diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index ccd7436..a4ac57c 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -171,6 +171,7 @@ void ChatMessageItemContainer::UpdateTextComponent(Gtk::TextView *tv) { switch (data->Type) { case MessageType::DEFAULT: b->insert_markup(s, ParseMessageContent(Glib::Markup::escape_text(data->Content))); + HandleLinks(tv); break; case MessageType::GUILD_MEMBER_JOIN: b->insert_markup(s, "<span color='#999999'><i>[user joined]</i></span>"); @@ -388,6 +389,82 @@ std::string ChatMessageItemContainer::ParseMentions(std::string content) { }); } +void ChatMessageItemContainer::HandleLinks(Gtk::TextView *tv) { + constexpr static const auto links_regex = R"(\bhttps?:\/\/[^\s]+\.[^\s]+\b)"; + + std::regex rgx(links_regex, std::regex_constants::ECMAScript); + + tv->signal_button_press_event().connect(sigc::mem_fun(*this, &ChatMessageItemContainer::OnLinkClick), false); + + auto buf = tv->get_buffer(); + std::string text = buf->get_text(); + buf->set_text(""); + + std::string::const_iterator sstart(text.begin()); + std::smatch match; + bool any = false; + + // i'd like to let this be done thru css like .message-link { color: #bitch; } but idk how + auto &settings = Abaddon::Get().GetSettings(); + auto link_color = settings.GetSettingString("misc", "linkcolor", "rgba(40, 200, 180, 255)"); + + while (std::regex_search(sstart, text.cend(), match, rgx)) { + any = true; + + Gtk::TextBuffer::iterator start, end; + buf->get_bounds(start, end); + + std::string pre = match.prefix().str(); + + std::string link = match.str(); + auto tag = buf->create_tag(); + m_linkmap[tag] = link; + tag->property_foreground_rgba() = Gdk::RGBA(link_color); + buf->get_bounds(start, end); + end = buf->insert(end, pre); + end = buf->insert_with_tag(end, link, tag); + + sstart = match.suffix().first; + } + + Gtk::TextBuffer::iterator start, end; + buf->get_bounds(start, end); + if (any) { + buf->insert(end, match.suffix().str()); + } else { + buf->insert(end, text); + } +} + +bool ChatMessageItemContainer::OnLinkClick(GdkEventButton *ev) { + if (m_text_component == nullptr) return false; + if (ev->type != Gdk::BUTTON_PRESS) return false; + if (ev->button != GDK_BUTTON_PRIMARY) return false; + + auto buf = m_text_component->get_buffer(); + Gtk::TextBuffer::iterator start, end; + buf->get_selection_bounds(start, end); // no open if selection + if (start.get_offset() != end.get_offset()) + return false; + + int x, y; + m_text_component->window_to_buffer_coords(Gtk::TEXT_WINDOW_WIDGET, ev->x, ev->y, x, y); + Gtk::TextBuffer::iterator iter; + m_text_component->get_iter_at_location(iter, x, y); + + const auto tags = iter.get_tags(); + for (auto tag : tags) { + const auto it = m_linkmap.find(tag); + if (it != m_linkmap.end()) { + LaunchBrowser(it->second); + + return true; + } + } + + return false; +} + void ChatMessageItemContainer::ShowMenu(GdkEvent *event) { const auto &client = Abaddon::Get().GetDiscordClient(); const auto *data = client.GetMessage(ID); diff --git a/components/chatmessage.hpp b/components/chatmessage.hpp index 7dd057e..f01dc02 100644 --- a/components/chatmessage.hpp +++ b/components/chatmessage.hpp @@ -30,6 +30,10 @@ protected: std::string ParseMessageContent(std::string content); std::string ParseMentions(std::string content); + void HandleLinks(Gtk::TextView *tv); + bool OnLinkClick(GdkEventButton *ev); + std::map<Glib::RefPtr<Gtk::TextTag>, std::string> m_linkmap; // sue me + std::unordered_map<std::string, std::pair<Gtk::Image *, AttachmentData>> m_img_loadmap; void AttachMenuHandler(Gtk::Widget *widget); |