Merge remote-tracking branch 'origin/master' into zneix/enhancement/login-overhaul

This commit is contained in:
zneix 2021-08-15 18:08:10 +02:00
commit 094afff30b
No known key found for this signature in database
GPG key ID: 911916E0523B22F6
10 changed files with 141 additions and 43 deletions

View file

@ -6,8 +6,11 @@
- Minor: Remove TwitchEmotes.com attribution and the open/copy options when right-clicking a Twitch Emote. (#2214, #3136) - Minor: Remove TwitchEmotes.com attribution and the open/copy options when right-clicking a Twitch Emote. (#2214, #3136)
- Minor: Strip leading @ and trailing , from username in /user and /usercard commands. (#3143) - Minor: Strip leading @ and trailing , from username in /user and /usercard commands. (#3143)
- Minor: Display a system message when reloading subscription emotes to match BTTV/FFZ behavior (#3135) - Minor: Display a system message when reloading subscription emotes to match BTTV/FFZ behavior (#3135)
- Minor: Allow resub messages to show in `/mentions` tab (#3148)
- Minor: Added a setting to hide similar messages by any user. (#2716) - Minor: Added a setting to hide similar messages by any user. (#2716)
- Minor: Duplicate spaces now count towards the display message length. (#3002) - Minor: Duplicate spaces now count towards the display message length. (#3002)
- Minor: Commands are now backed up. (#3168)
- Bugfix: Restored ability to send duplicate `/me` messages. (#3166)
- Bugfix: Notifications for moderators about other moderators deleting messages can now be disabled. (#3121) - Bugfix: Notifications for moderators about other moderators deleting messages can now be disabled. (#3121)
- Bugfix: Moderation mode and active filters are now preserved when opening a split as a popup. (#3113, #3130) - Bugfix: Moderation mode and active filters are now preserved when opening a split as a popup. (#3113, #3130)
- Bugfix: Fixed a bug that caused all badge highlights to use the same color. (#3132, #3134) - Bugfix: Fixed a bug that caused all badge highlights to use the same color. (#3132, #3134)

View file

@ -267,6 +267,8 @@ void CommandController::initialize(Settings &, Paths &paths)
auto path = combinePath(paths.settingsDirectory, "commands.json"); auto path = combinePath(paths.settingsDirectory, "commands.json");
this->sm_ = std::make_shared<pajlada::Settings::SettingManager>(); this->sm_ = std::make_shared<pajlada::Settings::SettingManager>();
this->sm_->setPath(path.toStdString()); this->sm_->setPath(path.toStdString());
this->sm_->setBackupEnabled(true);
this->sm_->setBackupSlots(9);
// Delayed initialization of the setting storing all commands // Delayed initialization of the setting storing all commands
this->commandsSetting_.reset( this->commandsSetting_.reset(

View file

@ -157,10 +157,6 @@ void SharedMessageBuilder::parseHighlights()
this->message().flags.set(MessageFlag::Highlighted); this->message().flags.set(MessageFlag::Highlighted);
this->message().highlightColor = this->message().highlightColor =
ColorProvider::instance().color(ColorType::Subscription); ColorProvider::instance().color(ColorType::Subscription);
// This message was a subscription.
// Don't check for any other highlight phrases.
return;
} }
// XXX: Non-common term in SharedMessageBuilder // XXX: Non-common term in SharedMessageBuilder
@ -220,7 +216,10 @@ void SharedMessageBuilder::parseHighlights()
<< "sent a message"; << "sent a message";
this->message().flags.set(MessageFlag::Highlighted); this->message().flags.set(MessageFlag::Highlighted);
this->message().highlightColor = userHighlight.getColor(); if (!this->message().flags.has(MessageFlag::Subscription))
{
this->message().highlightColor = userHighlight.getColor();
}
if (userHighlight.showInMentions()) if (userHighlight.showInMentions())
{ {
@ -289,7 +288,10 @@ void SharedMessageBuilder::parseHighlights()
} }
this->message().flags.set(MessageFlag::Highlighted); this->message().flags.set(MessageFlag::Highlighted);
this->message().highlightColor = highlight.getColor(); if (!this->message().flags.has(MessageFlag::Subscription))
{
this->message().highlightColor = highlight.getColor();
}
if (highlight.showInMentions()) if (highlight.showInMentions())
{ {
@ -344,7 +346,11 @@ void SharedMessageBuilder::parseHighlights()
if (!badgeHighlightSet) if (!badgeHighlightSet)
{ {
this->message().flags.set(MessageFlag::Highlighted); this->message().flags.set(MessageFlag::Highlighted);
this->message().highlightColor = highlight.getColor(); if (!this->message().flags.has(MessageFlag::Subscription))
{
this->message().highlightColor = highlight.getColor();
}
badgeHighlightSet = true; badgeHighlightSet = true;
} }

View file

@ -313,12 +313,9 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
const auto highlighted = msg->flags.has(MessageFlag::Highlighted); const auto highlighted = msg->flags.has(MessageFlag::Highlighted);
const auto showInMentions = msg->flags.has(MessageFlag::ShowInMentions); const auto showInMentions = msg->flags.has(MessageFlag::ShowInMentions);
if (!isSub) if (highlighted && showInMentions)
{ {
if (highlighted && showInMentions) server.mentionsChannel->addMessage(msg);
{
server.mentionsChannel->addMessage(msg);
}
} }
chan->addMessage(msg); chan->addMessage(msg);

View file

@ -377,6 +377,16 @@ void TwitchChannel::sendMessage(const QString &message)
if (parsedMessage == this->lastSentMessage_) if (parsedMessage == this->lastSentMessage_)
{ {
auto spaceIndex = parsedMessage.indexOf(' '); auto spaceIndex = parsedMessage.indexOf(' ');
// If the message starts with either '/' or '.' Twitch will treat it as a command, omitting
// first space and only rest of the arguments treated as actual message content
// In cases when user sends a message like ". .a b" first character and first space are omitted as well
bool ignoreFirstSpace =
parsedMessage.at(0) == '/' || parsedMessage.at(0) == '.';
if (ignoreFirstSpace)
{
spaceIndex = parsedMessage.indexOf(' ', spaceIndex + 1);
}
if (spaceIndex == -1) if (spaceIndex == -1)
{ {
// no spaces found, fall back to old magic character // no spaces found, fall back to old magic character

View file

@ -200,7 +200,7 @@ void openStreamlinkForChannel(const QString &channel)
if (preferredQuality == "choose") if (preferredQuality == "choose")
{ {
getStreamQualities(channelURL, [=](QStringList qualityOptions) { getStreamQualities(channelURL, [=](QStringList qualityOptions) {
QualityPopup::showDialog(channel, qualityOptions); QualityPopup::showDialog(channelURL, qualityOptions);
}); });
return; return;

View file

@ -1,5 +1,7 @@
#include "widgets/BasePopup.hpp" #include "widgets/BasePopup.hpp"
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QKeyEvent> #include <QKeyEvent>
namespace chatterino { namespace chatterino {
@ -20,4 +22,66 @@ void BasePopup::keyPressEvent(QKeyEvent *e)
BaseWindow::keyPressEvent(e); BaseWindow::keyPressEvent(e);
} }
bool BasePopup::handleEscape(QKeyEvent *e, QDialogButtonBox *buttonBox)
{
assert(buttonBox != nullptr);
if (e->key() == Qt::Key_Escape)
{
auto buttons = buttonBox->buttons();
for (auto *button : buttons)
{
if (auto role = buttonBox->buttonRole(button);
role == QDialogButtonBox::ButtonRole::RejectRole)
{
button->click();
return true;
}
}
}
return false;
}
bool BasePopup::handleEnter(QKeyEvent *e, QDialogButtonBox *buttonBox)
{
assert(buttonBox != nullptr);
if (!e->modifiers() ||
(e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter))
{
switch (e->key())
{
case Qt::Key_Enter:
case Qt::Key_Return: {
auto buttons = buttonBox->buttons();
QAbstractButton *acceptButton = nullptr;
for (auto *button : buttons)
{
if (button->hasFocus())
{
button->click();
return true;
}
if (auto role = buttonBox->buttonRole(button);
role == QDialogButtonBox::ButtonRole::AcceptRole)
{
acceptButton = button;
}
}
if (acceptButton != nullptr)
{
acceptButton->click();
return true;
}
}
break;
}
}
return false;
}
} // namespace chatterino } // namespace chatterino

View file

@ -3,6 +3,8 @@
#include "common/FlagsEnum.hpp" #include "common/FlagsEnum.hpp"
#include "widgets/BaseWindow.hpp" #include "widgets/BaseWindow.hpp"
class QDialogButtonBox;
namespace chatterino { namespace chatterino {
class BasePopup : public BaseWindow class BasePopup : public BaseWindow
@ -13,6 +15,12 @@ public:
protected: protected:
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
// handleEscape is a helper function for clicking the "Reject" role button of a button box when the Escape button is pressed
bool handleEscape(QKeyEvent *e, QDialogButtonBox *buttonBox);
// handleEnter is a helper function for clicking the "Accept" role button of a button box when Return or Enter is pressed
bool handleEnter(QKeyEvent *e, QDialogButtonBox *buttonBox);
}; };
} // namespace chatterino } // namespace chatterino

View file

@ -7,35 +7,32 @@
namespace chatterino { namespace chatterino {
QualityPopup::QualityPopup(const QString &_channelName, QStringList options) QualityPopup::QualityPopup(const QString &channelURL, QStringList options)
: BasePopup({}, : BasePopup({},
static_cast<QWidget *>(&(getApp()->windows->getMainWindow()))) static_cast<QWidget *>(&(getApp()->windows->getMainWindow())))
, channelName_(_channelName) , channelURL_(channelURL)
{ {
this->ui_.okButton.setText("OK"); this->ui_.selector = new QComboBox(this);
this->ui_.cancelButton.setText("Cancel"); this->ui_.vbox = new QVBoxLayout(this);
this->ui_.buttonBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
QObject::connect(&this->ui_.okButton, &QPushButton::clicked, this, QObject::connect(this->ui_.buttonBox, &QDialogButtonBox::accepted, this,
&QualityPopup::okButtonClicked); &QualityPopup::okButtonClicked);
QObject::connect(&this->ui_.cancelButton, &QPushButton::clicked, this, QObject::connect(this->ui_.buttonBox, &QDialogButtonBox::rejected, this,
&QualityPopup::cancelButtonClicked); &QualityPopup::cancelButtonClicked);
this->ui_.buttonBox.addButton(&this->ui_.okButton, this->ui_.selector->addItems(options);
QDialogButtonBox::ButtonRole::AcceptRole);
this->ui_.buttonBox.addButton(&this->ui_.cancelButton,
QDialogButtonBox::ButtonRole::RejectRole);
this->ui_.selector.addItems(options); this->ui_.vbox->addWidget(this->ui_.selector);
this->ui_.vbox->addWidget(this->ui_.buttonBox);
this->ui_.vbox.addWidget(&this->ui_.selector); this->setLayout(this->ui_.vbox);
this->ui_.vbox.addWidget(&this->ui_.buttonBox);
this->setLayout(&this->ui_.vbox);
} }
void QualityPopup::showDialog(const QString &channelName, QStringList options) void QualityPopup::showDialog(const QString &channelURL, QStringList options)
{ {
QualityPopup *instance = new QualityPopup(channelName, options); QualityPopup *instance = new QualityPopup(channelURL, options);
instance->window()->setWindowTitle("Chatterino - select stream quality"); instance->window()->setWindowTitle("Chatterino - select stream quality");
instance->setAttribute(Qt::WA_DeleteOnClose, true); instance->setAttribute(Qt::WA_DeleteOnClose, true);
@ -43,16 +40,27 @@ void QualityPopup::showDialog(const QString &channelName, QStringList options)
instance->show(); instance->show();
instance->activateWindow(); instance->activateWindow();
instance->raise(); instance->raise();
instance->setFocus(); }
void QualityPopup::keyPressEvent(QKeyEvent *e)
{
if (this->handleEscape(e, this->ui_.buttonBox))
{
return;
}
if (this->handleEnter(e, this->ui_.buttonBox))
{
return;
}
BasePopup::keyPressEvent(e);
} }
void QualityPopup::okButtonClicked() void QualityPopup::okButtonClicked()
{ {
QString channelURL = "twitch.tv/" + this->channelName_;
try try
{ {
openStreamlink(channelURL, this->ui_.selector.currentText()); openStreamlink(this->channelURL_, this->ui_.selector->currentText());
} }
catch (const Exception &ex) catch (const Exception &ex)
{ {

View file

@ -4,7 +4,6 @@
#include <QComboBox> #include <QComboBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
namespace chatterino { namespace chatterino {
@ -12,22 +11,23 @@ namespace chatterino {
class QualityPopup : public BasePopup class QualityPopup : public BasePopup
{ {
public: public:
QualityPopup(const QString &_channelName, QStringList options); QualityPopup(const QString &channelURL, QStringList options);
static void showDialog(const QString &_channelName, QStringList options); static void showDialog(const QString &channelURL, QStringList options);
protected:
void keyPressEvent(QKeyEvent *e) override;
private: private:
void okButtonClicked(); void okButtonClicked();
void cancelButtonClicked(); void cancelButtonClicked();
struct { struct {
QVBoxLayout vbox; QVBoxLayout *vbox;
QComboBox selector; QComboBox *selector;
QDialogButtonBox buttonBox; QDialogButtonBox *buttonBox;
QPushButton okButton;
QPushButton cancelButton;
} ui_; } ui_;
QString channelName_; QString channelURL_;
}; };
} // namespace chatterino } // namespace chatterino