mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
added follow and ignore functionality to the user popup
This commit is contained in:
parent
c308883a2a
commit
45cda9b7a5
5 changed files with 181 additions and 31 deletions
|
@ -34,7 +34,7 @@ namespace widgets {
|
|||
|
||||
BaseWindow::BaseWindow(QWidget *parent, Flags _flags)
|
||||
: BaseWidget(parent,
|
||||
Qt::Window | ((_flags & TopMost) ? Qt::WindowStaysOnTopHint : Qt::WindowFlags(0)))
|
||||
Qt::Window | ((_flags & TopMost) ? Qt::WindowStaysOnTopHint : Qt::WindowFlags()))
|
||||
, enableCustomFrame(_flags & EnableCustomFrame)
|
||||
, frameless(_flags & Frameless)
|
||||
, flags(_flags)
|
||||
|
@ -207,7 +207,7 @@ void BaseWindow::themeRefreshEvent()
|
|||
|
||||
bool BaseWindow::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::WindowDeactivate) {
|
||||
if (event->type() == QEvent::WindowDeactivate /*|| event->type() == QEvent::FocusOut*/) {
|
||||
if (this->flags & DeleteOnFocusOut) {
|
||||
this->close();
|
||||
}
|
||||
|
|
|
@ -1108,6 +1108,8 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const messages::Link &link
|
|||
auto *userPopup = new UserInfoPopup;
|
||||
userPopup->setData(user, this->channel);
|
||||
userPopup->setAttribute(Qt::WA_DeleteOnClose);
|
||||
userPopup->move(event->globalPos());
|
||||
userPopup->setFocus();
|
||||
userPopup->show();
|
||||
|
||||
// this->userPopupWidget.setName(user);
|
||||
|
@ -1118,15 +1120,19 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const messages::Link &link
|
|||
qDebug() << "Clicked " << user << "s message";
|
||||
break;
|
||||
}
|
||||
|
||||
case messages::Link::Url: {
|
||||
QDesktopServices::openUrl(QUrl(link.value));
|
||||
break;
|
||||
}
|
||||
|
||||
case messages::Link::UserAction: {
|
||||
QString value = link.value;
|
||||
value.replace("{user}", layout->getMessage()->loginName);
|
||||
this->channel->sendMessage(value);
|
||||
}
|
||||
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ void RippleEffectButton::paintEvent(QPaintEvent *)
|
|||
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
this->fancyPaint(painter);
|
||||
|
||||
if (!this->pixmap_.isNull()) {
|
||||
QRect rect = this->rect();
|
||||
int s = int(6 * this->getScale());
|
||||
|
@ -65,6 +63,8 @@ void RippleEffectButton::paintEvent(QPaintEvent *)
|
|||
painter.drawPixmap(rect, this->pixmap_);
|
||||
}
|
||||
|
||||
this->fancyPaint(painter);
|
||||
|
||||
if (this->borderColor_.isValid()) {
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
painter.setPen(this->borderColor_);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "userinfopopup.hpp"
|
||||
|
||||
#include "application.hpp"
|
||||
#include "providers/twitch/twitchchannel.hpp"
|
||||
#include "singletons/resourcemanager.hpp"
|
||||
#include "util/layoutcreator.hpp"
|
||||
#include "util/posttothread.hpp"
|
||||
|
@ -12,11 +13,16 @@
|
|||
#include <QDesktopServices>
|
||||
#include <QLabel>
|
||||
|
||||
#define TEXT_FOLLOWERS "Followers: "
|
||||
#define TEXT_VIEWS "Views: "
|
||||
#define TEXT_CREATED "Created: "
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
|
||||
UserInfoPopup::UserInfoPopup()
|
||||
: BaseWindow(nullptr, BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::DeleteOnFocusOut))
|
||||
, hack_(new bool)
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
|
@ -41,9 +47,9 @@ UserInfoPopup::UserInfoPopup()
|
|||
auto font = name->font();
|
||||
font.setBold(true);
|
||||
name->setFont(font);
|
||||
vbox.emplace<QLabel>("Loading...").assign(&this->ui_.viewCountLabel);
|
||||
vbox.emplace<QLabel>().assign(&this->ui_.followerCountLabel);
|
||||
vbox.emplace<QLabel>().assign(&this->ui_.createdDateLabel);
|
||||
vbox.emplace<QLabel>(TEXT_VIEWS).assign(&this->ui_.viewCountLabel);
|
||||
vbox.emplace<QLabel>(TEXT_FOLLOWERS).assign(&this->ui_.followerCountLabel);
|
||||
vbox.emplace<QLabel>(TEXT_CREATED).assign(&this->ui_.createdDateLabel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,12 +60,9 @@ UserInfoPopup::UserInfoPopup()
|
|||
{
|
||||
user->addStretch(1);
|
||||
|
||||
auto ignore = user.emplace<QCheckBox>("Ignore").assign(&this->ui_.ignore);
|
||||
// ignore->setEnabled(false);
|
||||
|
||||
auto ignoreHighlights =
|
||||
user.emplace<QCheckBox>("Ignore highlights").assign(&this->ui_.ignoreHighlights);
|
||||
// ignoreHighlights->setEnabled(false);
|
||||
user.emplace<QCheckBox>("Follow").assign(&this->ui_.follow);
|
||||
user.emplace<QCheckBox>("Ignore").assign(&this->ui_.ignore);
|
||||
user.emplace<QCheckBox>("Ignore highlights").assign(&this->ui_.ignoreHighlights);
|
||||
|
||||
auto mod = user.emplace<RippleEffectButton>(this);
|
||||
mod->setPixmap(app->resources->buttons.mod);
|
||||
|
@ -69,17 +72,106 @@ UserInfoPopup::UserInfoPopup()
|
|||
unmod->setScaleIndependantSize(30, 30);
|
||||
|
||||
user->addStretch(1);
|
||||
|
||||
// userstate
|
||||
this->userStateChanged.connect([this, mod, unmod]() mutable {
|
||||
providers::twitch::TwitchChannel *twitchChannel =
|
||||
dynamic_cast<providers::twitch::TwitchChannel *>(this->channel_.get());
|
||||
|
||||
if (twitchChannel) {
|
||||
qDebug() << this->userName_;
|
||||
|
||||
bool isMyself =
|
||||
QString::compare(getApp()->accounts->twitch.getCurrent()->getUserName(),
|
||||
this->userName_, Qt::CaseInsensitive) == 0;
|
||||
|
||||
mod->setVisible(twitchChannel->isBroadcaster() && !isMyself);
|
||||
unmod->setVisible((twitchChannel->isBroadcaster() && !isMyself) ||
|
||||
(twitchChannel->isMod() && isMyself));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
layout.emplace<Line>(false);
|
||||
auto lineMod = layout.emplace<Line>(false);
|
||||
|
||||
// third line
|
||||
auto moderation = layout.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
moderation.emplace<TimeoutWidget>();
|
||||
auto timeout = moderation.emplace<TimeoutWidget>();
|
||||
|
||||
this->userStateChanged.connect([this, lineMod, timeout]() mutable {
|
||||
providers::twitch::TwitchChannel *twitchChannel =
|
||||
dynamic_cast<providers::twitch::TwitchChannel *>(this->channel_.get());
|
||||
|
||||
if (twitchChannel) {
|
||||
lineMod->setVisible(twitchChannel->hasModRights());
|
||||
timeout->setVisible(twitchChannel->hasModRights());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this->setStyleSheet("font-size: 11pt;");
|
||||
|
||||
this->installEvents();
|
||||
}
|
||||
|
||||
void UserInfoPopup::installEvents()
|
||||
{
|
||||
std::weak_ptr<bool> hack = this->hack_;
|
||||
|
||||
// follow
|
||||
QObject::connect(this->ui_.follow, &QCheckBox::stateChanged, [this](int) mutable {
|
||||
auto currentUser = getApp()->accounts->twitch.getCurrent();
|
||||
|
||||
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + currentUser->getUserId() +
|
||||
"/follows/channels/" + this->userId_);
|
||||
|
||||
this->ui_.follow->setEnabled(false);
|
||||
if (this->ui_.follow->isChecked()) {
|
||||
util::twitch::put(requestUrl,
|
||||
[this](QJsonObject) { this->ui_.follow->setEnabled(true); });
|
||||
} else {
|
||||
util::twitch::sendDelete(requestUrl, [this] { this->ui_.follow->setEnabled(true); });
|
||||
}
|
||||
});
|
||||
|
||||
std::shared_ptr<bool> ignoreNext = std::make_shared<bool>(false);
|
||||
|
||||
// ignore
|
||||
QObject::connect(
|
||||
this->ui_.ignore, &QCheckBox::stateChanged, [this, ignoreNext, hack](int) mutable {
|
||||
if (*ignoreNext) {
|
||||
*ignoreNext = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this->ui_.ignore->setEnabled(false);
|
||||
|
||||
auto currentUser = getApp()->accounts->twitch.getCurrent();
|
||||
if (this->ui_.ignore->isChecked()) {
|
||||
currentUser->ignoreByID(this->userId_, this->userName_,
|
||||
[=](auto result, const auto &message) mutable {
|
||||
if (hack.lock()) {
|
||||
if (result == IgnoreResult_Failed) {
|
||||
*ignoreNext = true;
|
||||
this->ui_.ignore->setChecked(false);
|
||||
}
|
||||
this->ui_.ignore->setEnabled(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
currentUser->unignoreByID(this->userId_, this->userName_,
|
||||
[=](auto result, const auto &message) mutable {
|
||||
if (hack.lock()) {
|
||||
if (result == UnignoreResult_Failed) {
|
||||
*ignoreNext = true;
|
||||
this->ui_.ignore->setChecked(true);
|
||||
}
|
||||
this->ui_.ignore->setEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UserInfoPopup::setData(const QString &name, const ChannelPtr &channel)
|
||||
|
@ -90,21 +182,59 @@ void UserInfoPopup::setData(const QString &name, const ChannelPtr &channel)
|
|||
this->ui_.nameLabel->setText(name);
|
||||
|
||||
this->updateUserData();
|
||||
|
||||
this->userStateChanged.invoke();
|
||||
}
|
||||
|
||||
void UserInfoPopup::updateUserData()
|
||||
{
|
||||
util::twitch::get("https://api.twitch.tv/kraken/channels/" + this->userName_, this,
|
||||
[=](const QJsonObject &obj) {
|
||||
this->ui_.followerCountLabel->setText(
|
||||
"Followers: " + QString::number(obj.value("followers").toInt()));
|
||||
this->ui_.viewCountLabel->setText(
|
||||
"Views: " + QString::number(obj.value("views").toInt()));
|
||||
this->ui_.createdDateLabel->setText(
|
||||
"Created: " + obj.value("created_at").toString().section("T", 0, 0));
|
||||
std::weak_ptr<bool> hack = this->hack_;
|
||||
|
||||
this->loadAvatar(QUrl(obj.value("logo").toString()));
|
||||
});
|
||||
// get user info
|
||||
util::twitch::getUserID(this->userName_, this, [this, hack](QString id) {
|
||||
auto currentUser = getApp()->accounts->twitch.getCurrent();
|
||||
|
||||
this->userId_ = id;
|
||||
|
||||
// get channel info
|
||||
util::twitch::get(
|
||||
"https://api.twitch.tv/kraken/channels/" + id, this, [this](const QJsonObject &obj) {
|
||||
this->ui_.followerCountLabel->setText(
|
||||
TEXT_FOLLOWERS + QString::number(obj.value("followers").toInt()));
|
||||
this->ui_.viewCountLabel->setText(TEXT_VIEWS +
|
||||
QString::number(obj.value("views").toInt()));
|
||||
this->ui_.createdDateLabel->setText(
|
||||
TEXT_CREATED + obj.value("created_at").toString().section("T", 0, 0));
|
||||
|
||||
this->loadAvatar(QUrl(obj.value("logo").toString()));
|
||||
});
|
||||
|
||||
// get follow state
|
||||
currentUser->checkFollow(id, [this, hack](auto result) {
|
||||
if (hack.lock()) {
|
||||
if (result != FollowResult_Failed) {
|
||||
this->ui_.follow->setEnabled(true);
|
||||
this->ui_.follow->setChecked(result == FollowResult_Following);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// get ignore state
|
||||
bool isIgnoring = false;
|
||||
for (const auto &ignoredUser : currentUser->getIgnores()) {
|
||||
if (id == ignoredUser.id) {
|
||||
isIgnoring = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->ui_.ignore->setEnabled(true);
|
||||
this->ui_.ignore->setChecked(isIgnoring);
|
||||
});
|
||||
|
||||
this->ui_.follow->setEnabled(false);
|
||||
this->ui_.ignore->setEnabled(false);
|
||||
this->ui_.ignoreHighlights->setEnabled(false);
|
||||
}
|
||||
|
||||
void UserInfoPopup::loadAvatar(const QUrl &url)
|
||||
|
@ -150,7 +280,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("unban");
|
||||
auto label = title.emplace<QLabel>("unban");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
@ -169,7 +300,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("sec");
|
||||
auto label = title.emplace<QLabel>("sec");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
@ -188,7 +320,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("min");
|
||||
auto label = title.emplace<QLabel>("min");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
@ -219,7 +352,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("hour");
|
||||
auto label = title.emplace<QLabel>("hour");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
@ -244,7 +378,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("week");
|
||||
auto label = title.emplace<QLabel>("week");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
@ -269,7 +404,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||
{
|
||||
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
title->addStretch(1);
|
||||
title.emplace<QLabel>("ban");
|
||||
auto label = title.emplace<QLabel>("ban");
|
||||
label->setStyleSheet("color: #BBB");
|
||||
title->addStretch(1);
|
||||
|
||||
auto hbox = vbox.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace widgets {
|
|||
|
||||
class UserInfoPopup final : public BaseWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UserInfoPopup();
|
||||
|
||||
|
@ -23,13 +25,18 @@ private:
|
|||
bool isBroadcaster_;
|
||||
|
||||
QString userName_;
|
||||
QString userId_;
|
||||
ChannelPtr channel_;
|
||||
|
||||
pajlada::Signals::NoArgSignal userStateChanged;
|
||||
|
||||
void installEvents();
|
||||
|
||||
void updateUserData();
|
||||
void loadAvatar(const QUrl &url);
|
||||
|
||||
std::shared_ptr<bool> hack_;
|
||||
|
||||
struct {
|
||||
RippleEffectButton *avatarButton = nullptr;
|
||||
|
||||
|
@ -38,6 +45,7 @@ private:
|
|||
QLabel *followerCountLabel = nullptr;
|
||||
QLabel *createdDateLabel = nullptr;
|
||||
|
||||
QCheckBox *follow = nullptr;
|
||||
QCheckBox *ignore = nullptr;
|
||||
QCheckBox *ignoreHighlights = nullptr;
|
||||
} ui_;
|
||||
|
|
Loading…
Reference in a new issue