UI: Add auth. support to settings/autoconfig

Adds the ability to connect/login to an account via the settings and
auto-configuration dialogs.  Checks registered Auth objects, and if the
Auth object matches the currently selected service in the settings
window or auto-configuration dialog, will display "connect account"
buttons for the user to be able to click (which are optional, they can
still use stream keys if they'd prefer).
This commit is contained in:
jp9000
2019-02-06 22:37:36 -08:00
parent ccc64df371
commit 67bb8d7028
8 changed files with 593 additions and 6 deletions

View File

@@ -141,6 +141,11 @@ Basic.AutoConfig.VideoPage.FPS.PreferHighRes="Either 60 or 30, but prefer high r
Basic.AutoConfig.VideoPage.CanvasExplanation="Note: The canvas (base) resolution is not necessarily the same as the resolution you will stream or record with. Your actual stream/recording resolution may be scaled down from the canvas resolution to reduce resource usage or bitrate requirements."
Basic.AutoConfig.StreamPage="Stream Information"
Basic.AutoConfig.StreamPage.SubTitle="Please enter your stream information"
Basic.AutoConfig.StreamPage.ConnectAccount="Connect Account (optional)"
Basic.AutoConfig.StreamPage.DisconnectAccount="Disconnect Account"
Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title="Disconnect Account?"
Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text="This change will apply immediately. Are you sure you want to disconnect your account?"
Basic.AutoConfig.StreamPage.UseStreamKey="Use Stream Key"
Basic.AutoConfig.StreamPage.Service="Service"
Basic.AutoConfig.StreamPage.Service.ShowAll="Show All..."
Basic.AutoConfig.StreamPage.Service.Custom="Custom..."

View File

@@ -79,8 +79,98 @@
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="loginPage">
<layout class="QFormLayout" name="loginPageLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>87</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="connectAccount">
<property name="text">
<string>Basic.AutoConfig.StreamPage.ConnectAccount</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>87</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="useStreamKey">
<property name="text">
<string>Basic.AutoConfig.StreamPage.UseStreamKey</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="streamkeyPage">
<layout class="QFormLayout" name="streamkeyPageLayout">
<property name="fieldGrowthPolicy">
@@ -294,6 +384,20 @@
</layout>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="connectAccount2">
<property name="text">
<string>Basic.AutoConfig.StreamPage.ConnectAccount</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="disconnectAccount">
<property name="text">
<string>Basic.AutoConfig.StreamPage.DisconnectAccount</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
@@ -301,5 +405,22 @@
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>connectAccount2</sender>
<signal>clicked()</signal>
<receiver>connectAccount</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>382</x>
<y>279</y>
</hint>
<hint type="destinationlabel">
<x>114</x>
<y>82</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -742,8 +742,92 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="loginPage">
<layout class="QFormLayout" name="loginPageLayout">
<item row="0" column="0">
<spacer name="horizontalSpacer_20">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>170</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QPushButton" name="connectAccount">
<property name="text">
<string>Basic.AutoConfig.StreamPage.ConnectAccount</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_21">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_22">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>170</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QPushButton" name="useStreamKey">
<property name="text">
<string>Basic.AutoConfig.StreamPage.UseStreamKey</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_23">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="streamKeyPage">
<layout class="QFormLayout" name="streamkeyPageLayout">
<property name="fieldGrowthPolicy">
@@ -868,6 +952,54 @@
</property>
</spacer>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QPushButton" name="connectAccount2">
<property name="text">
<string>Basic.AutoConfig.StreamPage.ConnectAccount</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_19">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_23">
<item>
<widget class="QPushButton" name="disconnectAccount">
<property name="text">
<string>Basic.AutoConfig.StreamPage.DisconnectAccount</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_24">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
@@ -898,8 +1030,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>818</width>
<height>697</height>
<width>601</width>
<height>640</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
@@ -5428,5 +5560,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>connectAccount2</sender>
<signal>clicked()</signal>
<receiver>connectAccount</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>484</x>
<y>142</y>
</hint>
<hint type="destinationlabel">
<x>454</x>
<y>87</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -12,6 +12,17 @@
#include "ui_AutoConfigVideoPage.h"
#include "ui_AutoConfigStreamPage.h"
#ifdef BROWSER_AVAILABLE
#include <browser-panel.hpp>
#include "auth-oauth.hpp"
#endif
struct QCef;
struct QCefCookieManager;
extern QCef *cef;
extern QCefCookieManager *panel_cookies;
#define wiz reinterpret_cast<AutoConfig*>(wizard())
/* ------------------------------------------------------------------------- */
@@ -222,6 +233,8 @@ AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
ui->setupUi(this);
ui->bitrateLabel->setVisible(false);
ui->bitrate->setVisible(false);
ui->connectAccount2->setVisible(false);
ui->disconnectAccount->setVisible(false);
int vertSpacing = ui->topLayout->verticalSpacing();
@@ -229,6 +242,10 @@ AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
m.setBottom(vertSpacing / 2);
ui->topLayout->setContentsMargins(m);
m = ui->loginPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->loginPageLayout->setContentsMargins(m);
m = ui->streamkeyPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->streamkeyPageLayout->setContentsMargins(m);
@@ -371,6 +388,94 @@ void AutoConfigStreamPage::on_show_clicked()
}
}
void AutoConfigStreamPage::OnOAuthStreamKeyConnected()
{
#ifdef BROWSER_AVAILABLE
OAuthStreamKey *a = reinterpret_cast<OAuthStreamKey*>(auth.get());
if (a) {
bool validKey = !a->key().empty();
if (validKey)
ui->key->setText(QT_UTF8(a->key().c_str()));
ui->streamKeyWidget->setVisible(!validKey);
ui->streamKeyLabel->setVisible(!validKey);
ui->connectAccount2->setVisible(!validKey);
ui->disconnectAccount->setVisible(validKey);
}
ui->stackedWidget->setCurrentIndex((int)Section::StreamKey);
UpdateCompleted();
#endif
}
void AutoConfigStreamPage::OnAuthConnected()
{
std::string service = QT_TO_UTF8(ui->service->currentText());
Auth::Type type = Auth::AuthType(service);
if (type == Auth::Type::OAuth_StreamKey) {
OnOAuthStreamKeyConnected();
}
}
void AutoConfigStreamPage::on_connectAccount_clicked()
{
#ifdef BROWSER_AVAILABLE
std::string service = QT_TO_UTF8(ui->service->currentText());
auth = OAuthStreamKey::Login(this, service);
if (!!auth)
OnAuthConnected();
#endif
}
#define DISCONNECT_COMFIRM_TITLE \
"Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title"
#define DISCONNECT_COMFIRM_TEXT \
"Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text"
void AutoConfigStreamPage::on_disconnectAccount_clicked()
{
QMessageBox::StandardButton button;
button = OBSMessageBox::question(this,
QTStr(DISCONNECT_COMFIRM_TITLE),
QTStr(DISCONNECT_COMFIRM_TEXT));
if (button == QMessageBox::No) {
return;
}
OBSBasic *main = OBSBasic::Get();
main->auth.reset();
auth.reset();
std::string service = QT_TO_UTF8(ui->service->currentText());
#ifdef BROWSER_AVAILABLE
OAuth::DeleteCookies(service);
#endif
ui->streamKeyWidget->setVisible(true);
ui->streamKeyLabel->setVisible(true);
ui->connectAccount2->setVisible(true);
ui->disconnectAccount->setVisible(false);
}
void AutoConfigStreamPage::on_useStreamKey_clicked()
{
ui->stackedWidget->setCurrentIndex((int)Section::StreamKey);
UpdateCompleted();
}
static inline bool is_auth_service(const std::string &service)
{
return Auth::AuthType(service) != Auth::Type::None;
}
void AutoConfigStreamPage::ServiceChanged()
{
bool showMore =
@@ -384,6 +489,32 @@ void AutoConfigStreamPage::ServiceChanged()
bool testBandwidth = ui->doBandwidthTest->isChecked();
bool custom = IsCustom();
ui->disconnectAccount->setVisible(false);
#ifdef BROWSER_AVAILABLE
if (cef) {
if (lastService != service.c_str()) {
bool can_auth = is_auth_service(service);
int page = can_auth
? (int)Section::Connect
: (int)Section::StreamKey;
ui->stackedWidget->setCurrentIndex(page);
ui->streamKeyWidget->setVisible(true);
ui->streamKeyLabel->setVisible(true);
ui->connectAccount2->setVisible(can_auth);
auth.reset();
if (lastService.isEmpty())
lastService = service.c_str();
}
} else {
ui->connectAccount2->setVisible(false);
}
#else
ui->connectAccount2->setVisible(false);
#endif
/* Test three closest servers if "Auto" is available for Twitch */
if (service == "Twitch" && wiz->twitchAuto)
regionBased = false;
@@ -415,6 +546,17 @@ void AutoConfigStreamPage::ServiceChanged()
ui->bitrateLabel->setHidden(testBandwidth);
ui->bitrate->setHidden(testBandwidth);
#ifdef BROWSER_AVAILABLE
OBSBasic *main = OBSBasic::Get();
auth.reset();
if (!!main->auth &&
service.find(main->auth->service()) != std::string::npos) {
auth = main->auth;
OnAuthConnected();
}
#endif
UpdateCompleted();
}
@@ -544,7 +686,8 @@ void AutoConfigStreamPage::UpdateServerList()
void AutoConfigStreamPage::UpdateCompleted()
{
if (ui->key->text().isEmpty()) {
if (ui->stackedWidget->currentIndex() == (int)Section::Connect ||
(ui->key->text().isEmpty() && !auth)) {
ready = false;
} else {
bool custom = IsCustom();
@@ -802,6 +945,9 @@ void AutoConfig::SaveStreamSettings()
main->SetService(newService);
main->SaveService();
main->auth = streamPage->auth;
if (!!main->auth)
main->auth->LoadUI();
/* ---------------------------------- */
/* save stream settings */

View File

@@ -8,6 +8,7 @@
#include <condition_variable>
#include <utility>
#include <thread>
#include <memory>
#include <vector>
#include <string>
#include <mutex>
@@ -18,6 +19,7 @@ class Ui_AutoConfigStreamPage;
class Ui_AutoConfigTestPage;
class AutoConfigStreamPage;
class Auth;
class AutoConfig : public QWizard {
Q_OBJECT
@@ -160,9 +162,12 @@ class AutoConfigStreamPage : public QWizardPage {
friend class AutoConfig;
enum class Section : int {
Connect,
StreamKey,
};
std::shared_ptr<Auth> auth;
Ui_AutoConfigStreamPage *ui;
QString lastService;
bool ready = false;
@@ -178,8 +183,14 @@ public:
virtual int nextId() const override;
virtual bool validatePage() override;
void OnAuthConnected();
void OnOAuthStreamKeyConnected();
public slots:
void on_show_clicked();
void on_connectAccount_clicked();
void on_disconnectAccount_clicked();
void on_useStreamKey_clicked();
void ServiceChanged();
void UpdateKeyLink();
void UpdateServerList();

View File

@@ -118,6 +118,8 @@ class OBSBasic : public OBSMainWindow {
friend class OBSBasicSourceSelect;
friend class OBSBasicSettings;
friend class Auth;
friend class AutoConfig;
friend class AutoConfigStreamPage;
friend struct OBSStudioAPI;
enum class MoveDir {

View File

@@ -5,12 +5,24 @@
#include "window-basic-main.hpp"
#include "qt-wrappers.hpp"
#ifdef BROWSER_AVAILABLE
#include <browser-panel.hpp>
#include "auth-oauth.hpp"
#endif
struct QCef;
struct QCefCookieManager;
extern QCef *cef;
extern QCefCookieManager *panel_cookies;
enum class ListOpt : int {
ShowAll = 1,
Custom,
};
enum class Section : int {
Connect,
StreamKey,
};
@@ -21,12 +33,19 @@ inline bool OBSBasicSettings::IsCustomService() const
void OBSBasicSettings::InitStreamPage()
{
ui->connectAccount2->setVisible(false);
ui->disconnectAccount->setVisible(false);
int vertSpacing = ui->topStreamLayout->verticalSpacing();
QMargins m = ui->topStreamLayout->contentsMargins();
m.setBottom(vertSpacing / 2);
ui->topStreamLayout->setContentsMargins(m);
m = ui->loginPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->loginPageLayout->setContentsMargins(m);
m = ui->streamkeyPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->streamkeyPageLayout->setContentsMargins(m);
@@ -124,6 +143,9 @@ void OBSBasicSettings::SaveStream1Settings()
main->SetService(newService);
main->SaveService();
main->auth = auth;
if (!!main->auth)
main->auth->LoadUI();
}
void OBSBasicSettings::UpdateKeyLink()
@@ -203,6 +225,11 @@ void OBSBasicSettings::LoadServices(bool showAll)
ui->service->blockSignals(false);
}
static inline bool is_auth_service(const std::string &service)
{
return Auth::AuthType(service) != Auth::Type::None;
}
void OBSBasicSettings::on_service_currentIndexChanged(int)
{
bool showMore =
@@ -213,6 +240,29 @@ void OBSBasicSettings::on_service_currentIndexChanged(int)
std::string service = QT_TO_UTF8(ui->service->currentText());
bool custom = IsCustomService();
ui->disconnectAccount->setVisible(false);
#ifdef BROWSER_AVAILABLE
if (cef) {
if (lastService != service.c_str()) {
QString key = ui->key->text();
bool can_auth = is_auth_service(service);
int page = can_auth && (!loading || key.isEmpty())
? (int)Section::Connect
: (int)Section::StreamKey;
ui->streamStackWidget->setCurrentIndex(page);
ui->streamKeyWidget->setVisible(true);
ui->streamKeyLabel->setVisible(true);
ui->connectAccount2->setVisible(can_auth);
}
} else {
ui->connectAccount2->setVisible(false);
}
#else
ui->connectAccount2->setVisible(false);
#endif
if (custom) {
ui->streamkeyPageLayout->insertRow(1, ui->serverLabel,
ui->serverStackedWidget);
@@ -223,6 +273,16 @@ void OBSBasicSettings::on_service_currentIndexChanged(int)
} else {
ui->serverStackedWidget->setCurrentIndex(0);
}
#ifdef BROWSER_AVAILABLE
auth.reset();
if (!!main->auth &&
service.find(main->auth->service()) != std::string::npos) {
auth = main->auth;
OnAuthConnected();
}
#endif
}
void OBSBasicSettings::UpdateServerList()
@@ -298,3 +358,88 @@ OBSService OBSBasicSettings::SpawnTempService()
return newService;
}
void OBSBasicSettings::OnOAuthStreamKeyConnected()
{
#ifdef BROWSER_AVAILABLE
OAuthStreamKey *a = reinterpret_cast<OAuthStreamKey*>(auth.get());
if (a) {
bool validKey = !a->key().empty();
if (validKey)
ui->key->setText(QT_UTF8(a->key().c_str()));
ui->streamKeyWidget->setVisible(!validKey);
ui->streamKeyLabel->setVisible(!validKey);
ui->connectAccount2->setVisible(!validKey);
ui->disconnectAccount->setVisible(validKey);
}
ui->streamStackWidget->setCurrentIndex((int)Section::StreamKey);
#endif
}
void OBSBasicSettings::OnAuthConnected()
{
std::string service = QT_TO_UTF8(ui->service->currentText());
Auth::Type type = Auth::AuthType(service);
if (type == Auth::Type::OAuth_StreamKey) {
OnOAuthStreamKeyConnected();
}
if (!loading) {
stream1Changed = true;
EnableApplyButton(true);
}
}
void OBSBasicSettings::on_connectAccount_clicked()
{
#ifdef BROWSER_AVAILABLE
std::string service = QT_TO_UTF8(ui->service->currentText());
auth = OAuthStreamKey::Login(this, service);
if (!!auth)
OnAuthConnected();
#endif
}
#define DISCONNECT_COMFIRM_TITLE \
"Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title"
#define DISCONNECT_COMFIRM_TEXT \
"Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text"
void OBSBasicSettings::on_disconnectAccount_clicked()
{
QMessageBox::StandardButton button;
button = OBSMessageBox::question(this,
QTStr(DISCONNECT_COMFIRM_TITLE),
QTStr(DISCONNECT_COMFIRM_TEXT));
if (button == QMessageBox::No) {
return;
}
main->auth.reset();
auth.reset();
std::string service = QT_TO_UTF8(ui->service->currentText());
#ifdef BROWSER_AVAILABLE
OAuth::DeleteCookies(service);
#endif
ui->streamKeyWidget->setVisible(true);
ui->streamKeyLabel->setVisible(true);
ui->connectAccount2->setVisible(true);
ui->disconnectAccount->setVisible(false);
ui->key->setText("");
}
void OBSBasicSettings::on_useStreamKey_clicked()
{
ui->streamStackWidget->setCurrentIndex((int)Section::StreamKey);
}

View File

@@ -28,6 +28,8 @@
#include <obs.hpp>
#include "auth-base.hpp"
class OBSBasic;
class QAbstractButton;
class QComboBox;
@@ -91,6 +93,8 @@ private:
std::unique_ptr<Ui::OBSBasicSettings> ui;
std::shared_ptr<Auth> auth;
bool generalChanged = false;
bool stream1Changed = false;
bool outputsChanged = false;
@@ -211,11 +215,16 @@ private:
void InitStreamPage();
inline bool IsCustomService() const;
void LoadServices(bool showAll);
void OnOAuthStreamKeyConnected();
void OnAuthConnected();
QString lastService;
private slots:
void UpdateServerList();
void UpdateKeyLink();
void on_show_clicked();
void on_connectAccount_clicked();
void on_disconnectAccount_clicked();
void on_useStreamKey_clicked();
private:
/* output */