Added "Open in: new tab, browser player, streamlink" in twitch link context menu. (#2988)
Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
- Minor: Channel name in `<channel> has gone offline. Exiting host mode.` messages is now clickable. (#2922)
|
- Minor: Channel name in `<channel> has gone offline. Exiting host mode.` messages is now clickable. (#2922)
|
||||||
- Minor: Added `/openurl` command. Usage: `/openurl <URL>`. Opens the provided URL in the browser. (#2461, #2926)
|
- Minor: Added `/openurl` command. Usage: `/openurl <URL>`. Opens the provided URL in the browser. (#2461, #2926)
|
||||||
- Minor: Updated to Emoji v13.1 (#2958)
|
- Minor: Updated to Emoji v13.1 (#2958)
|
||||||
|
- Minor: Added "Open in: new tab, browser player, streamlink" in twitch link context menu. (#2988)
|
||||||
- Minor: Sender username in automod messages shown to moderators shows correct color and display name. (#2967)
|
- Minor: Sender username in automod messages shown to moderators shows correct color and display name. (#2967)
|
||||||
- Bugfix: Now deleting cache files that weren't modified in the past 14 days. (#2947)
|
- Bugfix: Now deleting cache files that weren't modified in the past 14 days. (#2947)
|
||||||
- Bugfix: Fixed large timeout durations in moderation buttons overlapping with usernames or other buttons. (#2865, #2921)
|
- Bugfix: Fixed large timeout durations in moderation buttons overlapping with usernames or other buttons. (#2865, #2921)
|
||||||
|
|||||||
@@ -1924,7 +1924,7 @@ void ChannelView::addContextMenuItems(
|
|||||||
crossPlatformCopy(copyString);
|
crossPlatformCopy(copyString);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open in new split.
|
// If is a link to a twitch user/stream
|
||||||
if (hoveredElement->getLink().type == Link::Url)
|
if (hoveredElement->getLink().type == Link::Url)
|
||||||
{
|
{
|
||||||
static QRegularExpression twitchChannelRegex(
|
static QRegularExpression twitchChannelRegex(
|
||||||
@@ -1943,7 +1943,22 @@ void ChannelView::addContextMenuItems(
|
|||||||
{
|
{
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction("Open in new split", [twitchUsername, this] {
|
menu->addAction("Open in new split", [twitchUsername, this] {
|
||||||
this->joinToChannel.invoke(twitchUsername);
|
this->openChannelIn.invoke(twitchUsername,
|
||||||
|
FromTwitchLinkOpenChannelIn::Split);
|
||||||
|
});
|
||||||
|
menu->addAction("Open in new tab", [twitchUsername, this] {
|
||||||
|
this->openChannelIn.invoke(twitchUsername,
|
||||||
|
FromTwitchLinkOpenChannelIn::Tab);
|
||||||
|
});
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
menu->addAction("Open player in browser", [twitchUsername, this] {
|
||||||
|
this->openChannelIn.invoke(
|
||||||
|
twitchUsername, FromTwitchLinkOpenChannelIn::BrowserPlayer);
|
||||||
|
});
|
||||||
|
menu->addAction("Open in streamlink", [twitchUsername, this] {
|
||||||
|
this->openChannelIn.invoke(
|
||||||
|
twitchUsername, FromTwitchLinkOpenChannelIn::Streamlink);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,13 @@ enum class PauseReason {
|
|||||||
KeyboardModifier,
|
KeyboardModifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FromTwitchLinkOpenChannelIn {
|
||||||
|
Split,
|
||||||
|
Tab,
|
||||||
|
BrowserPlayer,
|
||||||
|
Streamlink,
|
||||||
|
};
|
||||||
|
|
||||||
using SteadyClock = std::chrono::steady_clock;
|
using SteadyClock = std::chrono::steady_clock;
|
||||||
|
|
||||||
class ChannelView final : public BaseWidget
|
class ChannelView final : public BaseWidget
|
||||||
@@ -96,7 +103,8 @@ public:
|
|||||||
pajlada::Signals::Signal<HighlightState> tabHighlightRequested;
|
pajlada::Signals::Signal<HighlightState> tabHighlightRequested;
|
||||||
pajlada::Signals::NoArgSignal liveStatusChanged;
|
pajlada::Signals::NoArgSignal liveStatusChanged;
|
||||||
pajlada::Signals::Signal<const Link &> linkClicked;
|
pajlada::Signals::Signal<const Link &> linkClicked;
|
||||||
pajlada::Signals::Signal<QString> joinToChannel;
|
pajlada::Signals::Signal<QString, FromTwitchLinkOpenChannelIn>
|
||||||
|
openChannelIn;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void themeChangedEvent() override;
|
void themeChangedEvent() override;
|
||||||
|
|||||||
@@ -163,9 +163,30 @@ Split::Split(QWidget *parent)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->view_->joinToChannel.connect([this](QString twitchChannel) {
|
this->view_->openChannelIn.connect([this](
|
||||||
this->openSplitRequested.invoke(
|
QString twitchChannel,
|
||||||
getApp()->twitch.server->getOrAddChannel(twitchChannel));
|
FromTwitchLinkOpenChannelIn openIn) {
|
||||||
|
ChannelPtr channel =
|
||||||
|
getApp()->twitch.server->getOrAddChannel(twitchChannel);
|
||||||
|
switch (openIn)
|
||||||
|
{
|
||||||
|
case FromTwitchLinkOpenChannelIn::Split:
|
||||||
|
this->openSplitRequested.invoke(channel);
|
||||||
|
break;
|
||||||
|
case FromTwitchLinkOpenChannelIn::Tab:
|
||||||
|
this->joinChannelInNewTab(channel);
|
||||||
|
break;
|
||||||
|
case FromTwitchLinkOpenChannelIn::BrowserPlayer:
|
||||||
|
this->openChannelInBrowserPlayer(channel);
|
||||||
|
break;
|
||||||
|
case FromTwitchLinkOpenChannelIn::Streamlink:
|
||||||
|
this->openChannelInStreamlink(twitchChannel);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(chatterinoWidget)
|
||||||
|
<< "Unhandled \"FromTwitchLinkOpenChannelIn\" enum value: "
|
||||||
|
<< static_cast<int>(openIn);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->input_->textChanged.connect([=](const QString &newText) {
|
this->input_->textChanged.connect([=](const QString &newText) {
|
||||||
@@ -309,6 +330,39 @@ void Split::updateInputPlaceholder()
|
|||||||
this->input_->ui_.textEdit->setPlaceholderText(placeholderText);
|
this->input_->ui_.textEdit->setPlaceholderText(placeholderText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Split::joinChannelInNewTab(ChannelPtr channel)
|
||||||
|
{
|
||||||
|
auto &nb = getApp()->windows->getMainWindow().getNotebook();
|
||||||
|
SplitContainer *container = nb.addPage(true);
|
||||||
|
|
||||||
|
Split *split = new Split(container);
|
||||||
|
split->setChannel(channel);
|
||||||
|
container->appendSplit(split);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Split::openChannelInBrowserPlayer(ChannelPtr channel)
|
||||||
|
{
|
||||||
|
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get()))
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(
|
||||||
|
"https://player.twitch.tv/?parent=twitch.tv&channel=" +
|
||||||
|
twitchChannel->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Split::openChannelInStreamlink(QString channelName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
openStreamlinkForChannel(channelName);
|
||||||
|
}
|
||||||
|
catch (const Exception &ex)
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoWidget)
|
||||||
|
<< "Error in doOpenStreamlink:" << ex.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IndirectChannel Split::getIndirectChannel()
|
IndirectChannel Split::getIndirectChannel()
|
||||||
{
|
{
|
||||||
return this->channel_;
|
return this->channel_;
|
||||||
@@ -595,13 +649,7 @@ void Split::openWhispersInBrowser()
|
|||||||
|
|
||||||
void Split::openBrowserPlayer()
|
void Split::openBrowserPlayer()
|
||||||
{
|
{
|
||||||
ChannelPtr channel = this->getChannel();
|
this->openChannelInBrowserPlayer(this->getChannel());
|
||||||
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get()))
|
|
||||||
{
|
|
||||||
QDesktopServices::openUrl(
|
|
||||||
"https://player.twitch.tv/?parent=twitch.tv&channel=" +
|
|
||||||
twitchChannel->getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Split::openModViewInBrowser()
|
void Split::openModViewInBrowser()
|
||||||
@@ -617,15 +665,7 @@ void Split::openModViewInBrowser()
|
|||||||
|
|
||||||
void Split::openInStreamlink()
|
void Split::openInStreamlink()
|
||||||
{
|
{
|
||||||
try
|
this->openChannelInStreamlink(this->getChannel()->getName());
|
||||||
{
|
|
||||||
openStreamlinkForChannel(this->getChannel()->getName());
|
|
||||||
}
|
|
||||||
catch (const Exception &ex)
|
|
||||||
{
|
|
||||||
qCWarning(chatterinoWidget)
|
|
||||||
<< "Error in doOpenStreamlink:" << ex.what();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Split::openWithCustomScheme()
|
void Split::openWithCustomScheme()
|
||||||
|
|||||||
@@ -114,6 +114,19 @@ private:
|
|||||||
void handleModifiers(Qt::KeyboardModifiers modifiers);
|
void handleModifiers(Qt::KeyboardModifiers modifiers);
|
||||||
void updateInputPlaceholder();
|
void updateInputPlaceholder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens twitch channel stream in a browser player (opens a formatted link)
|
||||||
|
*/
|
||||||
|
void openChannelInBrowserPlayer(ChannelPtr channel);
|
||||||
|
/**
|
||||||
|
* @brief Opens twitch channel stream in streamlink app (if stream is live and streamlink is installed)
|
||||||
|
*/
|
||||||
|
void openChannelInStreamlink(QString channelName);
|
||||||
|
/**
|
||||||
|
* @brief Opens twitch channel chat in a new chatterino tab
|
||||||
|
*/
|
||||||
|
void joinChannelInNewTab(ChannelPtr channel);
|
||||||
|
|
||||||
IndirectChannel channel_;
|
IndirectChannel channel_;
|
||||||
|
|
||||||
bool moderationMode_{};
|
bool moderationMode_{};
|
||||||
|
|||||||
Reference in New Issue
Block a user