diff --git a/CHANGELOG.md b/CHANGELOG.md index 7697a84c045..089522150b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Minor: 7TV badges now automatically update upon changing. (#4512) - Minor: Stream status requests are now batched. (#4713) - Minor: Added `/c2-theme-autoreload` command to automatically reload a custom theme. This is useful for when you're developing your own theme. (#4718) +- Minor: All channels opened in browser tabs are synced when using the extension for quicker switching between tabs. (#4741) - Minor: Show channel point redemptions without messages in usercard. (#4557) - Bugfix: Increased amount of blocked users loaded from 100 to 1,000. (#4721) - Bugfix: Fixed generation of crashdumps by the browser-extension process when the browser was closed. (#4667) diff --git a/src/singletons/NativeMessaging.cpp b/src/singletons/NativeMessaging.cpp index ef42e706da1..a7165c1f766 100644 --- a/src/singletons/NativeMessaging.cpp +++ b/src/singletons/NativeMessaging.cpp @@ -3,6 +3,7 @@ #include "Application.hpp" #include "common/Literals.hpp" #include "common/QLogging.hpp" +#include "debug/AssertInGuiThread.hpp" #include "providers/twitch/TwitchIrcServer.hpp" #include "singletons/Paths.hpp" #include "util/IpcQueue.hpp" @@ -129,12 +130,22 @@ namespace nm::client { } // namespace nm::client // SERVER +NativeMessagingServer::NativeMessagingServer() + : thread(*this) +{ +} void NativeMessagingServer::start() { this->thread.start(); } +NativeMessagingServer::ReceiverThread::ReceiverThread( + NativeMessagingServer &parent) + : parent_(parent) +{ +} + void NativeMessagingServer::ReceiverThread::run() { auto [messageQueue, error] = @@ -177,6 +188,11 @@ void NativeMessagingServer::ReceiverThread::handleMessage( this->handleDetach(root); return; } + if (action == "sync") + { + this->handleSync(root); + return; + } qCDebug(chatterinoNativeMessage) << "NM unknown action" << action; } @@ -263,6 +279,39 @@ void NativeMessagingServer::ReceiverThread::handleDetach( } // NOLINTEND(readability-convert-member-functions-to-static) +void NativeMessagingServer::ReceiverThread::handleSync(const QJsonObject &root) +{ + // Structure: + // { action: 'sync', twitchChannels?: string[] } + postToThread([&parent = this->parent_, + twitch = root["twitchChannels"_L1].toArray()] { + parent.syncChannels(twitch); + }); +} + +void NativeMessagingServer::syncChannels(const QJsonArray &twitchChannels) +{ + assertInGuiThread(); + + auto *app = getApp(); + + std::vector updated; + updated.reserve(twitchChannels.size()); + for (const auto &value : twitchChannels) + { + auto name = value.toString(); + if (name.isEmpty()) + { + continue; + } + // the deduping is done on the extension side + updated.emplace_back(app->twitch->getOrAddChannel(name)); + } + + // This will destroy channels that aren't used anymore. + this->channelWarmer_ = std::move(updated); +} + Atomic> &nmIpcError() { static Atomic> x; diff --git a/src/singletons/NativeMessaging.hpp b/src/singletons/NativeMessaging.hpp index 4f39057c020..4ed46ad0dad 100644 --- a/src/singletons/NativeMessaging.hpp +++ b/src/singletons/NativeMessaging.hpp @@ -6,10 +6,15 @@ #include #include +#include + namespace chatterino { class Application; class Paths; +class Channel; + +using ChannelPtr = std::shared_ptr; void registerNmHost(Paths &paths); std::string &getNmQueueName(Paths &paths); @@ -26,21 +31,40 @@ namespace nm::client { class NativeMessagingServer final { public: + NativeMessagingServer(); + NativeMessagingServer(const NativeMessagingServer &) = delete; + NativeMessagingServer(NativeMessagingServer &&) = delete; + NativeMessagingServer &operator=(const NativeMessagingServer &) = delete; + NativeMessagingServer &operator=(NativeMessagingServer &&) = delete; + void start(); private: class ReceiverThread : public QThread { public: + ReceiverThread(NativeMessagingServer &parent); + void run() override; private: void handleMessage(const QJsonObject &root); void handleSelect(const QJsonObject &root); void handleDetach(const QJsonObject &root); + void handleSync(const QJsonObject &root); + + NativeMessagingServer &parent_; }; + void syncChannels(const QJsonArray &twitchChannels); + ReceiverThread thread; + + /// This vector contains all channels that are open the user's browser. + /// These channels are joined to be able to switch channels more quickly. + std::vector channelWarmer_; + + friend ReceiverThread; }; } // namespace chatterino