feat(liveStreamting) add configuration to customize streaming dialog
This commit is contained in:
parent
3f0e50a9cd
commit
87f6d27fb2
20
config.js
20
config.js
|
@ -310,9 +310,6 @@ var config = {
|
||||||
// DEPRECATED. Use recordingService.sharingEnabled instead.
|
// DEPRECATED. Use recordingService.sharingEnabled instead.
|
||||||
// fileRecordingsServiceSharingEnabled: false,
|
// fileRecordingsServiceSharingEnabled: false,
|
||||||
|
|
||||||
// Whether to enable live streaming or not.
|
|
||||||
// liveStreamingEnabled: false,
|
|
||||||
|
|
||||||
// Local recording configuration.
|
// Local recording configuration.
|
||||||
// localRecording: {
|
// localRecording: {
|
||||||
// // Whether to disable local recording or not.
|
// // Whether to disable local recording or not.
|
||||||
|
@ -325,6 +322,23 @@ var config = {
|
||||||
// disableSelfRecording: false,
|
// disableSelfRecording: false,
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
// Customize the Live Streaming dialog. Can be modified for a non-YouTube provider.
|
||||||
|
// liveStreaming: {
|
||||||
|
// // Whether to enable live streaming or not.
|
||||||
|
// enabled: false,
|
||||||
|
// // Terms link
|
||||||
|
// termsLink: 'https://www.youtube.com/t/terms',
|
||||||
|
// // Data privacy link
|
||||||
|
// dataPrivacyLink: 'https://policies.google.com/privacy',
|
||||||
|
// // RegExp string that validates the stream key input field
|
||||||
|
// validatorRegExpString: '^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}',
|
||||||
|
// // Documentation reference for the live streaming feature.
|
||||||
|
// helpLink: 'https://jitsi.org/live'
|
||||||
|
// },
|
||||||
|
|
||||||
|
// DEPRECATED. Use liveStreaming.enabled instead.
|
||||||
|
// liveStreamingEnabled: false,
|
||||||
|
|
||||||
// DEPRECATED. Use transcription.enabled instead.
|
// DEPRECATED. Use transcription.enabled instead.
|
||||||
// transcribingEnabled: false,
|
// transcribingEnabled: false,
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,6 @@ var interfaceConfig = {
|
||||||
JITSI_WATERMARK_LINK: 'https://jitsi.org',
|
JITSI_WATERMARK_LINK: 'https://jitsi.org',
|
||||||
|
|
||||||
LANG_DETECTION: true, // Allow i18n to detect the system language
|
LANG_DETECTION: true, // Allow i18n to detect the system language
|
||||||
LIVE_STREAMING_HELP_LINK: 'https://jitsi.org/live', // Documentation reference for the live streaming feature.
|
|
||||||
LOCAL_THUMBNAIL_RATIO: 16 / 9, // 16:9
|
LOCAL_THUMBNAIL_RATIO: 16 / 9, // 16:9
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,6 +247,10 @@ var interfaceConfig = {
|
||||||
// Moved to config.js as `toolbarConfig.initialTimeout`.
|
// Moved to config.js as `toolbarConfig.initialTimeout`.
|
||||||
// INITIAL_TOOLBAR_TIMEOUT: 20000,
|
// INITIAL_TOOLBAR_TIMEOUT: 20000,
|
||||||
|
|
||||||
|
// Please use `liveStreaming.helpLink` from config.js
|
||||||
|
// Documentation reference for the live streaming feature.
|
||||||
|
// LIVE_STREAMING_HELP_LINK: 'https://jitsi.org/live',
|
||||||
|
|
||||||
// Moved to config.js as `toolbarConfig.alwaysVisible`.
|
// Moved to config.js as `toolbarConfig.alwaysVisible`.
|
||||||
// TOOLBAR_ALWAYS_VISIBLE: false,
|
// TOOLBAR_ALWAYS_VISIBLE: false,
|
||||||
|
|
||||||
|
|
|
@ -332,6 +332,13 @@ export interface IConfig {
|
||||||
lastNLimits?: {
|
lastNLimits?: {
|
||||||
[key: number]: number;
|
[key: number]: number;
|
||||||
};
|
};
|
||||||
|
liveStreaming?: {
|
||||||
|
dataPrivacyLink?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
helpLink?: string;
|
||||||
|
termsLink?: string;
|
||||||
|
validatorRegExpString?: string;
|
||||||
|
};
|
||||||
liveStreamingEnabled?: boolean;
|
liveStreamingEnabled?: boolean;
|
||||||
localRecording?: {
|
localRecording?: {
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
|
|
|
@ -183,6 +183,7 @@ export default [
|
||||||
'iceTransportPolicy',
|
'iceTransportPolicy',
|
||||||
'ignoreStartMuted',
|
'ignoreStartMuted',
|
||||||
'inviteAppName',
|
'inviteAppName',
|
||||||
|
'liveStreaming',
|
||||||
'liveStreamingEnabled',
|
'liveStreamingEnabled',
|
||||||
'localRecording',
|
'localRecording',
|
||||||
'localSubject',
|
'localSubject',
|
||||||
|
|
|
@ -420,6 +420,26 @@ function _translateLegacyConfig(oldValue: IConfig) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newValue.liveStreaming = newValue.liveStreaming || {};
|
||||||
|
|
||||||
|
// Migrate config.liveStreamingEnabled
|
||||||
|
if (oldValue.liveStreamingEnabled !== undefined) {
|
||||||
|
newValue.liveStreaming = {
|
||||||
|
...newValue.liveStreaming,
|
||||||
|
enabled: oldValue.liveStreamingEnabled
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate interfaceConfig.LIVE_STREAMING_HELP_LINK
|
||||||
|
if (oldValue.liveStreaming === undefined
|
||||||
|
&& typeof interfaceConfig === 'object'
|
||||||
|
&& interfaceConfig.hasOwnProperty('LIVE_STREAMING_HELP_LINK')) {
|
||||||
|
newValue.liveStreaming = {
|
||||||
|
...newValue.liveStreaming,
|
||||||
|
helpLink: interfaceConfig.LIVE_STREAMING_HELP_LINK
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { getShareInfoText } from '../invite';
|
import { getShareInfoText } from '../invite';
|
||||||
|
import { getLiveStreaming } from '../recording/components/LiveStream/functions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SET_GOOGLE_API_PROFILE,
|
SET_GOOGLE_API_PROFILE,
|
||||||
|
@ -36,15 +37,16 @@ export function loadGoogleAPI() {
|
||||||
googleApi.get()
|
googleApi.get()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const {
|
const {
|
||||||
liveStreamingEnabled,
|
|
||||||
enableCalendarIntegration,
|
enableCalendarIntegration,
|
||||||
googleApiApplicationClientID
|
googleApiApplicationClientID
|
||||||
} = getState()['features/base/config'];
|
} = getState()['features/base/config'];
|
||||||
|
|
||||||
|
const liveStreaming = getLiveStreaming(getState());
|
||||||
|
|
||||||
if (getState()['features/google-api'].googleAPIState
|
if (getState()['features/google-api'].googleAPIState
|
||||||
=== GOOGLE_API_STATES.NEEDS_LOADING) {
|
=== GOOGLE_API_STATES.NEEDS_LOADING) {
|
||||||
return googleApi.initializeClient(
|
return googleApi.initializeClient(
|
||||||
googleApiApplicationClientID, liveStreamingEnabled, enableCalendarIntegration);
|
googleApiApplicationClientID, liveStreaming.enabled, enableCalendarIntegration);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions';
|
||||||
import { FEATURES } from '../../../jaas/constants';
|
import { FEATURES } from '../../../jaas/constants';
|
||||||
import { getActiveSession } from '../../functions';
|
import { getActiveSession } from '../../functions';
|
||||||
|
|
||||||
|
import { getLiveStreaming } from './functions';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of
|
* The type of the React {@code Component} props of
|
||||||
|
@ -141,12 +143,12 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
|
||||||
// its own to be visible or not.
|
// its own to be visible or not.
|
||||||
const isModerator = isLocalParticipantModerator(state);
|
const isModerator = isLocalParticipantModerator(state);
|
||||||
const {
|
const {
|
||||||
enableFeaturesBasedOnToken,
|
enableFeaturesBasedOnToken
|
||||||
liveStreamingEnabled
|
|
||||||
} = state['features/base/config'];
|
} = state['features/base/config'];
|
||||||
|
const liveStreaming = getLiveStreaming(state);
|
||||||
const { features = {} } = getLocalParticipant(state);
|
const { features = {} } = getLocalParticipant(state);
|
||||||
|
|
||||||
visible = isModerator && liveStreamingEnabled;
|
visible = isModerator && liveStreaming.enabled;
|
||||||
|
|
||||||
if (enableFeaturesBasedOnToken) {
|
if (enableFeaturesBasedOnToken) {
|
||||||
visible = visible && String(features.livestreaming) === 'true';
|
visible = visible && String(features.livestreaming) === 'true';
|
||||||
|
|
|
@ -3,21 +3,35 @@
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
import { getLiveStreaming } from './functions';
|
||||||
|
|
||||||
/**
|
|
||||||
* The live streaming help link to display. On web it comes from
|
export type LiveStreaming = {
|
||||||
* interfaceConfig, but we don't have that on mobile.
|
enabled: boolean,
|
||||||
*
|
helpLink: string, // Documentation reference for the live streaming feature.
|
||||||
* FIXME: This is in props now to prepare for the Redux-based interfaceConfig.
|
termsLink: string, // Terms link
|
||||||
*/
|
dataPrivacyLink: string, // Data privacy link
|
||||||
const LIVE_STREAMING_HELP_LINK = 'https://jitsi.org/live';
|
validatorRegExpString: string // RegExp string that validates the stream key input field
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LiveStreamingProps = {
|
||||||
|
enabled: boolean,
|
||||||
|
helpURL: string,
|
||||||
|
termsURL: string,
|
||||||
|
dataPrivacyURL: string,
|
||||||
|
streamLinkRegexp: RegExp
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The props of the component.
|
* The props of the component.
|
||||||
*/
|
*/
|
||||||
export type Props = {
|
export type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The live streaming dialog properties.
|
||||||
|
*/
|
||||||
|
_liveStreaming: LiveStreamingProps,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback invoked when the entered stream key has changed.
|
* Callback invoked when the entered stream key has changed.
|
||||||
*/
|
*/
|
||||||
|
@ -54,7 +68,7 @@ type State = {
|
||||||
*/
|
*/
|
||||||
export default class AbstractStreamKeyForm<P: Props>
|
export default class AbstractStreamKeyForm<P: Props>
|
||||||
extends Component<P, State> {
|
extends Component<P, State> {
|
||||||
helpURL: string;
|
|
||||||
_debouncedUpdateValidationErrorVisibility: Function;
|
_debouncedUpdateValidationErrorVisibility: Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,10 +84,6 @@ export default class AbstractStreamKeyForm<P: Props>
|
||||||
&& !this._validateStreamKey(this.props.value)
|
&& !this._validateStreamKey(this.props.value)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.helpURL = (typeof interfaceConfig !== 'undefined'
|
|
||||||
&& interfaceConfig.LIVE_STREAMING_HELP_LINK)
|
|
||||||
|| LIVE_STREAMING_HELP_LINK;
|
|
||||||
|
|
||||||
this._debouncedUpdateValidationErrorVisibility = debounce(
|
this._debouncedUpdateValidationErrorVisibility = debounce(
|
||||||
this._updateValidationErrorVisibility.bind(this),
|
this._updateValidationErrorVisibility.bind(this),
|
||||||
800,
|
800,
|
||||||
|
@ -150,9 +160,22 @@ export default class AbstractStreamKeyForm<P: Props>
|
||||||
*/
|
*/
|
||||||
_validateStreamKey(streamKey = '') {
|
_validateStreamKey(streamKey = '') {
|
||||||
const trimmedKey = streamKey.trim();
|
const trimmedKey = streamKey.trim();
|
||||||
const fourGroupsDashSeparated = /^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}/;
|
const match = this.props._liveStreaming.streamLinkRegexp.exec(trimmedKey);
|
||||||
const match = fourGroupsDashSeparated.exec(trimmedKey);
|
|
||||||
|
|
||||||
return Boolean(match);
|
return Boolean(match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps part of the Redux state to the component's props.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @returns {{
|
||||||
|
* _liveStreaming: LiveStreamingProps
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function _mapStateToProps(state: Object) {
|
||||||
|
return {
|
||||||
|
_liveStreaming: getLiveStreaming(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -13,3 +13,14 @@ export const YOUTUBE_LIVE_DASHBOARD_URL = 'https://www.youtube.com/live_dashboar
|
||||||
* The URL for YouTube terms and conditions.
|
* The URL for YouTube terms and conditions.
|
||||||
*/
|
*/
|
||||||
export const YOUTUBE_TERMS_URL = 'https://www.youtube.com/t/terms';
|
export const YOUTUBE_TERMS_URL = 'https://www.youtube.com/t/terms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The live streaming help link to display.
|
||||||
|
*/
|
||||||
|
export const JITSI_LIVE_STREAMING_HELP_LINK = 'https://jitsi.org/live';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The YouTube stream link RegExp.
|
||||||
|
*/
|
||||||
|
export const FOUR_GROUPS_DASH_SEPARATED = /^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}/;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
FOUR_GROUPS_DASH_SEPARATED,
|
||||||
|
GOOGLE_PRIVACY_POLICY,
|
||||||
|
JITSI_LIVE_STREAMING_HELP_LINK,
|
||||||
|
YOUTUBE_TERMS_URL
|
||||||
|
} from './constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the live streaming options.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The global state.
|
||||||
|
* @returns {LiveStreaming}
|
||||||
|
*/
|
||||||
|
export function getLiveStreaming(state: Object) {
|
||||||
|
const { liveStreaming = {} } = state['features/base/config'];
|
||||||
|
|
||||||
|
const regexp = liveStreaming.validatorRegExpString
|
||||||
|
&& new RegExp(liveStreaming.validatorRegExpString);
|
||||||
|
|
||||||
|
return {
|
||||||
|
enabled: Boolean(liveStreaming.enabled),
|
||||||
|
helpURL: liveStreaming.helpLink || JITSI_LIVE_STREAMING_HELP_LINK,
|
||||||
|
termsURL: liveStreaming.termsLink || YOUTUBE_TERMS_URL,
|
||||||
|
dataPrivacyURL: liveStreaming.dataPrivacyLink || GOOGLE_PRIVACY_POLICY,
|
||||||
|
streamLinkRegexp: regexp || FOUR_GROUPS_DASH_SEPARATED
|
||||||
|
};
|
||||||
|
}
|
|
@ -10,7 +10,9 @@ import { StyleType } from '../../../../base/styles';
|
||||||
import AbstractStreamKeyForm, {
|
import AbstractStreamKeyForm, {
|
||||||
type Props as AbstractProps
|
type Props as AbstractProps
|
||||||
} from '../AbstractStreamKeyForm';
|
} from '../AbstractStreamKeyForm';
|
||||||
import { GOOGLE_PRIVACY_POLICY, YOUTUBE_TERMS_URL } from '../constants';
|
import { getLiveStreaming } from '../functions';
|
||||||
|
|
||||||
|
import styles, { PLACEHOLDER_COLOR } from './styles';
|
||||||
|
|
||||||
type Props = AbstractProps & {
|
type Props = AbstractProps & {
|
||||||
|
|
||||||
|
@ -20,8 +22,6 @@ type Props = AbstractProps & {
|
||||||
_dialogStyles: StyleType
|
_dialogStyles: StyleType
|
||||||
};
|
};
|
||||||
|
|
||||||
import styles, { PLACEHOLDER_COLOR } from './styles';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A React Component for entering a key for starting a YouTube live stream.
|
* A React Component for entering a key for starting a YouTube live stream.
|
||||||
*
|
*
|
||||||
|
@ -148,7 +148,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onOpenGooglePrivacyPolicy() {
|
_onOpenGooglePrivacyPolicy() {
|
||||||
Linking.openURL(GOOGLE_PRIVACY_POLICY);
|
Linking.openURL(this.props._liveStreaming.dataPrivacyURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onOpenHelp: () => void;
|
_onOpenHelp: () => void;
|
||||||
|
@ -161,7 +161,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onOpenHelp() {
|
_onOpenHelp() {
|
||||||
const { helpURL } = this;
|
const helpURL = this.props._liveStreaming.helpURL;
|
||||||
|
|
||||||
if (typeof helpURL === 'string') {
|
if (typeof helpURL === 'string') {
|
||||||
Linking.openURL(helpURL);
|
Linking.openURL(helpURL);
|
||||||
|
@ -177,8 +177,25 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onOpenYoutubeTerms() {
|
_onOpenYoutubeTerms() {
|
||||||
Linking.openURL(YOUTUBE_TERMS_URL);
|
Linking.openURL(this.props._liveStreaming.termsURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(connect(_abstractMapStateToProps)(StreamKeyForm));
|
/**
|
||||||
|
* Maps (parts of) the redux state to the associated props for the
|
||||||
|
* {@code StreamKeyForm} component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @private
|
||||||
|
* @returns {{
|
||||||
|
* _liveStreaming: LiveStreamingProps
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state: Object) {
|
||||||
|
return {
|
||||||
|
..._abstractMapStateToProps(state),
|
||||||
|
_liveStreaming: getLiveStreaming(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(StreamKeyForm));
|
||||||
|
|
|
@ -4,10 +4,10 @@ import { FieldTextStateless } from '@atlaskit/field-text';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { translate } from '../../../../base/i18n';
|
import { translate } from '../../../../base/i18n';
|
||||||
|
import { connect } from '../../../../base/redux';
|
||||||
import AbstractStreamKeyForm, {
|
import AbstractStreamKeyForm, {
|
||||||
type Props
|
type Props, _mapStateToProps
|
||||||
} from '../AbstractStreamKeyForm';
|
} from '../AbstractStreamKeyForm';
|
||||||
import { GOOGLE_PRIVACY_POLICY, YOUTUBE_TERMS_URL } from '../constants';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A React Component for entering a key for starting a YouTube live stream.
|
* A React Component for entering a key for starting a YouTube live stream.
|
||||||
|
@ -62,7 +62,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
</span>
|
</span>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{ this.helpURL
|
{ this.props._liveStreaming.helpURL
|
||||||
? <a
|
? <a
|
||||||
aria-label = { t('liveStreaming.streamIdHelp') }
|
aria-label = { t('liveStreaming.streamIdHelp') }
|
||||||
className = 'helper-link'
|
className = 'helper-link'
|
||||||
|
@ -77,14 +77,14 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
className = 'helper-link'
|
className = 'helper-link'
|
||||||
href = { YOUTUBE_TERMS_URL }
|
href = { this.props._liveStreaming.termsURL }
|
||||||
rel = 'noopener noreferrer'
|
rel = 'noopener noreferrer'
|
||||||
target = '_blank'>
|
target = '_blank'>
|
||||||
{ t('liveStreaming.youtubeTerms') }
|
{ t('liveStreaming.youtubeTerms') }
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
className = 'helper-link'
|
className = 'helper-link'
|
||||||
href = { GOOGLE_PRIVACY_POLICY }
|
href = { this.props._liveStreaming.dataPrivacyURL }
|
||||||
rel = 'noopener noreferrer'
|
rel = 'noopener noreferrer'
|
||||||
target = '_blank'>
|
target = '_blank'>
|
||||||
{ t('liveStreaming.googlePrivacyPolicy') }
|
{ t('liveStreaming.googlePrivacyPolicy') }
|
||||||
|
@ -106,7 +106,7 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onOpenHelp() {
|
_onOpenHelp() {
|
||||||
window.open(this.helpURL, '_blank', 'noopener');
|
window.open(this.props._liveStreaming.helpURL, '_blank', 'noopener');
|
||||||
}
|
}
|
||||||
|
|
||||||
_onOpenHelpKeyPress: () => void;
|
_onOpenHelpKeyPress: () => void;
|
||||||
|
@ -128,4 +128,4 @@ class StreamKeyForm extends AbstractStreamKeyForm<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(StreamKeyForm);
|
export default translate(connect(_mapStateToProps)(StreamKeyForm));
|
||||||
|
|
Loading…
Reference in New Issue