/live split for channels going live (#1998)

Co-authored-by: 23rd <23rd@vivaldi.net>
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
apa420 2021-05-09 16:17:04 +02:00 committed by GitHub
parent d96f4575ba
commit dcd65b5978
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 104 additions and 12 deletions

View file

@ -2,12 +2,14 @@
## Unversioned
- Major: New split for channels going live! /live. (#1797)
- Minor: Hosting messages are now clickable. (#2655)
- Minor: Messages held by automod are now shown to the user. (#2626)
- Bugfix: Strip newlines from stream titles to prevent text going off of split header (#2755)
- Bugfix: Automod messages now work properly again. (#2682)
- Bugfix: `Login expired` message no longer highlights all tabs. (#2735)
- Bugfix: Fix a deadlock that would occur during user badge loading. (#1704, #2756)
- Bugfix: Tabbing in `Select a channel to open` is now consistent. (#1797)
## 2.3.1

View file

@ -36,6 +36,7 @@ public:
TwitchWhispers,
TwitchWatching,
TwitchMentions,
TwitchLive,
TwitchEnd,
Irc,
Misc

View file

@ -6,6 +6,7 @@
#include "common/QLogging.hpp"
#include "controllers/notifications/NotificationModel.hpp"
#include "providers/twitch/TwitchIrcServer.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp"
#include "providers/twitch/api/Helix.hpp"
#include "singletons/Toasts.hpp"
#include "singletons/WindowManager.hpp"
@ -185,6 +186,9 @@ void NotificationController::getFakeTwitchChannelLiveStatus(
{
getApp()->windows->sendAlert();
}
MessageBuilder builder;
TwitchMessageBuilder::liveMessage(channelName, &builder);
getApp()->twitch2->liveChannel->addMessage(builder.release());
// Indicate that we have pushed notifications for this stream
fakeTwitchChannels.push_back(channelName);

View file

@ -563,10 +563,25 @@ void TwitchChannel::setLive(bool newLiveStatus)
getApp()->windows->sendAlert();
}
}
// Channel live message
MessageBuilder builder;
TwitchMessageBuilder::liveSystemMessage(this->getDisplayName(),
&builder);
this->addMessage(builder.release());
// Message in /live channel
MessageBuilder builder2;
TwitchMessageBuilder::liveMessage(this->getDisplayName(),
&builder2);
getApp()->twitch2->liveChannel->addMessage(builder2.release());
// Notify on all channels with a ping sound
if (getSettings()->notificationOnAnyChannel &&
!(isInStreamerMode() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getApp()->notifications->playSound();
}
}
else
{

View file

@ -28,6 +28,7 @@ TwitchIrcServer::TwitchIrcServer()
: whispersChannel(new Channel("/whispers", Channel::Type::TwitchWhispers))
, mentionsChannel(new Channel("/mentions", Channel::Type::TwitchMentions))
, watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching)
, liveChannel(new Channel("/live", Channel::Type::TwitchLive))
{
this->initializeIrc();
@ -257,6 +258,11 @@ std::shared_ptr<Channel> TwitchIrcServer::getCustomChannel(
return this->mentionsChannel;
}
if (channelName == "/live")
{
return this->liveChannel;
}
if (channelName == "$$$")
{
static auto channel =
@ -289,6 +295,7 @@ void TwitchIrcServer::forEachChannelAndSpecialChannels(
func(this->whispersChannel);
func(this->mentionsChannel);
func(this->liveChannel);
}
std::shared_ptr<Channel> TwitchIrcServer::getChannelOrEmptyByID(

View file

@ -35,6 +35,7 @@ public:
const ChannelPtr whispersChannel;
const ChannelPtr mentionsChannel;
const ChannelPtr liveChannel;
IndirectChannel watchingChannel;
PubSub *pubsub;

View file

@ -1302,6 +1302,18 @@ void TwitchMessageBuilder::appendChannelPointRewardMessage(
builder->message().flags.set(MessageFlag::RedeemedChannelPointReward);
}
void TwitchMessageBuilder::liveMessage(const QString &channelName,
MessageBuilder *builder)
{
builder->emplace<TimestampElement>();
builder
->emplace<TextElement>(channelName, MessageElementFlag::Username,
MessageColor::Text, FontStyle::ChatMediumBold)
->setLink({Link::UserInfo, channelName});
builder->emplace<TextElement>("is live!", MessageElementFlag::Text,
MessageColor::Text);
}
void TwitchMessageBuilder::liveSystemMessage(const QString &channelName,
MessageBuilder *builder)
{

View file

@ -52,6 +52,12 @@ public:
static void appendChannelPointRewardMessage(
const ChannelPointReward &reward, MessageBuilder *builder);
// Message in the /live chat for channel going live
static void liveMessage(const QString &channelName,
MessageBuilder *builder);
// Messages in normal chat for channel stuff
static void liveSystemMessage(const QString &channelName,
MessageBuilder *builder);
static void offlineSystemMessage(const QString &channelName,

View file

@ -300,6 +300,8 @@ public:
false};
QStringSetting notificationPathSound = {"/notifications/highlightSoundPath",
"qrc:/sounds/ping3.wav"};
BoolSetting notificationOnAnyChannel = {"/notifications/onAnyChannel",
false};
BoolSetting notificationToast = {"/notifications/enableToast", false};
IntSetting openFromToast = {"/notifications/openFromToast",

View file

@ -559,6 +559,10 @@ void WindowManager::encodeChannel(IndirectChannel channel, QJsonObject &obj)
obj.insert("type", "whispers");
}
break;
case Channel::Type::TwitchLive: {
obj.insert("type", "live");
}
break;
case Channel::Type::Irc: {
if (auto ircChannel =
dynamic_cast<IrcChannel *>(channel.get().get()))
@ -608,6 +612,10 @@ IndirectChannel WindowManager::decodeChannel(const SplitDescriptor &descriptor)
{
return app->twitch.server->whispersChannel;
}
else if (descriptor.type_ == "live")
{
return app->twitch.server->liveChannel;
}
else if (descriptor.type_ == "irc")
{
return Irc::instance().getOrAddChannel(descriptor.server_,

View file

@ -119,17 +119,31 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent)
watching_lbl->setVisible(enabled);
});
// live_btn
auto live_btn =
vbox.emplace<QRadioButton>("Live").assign(&this->ui_.twitch.live);
auto live_lbl =
vbox.emplace<QLabel>("Shows when channels go live.").hidden();
live_lbl->setWordWrap(true);
live_btn->installEventFilter(&this->tabFilter_);
QObject::connect(live_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable {
live_lbl->setVisible(enabled);
});
vbox->addStretch(1);
// tabbing order
QWidget::setTabOrder(watching_btn.getElement(),
channel_btn.getElement());
QWidget::setTabOrder(live_btn.getElement(), channel_btn.getElement());
QWidget::setTabOrder(channel_btn.getElement(),
whispers_btn.getElement());
QWidget::setTabOrder(whispers_btn.getElement(),
mentions_btn.getElement());
QWidget::setTabOrder(mentions_btn.getElement(),
watching_btn.getElement());
QWidget::setTabOrder(watching_btn.getElement(), live_btn.getElement());
// tab
auto tab = notebook->addPage(obj.getElement());
@ -294,6 +308,11 @@ void SelectChannelDialog::setSelectedChannel(IndirectChannel _channel)
this->ui_.twitch.whispers->setFocus();
}
break;
case Channel::Type::TwitchLive: {
this->ui_.notebook->selectIndex(TAB_TWITCH);
this->ui_.twitch.live->setFocus();
}
break;
case Channel::Type::Irc: {
this->ui_.notebook->selectIndex(TAB_IRC);
this->ui_.irc.channel->setText(_channel.get()->getName());
@ -357,6 +376,10 @@ IndirectChannel SelectChannelDialog::getSelectedChannel() const
{
return app->twitch.server->whispersChannel;
}
else if (this->ui_.twitch.live->isChecked())
{
return app->twitch.server->liveChannel;
}
}
break;
case TAB_IRC: {
@ -417,15 +440,22 @@ bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched,
event_key->key() == Qt::Key_Down) &&
event_key->modifiers() == Qt::NoModifier)
{
// Tab has been pressed, focus next entry in list
if (widget == this->dialog->ui_.twitch.channelName)
{
// Special case for when current selection is the "Channel" entry's edit box since the Edit box actually has the focus
this->dialog->ui_.twitch.whispers->setFocus();
return true;
}
else
else if (widget == this->dialog->ui_.twitch.live)
{
widget->nextInFocusChain()->setFocus();
// Special case for when current selection is "Live" (the last entry in the list), next wrap is Channel, but we need to select its edit box
this->dialog->ui_.twitch.channel->setFocus();
return true;
}
widget->nextInFocusChain()->setFocus();
return true;
}
else if (((event_key->key() == Qt::Key_Tab ||
@ -434,14 +464,12 @@ bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched,
((event_key->key() == Qt::Key_Up) &&
event_key->modifiers() == Qt::NoModifier))
{
// Shift+Tab has been pressed, focus previous entry in list
if (widget == this->dialog->ui_.twitch.channelName)
{
this->dialog->ui_.twitch.watching->setFocus();
return true;
}
else if (widget == this->dialog->ui_.twitch.whispers)
{
this->dialog->ui_.twitch.channel->setFocus();
// Special case for when current selection is the "Channel" entry's edit box since the Edit box actually has the focus
this->dialog->ui_.twitch.live->setFocus();
return true;
}

View file

@ -49,6 +49,7 @@ private:
QRadioButton *whispers;
QRadioButton *mentions;
QRadioButton *watching;
QRadioButton *live;
} twitch;
struct {
QLineEdit *channel;

View file

@ -994,7 +994,8 @@ MessageElementFlags ChannelView::getFlags() const
{
flags.set(MessageElementFlag::ModeratorTools);
}
if (this->underlyingChannel_ == app->twitch.server->mentionsChannel)
if (this->underlyingChannel_ == app->twitch.server->mentionsChannel ||
this->underlyingChannel_ == app->twitch.server->liveChannel)
{
flags.set(MessageElementFlag::ChannelName);
flags.unset(MessageElementFlag::ChannelPointReward);

View file

@ -35,8 +35,12 @@ NotificationPage::NotificationPage()
settings.append(this->createCheckBox(
"Flash taskbar", getSettings()->notificationFlashTaskbar));
settings.append(
this->createCheckBox("Play sound for selected channels",
getSettings()->notificationPlaySound));
settings.append(this->createCheckBox(
"Play sound", getSettings()->notificationPlaySound));
"Play sound for any channel going live",
getSettings()->notificationOnAnyChannel));
#ifdef Q_OS_WIN
settings.append(this->createCheckBox(
"Show notification", getSettings()->notificationToast));