diff --git a/chatterino.pro b/chatterino.pro index 0db816192..c41cea5a9 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -6,7 +6,7 @@ message(----) -QT += widgets core gui network multimedia svg +QT += widgets core gui network multimedia svg concurrent CONFIG += communi COMMUNI += core model util CONFIG += c++14 @@ -105,7 +105,6 @@ SOURCES += \ src/Application.cpp \ src/common/Channel.cpp \ src/common/CompletionModel.cpp \ - src/common/Emotemap.cpp \ src/common/NetworkData.cpp \ src/common/NetworkManager.cpp \ src/common/NetworkRequest.cpp \ @@ -258,7 +257,6 @@ HEADERS += \ src/common/Channel.hpp \ src/common/Common.hpp \ src/common/CompletionModel.hpp \ - src/common/Emotemap.hpp \ src/common/FlagsEnum.hpp \ src/common/LockedObject.hpp \ src/common/MutexValue.hpp \ diff --git a/src/common/Emotemap.cpp b/src/common/Emotemap.cpp deleted file mode 100644 index 9bfae628b..000000000 --- a/src/common/Emotemap.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "Emotemap.hpp" - -#include "Application.hpp" -#include "singletons/Settings.hpp" - -namespace chatterino { - -// EmoteData::EmoteData(Image *image) -// : image1x(image) -//{ -//} - -//// Emotes must have a 1x image to be valid -// bool EmoteData::isValid() const -//{ -// return this->image1x != nullptr; -//} - -// Image *EmoteData::getImage(float scale) const -//{ -// int quality = getApp()->settings->preferredEmoteQuality; - -// if (quality == 0) { -// scale *= getApp()->settings->emoteScale.getValue(); -// quality = [&] { -// if (scale <= 1) -// return 1; -// if (scale <= 2) -// return 2; -// return 3; -// }(); -// } - -// Image *_image; -// if (quality == 3 && this->image3x != nullptr) { -// _image = this->image3x; -// } else if (quality >= 2 && this->image2x != nullptr) { -// _image = this->image2x; -// } else { -// _image = this->image1x; -// } - -// return _image; -//} - -} // namespace chatterino diff --git a/src/common/Emotemap.hpp b/src/common/Emotemap.hpp deleted file mode 100644 index 8c219bc67..000000000 --- a/src/common/Emotemap.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "messages/Image.hpp" -#include "util/ConcurrentMap.hpp" - -namespace chatterino { - -// struct EmoteData { -// EmoteData() = default; - -// EmoteData(Image *image); - -// // Emotes must have a 1x image to be valid -// bool isValid() const; -// Image *getImage(float scale) const; - -// // Link to the emote page i.e. -// https://www.frankerfacez.com/emoticon/144722-pajaCringe QString pageLink; - -// Image *image1x = nullptr; -// Image *image2x = nullptr; -// Image *image3x = nullptr; -//}; - -// using EmoteMap = ConcurrentMap; - -} // namespace chatterino diff --git a/src/common/FlagsEnum.hpp b/src/common/FlagsEnum.hpp index 000c3da70..c5be885e5 100644 --- a/src/common/FlagsEnum.hpp +++ b/src/common/FlagsEnum.hpp @@ -4,19 +4,17 @@ namespace chatterino { -// = std::enable_if::value>::type - template ::type> class FlagsEnum { public: FlagsEnum() - : value(static_cast(0)) + : value_(static_cast(0)) { } FlagsEnum(T value) - : value(value) + : value_(value) { } @@ -29,22 +27,22 @@ public: bool operator==(const FlagsEnum &other) { - return this->value == other.value; + return this->value_ == other.value_; } bool operator!=(const FlagsEnum &other) { - return this->value != other.value; + return this->value_ != other.value_; } void set(T flag) { - reinterpret_cast(this->value) |= static_cast(flag); + reinterpret_cast(this->value_) |= static_cast(flag); } void unset(T flag) { - reinterpret_cast(this->value) &= ~static_cast(flag); + reinterpret_cast(this->value_) &= ~static_cast(flag); } void set(T flag, bool value) @@ -57,33 +55,17 @@ public: bool has(T flag) const { - return static_cast(this->value) & static_cast(flag); + return static_cast(this->value_) & static_cast(flag); } - // bool hasAny(std::initializer_list flags) const - //{ - // for (auto flag : flags) { - // if (this->has(flag)) return true; - // } - // return false; - //} - bool hasAny(FlagsEnum flags) const { - return static_cast(this->value) & static_cast(flags.value); + return static_cast(this->value_) & static_cast(flags.value_); } - // bool hasAll(std::initializer_list flags) const - //{ - // for (auto flag : flags) { - // if (!this->has(flag)) return false; - // } - // return true; - //} - bool hasAll(FlagsEnum flags) const { - return (static_cast(this->value) & static_cast(flags.value)) && + return (static_cast(this->value_) & static_cast(flags.value_)) && static_cast(flags->value); } @@ -93,7 +75,7 @@ public: } private: - T value; + T value_{}; }; } // namespace chatterino diff --git a/src/common/NetworkData.hpp b/src/common/NetworkData.hpp index d7fbf84ba..2d149fc09 100644 --- a/src/common/NetworkData.hpp +++ b/src/common/NetworkData.hpp @@ -19,6 +19,7 @@ struct NetworkData { QNetworkRequest request_; const QObject *caller_ = nullptr; bool useQuickLoadCache_{}; + bool executeConcurrently{}; NetworkReplyCreatedCallback onReplyCreated_; NetworkErrorCallback onError_; diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index 352762c3f..464061be4 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -8,6 +8,7 @@ #include "util/DebugCount.hpp" #include +#include #include namespace chatterino { @@ -80,6 +81,11 @@ void NetworkRequest::setTimeout(int ms) this->timer->timeoutMS_ = ms; } +void NetworkRequest::setExecuteConcurrently(bool value) +{ + this->data->executeConcurrently = value; +} + void NetworkRequest::makeAuthorizedV5(const QString &clientID, const QString &oauthToken) { @@ -228,7 +234,16 @@ void NetworkRequest::doRequest() NetworkResult result(bytes); DebugCount::increase("http request success"); - data->onSuccess_(result); + Log("starting {}", data->request_.url().toString()); + if (data->onSuccess_) { + if (data->executeConcurrently) + QtConcurrent::run( + [onSuccess = std::move(data->onSuccess_), + result = std::move(result)] { onSuccess(result); }); + else + data->onSuccess_(result); + } + Log("finished {}", data->request_.url().toString()); reply->deleteLater(); }; diff --git a/src/common/NetworkRequest.hpp b/src/common/NetworkRequest.hpp index 8112a4852..ea1361faf 100644 --- a/src/common/NetworkRequest.hpp +++ b/src/common/NetworkRequest.hpp @@ -27,19 +27,15 @@ class NetworkRequest bool executed_ = false; public: - NetworkRequest() = delete; - NetworkRequest(const NetworkRequest &other) = delete; - NetworkRequest &operator=(const NetworkRequest &other) = delete; - - NetworkRequest(NetworkRequest &&other) = default; - NetworkRequest &operator=(NetworkRequest &&other) = default; - explicit NetworkRequest( const std::string &url, NetworkRequestType requestType = NetworkRequestType::Get); explicit NetworkRequest( QUrl url, NetworkRequestType requestType = NetworkRequestType::Get); + NetworkRequest(NetworkRequest &&other) = default; + NetworkRequest &operator=(NetworkRequest &&other) = default; + ~NetworkRequest(); void setRequestType(NetworkRequestType newRequestType); @@ -55,6 +51,7 @@ public: void setRawHeader(const char *headerName, const QByteArray &value); void setRawHeader(const char *headerName, const QString &value); void setTimeout(int ms); + void setExecuteConcurrently(bool value); void makeAuthorizedV5(const QString &clientID, const QString &oauthToken = QString()); diff --git a/src/controllers/moderationactions/ModerationAction.cpp b/src/controllers/moderationactions/ModerationAction.cpp index 90abe815d..49d302b34 100644 --- a/src/controllers/moderationactions/ModerationAction.cpp +++ b/src/controllers/moderationactions/ModerationAction.cpp @@ -60,8 +60,7 @@ ModerationAction::ModerationAction(const QString &action) // str); // } } else if (action.startsWith("/ban ")) { - this->image_ = - Image::fromNonOwningPixmap(&getApp()->resources->buttons.ban); + this->image_ = Image::fromPixmap(getApp()->resources->buttons.ban); } else { QString xD = action; diff --git a/src/messages/Emote.hpp b/src/messages/Emote.hpp index c5817752e..9c7b5f680 100644 --- a/src/messages/Emote.hpp +++ b/src/messages/Emote.hpp @@ -37,29 +37,4 @@ using EmoteIdMap = std::unordered_map; using WeakEmoteMap = std::unordered_map>; using WeakEmoteIdMap = std::unordered_map>; -// struct EmoteData2 { -// EmoteName name; -// ImageSet images; -// Tooltip tooltip; -// Url homePage; -//}; -// -// class Emote -//{ -// public: -// Emote(EmoteData2 &&data); -// Emote(const EmoteData2 &data); -// -// const Url &getHomePage() const; -// const EmoteName &getName() const; -// const Tooltip &getTooltip() const; -// const ImageSet &getImages() const; -// const QString &getCopyString() const; -// bool operator==(const Emote &other) const; -// bool operator!=(const Emote &other) const; -// -// private: -// EmoteData2 data_; -//}; - } // namespace chatterino diff --git a/src/messages/Image.cpp b/src/messages/Image.cpp index b91ea1a44..29b093f36 100644 --- a/src/messages/Image.cpp +++ b/src/messages/Image.cpp @@ -21,22 +21,14 @@ namespace chatterino { namespace { -const QPixmap *getPixmap(const Pixmap &pixmap) -{ - if (pixmap.which() == 0) - return boost::get(pixmap); - else - return boost::get>(pixmap).get(); -} - // Frames Frames::Frames() { DebugCount::increase("images"); } -Frames::Frames(std::vector &&frames) - : items_(std::move(frames)) +Frames::Frames(const QVector> &frames) + : items_(frames) { DebugCount::increase("images"); if (this->animated()) DebugCount::increase("animated images"); @@ -68,22 +60,22 @@ bool Frames::animated() const return this->items_.size() > 1; } -const QPixmap *Frames::current() const +boost::optional Frames::current() const { - if (this->items_.size() == 0) return nullptr; - return getPixmap(this->items_[this->index_].pixmap); + if (this->items_.size() == 0) return boost::none; + return this->items_[this->index_].image; } -const QPixmap *Frames::first() const +boost::optional Frames::first() const { - if (this->items_.size() == 0) return nullptr; - return getPixmap(this->items_.front().pixmap); + if (this->items_.size() == 0) return boost::none; + return this->items_.front().image; } // functions -std::vector readFrames(QImageReader &reader, const Url &url) +QVector> readFrames(QImageReader &reader, const Url &url) { - std::vector frames; + QVector> frames; if (reader.imageCount() == 0) { Log("Error while reading image {}: '{}'", url.string, @@ -97,7 +89,7 @@ std::vector readFrames(QImageReader &reader, const Url &url) QPixmap::fromImage(image); int duration = std::max(20, reader.nextImageDelay()); - frames.push_back(ParseFrame{image, duration}); + frames.push_back(Frame{image, duration}); } } @@ -109,36 +101,22 @@ std::vector readFrames(QImageReader &reader, const Url &url) return frames; } -void queueLoadedEvent() -{ - static auto eventQueued = false; - - if (!eventQueued) { - eventQueued = true; - - QTimer::singleShot(250, [] { - getApp()->windows->incGeneration(); - getApp()->windows->layoutChannelViews(); - eventQueued = false; - }); - } -} - // parsed template -void asd(std::queue>> &queued, - std::mutex &mutex, std::atomic_bool &loadedEventQueued) +void assignDelayed( + std::queue>>> &queued, + std::mutex &mutex, std::atomic_bool &loadedEventQueued) { std::lock_guard lock(mutex); int i = 0; while (!queued.empty()) { - queued.front().first(std::move(queued.front().second)); + queued.front().first(queued.front().second); queued.pop(); if (++i > 50) { - QTimer::singleShot(3, - [&] { asd(queued, mutex, loadedEventQueued); }); + QTimer::singleShot( + 3, [&] { assignDelayed(queued, mutex, loadedEventQueued); }); return; } } @@ -148,34 +126,31 @@ void asd(std::queue>> &queued, } template -auto makeConvertCallback(std::vector parsed, Assign assign) +auto makeConvertCallback(const QVector> &parsed, Assign assign) { - return [parsed = std::move(parsed), assign] { - // BenchmarkGuard guard("convert image"); - + return [parsed, assign] { // convert to pixmap - auto frames = std::vector(); + auto frames = QVector>(); std::transform(parsed.begin(), parsed.end(), std::back_inserter(frames), [](auto &frame) { - return Frame{std::make_unique( - QPixmap::fromImage(frame.image)), - frame.duration}; + return Frame{ + QPixmap::fromImage(frame.image), frame.duration}; }); // put into stack - static std::queue>> queued; + static std::queue>>> queued; static std::mutex mutex; std::lock_guard lock(mutex); - queued.emplace(assign, std::move(frames)); + queued.emplace(assign, frames); static std::atomic_bool loadedEventQueued{false}; if (!loadedEventQueued) { loadedEventQueued = true; - QTimer::singleShot(100, - [=] { asd(queued, mutex, loadedEventQueued); }); + QTimer::singleShot( + 100, [=] { assignDelayed(queued, mutex, loadedEventQueued); }); } }; } @@ -200,12 +175,7 @@ ImagePtr Image::fromUrl(const Url &url, qreal scale) return shared; } -ImagePtr Image::fromOwningPixmap(std::unique_ptr pixmap, qreal scale) -{ - return ImagePtr(new Image(std::move(pixmap), scale)); -} - -ImagePtr Image::fromNonOwningPixmap(QPixmap *pixmap, qreal scale) +ImagePtr Image::fromPixmap(const QPixmap &pixmap, qreal scale) { return ImagePtr(new Image(pixmap, scale)); } @@ -228,20 +198,10 @@ Image::Image(const Url &url, qreal scale) { } -Image::Image(std::unique_ptr owning, qreal scale) +Image::Image(const QPixmap &pixmap, qreal scale) : scale_(scale) + , frames_(QVector>{Frame{pixmap}}) { - std::vector vec; - vec.push_back(Frame{std::move(owning)}); - this->frames_ = std::move(vec); -} - -Image::Image(QPixmap *nonOwning, qreal scale) - : scale_(scale) -{ - std::vector vec; - vec.push_back(Frame{nonOwning}); - this->frames_ = std::move(vec); } const Url &Image::url() const @@ -249,7 +209,7 @@ const Url &Image::url() const return this->url_; } -const QPixmap *Image::pixmap() const +boost::optional Image::pixmap() const { assertInGuiThread(); @@ -266,7 +226,7 @@ qreal Image::scale() const return this->scale_; } -bool Image::empty() const +bool Image::isEmpty() const { return this->empty_; } @@ -301,37 +261,24 @@ int Image::height() const void Image::load() { NetworkRequest req(this->url().string); + req.setExecuteConcurrently(true); req.setCaller(&this->object_); req.setUseQuickLoadCache(true); req.onSuccess([that = this, weak = weakOf(this)](auto result) -> Outcome { - assertInGuiThread(); - auto shared = weak.lock(); if (!shared) return Failure; - static auto parseThread = [] { - auto thread = std::make_unique(); - thread->start(); - return thread; - }(); + auto data = result.getData(); - postToThread( - [data = result.getData(), weak, that] { - // BenchmarkGuard guard("parse image"); + // const cast since we are only reading from it + QBuffer buffer(const_cast(&data)); + buffer.open(QIODevice::ReadOnly); + QImageReader reader(&buffer); + auto parsed = readFrames(reader, that->url()); - // const cast since we are only reading from it - QBuffer buffer(const_cast(&data)); - buffer.open(QIODevice::ReadOnly); - QImageReader reader(&buffer); - auto parsed = readFrames(reader, that->url()); - - postToThread( - makeConvertCallback(std::move(parsed), [weak](auto frames) { - if (auto shared = weak.lock()) - shared->frames_ = std::move(frames); - })); - }, - parseThread.get()); + postToThread(makeConvertCallback(parsed, [weak](auto frames) { + if (auto shared = weak.lock()) shared->frames_ = frames; + })); return Success; }); @@ -341,7 +288,7 @@ void Image::load() bool Image::operator==(const Image &other) const { - if (this->empty() && other.empty()) return true; + if (this->isEmpty() && other.isEmpty()) return true; if (!this->url_.string.isEmpty() && this->url_ == other.url_) return true; if (this->frames_.first() == other.frames_.first()) return true; diff --git a/src/messages/Image.hpp b/src/messages/Image.hpp index b5c4d1f58..511ae9c48 100644 --- a/src/messages/Image.hpp +++ b/src/messages/Image.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,31 +16,27 @@ namespace chatterino { namespace { -using Pixmap = boost::variant>; +template struct Frame { - Pixmap pixmap; - int duration; -}; -struct ParseFrame { - QImage image; + Image image; int duration; }; class Frames { public: Frames(); - Frames(std::vector &&frames); + Frames(const QVector> &frames); ~Frames(); Frames(Frames &&other) = default; Frames &operator=(Frames &&other) = default; bool animated() const; void advance(); - const QPixmap *current() const; - const QPixmap *first() const; + boost::optional current() const; + boost::optional first() const; private: - std::vector items_; + QVector> items_; int index_{0}; int durationOffset_{0}; }; @@ -52,15 +49,13 @@ class Image : public std::enable_shared_from_this, boost::noncopyable { public: static ImagePtr fromUrl(const Url &url, qreal scale = 1); - static ImagePtr fromOwningPixmap(std::unique_ptr pixmap, - qreal scale = 1); - static ImagePtr fromNonOwningPixmap(QPixmap *pixmap, qreal scale = 1); + static ImagePtr fromPixmap(const QPixmap &pixmap, qreal scale = 1); static ImagePtr getEmpty(); const Url &url() const; - const QPixmap *pixmap() const; + boost::optional pixmap() const; qreal scale() const; - bool empty() const; + bool isEmpty() const; int width() const; int height() const; bool animated() const; @@ -71,8 +66,7 @@ public: private: Image(); Image(const Url &url, qreal scale); - Image(std::unique_ptr owning, qreal scale); - Image(QPixmap *nonOwning, qreal scale); + Image(const QPixmap &nonOwning, qreal scale); void load(); diff --git a/src/messages/ImageSet.cpp b/src/messages/ImageSet.cpp index af3c5e6bd..0e500816f 100644 --- a/src/messages/ImageSet.cpp +++ b/src/messages/ImageSet.cpp @@ -71,11 +71,11 @@ const ImagePtr &ImageSet::getImage(float scale) const scale = 1; } - if (!this->imageX3_->empty() && quality == 3) { + if (!this->imageX3_->isEmpty() && quality == 3) { return this->imageX3_; } - if (!this->imageX2_->empty() && quality == 2) { + if (!this->imageX2_->isEmpty() && quality == 2) { return this->imageX3_; } diff --git a/src/messages/ImageSet.hpp b/src/messages/ImageSet.hpp index 8f2efab2d..e8872b0b7 100644 --- a/src/messages/ImageSet.hpp +++ b/src/messages/ImageSet.hpp @@ -21,8 +21,6 @@ public: const ImagePtr &getImage(float scale) const; - ImagePtr getImage(float scale); - bool operator==(const ImageSet &other) const; bool operator!=(const ImageSet &other) const; diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index bca2c3072..e31076107 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -1,7 +1,6 @@ #include "messages/MessageElement.hpp" #include "Application.hpp" -#include "common/Emotemap.hpp" #include "controllers/moderationactions/ModerationActions.hpp" #include "debug/Benchmark.hpp" #include "messages/layouts/MessageLayoutContainer.hpp" @@ -102,7 +101,7 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container, if (flags.hasAny(this->getFlags())) { if (flags.has(MessageElementFlag::EmoteImages)) { auto image = this->emote_->images.getImage(container.getScale()); - if (image->empty()) return; + if (image->isEmpty()) return; auto size = QSize(int(container.getScale() * image->width()), int(container.getScale() * image->height())); diff --git a/src/messages/MessageElement.hpp b/src/messages/MessageElement.hpp index 82edadd85..79f222789 100644 --- a/src/messages/MessageElement.hpp +++ b/src/messages/MessageElement.hpp @@ -1,6 +1,5 @@ #pragma once -#include "common/Emotemap.hpp" #include "common/FlagsEnum.hpp" #include "messages/Emote.hpp" #include "messages/Image.hpp" diff --git a/src/providers/emoji/Emojis.hpp b/src/providers/emoji/Emojis.hpp index 6a2f4e74e..c4ff69bbe 100644 --- a/src/providers/emoji/Emojis.hpp +++ b/src/providers/emoji/Emojis.hpp @@ -1,6 +1,5 @@ #pragma once -#include "common/Emotemap.hpp" #include "common/SimpleSignalVector.hpp" #include "messages/Emote.hpp" #include "util/ConcurrentMap.hpp" diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 7753f2668..57de91a5d 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -22,6 +22,32 @@ #include namespace chatterino { +namespace { +auto parseRecentMessages(const QJsonObject &jsonRoot, TwitchChannel &channel) +{ + QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); + std::vector messages; + + if (jsonMessages.empty()) return messages; + + for (const auto jsonMessage : jsonMessages) { + auto content = jsonMessage.toString().toUtf8(); + // passing nullptr as the channel makes the message invalid but we don't + // check for that anyways + auto message = Communi::IrcMessage::fromData(content, nullptr); + auto privMsg = dynamic_cast(message); + assert(privMsg); + + MessageParseArgs args; + TwitchMessageBuilder builder(&channel, privMsg, args); + if (!builder.isIgnored()) { + messages.push_back(builder.build()); + } + } + + return messages; +} +} // namespace TwitchChannel::TwitchChannel(const QString &name) : Channel(name, Channel::Type::Twitch) @@ -436,45 +462,23 @@ void TwitchChannel::loadRecentMessages() NetworkRequest request(genericURL.arg(this->getRoomId())); request.makeAuthorizedV5(getDefaultClientID()); request.setCaller(QThread::currentThread()); + // can't be concurrent right now due to SignalVector + // request.setExecuteConcurrently(true); - request.onSuccess( - [this, weak = weakOf(this)](auto result) -> Outcome { - ChannelPtr shared = weak.lock(); - if (!shared) return Failure; + request.onSuccess([that = this](auto result) -> Outcome { + auto messages = parseRecentMessages(result.parseJson(), *that); - return this->parseRecentMessages(result.parseJson()); - }); + // postToThread([that, weak = weakOf(that), + // messages = std::move(messages)]() mutable { + that->addMessagesAtStart(messages); + // }); + + return Success; + }); request.execute(); } -Outcome TwitchChannel::parseRecentMessages(const QJsonObject &jsonRoot) -{ - QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); - if (jsonMessages.empty()) return Failure; - - std::vector messages; - - for (const auto jsonMessage : jsonMessages) { - auto content = jsonMessage.toString().toUtf8(); - // passing nullptr as the channel makes the message invalid but we don't - // check for that anyways - auto message = Communi::IrcMessage::fromData(content, nullptr); - auto privMsg = dynamic_cast(message); - assert(privMsg); - - MessageParseArgs args; - TwitchMessageBuilder builder(this, privMsg, args); - if (!builder.isIgnored()) { - messages.push_back(builder.build()); - } - } - - this->addMessagesAtStart(messages); - - return Success; -} - void TwitchChannel::refreshPubsub() { // listen to moderation actions @@ -581,7 +585,7 @@ void TwitchChannel::loadBadges() void TwitchChannel::loadCheerEmotes() { - auto url = Url{"https://api.twitch.tv/kraken/bits/actions?channel_id=" + + /*auto url = Url{"https://api.twitch.tv/kraken/bits/actions?channel_id=" + this->getRoomId()}; auto request = NetworkRequest::twitchRequest(url.string); request.setCaller(QThread::currentThread()); @@ -589,6 +593,7 @@ void TwitchChannel::loadCheerEmotes() request.onSuccess( [this, weak = weakOf(this)](auto result) -> Outcome { auto cheerEmoteSets = ParseCheermoteSets(result.parseRapidJson()); + std::vector emoteSets; for (auto &set : cheerEmoteSets) { auto cheerEmoteSet = CheerEmoteSet(); @@ -631,13 +636,15 @@ void TwitchChannel::loadCheerEmotes() return lhs.minBits < rhs.minBits; // }); - this->cheerEmoteSets_.emplace_back(cheerEmoteSet); + emoteSets.emplace_back(cheerEmoteSet); } + *this->cheerEmoteSets_.access() = std::move(emoteSets); return Success; }); request.execute(); + */ } boost::optional TwitchChannel::getTwitchBadge( diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index bc084d73f..320be3b36 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -116,7 +116,6 @@ private: void refreshViewerList(); Outcome parseViewerList(const QJsonObject &jsonRoot); void loadRecentMessages(); - Outcome parseRecentMessages(const QJsonObject &jsonRoot); void setLive(bool newLiveStatus); @@ -144,7 +143,7 @@ private: // "subscribers": { "0": ... "3": ... "6": ... UniqueAccess>> badgeSets_; - std::vector cheerEmoteSets_; + UniqueAccess> cheerEmoteSets_; // -- QByteArray messageSuffix_; diff --git a/src/providers/twitch/TwitchEmotes.hpp b/src/providers/twitch/TwitchEmotes.hpp index 665e1e9cd..69cf65e5e 100644 --- a/src/providers/twitch/TwitchEmotes.hpp +++ b/src/providers/twitch/TwitchEmotes.hpp @@ -3,7 +3,6 @@ #include #include -#include "common/Emotemap.hpp" #include "common/UniqueAccess.hpp" #include "messages/Emote.hpp" #include "providers/twitch/EmoteValue.hpp" diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 740cccc05..eeb4ed4b0 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -715,41 +715,38 @@ void TwitchMessageBuilder::appendTwitchBadges() //} } else if (badge == "staff/1") { this->emplace( - Image::fromNonOwningPixmap(&app->resources->twitch.staff), + Image::fromPixmap(app->resources->twitch.staff), MessageElementFlag::BadgeGlobalAuthority) ->setTooltip("Twitch Staff"); } else if (badge == "admin/1") { this->emplace( - Image::fromNonOwningPixmap(&app->resources->twitch.admin), + Image::fromPixmap(app->resources->twitch.admin), MessageElementFlag::BadgeGlobalAuthority) ->setTooltip("Twitch Admin"); } else if (badge == "global_mod/1") { this->emplace( - Image::fromNonOwningPixmap( - &app->resources->twitch.globalmod), + Image::fromPixmap(app->resources->twitch.globalmod), MessageElementFlag::BadgeGlobalAuthority) ->setTooltip("Twitch Global Moderator"); } else if (badge == "moderator/1") { // TODO: Implement custom FFZ moderator badge this->emplace( - Image::fromNonOwningPixmap( - &app->resources->twitch.moderator), + Image::fromPixmap(app->resources->twitch.moderator), MessageElementFlag::BadgeChannelAuthority) ->setTooltip("Twitch Channel Moderator"); } else if (badge == "turbo/1") { this->emplace( - Image::fromNonOwningPixmap(&app->resources->twitch.turbo), + Image::fromPixmap(app->resources->twitch.turbo), MessageElementFlag::BadgeGlobalAuthority) ->setTooltip("Twitch Turbo Subscriber"); } else if (badge == "broadcaster/1") { this->emplace( - Image::fromNonOwningPixmap( - &app->resources->twitch.broadcaster), + Image::fromPixmap(app->resources->twitch.broadcaster), MessageElementFlag::BadgeChannelAuthority) ->setTooltip("Twitch Broadcaster"); } else if (badge == "premium/1") { this->emplace( - Image::fromNonOwningPixmap(&app->resources->twitch.prime), + Image::fromPixmap(app->resources->twitch.prime), MessageElementFlag::BadgeVanity) ->setTooltip("Twitch Prime Subscriber"); } else if (badge.startsWith("partner/")) { @@ -757,8 +754,8 @@ void TwitchMessageBuilder::appendTwitchBadges() switch (index) { case 1: { this->emplace( - Image::fromNonOwningPixmap( - &app->resources->twitch.verified, 0.25), + Image::fromPixmap(app->resources->twitch.verified, + 0.25), MessageElementFlag::BadgeVanity) ->setTooltip("Twitch Verified"); } break; diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index e1dca8cfb..e8f90d0fc 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -52,7 +52,7 @@ void addEmoteContextMenuItems(const Emote &emote, // Add copy and open links for 1x, 2x, 3x auto addImageLink = [&](const ImagePtr &image, char scale) { - if (!image->empty()) { + if (!image->isEmpty()) { copyMenu->addAction( QString(scale) + "x link", [url = image->url()] { QApplication::clipboard()->setText(url.string); diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 6f7032e46..8cdcfd5f9 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -322,11 +322,11 @@ ChannelPtr LookPage::createPreviewChannel() { MessageBuilder builder; builder.emplace(QTime(8, 13, 42)); - builder.emplace(Image::fromNonOwningPixmap(&getApp()->resources->twitch.moderator), MessageElementFlag::BadgeChannelAuthority); - builder.emplace(Image::fromNonOwningPixmap(&getApp()->resources->twitch.subscriber, 0.25), MessageElementFlag::BadgeSubscription); + builder.emplace(Image::fromPixmap(getApp()->resources->twitch.moderator), MessageElementFlag::BadgeChannelAuthority); + builder.emplace(Image::fromPixmap(getApp()->resources->twitch.subscriber, 0.25), MessageElementFlag::BadgeSubscription); builder.emplace("username1:", MessageElementFlag::Username, QColor("#0094FF"), FontStyle::ChatMediumBold); builder.emplace("This is a preview message", MessageElementFlag::Text); - builder.emplace(Image::fromNonOwningPixmap(&getApp()->resources->pajaDank, 0.25), MessageElementFlag::AlwaysShow); + builder.emplace(Image::fromPixmap(getApp()->resources->pajaDank, 0.25), MessageElementFlag::AlwaysShow); builder.emplace("@fourtf", MessageElementFlag::BoldUsername, MessageColor::Text, FontStyle::ChatMediumBold); builder.emplace("@fourtf", MessageElementFlag::NonBoldUsername); channel->addMessage(builder.release()); @@ -334,7 +334,7 @@ ChannelPtr LookPage::createPreviewChannel() { MessageBuilder message; message.emplace(QTime(8, 15, 21)); - message.emplace(Image::fromNonOwningPixmap(&getApp()->resources->twitch.broadcaster), MessageElementFlag::BadgeChannelAuthority); + message.emplace(Image::fromPixmap(getApp()->resources->twitch.broadcaster), MessageElementFlag::BadgeChannelAuthority); message.emplace("username2:", MessageElementFlag::Username, QColor("#FF6A00"), FontStyle::ChatMediumBold); message.emplace("This is another one", MessageElementFlag::Text); // message.emplace(Image::fromNonOwningPixmap(&getApp()->resources->ppHop), MessageElementFlag::BttvEmote);