Skip to content

Commit

Permalink
Merge branch 'Chatterino:master' into chatterino7
Browse files Browse the repository at this point in the history
  • Loading branch information
TroyKomodo committed Jun 28, 2022
2 parents 73a8a8d + f49e8b4 commit a643ba7
Show file tree
Hide file tree
Showing 23 changed files with 289 additions and 128 deletions.
5 changes: 3 additions & 2 deletions BUILDING_ON_WINDOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Note: This installation will take about 2.1 GB of disk space.

### For our websocket library, we need OpenSSL 1.1

1. Download OpenSSL for windows, version `1.1.1o`: **[Download](https://slproweb.com/download/Win64OpenSSL-1_1_1o.exe)**
1. Download OpenSSL for windows, version `1.1.1p`: **[Download](https://slproweb.com/download/Win64OpenSSL-1_1_1p.exe)**
2. When prompted, install OpenSSL to `C:\local\openssl`
3. When prompted, copy the OpenSSL DLLs to "The OpenSSL binaries (/bin) directory".

Expand All @@ -46,7 +46,8 @@ Note: This installation will take about 2.1 GB of disk space.
5. Then copy the OpenSSL 1.1 files from its `\bin` folder to `C:\local\bin` (Overwrite any duplicate files)
6. Add `C:\local\bin` to your path folder ([Follow the guide here if you don't know how to do it](https://www.computerhope.com/issues/ch000549.htm#windows10))

**If the download links above do not work, try downloading similar 1.1.x & 1.0.x versions [here](https://slproweb.com/products/Win32OpenSSL.html). Note: Don't download the "light" installers, they do not have the required files.**
**If the 1.1.x download link above does not work, try downloading the similar 1.1.x version found [here](https://slproweb.com/products/Win32OpenSSL.html). Note: Don't download the "light" installer, it does not have the required files.**
![Screenshot Slproweb layout](https://user-images.githubusercontent.com/41973452/175827529-97802939-5549-4ab1-95c4-d39f012d06e9.png)

Note: This installation will take about 200 MB of disk space.

Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
- Bugfix: Fixed automod queue pubsub topic persisting after user change. (#3718)
- Bugfix: Fixed viewer list not closing after pressing escape key. (#3734)
- Bugfix: Fixed links with no thumbnail having previous link's thumbnail. (#3720)
- Bugfix: Fixed message only showing a maximum of one global FrankerFaceZ badge even if the user has multiple. (#3818)
- Bugfix: Add icon in the CMake macOS bundle. (#3832)
- Bugfix: Adopt popup windows in order to force floating behavior on some window managers. (#3836)
- Bugfix: Fix split focusing being broken in certain circumstances when the "Show input when it's empty" setting was disabled. (#3838)
- Dev: Rewrite LimitedQueue (#3798)
- Dev: Overhaul highlight system by moving all checks into a Controller allowing for easier tests. (#3399, #3801)
- Dev: Overhaul highlight system by moving all checks into a Controller allowing for easier tests. (#3399, #3801, #3835)
- Dev: Use Game Name returned by Get Streams instead of querying it from the Get Games API. (#3662)
- Dev: Batch checking live status for all channels after startup. (#3757, #3762, #3767)
- Dev: Move most command context into the command controller. (#3824)
Expand Down
2 changes: 1 addition & 1 deletion src/common/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ IndirectChannel::IndirectChannel(ChannelPtr channel, Channel::Type type)
{
}

ChannelPtr IndirectChannel::get()
ChannelPtr IndirectChannel::get() const
{
return data_->channel;
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/Channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class IndirectChannel
IndirectChannel(ChannelPtr channel,
Channel::Type type = Channel::Type::Direct);

ChannelPtr get();
ChannelPtr get() const;
void reset(ChannelPtr channel);
pajlada::Signals::NoArgSignal &getChannelChanged();
Channel::Type getType();
Expand Down
48 changes: 32 additions & 16 deletions src/controllers/highlights/HighlightController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@ namespace {

using namespace chatterino;

auto highlightPhraseCheck(HighlightPhrase highlight) -> HighlightCheck
auto highlightPhraseCheck(const HighlightPhrase &highlight) -> HighlightCheck
{
return HighlightCheck{
[highlight](
const auto &args, const auto &badges, const auto &senderName,
const auto &originalMessage) -> boost::optional<HighlightResult> {
(void)args; // unused
(void)badges; // unused
(void)originalMessage; // unused
[highlight](const auto &args, const auto &badges,
const auto &senderName, const auto &originalMessage,
const auto self) -> boost::optional<HighlightResult> {
(void)args; // unused
(void)badges; // unused
(void)senderName; // unused

if (self)
{
// Phrase checks should ignore highlights from the user
return boost::none;
}

if (!highlight.isMatch(originalMessage))
{
Expand Down Expand Up @@ -54,11 +60,13 @@ void rebuildSubscriptionHighlights(Settings &settings,

checks.emplace_back(HighlightCheck{
[=](const auto &args, const auto &badges, const auto &senderName,
const auto &originalMessage)
-> boost::optional<HighlightResult> {
const auto &originalMessage,
const auto self) -> boost::optional<HighlightResult> {
(void)badges; // unused
(void)senderName; // unused
(void)originalMessage; // unused
(void)self; // unused

if (!args.isSubscriptionMessage)
{
return boost::none;
Expand Down Expand Up @@ -97,11 +105,13 @@ void rebuildWhisperHighlights(Settings &settings,

checks.emplace_back(HighlightCheck{
[=](const auto &args, const auto &badges, const auto &senderName,
const auto &originalMessage)
-> boost::optional<HighlightResult> {
const auto &originalMessage,
const auto self) -> boost::optional<HighlightResult> {
(void)badges; // unused
(void)senderName; // unused
(void)originalMessage; // unused
(void)self; // unused

if (!args.isReceivedWhisper)
{
return boost::none;
Expand Down Expand Up @@ -152,11 +162,12 @@ void rebuildUserHighlights(Settings &settings,
{
checks.emplace_back(HighlightCheck{
[highlight](const auto &args, const auto &badges,
const auto &senderName, const auto &originalMessage)
-> boost::optional<HighlightResult> {
const auto &senderName, const auto &originalMessage,
const auto self) -> boost::optional<HighlightResult> {
(void)args; // unused
(void)badges; // unused
(void)originalMessage; // unused
(void)self; // unused

if (!highlight.isMatch(senderName))
{
Expand Down Expand Up @@ -187,11 +198,13 @@ void rebuildBadgeHighlights(Settings &settings,
{
checks.emplace_back(HighlightCheck{
[highlight](const auto &args, const auto &badges,
const auto &senderName, const auto &originalMessage)
-> boost::optional<HighlightResult> {
const auto &senderName, const auto &originalMessage,
const auto self) -> boost::optional<HighlightResult> {
(void)args; // unused
(void)senderName; // unused
(void)originalMessage; // unused
(void)self; // unused

for (const Badge &badge : badges)
{
if (highlight.isMatch(badge))
Expand Down Expand Up @@ -302,10 +315,13 @@ std::pair<bool, HighlightResult> HighlightController::check(
// Access for checking
const auto checks = this->checks_.accessConst();

auto currentUser = getIApp()->getAccounts()->twitch.getCurrent();
auto self = (senderName == currentUser->getUserName());

for (const auto &check : *checks)
{
if (auto checkResult =
check.cb(args, badges, senderName, originalMessage);
check.cb(args, badges, senderName, originalMessage, self);
checkResult)
{
highlighted = true;
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/highlights/HighlightController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ struct HighlightResult {
struct HighlightCheck {
using Checker = std::function<boost::optional<HighlightResult>(
const MessageParseArgs &args, const std::vector<Badge> &badges,
const QString &senderName, const QString &originalMessage)>;
const QString &senderName, const QString &originalMessage, bool self)>;
Checker cb;
};

Expand Down
4 changes: 2 additions & 2 deletions src/messages/MessageElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,10 @@ MessageLayoutElement *VipBadgeElement::makeImageLayoutElement(

// FFZ Badge
FfzBadgeElement::FfzBadgeElement(const EmotePtr &data,
MessageElementFlags flags_, QColor &color)
MessageElementFlags flags_, QColor color_)
: BadgeElement(data, flags_)
, color(std::move(color_))
{
this->color = color;
}

MessageLayoutElement *FfzBadgeElement::makeImageLayoutElement(
Expand Down
4 changes: 2 additions & 2 deletions src/messages/MessageElement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,12 @@ class FfzBadgeElement : public BadgeElement
{
public:
FfzBadgeElement(const EmotePtr &data, MessageElementFlags flags_,
QColor &color);
QColor color_);

protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size) override;
QColor color;
const QColor color;
};

// contains a text, formated depending on the preferences
Expand Down
7 changes: 0 additions & 7 deletions src/messages/SharedMessageBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,6 @@ void SharedMessageBuilder::parseHighlights()
return;
}

auto currentUser = getIApp()->getAccounts()->twitch.getCurrent();
if (this->ircMessage->nick() == currentUser->getUserName())
{
// Do nothing. We ignore any potential highlights from the logged in user
return;
}

auto badges = SharedMessageBuilder::parseBadgeTag(this->tags);
auto [highlighted, highlightResult] = getIApp()->getHighlights()->check(
this->args, badges, this->ircMessage->nick(), this->originalMessage_);
Expand Down
70 changes: 43 additions & 27 deletions src/providers/ffz/FfzBadges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,42 @@ namespace chatterino {

void FfzBadges::initialize(Settings &settings, Paths &paths)
{
this->loadFfzBadges();
this->load();
}

boost::optional<EmotePtr> FfzBadges::getBadge(const UserId &id)
std::vector<FfzBadges::Badge> FfzBadges::getUserBadges(const UserId &id)
{
std::vector<Badge> badges;

std::shared_lock lock(this->mutex_);

auto it = this->badgeMap.find(id.string);
if (it != this->badgeMap.end())
auto it = this->userBadges.find(id.string);
if (it != this->userBadges.end())
{
return this->badges[it->second];
for (const auto &badgeID : it->second)
{
if (auto badge = this->getBadge(badgeID); badge)
{
badges.emplace_back(*badge);
}
}
}
return boost::none;

return badges;
}
boost::optional<QColor> FfzBadges::getBadgeColor(const UserId &id)
{
std::shared_lock lock(this->mutex_);

auto badgeIt = this->badgeMap.find(id.string);
if (badgeIt != this->badgeMap.end())
boost::optional<FfzBadges::Badge> FfzBadges::getBadge(const int badgeID)
{
auto it = this->badges.find(badgeID);
if (it != this->badges.end())
{
auto colorIt = this->colorMap.find(badgeIt->second);
if (colorIt != this->colorMap.end())
{
return colorIt->second;
}
return boost::none;
return it->second;
}

return boost::none;
}

void FfzBadges::loadFfzBadges()
void FfzBadges::load()
{
static QUrl url("https://api.frankerfacez.com/v1/badges/ids");

Expand All @@ -55,7 +59,6 @@ void FfzBadges::loadFfzBadges()
std::unique_lock lock(this->mutex_);

auto jsonRoot = result.parseJson();
int index = 0;
for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray())
{
auto jsonBadge = jsonBadge_.toObject();
Expand All @@ -70,20 +73,33 @@ void FfzBadges::loadFfzBadges()
jsonUrls.value("4").toString()}},
Tooltip{jsonBadge.value("title").toString()}, Url{}};

this->badges.push_back(
std::make_shared<const Emote>(std::move(emote)));
this->colorMap[index] =
QColor(jsonBadge.value("color").toString());
Badge badge;

int badgeID = jsonBadge.value("id").toInt();

auto badgeId = QString::number(jsonBadge.value("id").toInt());
this->badges[badgeID] = Badge{
std::make_shared<const Emote>(std::move(emote)),
QColor(jsonBadge.value("color").toString()),
};

// Find users with this badge
auto badgeIDString = QString::number(badgeID);
for (const auto &user : jsonRoot.value("users")
.toObject()
.value(badgeId)
.value(badgeIDString)
.toArray())
{
this->badgeMap[QString::number(user.toInt())] = index;
auto userIDString = QString::number(user.toInt());

auto [userBadges, created] = this->userBadges.emplace(
std::make_pair<QString, std::vector<int>>(
std::move(userIDString), {badgeID}));
if (!created)
{
// User already had a badge assigned
userBadges->second.push_back(badgeID);
}
}
++index;
}

return Success;
Expand Down
21 changes: 15 additions & 6 deletions src/providers/ffz/FfzBadges.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <common/Singleton.hpp>

#include "common/Aliases.hpp"
#include "common/UniqueAccess.hpp"
#include "util/QStringHash.hpp"

#include <map>
Expand All @@ -25,17 +26,25 @@ class FfzBadges : public Singleton
virtual void initialize(Settings &settings, Paths &paths) override;
FfzBadges() = default;

boost::optional<EmotePtr> getBadge(const UserId &id);
boost::optional<QColor> getBadgeColor(const UserId &id);
struct Badge {
EmotePtr emote;
QColor color;
};

std::vector<Badge> getUserBadges(const UserId &id);

private:
void loadFfzBadges();
boost::optional<Badge> getBadge(int badgeID);

void load();

std::shared_mutex mutex_;

std::unordered_map<QString, int> badgeMap;
std::vector<EmotePtr> badges;
std::unordered_map<int, QColor> colorMap;
// userBadges points a user ID to the list of badges they have
std::unordered_map<QString, std::vector<int>> userBadges;

// badges points a badge ID to the information about the badge
std::unordered_map<int, Badge> badges;
};

} // namespace chatterino
10 changes: 4 additions & 6 deletions src/providers/twitch/TwitchMessageBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1134,13 +1134,11 @@ void TwitchMessageBuilder::appendSeventvBadges()

void TwitchMessageBuilder::appendFfzBadges()
{
if (auto badge = getApp()->ffzBadges->getBadge({this->userId_}))
for (const auto &badge :
getApp()->ffzBadges->getUserBadges({this->userId_}))
{
if (auto color = getApp()->ffzBadges->getBadgeColor({this->userId_}))
{
this->emplace<FfzBadgeElement>(*badge, MessageElementFlag::BadgeFfz,
color.get());
}
this->emplace<FfzBadgeElement>(
badge.emote, MessageElementFlag::BadgeFfz, badge.color);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/widgets/Notebook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ void SplitNotebook::showEvent(QShowEvent *)
{
if (auto split = page->findChild<Split *>())
{
split->giveFocus(Qt::OtherFocusReason);
split->setFocus(Qt::FocusReason::OtherFocusReason);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/widgets/helper/ChannelView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ ChannelView::ChannelView(BaseWidget *parent)
QObject::connect(&this->scrollTimer_, &QTimer::timeout, this,
&ChannelView::scrollUpdateRequested);

// TODO: Figure out if we need this, and if so, why
// StrongFocus means we can focus this event through clicking it
// and tabbing to it from another widget. I don't currently know
// of any place where you can, or where it would make sense,
// to tab to a ChannelVieChannelView
this->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
}

Expand Down
Loading

0 comments on commit a643ba7

Please sign in to comment.