mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Merge remote-tracking branch 'origin/master' into zneix/enhancement/login-overhaul
This commit is contained in:
commit
094afff30b
10 changed files with 141 additions and 43 deletions
|
@ -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)
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
|
if (!this->message().flags.has(MessageFlag::Subscription))
|
||||||
|
{
|
||||||
this->message().highlightColor = userHighlight.getColor();
|
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);
|
||||||
|
if (!this->message().flags.has(MessageFlag::Subscription))
|
||||||
|
{
|
||||||
this->message().highlightColor = highlight.getColor();
|
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);
|
||||||
|
if (!this->message().flags.has(MessageFlag::Subscription))
|
||||||
|
{
|
||||||
this->message().highlightColor = highlight.getColor();
|
this->message().highlightColor = highlight.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
badgeHighlightSet = true;
|
badgeHighlightSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -313,13 +313,10 @@ 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);
|
||||||
if (auto chatters = dynamic_cast<ChannelChatters *>(chan.get()))
|
if (auto chatters = dynamic_cast<ChannelChatters *>(chan.get()))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue