fix(live-streaming): show message if no broadcasts are found
It's possible for the YouTube api to return zero broadcasts or broadcasts without any streams--streams are what are associated with stream keys. In this case, instead of showing an empty selector or no selector, show a message with a link to where the stream key can be obtained.
This commit is contained in:
parent
699b13066e
commit
07bcb38dd6
|
@ -95,7 +95,6 @@
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stream-key-form {
|
|
||||||
.helper-link {
|
.helper-link {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -103,9 +102,8 @@
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.validation-error {
|
.warning-text {
|
||||||
color:#FFD740;
|
color:#FFD740;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,6 +516,7 @@
|
||||||
"expandedPending": "The live streaming is being started...",
|
"expandedPending": "The live streaming is being started...",
|
||||||
"failedToStart": "Live Streaming failed to start",
|
"failedToStart": "Live Streaming failed to start",
|
||||||
"invalidStreamKey": "Live stream key may be incorrect.",
|
"invalidStreamKey": "Live stream key may be incorrect.",
|
||||||
|
"getStreamKeyManually": "We weren’t able to fetch any live streams. Try getting your live stream key from YouTube.",
|
||||||
"off": "Live Streaming stopped",
|
"off": "Live Streaming stopped",
|
||||||
"on": "Live Streaming",
|
"on": "Live Streaming",
|
||||||
"pending": "Starting Live Stream...",
|
"pending": "Starting Live Stream...",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* The URL that is the main landing page for YouTube live streaming and should
|
||||||
|
* have a user's live stream key.
|
||||||
|
*/
|
||||||
|
export const YOUTUBE_LIVE_DASHBOARD_URL
|
||||||
|
= 'https://www.youtube.com/live_dashboard';
|
|
@ -1,10 +1,18 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Text, TouchableHighlight, View } from 'react-native';
|
import {
|
||||||
|
Linking,
|
||||||
|
Text,
|
||||||
|
TouchableHighlight,
|
||||||
|
TouchableOpacity,
|
||||||
|
View
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
import { translate } from '../../../../base/i18n';
|
import { translate } from '../../../../base/i18n';
|
||||||
|
|
||||||
|
import { YOUTUBE_LIVE_DASHBOARD_URL } from '../constants';
|
||||||
|
|
||||||
import styles, { ACTIVE_OPACITY, TOUCHABLE_UNDERLAY } from './styles';
|
import styles, { ACTIVE_OPACITY, TOUCHABLE_UNDERLAY } from './styles';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -56,6 +64,7 @@ class StreamKeyPicker extends Component<Props, State> {
|
||||||
streamKey: null
|
streamKey: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._onOpenYoutubeDashboard = this._onOpenYoutubeDashboard.bind(this);
|
||||||
this._onStreamPick = this._onStreamPick.bind(this);
|
this._onStreamPick = this._onStreamPick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,10 +76,24 @@ class StreamKeyPicker extends Component<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const { broadcasts } = this.props;
|
const { broadcasts } = this.props;
|
||||||
|
|
||||||
if (!broadcasts || !broadcasts.length) {
|
if (!broadcasts) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!broadcasts.length) {
|
||||||
|
return (
|
||||||
|
<View style = { styles.formWrapper }>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress = { this._onOpenYoutubeDashboard }>
|
||||||
|
<Text style = { styles.warningText }>
|
||||||
|
{ this.props.t(
|
||||||
|
'liveStreaming.getStreamKeyManually') }
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style = { styles.formWrapper }>
|
<View style = { styles.formWrapper }>
|
||||||
<View style = { styles.streamKeyPickerCta }>
|
<View style = { styles.streamKeyPickerCta }>
|
||||||
|
@ -100,6 +123,19 @@ class StreamKeyPicker extends Component<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onOpenYoutubeDashboard: () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the link which should display the YouTube broadcast live stream
|
||||||
|
* key.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onOpenYoutubeDashboard() {
|
||||||
|
Linking.openURL(YOUTUBE_LIVE_DASHBOARD_URL);
|
||||||
|
}
|
||||||
|
|
||||||
_onStreamPick: string => Function
|
_onStreamPick: string => Function
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -280,12 +280,21 @@ class StartLiveStreamDialog
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GOOGLE_API_STATES.SIGNED_IN:
|
case GOOGLE_API_STATES.SIGNED_IN:
|
||||||
|
if (broadcasts) {
|
||||||
googleContent = (
|
googleContent = (
|
||||||
<StreamKeyPicker
|
<StreamKeyPicker
|
||||||
broadcasts = { broadcasts }
|
broadcasts = { broadcasts }
|
||||||
onBroadcastSelected = { this._onYouTubeBroadcastIDSelected }
|
onBroadcastSelected
|
||||||
|
= { this._onYouTubeBroadcastIDSelected }
|
||||||
selectedBoundStreamID = { selectedBoundStreamID } />
|
selectedBoundStreamID = { selectedBoundStreamID } />
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
googleContent = (
|
||||||
|
<Spinner
|
||||||
|
isCompleting = { false }
|
||||||
|
size = 'medium' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXME: Ideally this help text would be one translation string
|
* FIXME: Ideally this help text would be one translation string
|
||||||
|
|
|
@ -55,7 +55,7 @@ class StreamKeyForm extends AbstractStreamKeyForm {
|
||||||
<div className = 'form-footer'>
|
<div className = 'form-footer'>
|
||||||
{
|
{
|
||||||
this.state.showValidationError
|
this.state.showValidationError
|
||||||
? <span className = 'validation-error'>
|
? <span className = 'warning-text'>
|
||||||
{ t('liveStreaming.invalidStreamKey') }
|
{ t('liveStreaming.invalidStreamKey') }
|
||||||
</span>
|
</span>
|
||||||
: null
|
: null
|
||||||
|
|
|
@ -9,6 +9,8 @@ import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { translate } from '../../../../base/i18n';
|
import { translate } from '../../../../base/i18n';
|
||||||
|
|
||||||
|
import { YOUTUBE_LIVE_DASHBOARD_URL } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link StreamKeyPicker}.
|
* The type of the React {@code Component} props of {@link StreamKeyPicker}.
|
||||||
*/
|
*/
|
||||||
|
@ -95,6 +97,18 @@ class StreamKeyPicker extends PureComponent<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const { broadcasts, selectedBoundStreamID, t } = this.props;
|
const { broadcasts, selectedBoundStreamID, t } = this.props;
|
||||||
|
|
||||||
|
if (!broadcasts.length) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className = 'warning-text'
|
||||||
|
href = { YOUTUBE_LIVE_DASHBOARD_URL }
|
||||||
|
rel = 'noopener noreferrer'
|
||||||
|
target = '_blank'>
|
||||||
|
{ t('liveStreaming.getStreamKeyManually') }
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const dropdownItems
|
const dropdownItems
|
||||||
= broadcasts.map(broadcast => (
|
= broadcasts.map(broadcast => (
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
|
|
Loading…
Reference in New Issue