feat: support /watching on all platforms (#6031)

This commit is contained in:
nerix
2025-03-08 14:37:25 +01:00
committed by GitHub
parent 77c4d858f9
commit 9913c6ffd7
4 changed files with 95 additions and 42 deletions
+1
View File
@@ -16,6 +16,7 @@
- Minor: Added Linux support for Live Notifications toasts. (#5881, #5971, #5976) - Minor: Added Linux support for Live Notifications toasts. (#5881, #5971, #5976)
- Minor: Messages can now be deleted from the context menu in a channel. (#5956) - Minor: Messages can now be deleted from the context menu in a channel. (#5956)
- Minor: Overlay windows now inherit the global zoom level and can be zoomed independently. (#6016) - Minor: Overlay windows now inherit the global zoom level and can be zoomed independently. (#6016)
- Minor: The `/watching` channel is now supported on all platforms. (#6031)
- Minor: The font weight of chat messages can now be changed. (#6037) - Minor: The font weight of chat messages can now be changed. (#6037)
- Bugfix: Fixed a potential way to escape the Lua Plugin sandbox. (#5846) - Bugfix: Fixed a potential way to escape the Lua Plugin sandbox. (#5846)
- Bugfix: Fixed a crash relating to Lua HTTP. (#5800) - Bugfix: Fixed a crash relating to Lua HTTP. (#5800)
+1 -3
View File
@@ -607,11 +607,9 @@ void Application::initNm(const Paths &paths)
{ {
(void)paths; (void)paths;
#ifdef Q_OS_WIN #if defined QT_NO_DEBUG || defined CHATTERINO_DEBUG_NM
# if defined QT_NO_DEBUG || defined CHATTERINO_DEBUG_NM
registerNmHost(paths); registerNmHost(paths);
this->nmServer.start(); this->nmServer.start();
# endif
#endif #endif
} }
+92 -38
View File
@@ -12,12 +12,14 @@
#include "util/PostToThread.hpp" #include "util/PostToThread.hpp"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir>
#include <QFile> #include <QFile>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonValue> #include <QJsonValue>
#include <QSettings> #include <QSettings>
#include <QStringBuilder>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# include "widgets/AttachedWindow.hpp" # include "widgets/AttachedWindow.hpp"
@@ -25,21 +27,92 @@
namespace { namespace {
using namespace chatterino;
using namespace chatterino::literals; using namespace chatterino::literals;
const QString EXTENSION_ID = u"glknmaideaikkmemifbfkhnomoknepka"_s; const QString EXTENSION_ID = u"glknmaideaikkmemifbfkhnomoknepka"_s;
constexpr const size_t MESSAGE_SIZE = 1024; constexpr const size_t MESSAGE_SIZE = 1024;
struct Config {
#ifdef Q_OS_WIN
QString fileName;
QString registryKey;
#else
QString directory;
#endif
};
const Config FIREFOX{
#ifdef Q_OS_WIN
.fileName = u"native-messaging-manifest-firefox.json"_s,
.registryKey =
u"HKCU\\Software\\Mozilla\\NativeMessagingHosts\\com.chatterino.chatterino"_s,
#elif defined(Q_OS_MACOS)
.directory =
u"~/Library/Application Support/Mozilla/NativeMessagingHosts"_s,
#else
.directory = u"~/.mozilla/native-messaging-hosts"_s,
#endif
};
const Config CHROME{
#ifdef Q_OS_WIN
.fileName = u"native-messaging-manifest-chrome.json"_s,
.registryKey =
u"HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.chatterino.chatterino"_s,
#elif defined(Q_OS_MACOS)
.directory =
u"~/Library/Application Support/Google/Chrome/NativeMessagingHosts"_s,
#else
.directory = u"~/.config/google-chrome/NativeMessagingHosts"_s,
#endif
};
void writeManifestTo(QString directory, const QString &filename,
const QJsonDocument &json)
{
if (directory.startsWith('~'))
{
directory = QDir::homePath() % QStringView{directory}.sliced(1);
}
QDir dir(directory);
if (!dir.mkpath(u"."_s))
{
qCWarning(chatterinoNativeMessage) << "Failed to create" << directory;
return;
}
QFile file(dir.filePath(filename));
if (!file.open(QFile::WriteOnly | QFile::Truncate))
{
qCWarning(chatterinoNativeMessage)
<< "Failed to open" << filename << "in" << directory;
return;
}
file.write(json.toJson());
}
void registerNmManifest([[maybe_unused]] const Paths &paths,
const Config &config, const QJsonDocument &document)
{
#ifdef Q_OS_WIN
writeManifestTo(paths.miscDirectory, config.fileName, document);
QSettings registry(config.registryKey, QSettings::NativeFormat);
registry.setValue("Default",
QString(paths.miscDirectory % u'/' % config.fileName));
#else
writeManifestTo(config.directory, u"com.chatterino.chatterino.json"_s,
document);
#endif
}
} // namespace } // namespace
namespace chatterino { namespace chatterino {
using namespace literals; using namespace literals;
void registerNmManifest(const Paths &paths, const QString &manifestFilename,
const QString &registryKeyName,
const QJsonDocument &document);
void registerNmHost(const Paths &paths) void registerNmHost(const Paths &paths)
{ {
if (Modes::instance().isPortable) if (Modes::instance().isPortable)
@@ -78,10 +151,7 @@ void registerNmHost(const Paths &paths)
obj.insert("allowed_origins", allowedOriginsArr); obj.insert("allowed_origins", allowedOriginsArr);
registerNmManifest(paths, "/native-messaging-manifest-chrome.json", registerNmManifest(paths, CHROME, QJsonDocument{obj});
"HKCU\\Software\\Google\\Chrome\\NativeMessagingHost"
"s\\com.chatterino.chatterino",
QJsonDocument(obj));
} }
// firefox // firefox
@@ -100,32 +170,10 @@ void registerNmHost(const Paths &paths)
obj.insert("allowed_extensions", allowedExtensions); obj.insert("allowed_extensions", allowedExtensions);
registerNmManifest(paths, "/native-messaging-manifest-firefox.json", registerNmManifest(paths, FIREFOX, QJsonDocument{obj});
"HKCU\\Software\\Mozilla\\NativeMessagingHosts\\com."
"chatterino.chatterino",
QJsonDocument(obj));
} }
} }
void registerNmManifest(const Paths &paths, const QString &manifestFilename,
const QString &registryKeyName,
const QJsonDocument &document)
{
(void)registryKeyName;
// save the manifest
QString manifestPath = paths.miscDirectory + manifestFilename;
QFile file(manifestPath);
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.write(document.toJson());
file.flush();
#ifdef Q_OS_WIN
QSettings registry(registryKeyName, QSettings::NativeFormat);
registry.setValue("Default", manifestPath);
#endif
}
std::string &getNmQueueName(const Paths &paths) std::string &getNmQueueName(const Paths &paths)
{ {
static std::string name = static std::string name =
@@ -158,9 +206,9 @@ namespace nm::client {
// SERVER // SERVER
NativeMessagingServer::NativeMessagingServer() NativeMessagingServer::NativeMessagingServer()
: thread(*this) : thread(new ReceiverThread(*this))
{ {
this->thread.setObjectName("NativeMessagingReceiver"); this->thread->setObjectName("C2NMReceiver");
} }
NativeMessagingServer::~NativeMessagingServer() NativeMessagingServer::~NativeMessagingServer()
@@ -169,18 +217,24 @@ NativeMessagingServer::~NativeMessagingServer()
{ {
qCWarning(chatterinoNativeMessage) << "Failed to remove message queue"; qCWarning(chatterinoNativeMessage) << "Failed to remove message queue";
} }
this->thread.requestInterruption(); this->thread->requestInterruption();
this->thread.quit(); this->thread->quit();
// Most likely, the receiver thread will still wait for a message // Most likely, the receiver thread will still wait for a message
if (!this->thread.wait(250)) if (!this->thread->wait(100))
{ {
this->thread.terminate(); this->thread->terminate();
if (!this->thread->wait(100))
{
qCWarning(chatterinoNativeMessage)
<< "Failed to terminate thread cleanly";
}
} }
} }
void NativeMessagingServer::start() void NativeMessagingServer::start()
{ {
this->thread.start(); this->thread->start();
} }
NativeMessagingServer::ReceiverThread::ReceiverThread( NativeMessagingServer::ReceiverThread::ReceiverThread(
+1 -1
View File
@@ -59,7 +59,7 @@ private:
void syncChannels(const QJsonArray &twitchChannels); void syncChannels(const QJsonArray &twitchChannels);
ReceiverThread thread; ReceiverThread *thread;
/// This vector contains all channels that are open the user's browser. /// This vector contains all channels that are open the user's browser.
/// These channels are joined to be able to switch channels more quickly. /// These channels are joined to be able to switch channels more quickly.