Skip to content

Commit

Permalink
Mostly implement community posts
Browse files Browse the repository at this point in the history
Liking, disliking, and the reply view are not implemented. They also
don't show in the Subscriptions tab yet, though I don't know if I will
ever add that because I don't really care to.
  • Loading branch information
BowDown097 committed Dec 12, 2023
1 parent 534ab9c commit 7d2c18b
Show file tree
Hide file tree
Showing 16 changed files with 555 additions and 11 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ set(SOURCE_FILES
src/ui/widgets/labels/elidedtubelabel.cpp
src/ui/widgets/labels/iconlabel.cpp
src/ui/widgets/labels/tubelabel.cpp
src/ui/widgets/renderers/backstage/backstagepollchoicerenderer.cpp
src/ui/widgets/renderers/backstage/backstagepollrenderer.cpp
src/ui/widgets/renderers/backstage/backstagepostrenderer.cpp
src/ui/widgets/renderers/browsechannelrenderer.cpp
src/ui/widgets/renderers/browsenotificationrenderer.cpp
src/ui/widgets/renderers/video/browsevideorenderer.cpp
Expand Down Expand Up @@ -192,6 +195,9 @@ set(HEADERS
src/ui/widgets/labels/elidedtubelabel.h
src/ui/widgets/labels/iconlabel.h
src/ui/widgets/labels/tubelabel.h
src/ui/widgets/renderers/backstage/backstagepollchoicerenderer.h
src/ui/widgets/renderers/backstage/backstagepollrenderer.h
src/ui/widgets/renderers/backstage/backstagepostrenderer.h
src/ui/widgets/renderers/browsechannelrenderer.h
src/ui/widgets/renderers/browsenotificationrenderer.h
src/ui/widgets/renderers/video/browsevideorenderer.h
Expand Down
15 changes: 15 additions & 0 deletions src/stores/settingsstore.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "settingsstore.h"
#include "innertube/objects/video/reel.h"
#include "innertube/objects/video/video.h"
#include <QSettings>

bool SettingsStore::channelIsFiltered(const QString& channelId) const
Expand Down Expand Up @@ -106,6 +108,19 @@ bool SettingsStore::strHasFilteredTerm(const QString& str) const
return std::ranges::any_of(filteredTerms, [&str](const QString& t) { return str.contains(t, Qt::CaseInsensitive); });
}

bool SettingsStore::videoIsFiltered(const InnertubeObjects::Reel& reel) const
{
return channelIsFiltered(reel.owner.id) || strHasFilteredTerm(reel.headline);
}

bool SettingsStore::videoIsFiltered(const InnertubeObjects::Video& video) const
{
return channelIsFiltered(video.owner.id) || strHasFilteredTerm(video.title.text) ||
(filterLengthEnabled && !video.isLive && QTime(0, 0).secsTo(video.length()) <= filterLength) ||
(hideShorts && video.isReel()) ||
(hideStreams && video.isLive);
}

void SettingsStore::writeStringList(QSettings& settings, const QStringList& list, const QString& prefix, const QString& key)
{
settings.beginWriteArray(prefix);
Expand Down
4 changes: 4 additions & 0 deletions src/stores/settingsstore.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "genericstore.h"
#include <QObject>

namespace InnertubeObjects { class Reel; class Video; }

class QSettings;

class SettingsStore : public GenericStore
Expand Down Expand Up @@ -55,6 +57,8 @@ class SettingsStore : public GenericStore

bool channelIsFiltered(const QString& channelId) const;
bool strHasFilteredTerm(const QString& str) const;
bool videoIsFiltered(const InnertubeObjects::Reel& reel) const;
bool videoIsFiltered(const InnertubeObjects::Video& video) const;

void initialize() override;
void save() override;
Expand Down
2 changes: 2 additions & 0 deletions src/ui/browsehelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ void BrowseHelper::browseChannel(QListWidget* widget, int index, const Innertube
ChannelBrowser::setupLive(widget, tabRenderer, resp);
else if (title == "Membership")
ChannelBrowser::setupMembership(widget, tabRenderer);
else if (title == "Community")
ChannelBrowser::setupCommunity(widget, tabRenderer);
else if (title == "Channels")
ChannelBrowser::setupChannels(widget, tabRenderer);
else if (title == "About")
Expand Down
15 changes: 15 additions & 0 deletions src/ui/channelbrowser.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "channelbrowser.h"
#include "innertube/innertubeexception.h"
#include "innertube/objects/backstage/backstagepost.h"
#include "innertube/objects/channel/aboutfullmetadata.h"
#include "innertube/objects/channel/channel.h"
#include "innertube/objects/video/reel.h"
Expand Down Expand Up @@ -105,6 +106,20 @@ void ChannelBrowser::setupChannels(QListWidget* widget, const QJsonValue& render
widget->addItem("This channel doesn't feature any other channels.");
}

void ChannelBrowser::setupCommunity(QListWidget* widget, const QJsonValue& renderer)
{
const QJsonArray contents = renderer["content"]["sectionListRenderer"]["contents"][0]
["itemSectionRenderer"]["contents"].toArray();
for (const QJsonValue& v : contents)
{
InnertubeObjects::BackstagePost post(v["backstagePostThreadRenderer"]["post"]["backstagePostRenderer"]);
UIUtils::addBackstagePostToList(widget, post);
}

if (widget->count() == 0)
widget->addItem("This channel hasn't posted yet.");
}

void ChannelBrowser::setupHome(QListWidget* widget, const QJsonValue& renderer,
const InnertubeEndpoints::ChannelResponse& resp)
{
Expand Down
1 change: 1 addition & 0 deletions src/ui/channelbrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ChannelBrowser
public:
static void setupAbout(QListWidget* widget, const QJsonValue& renderer);
static void setupChannels(QListWidget* widget, const QJsonValue& renderer);
static void setupCommunity(QListWidget* widget, const QJsonValue& renderer);
static void setupHome(QListWidget* widget, const QJsonValue& renderer, const InnertubeEndpoints::ChannelResponse& resp);
static void setupLive(QListWidget* widget, const QJsonValue& renderer, const InnertubeEndpoints::ChannelResponse& resp);
static void setupMembership(QListWidget* widget, const QJsonValue& renderer);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/views/watchview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void WatchView::processNext(const InnertubeEndpoints::Next& endpoint)

ui->description->setText(generateFormattedDescription(unattributeDescription(nextResp.secondaryInfo.attributedDescription)));
ui->description->setVisible(!ui->description->text().isEmpty());
ui->showMoreLabel->setVisible(ui->description->heightForWidth(ui->description->width()) > ui->description->maximumWidth());
ui->showMoreLabel->setVisible(ui->description->heightForWidth(ui->description->width()) > ui->description->maximumHeight());
}

void WatchView::processPlayer(const InnertubeEndpoints::Player& endpoint)
Expand Down
79 changes: 79 additions & 0 deletions src/ui/widgets/renderers/backstage/backstagepollchoicerenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "backstagepollchoicerenderer.h"
#include "innertube.h"
#include <QBoxLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QProgressBar>

constexpr const char* notSelectedStylesheet = "QProgressBar::chunk { background-color: rgba(255, 255, 255, 0.2) }";

BackstagePollChoiceRenderer::BackstagePollChoiceRenderer(QWidget* parent)
: m_choiceTextLabel(new QLabel(this)),
m_percentageLabel(new QLabel(this)),
m_progressBar(new QProgressBar(this))
{
m_choiceTextLabel->setMaximumWidth(width() - 100);

m_progressBar->setFixedWidth(width());
m_progressBar->setMaximum(100);
m_progressBar->setTextVisible(false);

m_innerLayout = new QHBoxLayout(m_progressBar);
m_innerLayout->addWidget(m_choiceTextLabel, 0, Qt::AlignLeft);
m_innerLayout->addWidget(m_percentageLabel, 0, Qt::AlignRight);
m_innerLayout->setContentsMargins(5, 0, 20, 0);
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void BackstagePollChoiceRenderer::enterEvent(QEnterEvent*)
#else
void BackstagePollChoiceRenderer::enterEvent(QEvent*)
#endif
{
setCursor(QCursor(Qt::PointingHandCursor));
}

bool BackstagePollChoiceRenderer::hasStyle() const
{
return !m_progressBar->styleSheet().isEmpty();
}

void BackstagePollChoiceRenderer::leaveEvent(QEvent*)
{
setCursor(QCursor());
}

void BackstagePollChoiceRenderer::mousePressEvent(QMouseEvent* event)
{
if (event->button() != Qt::LeftButton)
return;

QJsonValue endpoint = hasStyle() || value() == -1 ? m_data.selectServiceEndpoint : m_data.deselectServiceEndpoint;
emit clicked();
InnerTube::instance()->get<InnertubeEndpoints::PerformCommentAction>(endpoint["performCommentActionEndpoint"]["action"].toString());
}

void BackstagePollChoiceRenderer::reset()
{
m_progressBar->reset();
m_progressBar->setStyleSheet(QString());
m_percentageLabel->clear();
}

void BackstagePollChoiceRenderer::setData(const InnertubeObjects::PollChoice& pollChoice)
{
m_data = pollChoice;
m_choiceTextLabel->setText(pollChoice.text.text);
}

void BackstagePollChoiceRenderer::setValue(double value, bool selected)
{
m_percentageLabel->setText(selected ? m_data.votePercentageIfSelected : m_data.votePercentageIfNotSelected);
m_progressBar->setStyleSheet(selected ? QString() : notSelectedStylesheet);
m_progressBar->setValue(value);
}

int BackstagePollChoiceRenderer::value() const
{
return m_progressBar->value();
}
42 changes: 42 additions & 0 deletions src/ui/widgets/renderers/backstage/backstagepollchoicerenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef BACKSTAGEPOLLCHOICERENDERER_H
#define BACKSTAGEPOLLCHOICERENDERER_H
#include "innertube/objects/backstage/poll/pollchoice.h"
#include <QWidget>

class QHBoxLayout;
class QLabel;
class QProgressBar;

class BackstagePollChoiceRenderer : public QWidget
{
Q_OBJECT
public:
explicit BackstagePollChoiceRenderer(QWidget* parent = nullptr);
bool hasStyle() const;
void reset();
void setData(const InnertubeObjects::PollChoice& pollChoice);

void setValue(double value, bool selected);
int value() const;

double voteRatioIfNotSelected() const { return m_data.voteRatioIfNotSelected; }
double voteRatioIfSelected() const { return m_data.voteRatioIfSelected; }
protected:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void enterEvent(QEnterEvent*) override;
#else
void enterEvent(QEvent*) override;
#endif
void leaveEvent(QEvent*) override;
void mousePressEvent(QMouseEvent* event) override;
private:
QLabel* m_choiceTextLabel;
InnertubeObjects::PollChoice m_data;
QHBoxLayout* m_innerLayout;
QLabel* m_percentageLabel;
QProgressBar* m_progressBar;
signals:
void clicked();
};

#endif // BACKSTAGEPOLLCHOICERENDERER_H
80 changes: 80 additions & 0 deletions src/ui/widgets/renderers/backstage/backstagepollrenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "backstagepollrenderer.h"
#include "backstagepollchoicerenderer.h"
#include "innertube/objects/backstage/poll/poll.h"
#include <QApplication>
#include <QBoxLayout>
#include <QLabel>
#include <QProgressBar>

BackstagePollRenderer::BackstagePollRenderer(QWidget* parent)
: layout(new QVBoxLayout(this)),
voteCount(new QLabel(this))
{
voteCount->setFont(QFont(qApp->font().toString(), qApp->font().pointSize() - 1));
layout->addWidget(voteCount);
}

QList<BackstagePollChoiceRenderer*> BackstagePollRenderer::choiceRenderers() const
{
QList<BackstagePollChoiceRenderer*> list;
list.reserve(layout->count());

for (int i = 0; i < layout->count(); ++i)
if (auto choice = qobject_cast<BackstagePollChoiceRenderer*>(layout->itemAt(i)->widget()))
list.append(choice);

return list;
}

void BackstagePollRenderer::pollChoiceClicked()
{
BackstagePollChoiceRenderer* senderChoice = qobject_cast<BackstagePollChoiceRenderer*>(sender());
if (senderChoice->hasStyle())
{
for (BackstagePollChoiceRenderer* pollChoiceRenderer : choiceRenderers())
{
if (!pollChoiceRenderer->hasStyle())
{
pollChoiceRenderer->setValue(pollChoiceRenderer->voteRatioIfNotSelected() * 100, false);
}
}
}
else if (senderChoice->value() != -1)
{
for (BackstagePollChoiceRenderer* pollChoiceRenderer : choiceRenderers())
{
pollChoiceRenderer->reset();
}
return;
}
else
{
for (BackstagePollChoiceRenderer* pollChoiceRenderer : choiceRenderers())
{
pollChoiceRenderer->setValue(pollChoiceRenderer->voteRatioIfNotSelected() * 100, false);
}
}

senderChoice->setValue(senderChoice->voteRatioIfSelected() * 100, true);
}

void BackstagePollRenderer::setData(const InnertubeObjects::Poll& poll)
{
voteCount->setText(poll.totalVotes);
bool hasSelected = std::ranges::any_of(poll.choices, [](const InnertubeObjects::PollChoice& choice) {
return choice.selected;
});

for (const InnertubeObjects::PollChoice& pollChoice : poll.choices)
{
BackstagePollChoiceRenderer* pollChoiceRenderer = new BackstagePollChoiceRenderer(this);
pollChoiceRenderer->setData(pollChoice);
pollChoiceRenderer->setFixedHeight(36);

if (hasSelected)
pollChoiceRenderer->setValue(pollChoice.voteRatio * 100, pollChoice.selected);

layout->addWidget(pollChoiceRenderer);
connect(pollChoiceRenderer, &BackstagePollChoiceRenderer::clicked, this, &BackstagePollRenderer::pollChoiceClicked);
}
}
25 changes: 25 additions & 0 deletions src/ui/widgets/renderers/backstage/backstagepollrenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef BACKSTAGEPOLLRENDERER_H
#define BACKSTAGEPOLLRENDERER_H
#include <QWidget>

class BackstagePollChoiceRenderer;
class QLabel;
class QVBoxLayout;

namespace InnertubeObjects { class Poll; }

class BackstagePollRenderer : public QWidget
{
Q_OBJECT
public:
explicit BackstagePollRenderer(QWidget* parent = nullptr);
QList<BackstagePollChoiceRenderer*> choiceRenderers() const;
void setData(const InnertubeObjects::Poll& poll);
private:
QVBoxLayout* layout;
QLabel* voteCount;
private slots:
void pollChoiceClicked();
};

#endif // BACKSTAGEPOLLRENDERER_H
Loading

0 comments on commit 7d2c18b

Please sign in to comment.