Added recent messages to UserInfoPopup (#1729)

There's a Refresh button added to the popup to refresh the users messages in the popup. Not automatic now while we figure out how fast/slow it would be.

Co-authored-by: dnsge <sagedanielr@gmail.com>
This commit is contained in:
0xRainy 2020-06-21 05:15:14 -07:00 committed by GitHub
parent c5f6fd7568
commit 0e564065ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 117 additions and 8 deletions

View file

@ -59,6 +59,11 @@ bool Channel::isEmpty() const
return this->name_.isEmpty();
}
bool Channel::hasMessages() const
{
return !this->messages_.empty();
}
LimitedQueueSnapshot<MessagePtr> Channel::getMessageSnapshot()
{
return this->messages_.getSnapshot();

View file

@ -75,6 +75,8 @@ public:
void deleteMessage(QString messageID);
void clearMessages();
bool hasMessages() const;
QStringList modList;
// CHANNEL INFO

View file

@ -223,8 +223,13 @@ public:
this->firstChunkOffset_, this->lastChunkEnd_);
}
bool empty() const
{
return this->limit_ - this->space() == 0;
}
private:
qsizetype space()
qsizetype space() const
{
size_t totalSize = 0;
for (auto &chunk : *this->chunks_)

View file

@ -5,6 +5,7 @@
#include "common/NetworkRequest.hpp"
#include "controllers/accounts/AccountController.hpp"
#include "controllers/highlights/HighlightBlacklistUser.hpp"
#include "messages/Message.hpp"
#include "providers/twitch/TwitchChannel.hpp"
#include "providers/twitch/api/Helix.hpp"
#include "providers/twitch/api/Kraken.hpp"
@ -14,6 +15,7 @@
#include "util/PostToThread.hpp"
#include "util/Shortcut.hpp"
#include "widgets/Label.hpp"
#include "widgets/helper/ChannelView.hpp"
#include "widgets/helper/EffectLabel.hpp"
#include "widgets/helper/Line.hpp"
@ -26,6 +28,7 @@
const QString TEXT_VIEWS("Views: %1");
const QString TEXT_FOLLOWERS("Followers: %1");
const QString TEXT_CREATED("Created: %1");
const QString TEXT_TITLE("%1's Usercard");
#define TEXT_USER_ID "ID: "
#define TEXT_UNAVAILABLE "(not available)"
@ -49,16 +52,48 @@ namespace {
return label.getElement();
};
ChannelPtr filterMessages(const QString &userName, ChannelPtr channel)
{
LimitedQueueSnapshot<MessagePtr> snapshot =
channel->getMessageSnapshot();
ChannelPtr channelPtr(
new Channel(channel->getName(), Channel::Type::None));
for (size_t i = 0; i < snapshot.size(); i++)
{
MessagePtr message = snapshot[i];
bool isSubscription =
message->flags.has(MessageFlag::Subscription) &&
message->loginName == "" &&
message->messageText.split(" ").at(0).compare(
userName, Qt::CaseInsensitive) == 0;
bool isModAction = message->timeoutUser.compare(
userName, Qt::CaseInsensitive) == 0;
bool isSelectedUser =
message->loginName.compare(userName, Qt::CaseInsensitive) == 0;
if ((isSubscription || isModAction || isSelectedUser) &&
!message->flags.has(MessageFlag::Whisper))
{
channelPtr->addMessage(message);
}
}
return channelPtr;
};
} // namespace
UserInfoPopup::UserInfoPopup()
: BaseWindow({BaseWindow::Frameless, BaseWindow::FramelessDraggable})
: BaseWindow(BaseWindow::EnableCustomFrame)
, hack_(new bool)
{
this->setWindowTitle("Usercard");
this->setStayInScreenRect(true);
#ifdef Q_OS_LINUX
this->setWindowFlag(Qt::Popup);
this->setWindowFlag(Qt::Dialog);
#endif
// Close the popup when Escape is pressed
@ -118,7 +153,8 @@ UserInfoPopup::UserInfoPopup()
.assign(&this->ui_.ignoreHighlights);
auto usercard = user.emplace<EffectLabel2>(this);
usercard->getLabel().setText("Usercard");
auto refresh = user.emplace<EffectLabel2>(this);
refresh->getLabel().setText("Refresh");
auto mod = user.emplace<Button>(this);
mod->setPixmap(getResources().buttons.mod);
mod->setScaleIndependantSize(30, 30);
@ -134,6 +170,8 @@ UserInfoPopup::UserInfoPopup()
"/viewercard/" + this->userName_);
});
QObject::connect(refresh.getElement(), &Button::leftClicked,
[this] { this->updateLatestMessages(); });
QObject::connect(mod.getElement(), &Button::leftClicked, [this] {
this->channel_->sendMessage("/mod " + this->userName_);
});
@ -215,8 +253,25 @@ UserInfoPopup::UserInfoPopup()
});
}
this->installEvents();
layout.emplace<Line>(false);
// fourth line (last messages)
auto logs = layout.emplace<QVBoxLayout>().withoutMargin();
{
this->ui_.noMessagesLabel = new Label("No recent messages");
this->ui_.noMessagesLabel->setVisible(false);
this->ui_.latestMessages = new ChannelView(this);
this->ui_.latestMessages->setMinimumSize(400, 275);
this->ui_.latestMessages->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
logs->addWidget(this->ui_.noMessagesLabel);
logs->addWidget(this->ui_.latestMessages);
logs->setAlignment(this->ui_.noMessagesLabel, Qt::AlignHCenter);
}
this->installEvents();
this->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Policy::Ignored);
}
@ -358,6 +413,7 @@ void UserInfoPopup::setData(const QString &name, const ChannelPtr &channel)
{
this->userName_ = name;
this->channel_ = channel;
this->setWindowTitle(TEXT_TITLE.arg(name));
this->ui_.nameLabel->setText(name);
this->ui_.nameLabel->setProperty("copy-text", name);
@ -365,6 +421,20 @@ void UserInfoPopup::setData(const QString &name, const ChannelPtr &channel)
this->updateUserData();
this->userStateChanged_.invoke();
this->updateLatestMessages();
QTimer::singleShot(1, this, [this] { this->setStayInScreenRect(true); });
}
void UserInfoPopup::updateLatestMessages()
{
auto filteredChannel = filterMessages(this->userName_, this->channel_);
this->ui_.latestMessages->setChannel(filteredChannel);
this->ui_.latestMessages->setSourceChannel(this->channel_);
const bool hasMessages = filteredChannel->hasMessages();
this->ui_.latestMessages->setVisible(hasMessages);
this->ui_.noMessagesLabel->setVisible(!hasMessages);
}
void UserInfoPopup::updateUserData()

View file

@ -1,6 +1,7 @@
#pragma once
#include "widgets/BaseWindow.hpp"
#include "widgets/helper/ChannelView.hpp"
#include <pajlada/signals/signal.hpp>
@ -28,6 +29,7 @@ protected:
private:
void installEvents();
void updateUserData();
void updateLatestMessages();
void loadAvatar(const QUrl &url);
bool isMod_;
@ -53,6 +55,10 @@ private:
QCheckBox *follow = nullptr;
QCheckBox *ignore = nullptr;
QCheckBox *ignoreHighlights = nullptr;
Label *noMessagesLabel = nullptr;
ChannelView *latestMessages = nullptr;
QPushButton *refreshButton = nullptr;
} ui_;
class TimeoutWidget : public BaseWidget

View file

@ -109,6 +109,7 @@ namespace {
ChannelView::ChannelView(BaseWidget *parent)
: BaseWidget(parent)
, sourceChannel_(nullptr)
, scrollBar_(new Scrollbar(this))
{
this->setMouseTracking(true);
@ -621,6 +622,21 @@ void ChannelView::setChannel(ChannelPtr channel)
}
}
ChannelPtr ChannelView::sourceChannel() const
{
return this->sourceChannel_;
}
void ChannelView::setSourceChannel(ChannelPtr sourceChannel)
{
this->sourceChannel_ = sourceChannel;
}
bool ChannelView::hasSourceChannel() const
{
return this->sourceChannel_ != nullptr;
}
void ChannelView::messageAppended(MessagePtr &message,
boost::optional<MessageFlags> overridingFlags)
{
@ -1791,8 +1807,8 @@ void ChannelView::hideEvent(QHideEvent *)
void ChannelView::showUserInfoPopup(const QString &userName)
{
auto *userPopup = new UserInfoPopup;
userPopup->setData(userName, this->channel_);
userPopup->setActionOnFocusLoss(BaseWindow::Delete);
userPopup->setData(userName, this->hasSourceChannel() ? this->sourceChannel_
: this->channel_);
QPoint offset(int(150 * this->scale()), int(70 * this->scale()));
userPopup->move(QCursor::pos() - offset);
userPopup->show();

View file

@ -76,6 +76,10 @@ public:
ChannelPtr channel();
void setChannel(ChannelPtr channel_);
ChannelPtr sourceChannel() const;
void setSourceChannel(ChannelPtr sourceChannel);
bool hasSourceChannel() const;
LimitedQueueSnapshot<MessageLayoutPtr> getMessagesSnapshot();
void queueLayout();
@ -174,6 +178,7 @@ private:
LimitedQueueSnapshot<MessageLayoutPtr> snapshot_;
ChannelPtr channel_;
ChannelPtr sourceChannel_;
Scrollbar *scrollBar_;
EffectLabel *goToBottom_;