

18 changed files with 1589 additions and 60 deletions
@ -1,59 +1,120 @@
|
||||
// @flow
|
||||
|
||||
import { Component } from 'react'; |
||||
import React, { Component } from 'react'; |
||||
|
||||
import { |
||||
RemoteControl, |
||||
setupScreenSharingForWindow, |
||||
setupAlwaysOnTopRender, |
||||
setupWiFiStats |
||||
|
||||
// $FlowFixMe
|
||||
} from 'jitsi-meet-electron-utils'; |
||||
|
||||
import config from '../../config'; |
||||
|
||||
import { Wrapper } from '../styled'; |
||||
|
||||
type Props = { |
||||
|
||||
/** |
||||
* React Router history object. |
||||
* This contains implementations for managing session history. |
||||
*/ |
||||
history: Object; |
||||
|
||||
/** |
||||
* React Router match object. |
||||
* This contains parameters passed through <Route /> component. |
||||
*/ |
||||
match: Object; |
||||
}; |
||||
|
||||
/** |
||||
* Conference component. |
||||
*/ |
||||
export default class Conference extends Component<*> { |
||||
export default class Conference extends Component<Props, *> { |
||||
/** |
||||
* Reference to the element of this component. |
||||
*/ |
||||
_ref: Object; |
||||
|
||||
/** |
||||
* External API object. |
||||
*/ |
||||
_api: Object; |
||||
|
||||
/** |
||||
* Attach the script |
||||
* Initializes a new {@code Conference} instance. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
constructor() { |
||||
super(); |
||||
|
||||
this._ref = React.createRef(); |
||||
} |
||||
|
||||
/** |
||||
* Attach the script to this component. |
||||
*/ |
||||
componentDidMount() { |
||||
const parentNode = this._ref.current; |
||||
const room = this.props.match.params.room; |
||||
const domain = this.props.match.params.domain || config.defaultDomain; |
||||
|
||||
const script = document.createElement('script'); |
||||
|
||||
script.async = true; |
||||
script.onload = this._onScriptLoad; |
||||
script.onerror = console.error; |
||||
script.src = `https://${config.defaultDomain}/external_api.js`; |
||||
script.onload = () => this._onScriptLoad(parentNode, room, domain); |
||||
script.onerror = () => this._navigateToHome(); |
||||
script.src = `https://${domain}/external_api.js`; |
||||
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(script); |
||||
this._ref.current.appendChild(script); |
||||
} |
||||
|
||||
/** |
||||
* Remove conference on unmounting. |
||||
*/ |
||||
componentWillUnmount() { |
||||
if (this._api) { |
||||
this._api.dispose(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Render function of component. |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @return {ReactElement} |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
return null; |
||||
return <Wrapper innerRef={this._ref} />; |
||||
} |
||||
|
||||
/** |
||||
* When the script is loaded attach utils from jitsi-meet-electron-utils |
||||
* Navigates to home screen (Welcome). |
||||
*/ |
||||
_onScriptLoad() { |
||||
_navigateToHome() { |
||||
this.props.history.push('/'); |
||||
} |
||||
|
||||
/** |
||||
* When the script is loaded create the iframe element in this component |
||||
* and attach utils from jitsi-meet-electron-utils. |
||||
*/ |
||||
_onScriptLoad(parentNode: Object, roomName: string, domain: string) { |
||||
const JitsiMeetExternalAPI = window.JitsiMeetExternalAPI; |
||||
|
||||
const api = new JitsiMeetExternalAPI(config.defaultDomain); |
||||
const iframe = api.getIFrame(); |
||||
this._api = new JitsiMeetExternalAPI(domain, { |
||||
parentNode, |
||||
roomName |
||||
}); |
||||
const iframe = this._api.getIFrame(); |
||||
|
||||
setupScreenSharingForWindow(iframe); |
||||
new RemoteControl(iframe); // eslint-disable-line no-new
|
||||
setupAlwaysOnTopRender(api); |
||||
setupAlwaysOnTopRender(this._api); |
||||
setupWiFiStats(iframe); |
||||
|
||||
this._api.on('readyToClose', () => this._navigateToHome()); |
||||
} |
||||
} |
||||
|
@ -1 +1,3 @@
|
||||
export * from './components'; |
||||
export * from './styled'; |
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import styled from 'styled-components'; |
||||
|
||||
export default styled.div` |
||||
height: 100vh; |
||||
`;
|
@ -0,0 +1 @@
|
||||
export { default as Wrapper } from './Wrapper'; |
@ -0,0 +1,124 @@
|
||||
// @flow
|
||||
|
||||
import { AtlasKitThemeProvider } from '@atlaskit/theme'; |
||||
import Button from '@atlaskit/button'; |
||||
import { FieldTextStateless } from '@atlaskit/field-text'; |
||||
|
||||
import React, { Component } from 'react'; |
||||
import URL from 'url'; |
||||
|
||||
import { WelcomeWrapper as Wrapper, Content, Form } from '../styled'; |
||||
|
||||
|
||||
type Props = { |
||||
|
||||
/** |
||||
* React Router history object. |
||||
* This contains implementations for managing session history. |
||||
*/ |
||||
history: Object; |
||||
}; |
||||
|
||||
type State = { |
||||
|
||||
/** |
||||
* URL of the room to join. |
||||
* If this is not a url it will be treated as room name for default domain. |
||||
*/ |
||||
url: string; |
||||
}; |
||||
|
||||
/** |
||||
* Welcome Component. |
||||
*/ |
||||
export default class Welcome extends Component<Props, State> { |
||||
/** |
||||
* Initializes a new {@code Welcome} instance. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
constructor(props: Props) { |
||||
super(props); |
||||
|
||||
this.state = { |
||||
url: '' |
||||
}; |
||||
|
||||
// Bind event handlers.
|
||||
this._onURLChange = this._onURLChange.bind(this); |
||||
this._onFormSubmit = this._onFormSubmit.bind(this); |
||||
this._onJoin = this._onJoin.bind(this); |
||||
} |
||||
|
||||
/** |
||||
* Render function of component. |
||||
* |
||||
* @return {ReactElement} |
||||
*/ |
||||
render() { |
||||
return ( |
||||
<AtlasKitThemeProvider mode = 'light'> |
||||
<Wrapper> |
||||
<Content> |
||||
<Form onSubmit = { this._onFormSubmit }> |
||||
<FieldTextStateless |
||||
autoFocus = { true } |
||||
isLabelHidden = { true } |
||||
shouldFitContainer = { true } |
||||
onChange = { this._onURLChange } |
||||
type = 'text' |
||||
value = { this.state.url } /> |
||||
</Form> |
||||
<Button |
||||
appearance = 'primary' |
||||
type = 'button' |
||||
onClick = { this._onJoin }> |
||||
GO |
||||
</Button> |
||||
</Content> |
||||
</Wrapper> |
||||
</AtlasKitThemeProvider> |
||||
); |
||||
} |
||||
|
||||
_onFormSubmit: (*) => void; |
||||
|
||||
/** |
||||
* Prevents submission of the form and delegates the join logic. |
||||
*/ |
||||
_onFormSubmit(event: Event) { |
||||
event.preventDefault(); |
||||
this._onJoin(); |
||||
} |
||||
|
||||
_onJoin: (*) => void; |
||||
|
||||
/** |
||||
* Redirect and join conference. |
||||
*/ |
||||
_onJoin() { |
||||
const url = URL.parse(this.state.url); |
||||
|
||||
// Check if the parsed url is a full url or just room name.
|
||||
if (url.host && url.path) { |
||||
|
||||
// This will be triggered when the full url is present.
|
||||
this.props.history.push(url.host + url.path); |
||||
} else { |
||||
|
||||
// Directly to the the path.
|
||||
this.props.history.push(url.path); |
||||
} |
||||
} |
||||
|
||||
_onURLChange: (*) => void; |
||||
|
||||
/** |
||||
* Keeps URL input value and URL in state in sync. |
||||
*/ |
||||
_onURLChange(event: SyntheticInputEvent<HTMLInputElement>) { |
||||
this.setState({ |
||||
url: event.currentTarget.value |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1 @@
|
||||
export { default as Welcome } from './Welcome'; |
@ -0,0 +1,2 @@
|
||||
export * from './components'; |
||||
export * from './styled'; |
@ -0,0 +1,10 @@
|
||||
// @flow
|
||||
|
||||
import styled from 'styled-components'; |
||||
|
||||
export default styled.div` |
||||
align-items: center; |
||||
display: flex; |
||||
margin: 0 auto; |
||||
padding: 30px; |
||||
`;
|
@ -0,0 +1,8 @@
|
||||
// Flow
|
||||
|
||||
import styled from 'styled-components'; |
||||
|
||||
export default styled.form` |
||||
width: 350px; |
||||
margin: 0 15px; |
||||
`;
|
@ -0,0 +1,9 @@
|
||||
// @flow
|
||||
|
||||
import styled from 'styled-components'; |
||||
|
||||
export default styled.div` |
||||
background: linear-gradient(#165ecc,#44A5FF); |
||||
display: flex; |
||||
height: 100vh; |
||||
`;
|
@ -0,0 +1,3 @@
|
||||
export { default as Content } from './Content'; |
||||
export { default as Form } from './Form'; |
||||
export { default as WelcomeWrapper } from './WelcomeWrapper'; |
Loading…
Reference in new issue