diff --git a/chatterino.pro b/chatterino.pro index 2e0ae0055..69fe3e0c3 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -237,6 +237,7 @@ SOURCES += \ src/messages/Emote.cpp \ src/messages/ImageSet.cpp \ src/providers/bttv/BttvEmotes.cpp \ + src/providers/LinkResolver.cpp \ src/providers/ffz/FfzEmotes.cpp \ src/autogenerated/ResourcesAutogen.cpp \ src/singletons/Badges.cpp \ @@ -431,6 +432,7 @@ HEADERS += \ src/messages/ImageSet.hpp \ src/common/Outcome.hpp \ src/providers/bttv/BttvEmotes.hpp \ + src/providers/LinkResolver.hpp \ src/providers/ffz/FfzEmotes.hpp \ src/autogenerated/ResourcesAutogen.hpp \ src/singletons/Badges.hpp \ diff --git a/src/providers/LinkResolver.cpp b/src/providers/LinkResolver.cpp new file mode 100644 index 000000000..d6917157d --- /dev/null +++ b/src/providers/LinkResolver.cpp @@ -0,0 +1,42 @@ +#include "providers/LinkResolver.hpp" + +#include "common/Common.hpp" +#include "common/NetworkRequest.hpp" + +#include + +namespace chatterino { + +void LinkResolver::getLinkInfo(const QString url, + std::function successCallback) +{ + QString requestUrl("https://braize.pajlada.com/chatterino/link_resolver/" + + QUrl::toPercentEncoding(url, "", "/:")); + + NetworkRequest request(requestUrl); + request.setCaller(QThread::currentThread()); + request.setTimeout(30000); + request.onSuccess([successCallback](auto result) mutable -> Outcome { + auto root = result.parseJson(); + auto statusCode = root.value("status").toInt(); + QString response = QString(); + if (statusCode == 200) { + response = root.value("tooltip").toString(); + } else { + response = root.value("message").toString(); + } + successCallback(QUrl::fromPercentEncoding(response.toUtf8())); + + return Success; + }); + + request.onError([successCallback](auto result) { + successCallback("No link info found"); + + return true; + }); + + request.execute(); +} + +} // namespace chatterino diff --git a/src/providers/LinkResolver.hpp b/src/providers/LinkResolver.hpp new file mode 100644 index 000000000..919109aaf --- /dev/null +++ b/src/providers/LinkResolver.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace chatterino { + +class LinkResolver +{ +public: + static void getLinkInfo(const QString url, + std::function callback); + +private: +}; + +} // namespace chatterino diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index a5bf3a4d2..756225769 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -8,6 +8,7 @@ #include "messages/Message.hpp" #include "providers/twitch/TwitchBadges.hpp" #include "providers/twitch/TwitchChannel.hpp" +#include "providers/LinkResolver.hpp" #include "singletons/Emotes.hpp" #include "singletons/Resources.hpp" #include "singletons/Settings.hpp" @@ -268,12 +269,20 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) link = Link(Link::Url, linkString); textColor = MessageColor(MessageColor::Link); - this->emplace(lowercaseLinkString, + auto linkMELowercase = this->emplace(lowercaseLinkString, MessageElementFlag::LowercaseLink, textColor) ->setLink(link); - this->emplace(string, MessageElementFlag::OriginalLink, - textColor) + auto linkMEOriginal = this->emplace(string, + MessageElementFlag::OriginalLink, textColor) ->setLink(link); + + LinkResolver::getLinkInfo( + linkString, [linkMELowercase, linkMEOriginal](QString tooltipText) { + if (!tooltipText.isEmpty()) { + linkMELowercase->setTooltip(tooltipText); + linkMEOriginal->setTooltip(tooltipText); + } + }); } // if (!linkString.isEmpty()) { diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index 861a0aec0..3f9a26f74 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -103,6 +103,7 @@ public: /// Links BoolSetting linksDoubleClickOnly = {"/links/doubleClickToOpen", false}; + BoolSetting enableLinkInfoTooltip = {"/links/linkInfoTooltip", false}; BoolSetting enableLowercaseLink = {"/links/linkLowercase", true}; /// Ingored Users diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index 084f729ac..5ee0b1daf 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -87,6 +87,11 @@ void TooltipWidget::setText(QString text) this->displayText_->setText(text); } +void TooltipWidget::setWordWrap(bool wrap) +{ + this->displayText_->setWordWrap(wrap); +} + void TooltipWidget::changeEvent(QEvent *) { // clear parents event diff --git a/src/widgets/TooltipWidget.hpp b/src/widgets/TooltipWidget.hpp index 7d8c95dc2..2228e5662 100644 --- a/src/widgets/TooltipWidget.hpp +++ b/src/widgets/TooltipWidget.hpp @@ -19,6 +19,7 @@ public: virtual ~TooltipWidget() override; void setText(QString text); + void setWordWrap(bool wrap); #ifdef USEWINSDK void raise(); diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 64ccfbf4f..554d00bf2 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -861,11 +861,15 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } const auto &tooltip = hoverLayoutElement->getCreator().getTooltip(); + bool isLinkValid = hoverLayoutElement->getLink().isValid(); if (tooltip.isEmpty()) { tooltipWidget->hide(); + } else if (isLinkValid && !getSettings()->enableLinkInfoTooltip) { + tooltipWidget->hide(); } else { tooltipWidget->moveTo(this, event->globalPos()); + tooltipWidget->setWordWrap(isLinkValid); tooltipWidget->setText(tooltip); tooltipWidget->adjustSize(); tooltipWidget->show(); @@ -873,7 +877,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) } // check if word has a link - if (hoverLayoutElement->getLink().isValid()) { + if (isLinkValid) { this->setCursor(Qt::PointingHandCursor); } else { this->setCursor(Qt::ArrowCursor); diff --git a/src/widgets/settingspages/FeelPage.cpp b/src/widgets/settingspages/FeelPage.cpp index 78b41c45d..b87a2d098 100644 --- a/src/widgets/settingspages/FeelPage.cpp +++ b/src/widgets/settingspages/FeelPage.cpp @@ -50,6 +50,9 @@ FeelPage::FeelPage() form->addRow("Links:", this->createCheckBox("Open links only on double click", getSettings()->linksDoubleClickOnly)); + form->addRow("", + this->createCheckBox("Show link info in tooltips", + getSettings()->enableLinkInfoTooltip)); } layout->addSpacing(16); diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index 611bbaace..42656fde0 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -458,6 +458,8 @@ void SplitHeader::enterEvent(QEvent *event) tooltip->moveTo(this, this->mapToGlobal(this->rect().bottomLeft()), false); tooltip->setText(this->tooltipText_); + tooltip->setWordWrap(false); + tooltip->adjustSize(); tooltip->show(); tooltip->raise(); }