mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Compare commits
4 commits
36931fac62
...
84a61fdad2
Author | SHA1 | Date | |
---|---|---|---|
84a61fdad2 | |||
7951af6104 | |||
acee654bd2 | |||
97702e0a1f |
|
@ -24,6 +24,7 @@
|
||||||
- Minor: Improved color selection and display. (#5057)
|
- Minor: Improved color selection and display. (#5057)
|
||||||
- Minor: Improved Streamlink documentation in the settings dialog. (#5076)
|
- Minor: Improved Streamlink documentation in the settings dialog. (#5076)
|
||||||
- Minor: Normalized the input padding between light & dark themes. (#5095)
|
- Minor: Normalized the input padding between light & dark themes. (#5095)
|
||||||
|
- Minor: Add `--activate <channel>` (or `-a`) command line option to activate or add a Twitch channel. (#5111)
|
||||||
- Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840)
|
- Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840)
|
||||||
- Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848)
|
- Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848)
|
||||||
- Bugfix: Trimmed custom streamlink paths on all platforms making sure you don't accidentally add spaces at the beginning or end of its path. (#4834)
|
- Bugfix: Trimmed custom streamlink paths on all platforms making sure you don't accidentally add spaces at the beginning or end of its path. (#4834)
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
- Bugfix: Fixed an occasional crash for channel point redemptions with text input. (#4949)
|
- Bugfix: Fixed an occasional crash for channel point redemptions with text input. (#4949)
|
||||||
- Bugfix: Fixed triple click on message also selecting moderation buttons. (#4961)
|
- Bugfix: Fixed triple click on message also selecting moderation buttons. (#4961)
|
||||||
- Bugfix: Fixed a freeze from a bad regex in _Ignores_. (#4965)
|
- Bugfix: Fixed a freeze from a bad regex in _Ignores_. (#4965)
|
||||||
|
- Bugfix: Fixed badge highlight changes not immediately being reflected. (#5110)
|
||||||
- Bugfix: Fixed some emotes not appearing when using _Ignores_. (#4965)
|
- Bugfix: Fixed some emotes not appearing when using _Ignores_. (#4965)
|
||||||
- Bugfix: Fixed lookahead/-behind not working in _Ignores_. (#4965)
|
- Bugfix: Fixed lookahead/-behind not working in _Ignores_. (#4965)
|
||||||
- Bugfix: Fixed Image Uploader accidentally deleting images with some hosts when link resolver was enabled. (#4971)
|
- Bugfix: Fixed Image Uploader accidentally deleting images with some hosts when link resolver was enabled. (#4971)
|
||||||
|
@ -110,6 +112,7 @@
|
||||||
- Dev: Refactored the SplitOverlay code. (#5082)
|
- Dev: Refactored the SplitOverlay code. (#5082)
|
||||||
- Dev: Refactored the TwitchBadges structure, making it less of a singleton. (#5096)
|
- Dev: Refactored the TwitchBadges structure, making it less of a singleton. (#5096)
|
||||||
- Dev: Refactored the ChatterinoBadges structure, making it less of a singleton. (#5103)
|
- Dev: Refactored the ChatterinoBadges structure, making it less of a singleton. (#5103)
|
||||||
|
- Dev: Refactored the ColorProvider class a bit. (#5112)
|
||||||
- Dev: Moved the Network files to their own folder. (#5089)
|
- Dev: Moved the Network files to their own folder. (#5089)
|
||||||
- Dev: Fixed deadlock and use-after-free in tests. (#4981)
|
- Dev: Fixed deadlock and use-after-free in tests. (#4981)
|
||||||
- Dev: Moved all `.clang-format` files to the root directory. (#5037)
|
- Dev: Moved all `.clang-format` files to the root directory. (#5037)
|
||||||
|
|
|
@ -265,6 +265,10 @@ int Application::run(QApplication &qtApp)
|
||||||
getSettings()->highlightedUsers.delayedItemsChanged.connect([this] {
|
getSettings()->highlightedUsers.delayedItemsChanged.connect([this] {
|
||||||
this->windows->forceLayoutChannelViews();
|
this->windows->forceLayoutChannelViews();
|
||||||
});
|
});
|
||||||
|
std::ignore =
|
||||||
|
getSettings()->highlightedBadges.delayedItemsChanged.connect([this] {
|
||||||
|
this->windows->forceLayoutChannelViews();
|
||||||
|
});
|
||||||
|
|
||||||
getSettings()->removeSpacesBetweenEmotes.connect([this] {
|
getSettings()->removeSpacesBetweenEmotes.connect([this] {
|
||||||
this->windows->forceLayoutChannelViews();
|
this->windows->forceLayoutChannelViews();
|
||||||
|
|
|
@ -128,11 +128,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Theme *const themes{};
|
Theme *const themes{};
|
||||||
Fonts *const fonts{};
|
Fonts *const fonts{};
|
||||||
|
|
||||||
public:
|
|
||||||
Emotes *const emotes{};
|
Emotes *const emotes{};
|
||||||
|
|
||||||
private:
|
|
||||||
AccountController *const accounts{};
|
AccountController *const accounts{};
|
||||||
HotkeyController *const hotkeys{};
|
HotkeyController *const hotkeys{};
|
||||||
WindowManager *const windows{};
|
WindowManager *const windows{};
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using namespace chatterino;
|
||||||
|
|
||||||
template <class... Args>
|
template <class... Args>
|
||||||
QCommandLineOption hiddenOption(Args... args)
|
QCommandLineOption hiddenOption(Args... args)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +64,29 @@ QStringList extractCommandLine(
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<Args::Channel> parseActivateOption(QString input)
|
||||||
|
{
|
||||||
|
auto colon = input.indexOf(u':');
|
||||||
|
if (colon >= 0)
|
||||||
|
{
|
||||||
|
auto ty = input.left(colon);
|
||||||
|
if (ty != u"t")
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoApp).nospace()
|
||||||
|
<< "Failed to parse active channel (unknown type: " << ty
|
||||||
|
<< ")";
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
input = input.mid(colon + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Args::Channel{
|
||||||
|
.provider = ProviderId::Twitch,
|
||||||
|
.name = input,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
@ -100,6 +125,14 @@ Args::Args(const QApplication &app, const Paths &paths)
|
||||||
"If platform isn't specified, default is Twitch.",
|
"If platform isn't specified, default is Twitch.",
|
||||||
"t:channel1;t:channel2;...");
|
"t:channel1;t:channel2;...");
|
||||||
|
|
||||||
|
QCommandLineOption activateOption(
|
||||||
|
{"a", "activate"},
|
||||||
|
"Activate the tab with this channel or add one in the main "
|
||||||
|
"window.\nOnly Twitch is "
|
||||||
|
"supported at the moment (prefix: 't:').\nIf the platform isn't "
|
||||||
|
"specified, Twitch is assumed.",
|
||||||
|
"t:channel");
|
||||||
|
|
||||||
parser.addOptions({
|
parser.addOptions({
|
||||||
{{"V", "version"}, "Displays version information."},
|
{{"V", "version"}, "Displays version information."},
|
||||||
crashRecoveryOption,
|
crashRecoveryOption,
|
||||||
|
@ -110,6 +143,7 @@ Args::Args(const QApplication &app, const Paths &paths)
|
||||||
verboseOption,
|
verboseOption,
|
||||||
safeModeOption,
|
safeModeOption,
|
||||||
channelLayout,
|
channelLayout,
|
||||||
|
activateOption,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!parser.parse(app.arguments()))
|
if (!parser.parse(app.arguments()))
|
||||||
|
@ -163,10 +197,17 @@ Args::Args(const QApplication &app, const Paths &paths)
|
||||||
this->safeMode = true;
|
this->safeMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(activateOption))
|
||||||
|
{
|
||||||
|
this->activateChannel =
|
||||||
|
parseActivateOption(parser.value(activateOption));
|
||||||
|
}
|
||||||
|
|
||||||
this->currentArguments_ = extractCommandLine(parser, {
|
this->currentArguments_ = extractCommandLine(parser, {
|
||||||
verboseOption,
|
verboseOption,
|
||||||
safeModeOption,
|
safeModeOption,
|
||||||
channelLayout,
|
channelLayout,
|
||||||
|
activateOption,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/ProviderId.hpp"
|
||||||
#include "common/WindowDescriptors.hpp"
|
#include "common/WindowDescriptors.hpp"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
@ -26,12 +27,18 @@ class Paths;
|
||||||
/// -v, --verbose
|
/// -v, --verbose
|
||||||
/// -V, --version
|
/// -V, --version
|
||||||
/// -c, --channels=t:channel1;t:channel2;...
|
/// -c, --channels=t:channel1;t:channel2;...
|
||||||
|
/// -a, --activate=t:channel
|
||||||
/// --safe-mode
|
/// --safe-mode
|
||||||
///
|
///
|
||||||
/// See documentation on `QGuiApplication` for documentation on Qt arguments like -platform.
|
/// See documentation on `QGuiApplication` for documentation on Qt arguments like -platform.
|
||||||
class Args
|
class Args
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Channel {
|
||||||
|
ProviderId provider;
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
|
||||||
Args() = default;
|
Args() = default;
|
||||||
Args(const QApplication &app, const Paths &paths);
|
Args(const QApplication &app, const Paths &paths);
|
||||||
|
|
||||||
|
@ -52,6 +59,7 @@ public:
|
||||||
bool dontSaveSettings{};
|
bool dontSaveSettings{};
|
||||||
bool dontLoadMainWindow{};
|
bool dontLoadMainWindow{};
|
||||||
std::optional<WindowLayout> customChannelLayout;
|
std::optional<WindowLayout> customChannelLayout;
|
||||||
|
std::optional<Channel> activateChannel;
|
||||||
bool verbose{};
|
bool verbose{};
|
||||||
bool safeMode{};
|
bool safeMode{};
|
||||||
|
|
||||||
|
|
|
@ -229,4 +229,108 @@ WindowLayout WindowLayout::loadFromFile(const QString &path)
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowLayout::activateOrAddChannel(ProviderId provider,
|
||||||
|
const QString &name)
|
||||||
|
{
|
||||||
|
if (provider != ProviderId::Twitch || name.startsWith(u'/') ||
|
||||||
|
name.startsWith(u'$'))
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoWindowmanager)
|
||||||
|
<< "Only twitch channels can be set as active";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mainWindow = std::find_if(this->windows_.begin(), this->windows_.end(),
|
||||||
|
[](const auto &win) {
|
||||||
|
return win.type_ == WindowType::Main;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mainWindow == this->windows_.end())
|
||||||
|
{
|
||||||
|
this->windows_.emplace_back(WindowDescriptor{
|
||||||
|
.type_ = WindowType::Main,
|
||||||
|
.geometry_ = {-1, -1, -1, -1},
|
||||||
|
.tabs_ =
|
||||||
|
{
|
||||||
|
TabDescriptor{
|
||||||
|
.selected_ = true,
|
||||||
|
.rootNode_ = SplitNodeDescriptor{{
|
||||||
|
.type_ = "twitch",
|
||||||
|
.channelName_ = name,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabDescriptor *bestTab = nullptr;
|
||||||
|
// The tab score is calculated as follows:
|
||||||
|
// +2 for every split
|
||||||
|
// +1 if the desired split has filters
|
||||||
|
// Thus lower is better and having one split of a channel is preferred over multiple
|
||||||
|
size_t bestTabScore = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
|
for (auto &tab : mainWindow->tabs_)
|
||||||
|
{
|
||||||
|
tab.selected_ = false;
|
||||||
|
|
||||||
|
if (!tab.rootNode_)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursive visitor
|
||||||
|
struct Visitor {
|
||||||
|
const QString &spec;
|
||||||
|
size_t score = 0;
|
||||||
|
bool hasChannel = false;
|
||||||
|
|
||||||
|
void operator()(const SplitNodeDescriptor &split)
|
||||||
|
{
|
||||||
|
this->score += 2;
|
||||||
|
if (split.channelName_ == this->spec)
|
||||||
|
{
|
||||||
|
hasChannel = true;
|
||||||
|
if (!split.filters_.empty())
|
||||||
|
{
|
||||||
|
this->score += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const ContainerNodeDescriptor &container)
|
||||||
|
{
|
||||||
|
for (const auto &item : container.items_)
|
||||||
|
{
|
||||||
|
std::visit(*this, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} visitor{name};
|
||||||
|
|
||||||
|
std::visit(visitor, *tab.rootNode_);
|
||||||
|
|
||||||
|
if (visitor.hasChannel && visitor.score < bestTabScore)
|
||||||
|
{
|
||||||
|
bestTab = &tab;
|
||||||
|
bestTabScore = visitor.score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestTab)
|
||||||
|
{
|
||||||
|
bestTab->selected_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabDescriptor tab{
|
||||||
|
.selected_ = true,
|
||||||
|
.rootNode_ = SplitNodeDescriptor{{
|
||||||
|
.type_ = "twitch",
|
||||||
|
.channelName_ = name,
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
mainWindow->tabs_.emplace_back(tab);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/ProviderId.hpp"
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
|
@ -95,12 +97,22 @@ struct WindowDescriptor {
|
||||||
class WindowLayout
|
class WindowLayout
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static WindowLayout loadFromFile(const QString &path);
|
|
||||||
|
|
||||||
// A complete window layout has a single emote popup position that is shared among all windows
|
// A complete window layout has a single emote popup position that is shared among all windows
|
||||||
QPoint emotePopupPos_;
|
QPoint emotePopupPos_;
|
||||||
|
|
||||||
std::vector<WindowDescriptor> windows_;
|
std::vector<WindowDescriptor> windows_;
|
||||||
|
|
||||||
|
/// Selects the split containing the channel specified by @a name for the specified
|
||||||
|
/// @a provider. Currently, only Twitch is supported as the provider
|
||||||
|
/// and special channels (such as /mentions) are ignored.
|
||||||
|
///
|
||||||
|
/// Tabs with fewer splits are preferred.
|
||||||
|
/// Channels without filters are preferred.
|
||||||
|
///
|
||||||
|
/// If no split with the channel exists, a new one is added.
|
||||||
|
/// If no window exists, a new one is added.
|
||||||
|
void activateOrAddChannel(ProviderId provider, const QString &name);
|
||||||
|
static WindowLayout loadFromFile(const QString &path);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -476,7 +476,8 @@ CommandModel *CommandController::createModel(QObject *parent)
|
||||||
QString CommandController::execCommand(const QString &textNoEmoji,
|
QString CommandController::execCommand(const QString &textNoEmoji,
|
||||||
ChannelPtr channel, bool dryRun)
|
ChannelPtr channel, bool dryRun)
|
||||||
{
|
{
|
||||||
QString text = getApp()->emotes->emojis.replaceShortCodes(textNoEmoji);
|
QString text =
|
||||||
|
getIApp()->getEmotes()->getEmojis()->replaceShortCodes(textNoEmoji);
|
||||||
QStringList words = text.split(' ', Qt::SkipEmptyParts);
|
QStringList words = text.split(' ', Qt::SkipEmptyParts);
|
||||||
|
|
||||||
if (words.length() == 0)
|
if (words.length() == 0)
|
||||||
|
@ -491,7 +492,7 @@ QString CommandController::execCommand(const QString &textNoEmoji,
|
||||||
const auto it = this->userCommands_.find(commandName);
|
const auto it = this->userCommands_.find(commandName);
|
||||||
if (it != this->userCommands_.end())
|
if (it != this->userCommands_.end())
|
||||||
{
|
{
|
||||||
text = getApp()->emotes->emojis.replaceShortCodes(
|
text = getIApp()->getEmotes()->getEmojis()->replaceShortCodes(
|
||||||
this->execCustomCommand(words, it.value(), dryRun, channel));
|
this->execCustomCommand(words, it.value(), dryRun, channel));
|
||||||
|
|
||||||
words = text.split(' ', Qt::SkipEmptyParts);
|
words = text.split(' ', Qt::SkipEmptyParts);
|
||||||
|
|
|
@ -137,7 +137,7 @@ bool appendWhisperMessageWordsLocally(const QStringList &words)
|
||||||
}
|
}
|
||||||
} // bttv/ffz emote
|
} // bttv/ffz emote
|
||||||
{ // emoji/text
|
{ // emoji/text
|
||||||
for (auto &variant : app->emotes->emojis.parse(words[i]))
|
for (auto &variant : app->getEmotes()->getEmojis()->parse(words[i]))
|
||||||
{
|
{
|
||||||
constexpr const static struct {
|
constexpr const static struct {
|
||||||
void operator()(EmotePtr emote, MessageBuilder &b) const
|
void operator()(EmotePtr emote, MessageBuilder &b) const
|
||||||
|
|
|
@ -465,8 +465,6 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
||||||
const auto setColor = [&](auto &setting, ColorType ty) {
|
const auto setColor = [&](auto &setting, ColorType ty) {
|
||||||
auto color = value.value<QColor>();
|
auto color = value.value<QColor>();
|
||||||
setting.setValue(color.name(QColor::HexArgb));
|
setting.setValue(color.name(QColor::HexArgb));
|
||||||
const_cast<ColorProvider &>(ColorProvider::instance())
|
|
||||||
.updateColor(ty, color);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (rowIndex == HighlightRowIndexes::SelfHighlightRow)
|
if (rowIndex == HighlightRowIndexes::SelfHighlightRow)
|
||||||
|
|
|
@ -103,10 +103,6 @@ void UserHighlightModel::customRowSetData(
|
||||||
// Update the setting with the new value
|
// Update the setting with the new value
|
||||||
getSettings()->selfMessageHighlightColor.setValue(
|
getSettings()->selfMessageHighlightColor.setValue(
|
||||||
colorName);
|
colorName);
|
||||||
// Update the color provider with the new color to be used for future
|
|
||||||
const_cast<ColorProvider &>(ColorProvider::instance())
|
|
||||||
.updateColor(ColorType::SelfMessageHighlight,
|
|
||||||
QColor(colorName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace detail {
|
||||||
DebugCount::increase("animated images");
|
DebugCount::increase("animated images");
|
||||||
|
|
||||||
this->gifTimerConnection_ =
|
this->gifTimerConnection_ =
|
||||||
getApp()->emotes->gifTimer.signal.connect([this] {
|
getIApp()->getEmotes()->getGIFTimer().signal.connect([this] {
|
||||||
this->advance();
|
this->advance();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,7 +814,7 @@ void MessageBuilder::addIrcWord(const QString &text, const QColor &color,
|
||||||
bool addSpace)
|
bool addSpace)
|
||||||
{
|
{
|
||||||
this->textColor_ = color;
|
this->textColor_ = color;
|
||||||
for (auto &variant : getApp()->emotes->emojis.parse(text))
|
for (auto &variant : getIApp()->getEmotes()->getEmojis()->parse(text))
|
||||||
{
|
{
|
||||||
boost::apply_visitor(
|
boost::apply_visitor(
|
||||||
[&](auto &&arg) {
|
[&](auto &&arg) {
|
||||||
|
|
|
@ -685,7 +685,8 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
|
||||||
currentText += ' ';
|
currentText += ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &parsedWord : app->emotes->emojis.parse(word.text))
|
for (const auto &parsedWord :
|
||||||
|
app->getEmotes()->getEmojis()->parse(word.text))
|
||||||
{
|
{
|
||||||
if (parsedWord.type() == typeid(QString))
|
if (parsedWord.type() == typeid(QString))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "providers/colors/ColorProvider.hpp"
|
#include "providers/colors/ColorProvider.hpp"
|
||||||
|
|
||||||
|
#include "common/QLogging.hpp"
|
||||||
#include "controllers/highlights/HighlightPhrase.hpp"
|
#include "controllers/highlights/HighlightPhrase.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
|
||||||
|
@ -14,24 +15,16 @@ const ColorProvider &ColorProvider::instance()
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorProvider::ColorProvider()
|
ColorProvider::ColorProvider()
|
||||||
: typeColorMap_()
|
|
||||||
, defaultColors_()
|
|
||||||
{
|
{
|
||||||
this->initTypeColorMap();
|
this->initTypeColorMap();
|
||||||
this->initDefaultColors();
|
this->initDefaultColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<QColor> ColorProvider::color(ColorType type) const
|
std::shared_ptr<QColor> ColorProvider::color(ColorType type) const
|
||||||
{
|
{
|
||||||
return this->typeColorMap_.at(type);
|
return this->typeColorMap_.at(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProvider::updateColor(ColorType type, QColor color)
|
|
||||||
{
|
|
||||||
auto colorPtr = this->typeColorMap_.at(type);
|
|
||||||
*colorPtr = std::move(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QColor> ColorProvider::recentColors() const
|
QSet<QColor> ColorProvider::recentColors() const
|
||||||
{
|
{
|
||||||
QSet<QColor> retVal;
|
QSet<QColor> retVal;
|
||||||
|
@ -40,12 +33,12 @@ QSet<QColor> ColorProvider::recentColors() const
|
||||||
* Currently, only colors used in highlight phrases are considered. This
|
* Currently, only colors used in highlight phrases are considered. This
|
||||||
* may change at any point in the future.
|
* may change at any point in the future.
|
||||||
*/
|
*/
|
||||||
for (auto phrase : getSettings()->highlightedMessages)
|
for (const auto &phrase : getSettings()->highlightedMessages)
|
||||||
{
|
{
|
||||||
retVal.insert(*phrase.getColor());
|
retVal.insert(*phrase.getColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto userHl : getSettings()->highlightedUsers)
|
for (const auto &userHl : getSettings()->highlightedUsers)
|
||||||
{
|
{
|
||||||
retVal.insert(*userHl.getColor());
|
retVal.insert(*userHl.getColor());
|
||||||
}
|
}
|
||||||
|
@ -67,117 +60,74 @@ void ColorProvider::initTypeColorMap()
|
||||||
{
|
{
|
||||||
// Read settings for custom highlight colors and save them in map.
|
// Read settings for custom highlight colors and save them in map.
|
||||||
// If no custom values can be found, set up default values instead.
|
// If no custom values can be found, set up default values instead.
|
||||||
|
// Set up a signal to the respective setting for updating the color when it's changed
|
||||||
|
auto initColor = [this](ColorType colorType, QStringSetting &setting,
|
||||||
|
QColor fallbackColor) {
|
||||||
|
const auto &colorString = setting.getValue();
|
||||||
|
QColor color(colorString);
|
||||||
|
if (color.isValid())
|
||||||
|
{
|
||||||
|
this->typeColorMap_.insert({
|
||||||
|
colorType,
|
||||||
|
std::make_shared<QColor>(color),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->typeColorMap_.insert({
|
||||||
|
colorType,
|
||||||
|
std::make_shared<QColor>(fallbackColor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QString customColor = getSettings()->selfHighlightColor;
|
setting.connect(
|
||||||
if (QColor(customColor).isValid())
|
[this, colorType](const auto &colorString) {
|
||||||
{
|
QColor color(colorString);
|
||||||
this->typeColorMap_.insert(
|
if (color.isValid())
|
||||||
{ColorType::SelfHighlight, std::make_shared<QColor>(customColor)});
|
{
|
||||||
}
|
// Update color based on the update from the setting
|
||||||
else
|
*this->typeColorMap_.at(colorType) = color;
|
||||||
{
|
}
|
||||||
this->typeColorMap_.insert(
|
else
|
||||||
{ColorType::SelfHighlight,
|
{
|
||||||
std::make_shared<QColor>(
|
qCWarning(chatterinoCommon)
|
||||||
HighlightPhrase::FALLBACK_HIGHLIGHT_COLOR)});
|
<< "Updated"
|
||||||
}
|
<< static_cast<std::underlying_type_t<ColorType>>(
|
||||||
|
colorType)
|
||||||
|
<< "to invalid color" << colorString;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
};
|
||||||
|
|
||||||
customColor = getSettings()->selfMessageHighlightColor;
|
initColor(ColorType::SelfHighlight, getSettings()->selfHighlightColor,
|
||||||
if (QColor(customColor).isValid())
|
HighlightPhrase::FALLBACK_HIGHLIGHT_COLOR);
|
||||||
{
|
|
||||||
this->typeColorMap_.insert({ColorType::SelfMessageHighlight,
|
|
||||||
std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::SelfMessageHighlight,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_SELF_MESSAGE_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->subHighlightColor;
|
initColor(ColorType::SelfMessageHighlight,
|
||||||
if (QColor(customColor).isValid())
|
getSettings()->selfMessageHighlightColor,
|
||||||
{
|
HighlightPhrase::FALLBACK_SELF_MESSAGE_HIGHLIGHT_COLOR);
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::Subscription, std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::Subscription,
|
|
||||||
std::make_shared<QColor>(HighlightPhrase::FALLBACK_SUB_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->whisperHighlightColor;
|
initColor(ColorType::Subscription, getSettings()->subHighlightColor,
|
||||||
if (QColor(customColor).isValid())
|
HighlightPhrase::FALLBACK_SUB_COLOR);
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::Whisper, std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::Whisper,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->redeemedHighlightColor;
|
initColor(ColorType::Whisper, getSettings()->whisperHighlightColor,
|
||||||
if (QColor(customColor).isValid())
|
HighlightPhrase::FALLBACK_HIGHLIGHT_COLOR);
|
||||||
{
|
|
||||||
this->typeColorMap_.insert({ColorType::RedeemedHighlight,
|
|
||||||
std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::RedeemedHighlight,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_REDEEMED_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->firstMessageHighlightColor;
|
initColor(ColorType::RedeemedHighlight,
|
||||||
if (QColor(customColor).isValid())
|
getSettings()->redeemedHighlightColor,
|
||||||
{
|
HighlightPhrase::FALLBACK_REDEEMED_HIGHLIGHT_COLOR);
|
||||||
this->typeColorMap_.insert({ColorType::FirstMessageHighlight,
|
|
||||||
std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::FirstMessageHighlight,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_FIRST_MESSAGE_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->elevatedMessageHighlightColor;
|
initColor(ColorType::FirstMessageHighlight,
|
||||||
if (QColor(customColor).isValid())
|
getSettings()->firstMessageHighlightColor,
|
||||||
{
|
HighlightPhrase::FALLBACK_FIRST_MESSAGE_HIGHLIGHT_COLOR);
|
||||||
this->typeColorMap_.insert({ColorType::ElevatedMessageHighlight,
|
|
||||||
std::make_shared<QColor>(customColor)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::ElevatedMessageHighlight,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_ELEVATED_MESSAGE_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
|
|
||||||
customColor = getSettings()->threadHighlightColor;
|
initColor(ColorType::ElevatedMessageHighlight,
|
||||||
if (QColor(customColor).isValid())
|
getSettings()->elevatedMessageHighlightColor,
|
||||||
{
|
HighlightPhrase::FALLBACK_ELEVATED_MESSAGE_HIGHLIGHT_COLOR);
|
||||||
this->typeColorMap_.insert({ColorType::ThreadMessageHighlight,
|
|
||||||
std::make_shared<QColor>(customColor)});
|
initColor(ColorType::ThreadMessageHighlight,
|
||||||
}
|
getSettings()->threadHighlightColor,
|
||||||
else
|
HighlightPhrase::FALLBACK_THREAD_HIGHLIGHT_COLOR);
|
||||||
{
|
|
||||||
this->typeColorMap_.insert(
|
|
||||||
{ColorType::ThreadMessageHighlight,
|
|
||||||
std::make_shared<QColor>(
|
|
||||||
HighlightPhrase::FALLBACK_THREAD_HIGHLIGHT_COLOR)});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProvider::initDefaultColors()
|
void ColorProvider::initDefaultColors()
|
||||||
|
|
|
@ -36,9 +36,7 @@ public:
|
||||||
* of already parsed predefined (self highlights, subscriptions,
|
* of already parsed predefined (self highlights, subscriptions,
|
||||||
* and whispers) highlights.
|
* and whispers) highlights.
|
||||||
*/
|
*/
|
||||||
const std::shared_ptr<QColor> color(ColorType type) const;
|
std::shared_ptr<QColor> color(ColorType type) const;
|
||||||
|
|
||||||
void updateColor(ColorType type, QColor color);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a set of recently used colors used anywhere in Chatterino.
|
* @brief Return a set of recently used colors used anywhere in Chatterino.
|
||||||
|
|
|
@ -325,8 +325,10 @@ void TwitchAccount::loadUserstateEmotes(std::weak_ptr<Channel> weakChannel)
|
||||||
|
|
||||||
emoteSet->emotes.push_back(TwitchEmote{id, code});
|
emoteSet->emotes.push_back(TwitchEmote{id, code});
|
||||||
|
|
||||||
auto emote =
|
auto emote = getIApp()
|
||||||
getApp()->emotes->twitch.getOrCreateEmote(id, code);
|
->getEmotes()
|
||||||
|
->getTwitchEmotes()
|
||||||
|
->getOrCreateEmote(id, code);
|
||||||
|
|
||||||
// Follower emotes can be only used in their origin channel
|
// Follower emotes can be only used in their origin channel
|
||||||
// unless the user is subscribed, then they can be used anywhere.
|
// unless the user is subscribed, then they can be used anywhere.
|
||||||
|
|
|
@ -576,7 +576,8 @@ void TwitchChannel::roomIdChanged()
|
||||||
QString TwitchChannel::prepareMessage(const QString &message) const
|
QString TwitchChannel::prepareMessage(const QString &message) const
|
||||||
{
|
{
|
||||||
auto *app = getApp();
|
auto *app = getApp();
|
||||||
QString parsedMessage = app->emotes->emojis.replaceShortCodes(message);
|
QString parsedMessage =
|
||||||
|
app->getEmotes()->getEmojis()->replaceShortCodes(message);
|
||||||
|
|
||||||
parsedMessage = parsedMessage.simplified();
|
parsedMessage = parsedMessage.simplified();
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,12 @@ void WindowManager::initialize(Settings &settings, const Paths &paths)
|
||||||
windowLayout = this->loadWindowLayoutFromFile();
|
windowLayout = this->loadWindowLayoutFromFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto desired = getIApp()->getArgs().activateChannel;
|
||||||
|
if (desired)
|
||||||
|
{
|
||||||
|
windowLayout.activateOrAddChannel(desired->provider, desired->name);
|
||||||
|
}
|
||||||
|
|
||||||
this->emotePopupPos_ = windowLayout.emotePopupPos_;
|
this->emotePopupPos_ = windowLayout.emotePopupPos_;
|
||||||
|
|
||||||
this->applyWindowLayout(windowLayout);
|
this->applyWindowLayout(windowLayout);
|
||||||
|
|
|
@ -127,8 +127,8 @@ void addTwitchEmoteSets(
|
||||||
{
|
{
|
||||||
builder
|
builder
|
||||||
.emplace<EmoteElement>(
|
.emplace<EmoteElement>(
|
||||||
getApp()->emotes->twitch.getOrCreateEmote(emote.id,
|
getIApp()->getEmotes()->getTwitchEmotes()->getOrCreateEmote(
|
||||||
emote.name),
|
emote.id, emote.name),
|
||||||
MessageElementFlags{MessageElementFlag::AlwaysShow,
|
MessageElementFlags{MessageElementFlag::AlwaysShow,
|
||||||
MessageElementFlag::TwitchEmote})
|
MessageElementFlag::TwitchEmote})
|
||||||
->setLink(Link(Link::InsertText, emote.name.string));
|
->setLink(Link(Link::InsertText, emote.name.string));
|
||||||
|
|
Loading…
Reference in a new issue