feat(prejoin) Expose prejoin app
This commit is contained in:
parent
f376542441
commit
0e5091adba
|
@ -1,17 +1,21 @@
|
||||||
/**
|
/**
|
||||||
* Shared style for full screen local track based dialogs/modals.
|
* Shared style for full screen local track based dialogs/modals.
|
||||||
*/
|
*/
|
||||||
.premeeting-screen {
|
.premeeting-screen,
|
||||||
|
.preview-overlay {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.premeeting-screen {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
background: #1C2025;
|
background: radial-gradient(50% 50% at 50% 50%, #5D95C7 0%, #376288 100%), #FFFFFF;
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
z-index: $toolbarZ + 1;
|
z-index: $toolbarZ + 1;
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
|
@ -74,9 +78,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-overlay {
|
||||||
|
background-image: linear-gradient(transparent, black);
|
||||||
|
z-index: $toolbarZ + 1;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-image: linear-gradient(transparent, black);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
10
index.html
10
index.html
|
@ -8,7 +8,17 @@
|
||||||
|
|
||||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||||
<link rel="stylesheet" href="css/all.css">
|
<link rel="stylesheet" href="css/all.css">
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
if (!JitsiMeetJS.app) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JitsiMeetJS.app.renderEntryPoint({
|
||||||
|
Component: JitsiMeetJS.app.entryPoints.APP
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
<script>
|
<script>
|
||||||
// IE11 and earlier can be identified via their user agent and be
|
// IE11 and earlier can be identified via their user agent and be
|
||||||
// redirected to a page that is known to have no newer js syntax.
|
// redirected to a page that is known to have no newer js syntax.
|
||||||
|
|
|
@ -122,14 +122,14 @@ export default class BaseApp extends Component<*, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { route: { component }, store } = this.state;
|
const { route: { component, props }, store } = this.state;
|
||||||
|
|
||||||
if (store) {
|
if (store) {
|
||||||
return (
|
return (
|
||||||
<I18nextProvider i18n = { i18next }>
|
<I18nextProvider i18n = { i18next }>
|
||||||
<Provider store = { store }>
|
<Provider store = { store }>
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{ this._createMainElement(component) }
|
{ this._createMainElement(component, props) }
|
||||||
<SoundCollection />
|
<SoundCollection />
|
||||||
{ this._createExtraElement() }
|
{ this._createExtraElement() }
|
||||||
{ this._renderDialogContainer() }
|
{ this._renderDialogContainer() }
|
||||||
|
|
|
@ -24,6 +24,16 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
name?: string,
|
name?: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the avatar should be shown when video is off
|
||||||
|
*/
|
||||||
|
showAvatar: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the label and copy url action should be shown
|
||||||
|
*/
|
||||||
|
showConferenceInfo: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title of the screen.
|
* Title of the screen.
|
||||||
*/
|
*/
|
||||||
|
@ -45,13 +55,23 @@ type Props = {
|
||||||
* on the prejoin screen (pre-connection) or lobby (post-connection).
|
* on the prejoin screen (pre-connection) or lobby (post-connection).
|
||||||
*/
|
*/
|
||||||
export default class PreMeetingScreen extends PureComponent<Props> {
|
export default class PreMeetingScreen extends PureComponent<Props> {
|
||||||
|
/**
|
||||||
|
* Default values for {@code Prejoin} component's properties.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
static defaultProps = {
|
||||||
|
showAvatar: true,
|
||||||
|
showConferenceInfo: true
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements {@code PureComponent#render}.
|
* Implements {@code PureComponent#render}.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { name, title, videoMuted, videoTrack } = this.props;
|
const { name, showAvatar, showConferenceInfo, title, videoMuted, videoTrack } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -59,13 +79,19 @@ export default class PreMeetingScreen extends PureComponent<Props> {
|
||||||
id = 'lobby-screen'>
|
id = 'lobby-screen'>
|
||||||
<Preview
|
<Preview
|
||||||
name = { name }
|
name = { name }
|
||||||
|
showAvatar = { showAvatar }
|
||||||
videoMuted = { videoMuted }
|
videoMuted = { videoMuted }
|
||||||
videoTrack = { videoTrack } />
|
videoTrack = { videoTrack } />
|
||||||
|
{!videoMuted && <div className = 'preview-overlay' />}
|
||||||
<div className = 'content'>
|
<div className = 'content'>
|
||||||
<div className = 'title'>
|
{showConferenceInfo && (
|
||||||
{ title }
|
<>
|
||||||
</div>
|
<div className = 'title'>
|
||||||
<CopyMeetingUrl />
|
{ title }
|
||||||
|
</div>
|
||||||
|
<CopyMeetingUrl />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
<div className = 'media-btn-container'>
|
<div className = 'media-btn-container'>
|
||||||
<AudioSettingsButton visible = { true } />
|
<AudioSettingsButton visible = { true } />
|
||||||
|
|
|
@ -14,6 +14,11 @@ export type Props = {
|
||||||
*/
|
*/
|
||||||
name: string,
|
name: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the avatar should be shown when video is off
|
||||||
|
*/
|
||||||
|
showAvatar: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag signaling the visibility of camera preview.
|
* Flag signaling the visibility of camera preview.
|
||||||
*/
|
*/
|
||||||
|
@ -32,7 +37,7 @@ export type Props = {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
function Preview(props: Props) {
|
function Preview(props: Props) {
|
||||||
const { name, videoMuted, videoTrack } = props;
|
const { name, showAvatar, videoMuted, videoTrack } = props;
|
||||||
|
|
||||||
if (!videoMuted && videoTrack) {
|
if (!videoMuted && videoTrack) {
|
||||||
return (
|
return (
|
||||||
|
@ -44,19 +49,27 @@ function Preview(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
if (showAvatar) {
|
||||||
<div
|
return (
|
||||||
className = 'no-video'
|
<div
|
||||||
id = 'preview'>
|
className = 'no-video'
|
||||||
<Avatar
|
id = 'preview'>
|
||||||
className = 'preview-avatar'
|
<Avatar
|
||||||
displayName = { name }
|
className = 'preview-avatar'
|
||||||
participantId = 'local'
|
displayName = { name }
|
||||||
size = { 200 } />
|
participantId = 'local'
|
||||||
</div>
|
size = { 200 } />
|
||||||
);
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Preview.defaultProps = {
|
||||||
|
showAvatar: true
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps part of the Redux state to the props of this component.
|
* Maps part of the Redux state to the props of this component.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* global APP */
|
/* global APP */
|
||||||
|
|
||||||
import JitsiMeetJS, { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
|
import JitsiMeetJS, { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
|
||||||
import { MEDIA_TYPE } from '../media';
|
import { MEDIA_TYPE, setAudioMuted } from '../media';
|
||||||
import {
|
import {
|
||||||
getUserSelectedCameraDeviceId,
|
getUserSelectedCameraDeviceId,
|
||||||
getUserSelectedMicDeviceId
|
getUserSelectedMicDeviceId
|
||||||
|
@ -125,6 +125,89 @@ export function createLocalTracksF(options = {}, firePermissionPromptIsShownEven
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object containing a promise which resolves with the created tracks &
|
||||||
|
* the errors resulting from that process.
|
||||||
|
*
|
||||||
|
* @returns {Promise<JitsiLocalTrack>}
|
||||||
|
*
|
||||||
|
* @todo Refactor to not use APP
|
||||||
|
*/
|
||||||
|
export function createPrejoinTracks() {
|
||||||
|
const errors = {};
|
||||||
|
const initialDevices = [ 'audio' ];
|
||||||
|
const requestedAudio = true;
|
||||||
|
let requestedVideo = false;
|
||||||
|
const { startAudioOnly, startWithAudioMuted, startWithVideoMuted } = APP.store.getState()['features/base/settings'];
|
||||||
|
|
||||||
|
// Always get a handle on the audio input device so that we have statistics even if the user joins the
|
||||||
|
// conference muted. Previous implementation would only acquire the handle when the user first unmuted,
|
||||||
|
// which would results in statistics ( such as "No audio input" or "Are you trying to speak?") being available
|
||||||
|
// only after that point.
|
||||||
|
if (startWithAudioMuted) {
|
||||||
|
APP.store.dispatch(setAudioMuted(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!startWithVideoMuted && !startAudioOnly) {
|
||||||
|
initialDevices.push('video');
|
||||||
|
requestedVideo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tryCreateLocalTracks;
|
||||||
|
|
||||||
|
if (!requestedAudio && !requestedVideo) {
|
||||||
|
// Resolve with no tracks
|
||||||
|
tryCreateLocalTracks = Promise.resolve([]);
|
||||||
|
} else {
|
||||||
|
tryCreateLocalTracks = createLocalTracksF({ devices: initialDevices }, true)
|
||||||
|
.catch(err => {
|
||||||
|
if (requestedAudio && requestedVideo) {
|
||||||
|
|
||||||
|
// Try audio only...
|
||||||
|
errors.audioAndVideoError = err;
|
||||||
|
|
||||||
|
return (
|
||||||
|
createLocalTracksF({ devices: [ 'audio' ] }, true));
|
||||||
|
} else if (requestedAudio && !requestedVideo) {
|
||||||
|
errors.audioOnlyError = err;
|
||||||
|
|
||||||
|
return [];
|
||||||
|
} else if (requestedVideo && !requestedAudio) {
|
||||||
|
errors.videoOnlyError = err;
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
logger.error('Should never happen');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
// Log this just in case...
|
||||||
|
if (!requestedAudio) {
|
||||||
|
logger.error('The impossible just happened', err);
|
||||||
|
}
|
||||||
|
errors.audioOnlyError = err;
|
||||||
|
|
||||||
|
// Try video only...
|
||||||
|
return requestedVideo
|
||||||
|
? createLocalTracksF({ devices: [ 'video' ] }, true)
|
||||||
|
: [];
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
// Log this just in case...
|
||||||
|
if (!requestedVideo) {
|
||||||
|
logger.error('The impossible just happened', err);
|
||||||
|
}
|
||||||
|
errors.videoOnlyError = err;
|
||||||
|
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tryCreateLocalTracks,
|
||||||
|
errors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns local audio track.
|
* Returns local audio track.
|
||||||
*
|
*
|
||||||
|
|
|
@ -143,6 +143,10 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
if (typeof APP !== 'undefined') {
|
if (typeof APP !== 'undefined') {
|
||||||
const result = next(action);
|
const result = next(action);
|
||||||
|
|
||||||
|
if (isPrejoinPageVisible(store.getState())) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const { jitsiTrack } = action.track;
|
const { jitsiTrack } = action.track;
|
||||||
const muted = jitsiTrack.isMuted();
|
const muted = jitsiTrack.isMuted();
|
||||||
const participantID = jitsiTrack.getParticipantId();
|
const participantID = jitsiTrack.getParticipantId();
|
||||||
|
|
|
@ -79,11 +79,21 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
setJoinByPhoneDialogVisiblity: Function,
|
setJoinByPhoneDialogVisiblity: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the avatar should be shown when video is off
|
||||||
|
*/
|
||||||
|
showAvatar: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag signaling the visibility of camera preview.
|
* Flag signaling the visibility of camera preview.
|
||||||
*/
|
*/
|
||||||
showCameraPreview: boolean,
|
showCameraPreview: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag signaling the visibility of join label, input and buttons
|
||||||
|
*/
|
||||||
|
showJoinActions: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If 'JoinByPhoneDialog' is visible or not.
|
* If 'JoinByPhoneDialog' is visible or not.
|
||||||
*/
|
*/
|
||||||
|
@ -112,6 +122,15 @@ type State = {
|
||||||
* This component is displayed before joining a meeting.
|
* This component is displayed before joining a meeting.
|
||||||
*/
|
*/
|
||||||
class Prejoin extends Component<Props, State> {
|
class Prejoin extends Component<Props, State> {
|
||||||
|
/**
|
||||||
|
* Default values for {@code Prejoin} component's properties.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
static defaultProps = {
|
||||||
|
showJoinActions: true
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code Prejoin} instance.
|
* Initializes a new {@code Prejoin} instance.
|
||||||
*
|
*
|
||||||
|
@ -223,8 +242,10 @@ class Prejoin extends Component<Props, State> {
|
||||||
joinConference,
|
joinConference,
|
||||||
joinConferenceWithoutAudio,
|
joinConferenceWithoutAudio,
|
||||||
name,
|
name,
|
||||||
|
showAvatar,
|
||||||
showCameraPreview,
|
showCameraPreview,
|
||||||
showDialog,
|
showDialog,
|
||||||
|
showJoinActions,
|
||||||
t,
|
t,
|
||||||
videoTrack
|
videoTrack
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -236,61 +257,65 @@ class Prejoin extends Component<Props, State> {
|
||||||
<PreMeetingScreen
|
<PreMeetingScreen
|
||||||
footer = { this._renderFooter() }
|
footer = { this._renderFooter() }
|
||||||
name = { name }
|
name = { name }
|
||||||
|
showAvatar = { showAvatar }
|
||||||
|
showConferenceInfo = { showJoinActions }
|
||||||
title = { t('prejoin.joinMeeting') }
|
title = { t('prejoin.joinMeeting') }
|
||||||
videoMuted = { !showCameraPreview }
|
videoMuted = { !showCameraPreview }
|
||||||
videoTrack = { videoTrack }>
|
videoTrack = { videoTrack }>
|
||||||
<div className = 'prejoin-input-area-container'>
|
{showJoinActions && (
|
||||||
<div className = 'prejoin-input-area'>
|
<div className = 'prejoin-input-area-container'>
|
||||||
<InputField
|
<div className = 'prejoin-input-area'>
|
||||||
onChange = { _setName }
|
<InputField
|
||||||
onSubmit = { joinConference }
|
onChange = { _setName }
|
||||||
placeHolder = { t('dialog.enterDisplayName') }
|
onSubmit = { joinConference }
|
||||||
value = { name } />
|
placeHolder = { t('dialog.enterDisplayName') }
|
||||||
|
value = { name } />
|
||||||
|
|
||||||
<div className = 'prejoin-preview-dropdown-container'>
|
<div className = 'prejoin-preview-dropdown-container'>
|
||||||
<InlineDialog
|
<InlineDialog
|
||||||
content = { <div className = 'prejoin-preview-dropdown-btns'>
|
content = { <div className = 'prejoin-preview-dropdown-btns'>
|
||||||
<div
|
<div
|
||||||
className = 'prejoin-preview-dropdown-btn'
|
className = 'prejoin-preview-dropdown-btn'
|
||||||
onClick = { joinConferenceWithoutAudio }>
|
onClick = { joinConferenceWithoutAudio }>
|
||||||
<Icon
|
<Icon
|
||||||
className = 'prejoin-preview-dropdown-icon'
|
className = 'prejoin-preview-dropdown-icon'
|
||||||
size = { 24 }
|
size = { 24 }
|
||||||
src = { IconVolumeOff } />
|
src = { IconVolumeOff } />
|
||||||
{ t('prejoin.joinWithoutAudio') }
|
{ t('prejoin.joinWithoutAudio') }
|
||||||
</div>
|
</div>
|
||||||
{hasJoinByPhoneButton && <div
|
{hasJoinByPhoneButton && <div
|
||||||
className = 'prejoin-preview-dropdown-btn'
|
className = 'prejoin-preview-dropdown-btn'
|
||||||
onClick = { _showDialog }>
|
onClick = { _showDialog }>
|
||||||
<Icon
|
<Icon
|
||||||
className = 'prejoin-preview-dropdown-icon'
|
className = 'prejoin-preview-dropdown-icon'
|
||||||
size = { 24 }
|
size = { 24 }
|
||||||
src = { IconPhone } />
|
src = { IconPhone } />
|
||||||
{ t('prejoin.joinAudioByPhone') }
|
{ t('prejoin.joinAudioByPhone') }
|
||||||
</div>}
|
</div>}
|
||||||
</div> }
|
</div> }
|
||||||
isOpen = { showJoinByPhoneButtons }
|
isOpen = { showJoinByPhoneButtons }
|
||||||
onClose = { _onDropdownClose }>
|
onClose = { _onDropdownClose }>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
disabled = { joinButtonDisabled }
|
disabled = { joinButtonDisabled }
|
||||||
hasOptions = { true }
|
hasOptions = { true }
|
||||||
onClick = { joinConference }
|
onClick = { joinConference }
|
||||||
onOptionsClick = { _onOptionsClick }
|
onOptionsClick = { _onOptionsClick }
|
||||||
type = 'primary'>
|
type = 'primary'>
|
||||||
{ t('prejoin.joinMeeting') }
|
{ t('prejoin.joinMeeting') }
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</InlineDialog>
|
</InlineDialog>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className = 'prejoin-checkbox-container'>
|
||||||
|
<input
|
||||||
|
className = 'prejoin-checkbox'
|
||||||
|
onChange = { _onCheckboxChange }
|
||||||
|
type = 'checkbox' />
|
||||||
|
<span>{t('prejoin.doNotShow')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div className = 'prejoin-checkbox-container'>
|
|
||||||
<input
|
|
||||||
className = 'prejoin-checkbox'
|
|
||||||
onChange = { _onCheckboxChange }
|
|
||||||
type = 'checkbox' />
|
|
||||||
<span>{t('prejoin.doNotShow')}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{ showDialog && (
|
{ showDialog && (
|
||||||
<JoinByPhoneDialog
|
<JoinByPhoneDialog
|
||||||
joinConferenceWithoutAudio = { joinConferenceWithoutAudio }
|
joinConferenceWithoutAudio = { joinConferenceWithoutAudio }
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { BaseApp } from '../../../features/base/app';
|
||||||
|
import { setConfig } from '../../base/config';
|
||||||
|
import { createPrejoinTracks } from '../../base/tracks';
|
||||||
|
import { initPrejoin } from '../actions';
|
||||||
|
|
||||||
|
import Prejoin from './Prejoin';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the avatar should be shown when video is off
|
||||||
|
*/
|
||||||
|
showAvatar: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag signaling the visibility of join label, input and buttons
|
||||||
|
*/
|
||||||
|
showJoinActions: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper application for prejoin.
|
||||||
|
*
|
||||||
|
* @extends BaseApp
|
||||||
|
*/
|
||||||
|
export default class PrejoinApp extends BaseApp<Props> {
|
||||||
|
_init: Promise<*>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to {@link Prejoin} upon mount.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
componentDidMount() {
|
||||||
|
super.componentDidMount();
|
||||||
|
|
||||||
|
this._init.then(async () => {
|
||||||
|
const { store } = this.state;
|
||||||
|
const { dispatch } = store;
|
||||||
|
const { showAvatar, showJoinActions } = this.props;
|
||||||
|
|
||||||
|
super._navigate({
|
||||||
|
component: Prejoin,
|
||||||
|
props: {
|
||||||
|
showAvatar,
|
||||||
|
showJoinActions
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { startWithAudioMuted, startWithVideoMuted } = store.getState()['features/base/settings'];
|
||||||
|
|
||||||
|
dispatch(setConfig({
|
||||||
|
prejoinPageEnabled: true,
|
||||||
|
startWithAudioMuted,
|
||||||
|
startWithVideoMuted
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { tryCreateLocalTracks, errors } = createPrejoinTracks();
|
||||||
|
|
||||||
|
const tracks = await tryCreateLocalTracks;
|
||||||
|
|
||||||
|
dispatch(initPrejoin(tracks, errors));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the parent method to inject {@link AtlasKitThemeProvider} as
|
||||||
|
* the top most component.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
_createMainElement(component, props) {
|
||||||
|
return (
|
||||||
|
<AtlasKitThemeProvider mode = 'dark'>
|
||||||
|
{ super._createMainElement(component, props) }
|
||||||
|
</AtlasKitThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the platform specific dialog container.
|
||||||
|
*
|
||||||
|
* @returns {React$Element}
|
||||||
|
*/
|
||||||
|
_renderDialogContainer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ import { getJitsiMeetTransport } from '../modules/transport';
|
||||||
import { App } from './features/app/components';
|
import { App } from './features/app/components';
|
||||||
import { getLogger } from './features/base/logging/functions';
|
import { getLogger } from './features/base/logging/functions';
|
||||||
import { Platform } from './features/base/react';
|
import { Platform } from './features/base/react';
|
||||||
|
import { getJitsiMeetGlobalNS } from './features/base/util';
|
||||||
|
import PrejoinApp from './features/prejoin/components/PrejoinApp';
|
||||||
|
|
||||||
const logger = getLogger('index.web');
|
const logger = getLogger('index.web');
|
||||||
const OS = Platform.OS;
|
const OS = Platform.OS;
|
||||||
|
@ -20,9 +22,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
APP.connectionTimes['document.ready'] = now;
|
APP.connectionTimes['document.ready'] = now;
|
||||||
logger.log('(TIME) document ready:\t', now);
|
logger.log('(TIME) document ready:\t', now);
|
||||||
|
|
||||||
// Render the main/root Component.
|
|
||||||
ReactDOM.render(<App />, document.getElementById('react'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Workaround for the issue when returning to a page with the back button and
|
// Workaround for the issue when returning to a page with the back button and
|
||||||
|
@ -56,3 +55,21 @@ window.addEventListener('beforeunload', () => {
|
||||||
APP.API.dispose();
|
APP.API.dispose();
|
||||||
getJitsiMeetTransport().dispose();
|
getJitsiMeetTransport().dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const globalNS = getJitsiMeetGlobalNS();
|
||||||
|
|
||||||
|
globalNS.entryPoints = {
|
||||||
|
APP: App,
|
||||||
|
PREJOIN: PrejoinApp
|
||||||
|
};
|
||||||
|
|
||||||
|
globalNS.renderEntryPoint = ({
|
||||||
|
Component,
|
||||||
|
props = {},
|
||||||
|
elementId = 'react'
|
||||||
|
}) => {
|
||||||
|
ReactDOM.render(
|
||||||
|
<Component { ...props } />,
|
||||||
|
document.getElementById(elementId)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<html xmlns="http://www.w3.org/1999/html">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<!--#include virtual="/base.html" -->
|
||||||
|
<link rel="stylesheet" href="../css/all.css">
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
if (!JitsiMeetJS.app) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
const params = new URLSearchParams(url.search);
|
||||||
|
const showAvatar = params.get('showAvatar') === 'true';
|
||||||
|
const showJoinActions = params.get('showJoinActions') === 'true';
|
||||||
|
const css = params.get('style');
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.appendChild(document.createTextNode(css));
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
JitsiMeetJS.app.renderEntryPoint({
|
||||||
|
Component: JitsiMeetJS.app.entryPoints.PREJOIN,
|
||||||
|
props: {
|
||||||
|
showAvatar,
|
||||||
|
showJoinActions
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<!--#include virtual="/title.html" -->
|
||||||
|
<script>var config = {}</script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||||
|
<script>var interfaceConfig = {}</script>
|
||||||
|
<script src="../libs/lib-jitsi-meet.min.js?v=139"></script>
|
||||||
|
<script src="../libs/app.bundle.min.js?v=139"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="react"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue