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:
Leonard Kim 2018-12-17 20:21:18 -08:00 committed by Zoltan Bettenbuk
parent 699b13066e
commit 07bcb38dd6
7 changed files with 84 additions and 20 deletions

View File

@ -95,17 +95,15 @@
padding-bottom: 10px; padding-bottom: 10px;
} }
.stream-key-form { .helper-link {
.helper-link { cursor: pointer;
cursor: pointer; display: inline-block;
display: inline-block; flex-shrink: 0;
flex-shrink: 0; margin-left: auto;
margin-left: auto; }
}
.validation-error { .warning-text {
color:#FFD740; color:#FFD740;
font-size: 12px; font-size: 12px;
}
} }
} }

View File

@ -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 werent 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...",

View File

@ -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';

View File

@ -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
/** /**

View File

@ -280,12 +280,21 @@ class StartLiveStreamDialog
break; break;
case GOOGLE_API_STATES.SIGNED_IN: case GOOGLE_API_STATES.SIGNED_IN:
googleContent = ( if (broadcasts) {
<StreamKeyPicker googleContent = (
broadcasts = { broadcasts } <StreamKeyPicker
onBroadcastSelected = { this._onYouTubeBroadcastIDSelected } broadcasts = { broadcasts }
selectedBoundStreamID = { selectedBoundStreamID } /> onBroadcastSelected
); = { this._onYouTubeBroadcastIDSelected }
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

View File

@ -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

View File

@ -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