Skip to content

Commit

Permalink
UI: Enable first-party YouTube Chat features in OBS
Browse files Browse the repository at this point in the history
Unlock the full feature set of the YouTube Chat dock in OBS by removing
custom scripting/CSS logic. Enable the signed-in experience for live
streaming content creators (sharing login credentials with the YouTube
Control panel dock, see
#10747).

This will allow OBS users to utilize features _already_ supported in the
YouTube Chat plugin, such as

* creating polls
* managing Q&A sessions
* a rich emoji set in the input panel
* emoji fountains
* moderation tools

and many more. These features are available to users who are logged-in
to YouTube Chat and/or the YouTube Control panel.
  • Loading branch information
msuman-google committed Jun 26, 2024
1 parent 8892edd commit a36be2f
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 14 deletions.
50 changes: 38 additions & 12 deletions UI/auth-youtube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#ifdef BROWSER_AVAILABLE
#include "window-dock-browser.hpp"
#include <QTimerEvent>
#endif

using namespace json11;
Expand Down Expand Up @@ -130,14 +131,6 @@ bool YoutubeAuth::LoadInternal()
return implicit ? !token.empty() : !refresh_token.empty();
}

#ifdef BROWSER_AVAILABLE
static const char *ytchat_script = "\
const obsCSS = document.createElement('style');\
obsCSS.innerHTML = \"#panel-pages.yt-live-chat-renderer {display: none;}\
yt-live-chat-viewer-engagement-message-renderer {display: none;}\";\
document.querySelector('head').appendChild(obsCSS);";
#endif

void YoutubeAuth::LoadUI()
{
if (uiLoaded)
Expand All @@ -163,7 +156,6 @@ void YoutubeAuth::LoadUI()

browser = cef->create_widget(chat, YOUTUBE_CHAT_PLACEHOLDER_URL,
panel_cookies);
browser->setStartupScript(ytchat_script);

chat->SetWidget(browser);
main->AddDockWidget(chat, Qt::RightDockWidgetArea);
Expand Down Expand Up @@ -350,6 +342,36 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
}

#ifdef BROWSER_AVAILABLE
void YoutubeChatDock::timerEvent(QTimerEvent *event)
{
if (event->timerId() != awaitLoginTimer)
return;

QPointer<YoutubeChatDock> this_ = this;
auto cb = [this_](bool found) {
bool previouslyLoggedIn = this_->isLoggedIn;
this_->isLoggedIn = found;
if (found ^ previouslyLoggedIn) {
// There was a change in login state.
QMetaObject::invokeMethod(this_, "EnableChatInput",
Qt::QueuedConnection,
Q_ARG(bool, !found));
this_->cefWidget->reloadPage();
OBSBasic *main = OBSBasic::Get();
if (main->GetYouTubeAppDock() != nullptr) {
QMetaObject::invokeMethod(
main->GetYouTubeAppDock(),
"SettingsUpdated", Qt::QueuedConnection,
Q_ARG(bool, !found));
}
}
};
if (panel_cookies) {
panel_cookies->CheckForCookie("https://www.youtube.com", "SID",
cb);
}
}

YoutubeChatDock::YoutubeChatDock(const QString &title) : BrowserDock(title)
{
lineEdit = new LineEditAutoResize();
Expand All @@ -368,6 +390,9 @@ YoutubeChatDock::YoutubeChatDock(const QString &title) : BrowserDock(title)
&YoutubeChatDock::SendChatMessage);
QWidget::connect(sendButton, &QPushButton::pressed, this,
&YoutubeChatDock::SendChatMessage);

// Check youtube.com login status periodically
awaitLoginTimer = startTimer(1000);
}

void YoutubeChatDock::SetWidget(QCefWidget *widget_)
Expand Down Expand Up @@ -425,9 +450,10 @@ void YoutubeChatDock::ShowErrorMessage(const QString &error)
QTStr("YouTube.Chat.Error.Text").arg(error));
}

void YoutubeChatDock::EnableChatInput()
void YoutubeChatDock::EnableChatInput(bool visible)
{
lineEdit->setVisible(true);
sendButton->setVisible(true);
bool setVisible = visible && !isLoggedIn;
lineEdit->setVisible(setVisible);
sendButton->setVisible(setVisible);
}
#endif
9 changes: 8 additions & 1 deletion UI/auth-youtube.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@
#include "window-dock-browser.hpp"
#include "lineedit-autoresize.hpp"
#include <QHBoxLayout>
#include <QTimerEvent>

class YoutubeChatDock : public BrowserDock {
Q_OBJECT

private:
std::string apiChatId;
int awaitLoginTimer;
bool isLoggedIn;
LineEditAutoResize *lineEdit;
QPushButton *sendButton;
QHBoxLayout *chatLayout;

protected:
void timerEvent(QTimerEvent *event);

public:
YoutubeChatDock(const QString &title);
void SetWidget(QCefWidget *widget_);
Expand All @@ -28,7 +35,7 @@ class YoutubeChatDock : public BrowserDock {
private slots:
void SendChatMessage();
void ShowErrorMessage(const QString &error);
void EnableChatInput();
void EnableChatInput(bool visible = true);
};
#endif

Expand Down
4 changes: 3 additions & 1 deletion UI/window-dock-youtube-app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class YouTubeAppDock : public BrowserDock {

void AccountConnected();
void AccountDisconnected();
void SettingsUpdated(bool cleanup = false);
void Update();

void BroadcastCreated(const char *stream_id);
Expand All @@ -29,6 +28,9 @@ class YouTubeAppDock : public BrowserDock {
static YoutubeApiWrappers *GetYTApi();
static void CleanupYouTubeUrls();

public slots:
void SettingsUpdated(bool cleanup = false);

protected:
void IngestionStarted(const char *stream_id, streaming_mode_t mode);
void IngestionStopped(const char *stream_id, streaming_mode_t mode);
Expand Down

0 comments on commit a36be2f

Please sign in to comment.