mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Implement /ignore and /unignore commands
Simplify authorized network requests for Twitch V5 api add onShow virtual function to settings pages if they need to be refreshed when shown Actually ignoring messages from ignored users is still not implemented Working on #247
This commit is contained in:
parent
98082d1064
commit
bf0b5d08d8
12 changed files with 512 additions and 19 deletions
|
@ -179,6 +179,7 @@ SOURCES += \
|
||||||
src/util/rapidjson-helpers.cpp \
|
src/util/rapidjson-helpers.cpp \
|
||||||
src/providers/twitch/pubsubhelpers.cpp \
|
src/providers/twitch/pubsubhelpers.cpp \
|
||||||
src/providers/twitch/pubsubactions.cpp \
|
src/providers/twitch/pubsubactions.cpp \
|
||||||
|
src/providers/twitch/twitchuser.cpp \
|
||||||
src/widgets/selectchanneldialog.cpp \
|
src/widgets/selectchanneldialog.cpp \
|
||||||
src/singletons/updatemanager.cpp \
|
src/singletons/updatemanager.cpp \
|
||||||
src/widgets/lastruncrashdialog.cpp \
|
src/widgets/lastruncrashdialog.cpp \
|
||||||
|
@ -316,6 +317,7 @@ HEADERS += \
|
||||||
src/util/rapidjson-helpers.hpp \
|
src/util/rapidjson-helpers.hpp \
|
||||||
src/providers/twitch/pubsubhelpers.hpp \
|
src/providers/twitch/pubsubhelpers.hpp \
|
||||||
src/providers/twitch/pubsubactions.hpp \
|
src/providers/twitch/pubsubactions.hpp \
|
||||||
|
src/providers/twitch/twitchuser.hpp \
|
||||||
src/widgets/selectchanneldialog.hpp \
|
src/widgets/selectchanneldialog.hpp \
|
||||||
src/singletons/updatemanager.hpp \
|
src/singletons/updatemanager.hpp \
|
||||||
src/widgets/lastruncrashdialog.hpp \
|
src/widgets/lastruncrashdialog.hpp \
|
||||||
|
|
|
@ -119,26 +119,38 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel,
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
} else if (commandName == "/ignore" && words.size() >= 2) {
|
} else if (commandName == "/ignore" && words.size() >= 2) {
|
||||||
// fourtf: ignore user
|
auto app = getApp();
|
||||||
// QString messageText;
|
|
||||||
|
|
||||||
// if (IrcManager::getInstance().tryAddIgnoredUser(words.at(1),
|
auto user = app->accounts->Twitch.getCurrent();
|
||||||
// messageText)) {
|
auto target = words.at(1);
|
||||||
// messageText = "Ignored user \"" + words.at(1) + "\".";
|
|
||||||
// }
|
if (user->isAnon()) {
|
||||||
|
channel->addMessage(messages::Message::createSystemMessage(
|
||||||
|
"You must be logged in to ignore someone"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
user->ignore(target, [channel](const QString &message) {
|
||||||
|
channel->addMessage(messages::Message::createSystemMessage(message));
|
||||||
|
});
|
||||||
|
|
||||||
// channel->addMessage(messages::Message::createSystemMessage(messageText));
|
|
||||||
return "";
|
return "";
|
||||||
} else if (commandName == "/unignore") {
|
} else if (commandName == "/unignore" && words.size() >= 2) {
|
||||||
// fourtf: ignore user
|
auto app = getApp();
|
||||||
// QString messageText;
|
|
||||||
|
|
||||||
// if (IrcManager::getInstance().tryRemoveIgnoredUser(words.at(1),
|
auto user = app->accounts->Twitch.getCurrent();
|
||||||
// messageText)) {
|
auto target = words.at(1);
|
||||||
// messageText = "Ignored user \"" + words.at(1) + "\".";
|
|
||||||
// }
|
if (user->isAnon()) {
|
||||||
|
channel->addMessage(messages::Message::createSystemMessage(
|
||||||
|
"You must be logged in to ignore someone"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
user->unignore(target, [channel](const QString &message) {
|
||||||
|
channel->addMessage(messages::Message::createSystemMessage(message));
|
||||||
|
});
|
||||||
|
|
||||||
// channel->addMessage(messages::Message::createSystemMessage(messageText));
|
|
||||||
return "";
|
return "";
|
||||||
} else if (commandName == "/w") {
|
} else if (commandName == "/w") {
|
||||||
if (words.length() <= 2) {
|
if (words.length() <= 2) {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#include "providers/twitch/twitchaccount.hpp"
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
|
||||||
#include "const.hpp"
|
#include "const.hpp"
|
||||||
|
#include "debug/log.hpp"
|
||||||
|
#include "util/networkrequest.hpp"
|
||||||
|
#include "util/urlfetch.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace providers {
|
namespace providers {
|
||||||
|
@ -68,6 +72,146 @@ bool TwitchAccount::isAnon() const
|
||||||
return this->_isAnon;
|
return this->_isAnon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwitchAccount::loadIgnores()
|
||||||
|
{
|
||||||
|
QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks");
|
||||||
|
|
||||||
|
util::NetworkRequest req(url);
|
||||||
|
req.setRequestType(util::NetworkRequest::GET);
|
||||||
|
req.setCaller(QThread::currentThread());
|
||||||
|
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
|
||||||
|
req.onSuccess([=](const rapidjson::Document &document) {
|
||||||
|
if (!document.IsObject()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto blocksIt = document.FindMember("blocks");
|
||||||
|
if (blocksIt == document.MemberEnd()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto &blocks = blocksIt->value;
|
||||||
|
|
||||||
|
if (!blocks.IsArray()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->ignoresMutex);
|
||||||
|
this->ignores.clear();
|
||||||
|
|
||||||
|
for (const auto &block : blocks.GetArray()) {
|
||||||
|
if (!block.IsObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto userIt = block.FindMember("user");
|
||||||
|
if (userIt == block.MemberEnd()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this->ignores.insert(TwitchUser::fromJSON(userIt->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchAccount::ignore(const QString &targetName,
|
||||||
|
std::function<void(const QString &message)> onFinished)
|
||||||
|
{
|
||||||
|
util::twitch::getUserID(targetName, QThread::currentThread(), [=](QString targetUserID) {
|
||||||
|
QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks/" +
|
||||||
|
targetUserID);
|
||||||
|
|
||||||
|
util::NetworkRequest req(url);
|
||||||
|
req.setRequestType(util::NetworkRequest::PUT);
|
||||||
|
req.setCaller(QThread::currentThread());
|
||||||
|
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
|
||||||
|
|
||||||
|
req.onError([=](int errorCode) {
|
||||||
|
onFinished("An unknown error occured while trying to ignore user " + targetName + " (" +
|
||||||
|
QString::number(errorCode) + ")");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.onSuccess([=](const rapidjson::Document &document) {
|
||||||
|
if (!document.IsObject()) {
|
||||||
|
onFinished("Bad JSON data while ignoring user " + targetName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto userIt = document.FindMember("user");
|
||||||
|
if (userIt == document.MemberEnd()) {
|
||||||
|
onFinished("Bad JSON data while ignoring user (missing user) " + targetName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ignoredUser = TwitchUser::fromJSON(userIt->value);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->ignoresMutex);
|
||||||
|
|
||||||
|
auto res = this->ignores.insert(ignoredUser);
|
||||||
|
if (!res.second) {
|
||||||
|
const TwitchUser &existingUser = *(res.first);
|
||||||
|
existingUser.update(ignoredUser);
|
||||||
|
onFinished("User " + targetName + " is already ignored");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onFinished("Successfully ignored user " + targetName);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchAccount::unignore(const QString &targetName,
|
||||||
|
std::function<void(const QString &message)> onFinished)
|
||||||
|
{
|
||||||
|
util::twitch::getUserID(targetName, QThread::currentThread(), [=](QString targetUserID) {
|
||||||
|
QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks/" +
|
||||||
|
targetUserID);
|
||||||
|
|
||||||
|
util::NetworkRequest req(url);
|
||||||
|
req.setRequestType(util::NetworkRequest::DELETE);
|
||||||
|
req.setCaller(QThread::currentThread());
|
||||||
|
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
|
||||||
|
|
||||||
|
req.onError([=](int errorCode) {
|
||||||
|
onFinished("An unknown error occured while trying to unignore user " + targetName +
|
||||||
|
" (" + QString::number(errorCode) + ")");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.onSuccess([=](const rapidjson::Document &document) {
|
||||||
|
TwitchUser ignoredUser;
|
||||||
|
ignoredUser.id = targetUserID;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->ignoresMutex);
|
||||||
|
|
||||||
|
this->ignores.erase(ignoredUser);
|
||||||
|
}
|
||||||
|
onFinished("Successfully unignored user " + targetName);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<TwitchUser> TwitchAccount::getIgnores() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->ignoresMutex);
|
||||||
|
|
||||||
|
return this->ignores;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
} // namespace providers
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "controllers/accounts/account.hpp"
|
||||||
|
#include "providers/twitch/twitchuser.hpp"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "controllers/accounts/account.hpp"
|
#include <set>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace providers {
|
namespace providers {
|
||||||
|
@ -33,6 +36,12 @@ public:
|
||||||
|
|
||||||
bool isAnon() const;
|
bool isAnon() const;
|
||||||
|
|
||||||
|
void loadIgnores();
|
||||||
|
void ignore(const QString &targetName, std::function<void(const QString &)> onFinished);
|
||||||
|
void unignore(const QString &targetName, std::function<void(const QString &)> onFinished);
|
||||||
|
|
||||||
|
std::set<TwitchUser> getIgnores() const;
|
||||||
|
|
||||||
QColor color;
|
QColor color;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -41,6 +50,9 @@ private:
|
||||||
QString userName;
|
QString userName;
|
||||||
QString userId;
|
QString userId;
|
||||||
const bool _isAnon;
|
const bool _isAnon;
|
||||||
|
|
||||||
|
mutable std::mutex ignoresMutex;
|
||||||
|
std::set<TwitchUser> ignores;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
|
|
@ -11,6 +11,10 @@ namespace twitch {
|
||||||
TwitchAccountManager::TwitchAccountManager()
|
TwitchAccountManager::TwitchAccountManager()
|
||||||
: anonymousUser(new TwitchAccount(ANONYMOUS_USERNAME, "", "", ""))
|
: anonymousUser(new TwitchAccount(ANONYMOUS_USERNAME, "", "", ""))
|
||||||
{
|
{
|
||||||
|
this->currentUserChanged.connect([this] {
|
||||||
|
auto currentUser = this->getCurrent();
|
||||||
|
currentUser->loadIgnores();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TwitchAccount> TwitchAccountManager::getCurrent()
|
std::shared_ptr<TwitchAccount> TwitchAccountManager::getCurrent()
|
||||||
|
|
34
src/providers/twitch/twitchuser.cpp
Normal file
34
src/providers/twitch/twitchuser.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include "providers/twitch/twitchuser.hpp"
|
||||||
|
|
||||||
|
#include "util/rapidjson-helpers.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
|
|
||||||
|
TwitchUser TwitchUser::fromJSON(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
|
TwitchUser user;
|
||||||
|
|
||||||
|
if (!value.IsObject()) {
|
||||||
|
throw std::runtime_error("JSON value is not an object");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rj::getSafe(value, "_id", user.id)) {
|
||||||
|
throw std::runtime_error("Missing ID key");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rj::getSafe(value, "name", user.name)) {
|
||||||
|
throw std::runtime_error("Missing name key");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rj::getSafe(value, "display_name", user.displayName)) {
|
||||||
|
throw std::runtime_error("Missing display name key");
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
35
src/providers/twitch/twitchuser.hpp
Normal file
35
src/providers/twitch/twitchuser.hpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
|
|
||||||
|
struct TwitchUser {
|
||||||
|
QString id;
|
||||||
|
mutable QString name;
|
||||||
|
mutable QString displayName;
|
||||||
|
|
||||||
|
void update(const TwitchUser &other) const
|
||||||
|
{
|
||||||
|
assert(this->id == other.id);
|
||||||
|
|
||||||
|
this->name = other.name;
|
||||||
|
this->displayName = other.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TwitchUser fromJSON(const rapidjson::Value &value);
|
||||||
|
|
||||||
|
bool operator<(const TwitchUser &rhs) const
|
||||||
|
{
|
||||||
|
return this->id < rhs.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
|
@ -62,6 +62,15 @@ static rapidjson::Document parseJSONFromReply2(QNetworkReply *reply)
|
||||||
|
|
||||||
class NetworkRequest
|
class NetworkRequest
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum RequestType {
|
||||||
|
GET,
|
||||||
|
POST,
|
||||||
|
PUT,
|
||||||
|
DELETE,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
struct Data {
|
struct Data {
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
const QObject *caller = nullptr;
|
const QObject *caller = nullptr;
|
||||||
|
@ -69,6 +78,13 @@ class NetworkRequest
|
||||||
int timeoutMS = -1;
|
int timeoutMS = -1;
|
||||||
bool useQuickLoadCache = false;
|
bool useQuickLoadCache = false;
|
||||||
|
|
||||||
|
std::function<bool(int)> onError;
|
||||||
|
std::function<bool(const rapidjson::Document &)> onSuccess;
|
||||||
|
|
||||||
|
NetworkRequest::RequestType requestType;
|
||||||
|
|
||||||
|
QByteArray payload;
|
||||||
|
|
||||||
QString getHash()
|
QString getHash()
|
||||||
{
|
{
|
||||||
if (this->hash.isEmpty()) {
|
if (this->hash.isEmpty()) {
|
||||||
|
@ -100,6 +116,28 @@ public:
|
||||||
explicit NetworkRequest(const std::string &url);
|
explicit NetworkRequest(const std::string &url);
|
||||||
explicit NetworkRequest(const QString &url);
|
explicit NetworkRequest(const QString &url);
|
||||||
|
|
||||||
|
void setRequestType(RequestType newRequestType)
|
||||||
|
{
|
||||||
|
this->data.requestType = newRequestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void onError(Func cb)
|
||||||
|
{
|
||||||
|
this->data.onError = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void onSuccess(Func cb)
|
||||||
|
{
|
||||||
|
this->data.onSuccess = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPayload(const QByteArray &payload)
|
||||||
|
{
|
||||||
|
this->data.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
void setUseQuickLoadCache(bool value);
|
void setUseQuickLoadCache(bool value);
|
||||||
|
|
||||||
void setCaller(const QObject *_caller)
|
void setCaller(const QObject *_caller)
|
||||||
|
@ -112,16 +150,33 @@ public:
|
||||||
this->data.onReplyCreated = f;
|
this->data.onReplyCreated = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
|
void setRawHeader(const char *headerName, const char *value)
|
||||||
{
|
{
|
||||||
this->data.request.setRawHeader(headerName, value);
|
this->data.request.setRawHeader(headerName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRawHeader(const char *headerName, const QByteArray &value)
|
||||||
|
{
|
||||||
|
this->data.request.setRawHeader(headerName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRawHeader(const char *headerName, const QString &value)
|
||||||
|
{
|
||||||
|
this->data.request.setRawHeader(headerName, value.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
void setTimeout(int ms)
|
void setTimeout(int ms)
|
||||||
{
|
{
|
||||||
this->data.timeoutMS = ms;
|
this->data.timeoutMS = ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void makeAuthorizedV5(const QString &clientID, const QString &oauthToken)
|
||||||
|
{
|
||||||
|
this->setRawHeader("Client-ID", clientID);
|
||||||
|
this->setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
|
||||||
|
this->setRawHeader("Authorization", "OAuth " + oauthToken);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename FinishedCallback>
|
template <typename FinishedCallback>
|
||||||
void get(FinishedCallback onFinished)
|
void get(FinishedCallback onFinished)
|
||||||
{
|
{
|
||||||
|
@ -243,6 +298,169 @@ public:
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void execute()
|
||||||
|
{
|
||||||
|
switch (this->data.requestType) {
|
||||||
|
case GET: {
|
||||||
|
this->executeGet();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PUT: {
|
||||||
|
debug::Log("Call PUT request!");
|
||||||
|
this->executePut();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DELETE: {
|
||||||
|
debug::Log("Call DELETE request!");
|
||||||
|
this->executeDelete();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
debug::Log("Unhandled request type {}", (int)this->data.requestType);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void useCache()
|
||||||
|
{
|
||||||
|
if (this->data.useQuickLoadCache) {
|
||||||
|
auto app = getApp();
|
||||||
|
|
||||||
|
QFile cachedFile(app->paths->cacheFolderPath + "/" + this->data.getHash());
|
||||||
|
|
||||||
|
if (cachedFile.exists()) {
|
||||||
|
if (cachedFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray bytes = cachedFile.readAll();
|
||||||
|
|
||||||
|
// qDebug() << "Loaded cached resource" << this->data.request.url();
|
||||||
|
|
||||||
|
auto document = parseJSONFromData2(bytes);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
if (!document.IsNull()) {
|
||||||
|
success = this->data.onSuccess(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedFile.close();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
// The images were not successfully loaded from the file
|
||||||
|
// XXX: Invalidate the cache file so we don't attempt to load it again next
|
||||||
|
// time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doRequest()
|
||||||
|
{
|
||||||
|
QTimer *timer = nullptr;
|
||||||
|
if (this->data.timeoutMS > 0) {
|
||||||
|
timer = new QTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkRequester requester;
|
||||||
|
NetworkWorker *worker = new NetworkWorker;
|
||||||
|
|
||||||
|
worker->moveToThread(&NetworkManager::workerThread);
|
||||||
|
|
||||||
|
if (this->data.caller != nullptr) {
|
||||||
|
QObject::connect(worker, &NetworkWorker::doneUrl, this->data.caller,
|
||||||
|
[data = this->data](auto reply) mutable {
|
||||||
|
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
||||||
|
// TODO: We might want to call an onError callback here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray readBytes = reply->readAll();
|
||||||
|
QByteArray bytes;
|
||||||
|
bytes.setRawData(readBytes.data(), readBytes.size());
|
||||||
|
data.writeToCache(bytes);
|
||||||
|
data.onSuccess(parseJSONFromData2(bytes));
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer != nullptr) {
|
||||||
|
timer->start(this->data.timeoutMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(&requester, &NetworkRequester::requestUrl, worker,
|
||||||
|
[timer, data = std::move(this->data), worker]() {
|
||||||
|
QNetworkReply *reply;
|
||||||
|
switch (data.requestType) {
|
||||||
|
case GET: {
|
||||||
|
reply = NetworkManager::NaM.get(data.request);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PUT: {
|
||||||
|
reply = NetworkManager::NaM.put(data.request, data.payload);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DELETE: {
|
||||||
|
reply = NetworkManager::NaM.deleteResource(data.request);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply == nullptr) {
|
||||||
|
debug::Log("Unhandled request type {}", (int)data.requestType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer != nullptr) {
|
||||||
|
QObject::connect(timer, &QTimer::timeout, worker,
|
||||||
|
[reply, timer, data]() {
|
||||||
|
debug::Log("Aborted!");
|
||||||
|
reply->abort();
|
||||||
|
timer->deleteLater();
|
||||||
|
data.onError(-2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.onReplyCreated) {
|
||||||
|
data.onReplyCreated(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished, worker,
|
||||||
|
[data = std::move(data), worker, reply]() mutable {
|
||||||
|
if (data.caller == nullptr) {
|
||||||
|
QByteArray bytes = reply->readAll();
|
||||||
|
data.writeToCache(bytes);
|
||||||
|
data.onSuccess(parseJSONFromData2(bytes));
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
} else {
|
||||||
|
emit worker->doneUrl(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete worker;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
emit requester.requestUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeGet()
|
||||||
|
{
|
||||||
|
this->useCache();
|
||||||
|
|
||||||
|
this->doRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executePut()
|
||||||
|
{
|
||||||
|
this->doRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeDelete()
|
||||||
|
{
|
||||||
|
this->doRequest();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
|
@ -153,6 +153,10 @@ void SettingsDialog::refresh()
|
||||||
// this->ui.accountSwitchWidget->refresh();
|
// this->ui.accountSwitchWidget->refresh();
|
||||||
|
|
||||||
getApp()->settings->saveSnapshot();
|
getApp()->settings->saveSnapshot();
|
||||||
|
|
||||||
|
for (auto *tab : this->tabs) {
|
||||||
|
tab->getSettingsPage()->onShow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::scaleChangedEvent(float newDpi)
|
void SettingsDialog::scaleChangedEvent(float newDpi)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ignoreuserspage.hpp"
|
#include "ignoreuserspage.hpp"
|
||||||
|
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
#include "singletons/accountmanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "util/layoutcreator.hpp"
|
#include "util/layoutcreator.hpp"
|
||||||
|
|
||||||
|
@ -53,8 +54,7 @@ IgnoreUsersPage::IgnoreUsersPage()
|
||||||
addremove->addStretch(1);
|
addremove->addStretch(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto userList = users.emplace<QListView>();
|
users.emplace<QListView>()->setModel(&this->userListModel);
|
||||||
UNUSED(userList); // TODO: Fill this list in with ignored users
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
|
@ -68,6 +68,23 @@ IgnoreUsersPage::IgnoreUsersPage()
|
||||||
label->setStyleSheet("color: #BBB");
|
label->setStyleSheet("color: #BBB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IgnoreUsersPage::onShow()
|
||||||
|
{
|
||||||
|
auto app = getApp();
|
||||||
|
|
||||||
|
auto user = app->accounts->Twitch.getCurrent();
|
||||||
|
|
||||||
|
if (user->isAnon()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList users;
|
||||||
|
for (const auto &ignoredUser : user->getIgnores()) {
|
||||||
|
users << ignoredUser.name;
|
||||||
|
}
|
||||||
|
this->userListModel.setStringList(users);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace settingspages
|
} // namespace settingspages
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "widgets/settingspages/settingspage.hpp"
|
#include "widgets/settingspages/settingspage.hpp"
|
||||||
|
|
||||||
|
#include <QStringListModel>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
namespace settingspages {
|
namespace settingspages {
|
||||||
|
@ -10,6 +12,11 @@ class IgnoreUsersPage : public SettingsPage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IgnoreUsersPage();
|
IgnoreUsersPage();
|
||||||
|
|
||||||
|
void onShow() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringListModel userListModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace settingspages
|
} // namespace settingspages
|
||||||
|
|
|
@ -28,6 +28,10 @@ public:
|
||||||
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
|
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
|
||||||
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting, int min = 0, int max = 2500);
|
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting, int min = 0, int max = 2500);
|
||||||
|
|
||||||
|
virtual void onShow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString name;
|
QString name;
|
||||||
QString iconResource;
|
QString iconResource;
|
||||||
|
|
Loading…
Reference in a new issue