Moves google-api in its own feature. (#3339)
* Moves google-api in its own feature. * Stores the profile email in redux.
This commit is contained in:
parent
7ad0639f7a
commit
af7c69a1aa
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* The type of Redux action which changes Google API state.
|
||||
*
|
||||
* {
|
||||
* type: SET_GOOGLE_API_STATE
|
||||
* }
|
||||
* @public
|
||||
*/
|
||||
export const SET_GOOGLE_API_STATE = Symbol('SET_GOOGLE_API_STATE');
|
||||
|
||||
/**
|
||||
* The type of Redux action which changes Google API profile state.
|
||||
*
|
||||
* {
|
||||
* type: SET_GOOGLE_API_PROFILE
|
||||
* }
|
||||
* @public
|
||||
*/
|
||||
export const SET_GOOGLE_API_PROFILE = Symbol('SET_GOOGLE_API_PROFILE');
|
|
@ -0,0 +1,139 @@
|
|||
/* @flow */
|
||||
|
||||
import {
|
||||
SET_GOOGLE_API_PROFILE,
|
||||
SET_GOOGLE_API_STATE
|
||||
} from './actionTypes';
|
||||
import { GOOGLE_API_STATES } from './constants';
|
||||
import googleApi from './googleApi';
|
||||
|
||||
/**
|
||||
* Loads Google API.
|
||||
*
|
||||
* @param {string} clientId - The client ID to be used with the API library.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function loadGoogleAPI(clientId: string) {
|
||||
return (dispatch: Dispatch<*>) =>
|
||||
googleApi.get()
|
||||
.then(() => googleApi.initializeClient(clientId))
|
||||
.then(() => dispatch({
|
||||
type: SET_GOOGLE_API_STATE,
|
||||
googleAPIState: GOOGLE_API_STATES.LOADED }))
|
||||
.then(() => googleApi.isSignedIn())
|
||||
.then(isSignedIn => {
|
||||
if (isSignedIn) {
|
||||
dispatch({
|
||||
type: SET_GOOGLE_API_STATE,
|
||||
googleAPIState: GOOGLE_API_STATES.SIGNED_IN });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the participant to sign in to the Google API Client Library.
|
||||
*
|
||||
* @returns {function(Dispatch<*>): Promise<string | never>}
|
||||
*/
|
||||
export function signIn() {
|
||||
return (dispatch: Dispatch<*>) => googleApi.get()
|
||||
.then(() => googleApi.signInIfNotSignedIn())
|
||||
.then(() => dispatch({
|
||||
type: SET_GOOGLE_API_STATE,
|
||||
googleAPIState: GOOGLE_API_STATES.SIGNED_IN
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the profile data that is currently used.
|
||||
*
|
||||
* @returns {function(Dispatch<*>): Promise<string | never>}
|
||||
*/
|
||||
export function updateProfile() {
|
||||
return (dispatch: Dispatch<*>) => googleApi.get()
|
||||
.then(() => googleApi.signInIfNotSignedIn())
|
||||
.then(() => dispatch({
|
||||
type: SET_GOOGLE_API_STATE,
|
||||
googleAPIState: GOOGLE_API_STATES.SIGNED_IN
|
||||
}))
|
||||
.then(() => googleApi.getCurrentUserProfile())
|
||||
.then(profile => dispatch({
|
||||
type: SET_GOOGLE_API_PROFILE,
|
||||
profileEmail: profile.getEmail()
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a request for a list of all YouTube broadcasts associated with
|
||||
* user currently signed in to the Google API Client Library.
|
||||
*
|
||||
* @returns {function(): (Promise<*>|Promise<any[] | never>)}
|
||||
*/
|
||||
export function requestAvailableYouTubeBroadcasts() {
|
||||
return () =>
|
||||
googleApi.requestAvailableYouTubeBroadcasts()
|
||||
.then(response => {
|
||||
// Takes in a list of broadcasts from the YouTube API,
|
||||
// removes dupes, removes broadcasts that cannot get a stream key,
|
||||
// and parses the broadcasts into flat objects.
|
||||
const broadcasts = response.result.items;
|
||||
|
||||
const parsedBroadcasts = {};
|
||||
|
||||
for (let i = 0; i < broadcasts.length; i++) {
|
||||
const broadcast = broadcasts[i];
|
||||
const boundStreamID = broadcast.contentDetails.boundStreamId;
|
||||
|
||||
if (boundStreamID && !parsedBroadcasts[boundStreamID]) {
|
||||
parsedBroadcasts[boundStreamID] = {
|
||||
boundStreamID,
|
||||
id: broadcast.id,
|
||||
status: broadcast.status.lifeCycleStatus,
|
||||
title: broadcast.snippet.title
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(parsedBroadcasts);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the stream key for a YouTube broadcast and updates the internal
|
||||
* state to display the associated stream key as being entered.
|
||||
*
|
||||
* @param {string} boundStreamID - The bound stream ID associated with the
|
||||
* broadcast from which to get the stream key.
|
||||
* @returns {function(): (Promise<*>|Promise<{
|
||||
* streamKey: (*|string),
|
||||
* selectedBoundStreamID: *} | never>)}
|
||||
*/
|
||||
export function requestLiveStreamsForYouTubeBroadcast(boundStreamID: string) {
|
||||
return () =>
|
||||
googleApi.requestLiveStreamsForYouTubeBroadcast(boundStreamID)
|
||||
.then(response => {
|
||||
const broadcasts = response.result.items;
|
||||
const streamName = broadcasts
|
||||
&& broadcasts[0]
|
||||
&& broadcasts[0].cdn.ingestionInfo.streamName;
|
||||
const streamKey = streamName || '';
|
||||
|
||||
return {
|
||||
streamKey,
|
||||
selectedBoundStreamID: boundStreamID
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the Google web client application to prompt for a sign in, such as
|
||||
* when changing account, and will then fetch available YouTube broadcasts.
|
||||
*
|
||||
* @returns {function(): (Promise<*>|Promise<{
|
||||
* streamKey: (*|string),
|
||||
* selectedBoundStreamID: *} | never>)}
|
||||
*/
|
||||
export function showAccountSelection() {
|
||||
return () =>
|
||||
googleApi.showAccountSelection();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* The Google API scopes to request access to for streaming.
|
||||
*
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
export const GOOGLE_API_SCOPES = [
|
||||
'https://www.googleapis.com/auth/youtube.readonly'
|
||||
];
|
||||
|
||||
/**
|
||||
* An enumeration of the different states the Google API can be in.
|
||||
*
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
export const GOOGLE_API_STATES = {
|
||||
/**
|
||||
* The state in which the Google API still needs to be loaded.
|
||||
*/
|
||||
NEEDS_LOADING: 0,
|
||||
|
||||
/**
|
||||
* The state in which the Google API is loaded and ready for use.
|
||||
*/
|
||||
LOADED: 1,
|
||||
|
||||
/**
|
||||
* The state in which a user has been logged in through the Google API.
|
||||
*/
|
||||
SIGNED_IN: 2
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export { GOOGLE_API_STATES } from './constants';
|
||||
export * from './googleApi';
|
||||
export * from './actions';
|
||||
|
||||
import './reducer';
|
|
@ -0,0 +1,40 @@
|
|||
// @flow
|
||||
|
||||
import { ReducerRegistry } from '../base/redux';
|
||||
|
||||
import {
|
||||
SET_GOOGLE_API_PROFILE,
|
||||
SET_GOOGLE_API_STATE
|
||||
} from './actionTypes';
|
||||
import { GOOGLE_API_STATES } from './constants';
|
||||
|
||||
/**
|
||||
* The default state is the Google API needs loading.
|
||||
*
|
||||
* @type {{googleAPIState: number}}
|
||||
*/
|
||||
const DEFAULT_STATE = {
|
||||
googleAPIState: GOOGLE_API_STATES.NEEDS_LOADING,
|
||||
profileEmail: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Reduces the Redux actions of the feature features/google-api.
|
||||
*/
|
||||
ReducerRegistry.register('features/google-api',
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_GOOGLE_API_STATE:
|
||||
return {
|
||||
...state,
|
||||
googleAPIState: action.googleAPIState
|
||||
};
|
||||
case SET_GOOGLE_API_PROFILE:
|
||||
return {
|
||||
...state,
|
||||
profileEmail: action.profileEmail
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
});
|
|
@ -26,6 +26,18 @@ export type Props = {
|
|||
*/
|
||||
_googleApiApplicationClientID: string,
|
||||
|
||||
/**
|
||||
* The current state of interactions with the Google API. Determines what
|
||||
* Google related UI should display.
|
||||
*/
|
||||
_googleAPIState: number,
|
||||
|
||||
/**
|
||||
* The email of the user currently logged in to the Google web client
|
||||
* application.
|
||||
*/
|
||||
_googleProfileEmail: string,
|
||||
|
||||
/**
|
||||
* The live stream key that was used before.
|
||||
*/
|
||||
|
@ -60,18 +72,6 @@ export type State = {
|
|||
*/
|
||||
errorType: ?string,
|
||||
|
||||
/**
|
||||
* The current state of interactions with the Google API. Determines what
|
||||
* Google related UI should display.
|
||||
*/
|
||||
googleAPIState: number,
|
||||
|
||||
/**
|
||||
* The email of the user currently logged in to the Google web client
|
||||
* application.
|
||||
*/
|
||||
googleProfileEmail: string,
|
||||
|
||||
/**
|
||||
* The boundStreamID of the broadcast currently selected in the broadcast
|
||||
* dropdown.
|
||||
|
@ -84,36 +84,6 @@ export type State = {
|
|||
streamKey: string
|
||||
};
|
||||
|
||||
/**
|
||||
* An enumeration of the different states the Google API can be in while
|
||||
* interacting with {@code StartLiveStreamDialog}.
|
||||
*
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
export const GOOGLE_API_STATES = {
|
||||
/**
|
||||
* The state in which the Google API still needs to be loaded.
|
||||
*/
|
||||
NEEDS_LOADING: 0,
|
||||
|
||||
/**
|
||||
* The state in which the Google API is loaded and ready for use.
|
||||
*/
|
||||
LOADED: 1,
|
||||
|
||||
/**
|
||||
* The state in which a user has been logged in through the Google API.
|
||||
*/
|
||||
SIGNED_IN: 2,
|
||||
|
||||
/**
|
||||
* The state in which the Google API encountered an error either loading
|
||||
* or with an API request.
|
||||
*/
|
||||
ERROR: 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements an abstract class for the StartLiveStreamDialog on both platforms.
|
||||
*
|
||||
|
@ -136,8 +106,6 @@ export default class AbstractStartLiveStreamDialog
|
|||
this.state = {
|
||||
broadcasts: undefined,
|
||||
errorType: undefined,
|
||||
googleAPIState: GOOGLE_API_STATES.NEEDS_LOADING,
|
||||
googleProfileEmail: '',
|
||||
selectedBoundStreamID: undefined,
|
||||
streamKey: ''
|
||||
};
|
||||
|
@ -331,6 +299,8 @@ export function _mapStateToProps(state: Object) {
|
|||
_conference: state['features/base/conference'].conference,
|
||||
_googleApiApplicationClientID:
|
||||
state['features/base/config'].googleApiApplicationClientID,
|
||||
_googleAPIState: state['features/google-api'].googleAPIState,
|
||||
_googleProfileEmail: state['features/google-api'].profileEmail,
|
||||
_streamKey: state['features/recording'].streamKey
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,19 +6,24 @@ import { connect } from 'react-redux';
|
|||
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
||||
import googleApi from '../../googleApi';
|
||||
import {
|
||||
updateProfile,
|
||||
GOOGLE_API_STATES,
|
||||
loadGoogleAPI,
|
||||
requestAvailableYouTubeBroadcasts,
|
||||
requestLiveStreamsForYouTubeBroadcast,
|
||||
showAccountSelection,
|
||||
signIn
|
||||
} from '../../../google-api';
|
||||
|
||||
import AbstractStartLiveStreamDialog, {
|
||||
_mapStateToProps,
|
||||
GOOGLE_API_STATES,
|
||||
type Props
|
||||
} from './AbstractStartLiveStreamDialog';
|
||||
import BroadcastsDropdown from './BroadcastsDropdown';
|
||||
import GoogleSignInButton from './GoogleSignInButton';
|
||||
import StreamKeyForm from './StreamKeyForm';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* A React Component for requesting a YouTube stream key to use for live
|
||||
* streaming of the current conference.
|
||||
|
@ -40,6 +45,7 @@ class StartLiveStreamDialog
|
|||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onGetYouTubeBroadcasts = this._onGetYouTubeBroadcasts.bind(this);
|
||||
this._onInitializeGoogleApi = this._onInitializeGoogleApi.bind(this);
|
||||
this._onGoogleSignIn = this._onGoogleSignIn.bind(this);
|
||||
this._onRequestGoogleSignIn = this._onRequestGoogleSignIn.bind(this);
|
||||
this._onYouTubeBroadcastIDSelected
|
||||
= this._onYouTubeBroadcastIDSelected.bind(this);
|
||||
|
@ -58,23 +64,23 @@ class StartLiveStreamDialog
|
|||
* @returns {Promise}
|
||||
*/
|
||||
_onInitializeGoogleApi() {
|
||||
return googleApi.get()
|
||||
.then(() => googleApi.initializeClient(
|
||||
this.props._googleApiApplicationClientID))
|
||||
.then(() => this._setStateIfMounted({
|
||||
googleAPIState: GOOGLE_API_STATES.LOADED
|
||||
}))
|
||||
.then(() => googleApi.isSignedIn())
|
||||
.then(isSignedIn => {
|
||||
if (isSignedIn) {
|
||||
return this._onGetYouTubeBroadcasts();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this._setStateIfMounted({
|
||||
googleAPIState: GOOGLE_API_STATES.ERROR
|
||||
});
|
||||
});
|
||||
this.props.dispatch(
|
||||
loadGoogleAPI(this.props._googleApiApplicationClientID))
|
||||
.catch(response => this._parseErrorFromResponse(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically selects the input field's value after starting to edit the
|
||||
* display name.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidUpdate(previousProps) {
|
||||
if (previousProps._googleAPIState === GOOGLE_API_STATES.LOADED
|
||||
&& this.props._googleAPIState === GOOGLE_API_STATES.SIGNED_IN) {
|
||||
this._onGetYouTubeBroadcasts();
|
||||
}
|
||||
}
|
||||
|
||||
_onGetYouTubeBroadcasts: () => Promise<*>;
|
||||
|
@ -84,42 +90,39 @@ class StartLiveStreamDialog
|
|||
* list of the user's YouTube broadcasts.
|
||||
*
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
* @returns {void}
|
||||
*/
|
||||
_onGetYouTubeBroadcasts() {
|
||||
return googleApi.get()
|
||||
.then(() => googleApi.signInIfNotSignedIn())
|
||||
.then(() => googleApi.getCurrentUserProfile())
|
||||
.then(profile => {
|
||||
this._setStateIfMounted({
|
||||
googleProfileEmail: profile.getEmail(),
|
||||
googleAPIState: GOOGLE_API_STATES.SIGNED_IN
|
||||
});
|
||||
})
|
||||
.then(() => googleApi.requestAvailableYouTubeBroadcasts())
|
||||
.then(response => {
|
||||
const broadcasts = this._parseBroadcasts(response.result.items);
|
||||
this.props.dispatch(updateProfile())
|
||||
.catch(response => this._parseErrorFromResponse(response));
|
||||
|
||||
this.props.dispatch(requestAvailableYouTubeBroadcasts())
|
||||
.then(broadcasts => {
|
||||
this._setStateIfMounted({
|
||||
broadcasts
|
||||
});
|
||||
|
||||
if (broadcasts.length === 1 && !this.state.streamKey) {
|
||||
if (broadcasts.length === 1) {
|
||||
const broadcast = broadcasts[0];
|
||||
|
||||
this._onYouTubeBroadcastIDSelected(broadcast.boundStreamID);
|
||||
}
|
||||
})
|
||||
.catch(response => {
|
||||
// Only show an error if an external request was made with the
|
||||
// Google api. Do not error if the login in canceled.
|
||||
if (response && response.result) {
|
||||
this._setStateIfMounted({
|
||||
errorType: this._parseErrorFromResponse(response),
|
||||
googleAPIState: GOOGLE_API_STATES.ERROR
|
||||
});
|
||||
}
|
||||
});
|
||||
.catch(response => this._parseErrorFromResponse(response));
|
||||
}
|
||||
|
||||
_onGoogleSignIn: () => Object;
|
||||
|
||||
/**
|
||||
* Forces the Google web client application to prompt for a sign in, such as
|
||||
* when changing account, and will then fetch available YouTube broadcasts.
|
||||
*
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_onGoogleSignIn() {
|
||||
this.props.dispatch(signIn())
|
||||
.catch(response => this._parseErrorFromResponse(response));
|
||||
}
|
||||
|
||||
_onRequestGoogleSignIn: () => Object;
|
||||
|
@ -132,8 +135,14 @@ class StartLiveStreamDialog
|
|||
* @returns {Promise}
|
||||
*/
|
||||
_onRequestGoogleSignIn() {
|
||||
return googleApi.showAccountSelection()
|
||||
.then(() => this._setStateIfMounted({ broadcasts: undefined }))
|
||||
// when there is an error we show the google sign-in button.
|
||||
// once we click it we want to clear the error from the state
|
||||
this.props.dispatch(showAccountSelection())
|
||||
.then(() =>
|
||||
this._setStateIfMounted({
|
||||
broadcasts: undefined,
|
||||
errorType: undefined
|
||||
}))
|
||||
.then(() => this._onGetYouTubeBroadcasts());
|
||||
}
|
||||
|
||||
|
@ -151,55 +160,20 @@ class StartLiveStreamDialog
|
|||
* @returns {Promise}
|
||||
*/
|
||||
_onYouTubeBroadcastIDSelected(boundStreamID) {
|
||||
return googleApi.requestLiveStreamsForYouTubeBroadcast(boundStreamID)
|
||||
.then(response => {
|
||||
const broadcasts = response.result.items;
|
||||
const streamName = broadcasts
|
||||
&& broadcasts[0]
|
||||
&& broadcasts[0].cdn.ingestionInfo.streamName;
|
||||
const streamKey = streamName || '';
|
||||
|
||||
this.props.dispatch(
|
||||
requestLiveStreamsForYouTubeBroadcast(boundStreamID))
|
||||
.then(({ streamKey, selectedBoundStreamID }) =>
|
||||
this._setStateIfMounted({
|
||||
streamKey,
|
||||
selectedBoundStreamID: boundStreamID
|
||||
});
|
||||
});
|
||||
}
|
||||
selectedBoundStreamID
|
||||
}));
|
||||
|
||||
_parseBroadcasts: (Array<Object>) => Array<Object>;
|
||||
|
||||
/**
|
||||
* Takes in a list of broadcasts from the YouTube API, removes dupes,
|
||||
* removes broadcasts that cannot get a stream key, and parses the
|
||||
* broadcasts into flat objects.
|
||||
*
|
||||
* @param {Array} broadcasts - Broadcast descriptions as obtained from
|
||||
* calling the YouTube API.
|
||||
* @private
|
||||
* @returns {Array} An array of objects describing each unique broadcast.
|
||||
*/
|
||||
_parseBroadcasts(broadcasts) {
|
||||
const parsedBroadcasts = {};
|
||||
|
||||
for (let i = 0; i < broadcasts.length; i++) {
|
||||
const broadcast = broadcasts[i];
|
||||
const boundStreamID = broadcast.contentDetails.boundStreamId;
|
||||
|
||||
if (boundStreamID && !parsedBroadcasts[boundStreamID]) {
|
||||
parsedBroadcasts[boundStreamID] = {
|
||||
boundStreamID,
|
||||
id: broadcast.id,
|
||||
status: broadcast.status.lifeCycleStatus,
|
||||
title: broadcast.snippet.title
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(parsedBroadcasts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches in a Google API error response for the error type.
|
||||
* Only show an error if an external request was made with the Google api.
|
||||
* Do not error if the login in canceled.
|
||||
* And searches in a Google API error response for the error type.
|
||||
*
|
||||
* @param {Object} response - The Google API response that may contain an
|
||||
* error.
|
||||
|
@ -207,12 +181,19 @@ class StartLiveStreamDialog
|
|||
* @returns {string|null}
|
||||
*/
|
||||
_parseErrorFromResponse(response) {
|
||||
|
||||
if (!response || !response.result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = response.result;
|
||||
const error = result.error;
|
||||
const errors = error && error.errors;
|
||||
const firstError = errors && errors[0];
|
||||
|
||||
return (firstError && firstError.reason) || null;
|
||||
this._setStateIfMounted({
|
||||
errorType: (firstError && firstError.reason) || null
|
||||
});
|
||||
}
|
||||
|
||||
_renderDialogContent: () => React$Component<*>
|
||||
|
@ -243,20 +224,22 @@ class StartLiveStreamDialog
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderYouTubePanel() {
|
||||
const { t } = this.props;
|
||||
const {
|
||||
t,
|
||||
_googleProfileEmail
|
||||
} = this.props;
|
||||
const {
|
||||
broadcasts,
|
||||
googleProfileEmail,
|
||||
selectedBoundStreamID
|
||||
} = this.state;
|
||||
|
||||
let googleContent, helpText;
|
||||
|
||||
switch (this.state.googleAPIState) {
|
||||
switch (this.props._googleAPIState) {
|
||||
case GOOGLE_API_STATES.LOADED:
|
||||
googleContent = ( // eslint-disable-line no-extra-parens
|
||||
<GoogleSignInButton
|
||||
onClick = { this._onGetYouTubeBroadcasts }
|
||||
onClick = { this._onGoogleSignIn }
|
||||
text = { t('liveStreaming.signIn') } />
|
||||
);
|
||||
helpText = t('liveStreaming.signInCTA');
|
||||
|
@ -279,7 +262,7 @@ class StartLiveStreamDialog
|
|||
helpText = ( // eslint-disable-line no-extra-parens
|
||||
<div>
|
||||
{ `${t('liveStreaming.chooseCTA',
|
||||
{ email: googleProfileEmail })} ` }
|
||||
{ email: _googleProfileEmail })} ` }
|
||||
<a onClick = { this._onRequestGoogleSignIn }>
|
||||
{ t('liveStreaming.changeSignIn') }
|
||||
</a>
|
||||
|
@ -288,16 +271,6 @@ class StartLiveStreamDialog
|
|||
|
||||
break;
|
||||
|
||||
case GOOGLE_API_STATES.ERROR:
|
||||
googleContent = ( // eslint-disable-line no-extra-parens
|
||||
<GoogleSignInButton
|
||||
onClick = { this._onRequestGoogleSignIn }
|
||||
text = { t('liveStreaming.signIn') } />
|
||||
);
|
||||
helpText = this._getGoogleErrorMessageToDisplay();
|
||||
|
||||
break;
|
||||
|
||||
case GOOGLE_API_STATES.NEEDS_LOADING:
|
||||
default:
|
||||
googleContent = ( // eslint-disable-line no-extra-parens
|
||||
|
@ -309,6 +282,15 @@ class StartLiveStreamDialog
|
|||
break;
|
||||
}
|
||||
|
||||
if (this.state.errorType !== undefined) {
|
||||
googleContent = ( // eslint-disable-line no-extra-parens
|
||||
<GoogleSignInButton
|
||||
onClick = { this._onRequestGoogleSignIn }
|
||||
text = { t('liveStreaming.signIn') } />
|
||||
);
|
||||
helpText = this._getGoogleErrorMessageToDisplay();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = 'google-panel'>
|
||||
<div className = 'live-stream-cta'>
|
||||
|
@ -336,7 +318,7 @@ class StartLiveStreamDialog
|
|||
case 'liveStreamingNotEnabled':
|
||||
text = this.props.t(
|
||||
'liveStreaming.errorLiveStreamNotEnabled',
|
||||
{ email: this.state.googleProfileEmail });
|
||||
{ email: this.props._googleProfileEmail });
|
||||
break;
|
||||
default:
|
||||
text = this.props.t('liveStreaming.errorAPI');
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* The Google API scopes to request access to for streaming.
|
||||
*
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
export const GOOGLE_API_SCOPES = [
|
||||
'https://www.googleapis.com/auth/youtube.readonly'
|
||||
];
|
||||
|
||||
/**
|
||||
* The identifier of the sound to be played when a recording or live streaming
|
||||
* session is stopped.
|
||||
|
|
Loading…
Reference in New Issue