Add initial welcome page
This commit is contained in:
parent
6f35ddd792
commit
4773b12a3b
|
@ -1,6 +1,7 @@
|
|||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/node_modules/@atlaskit/.*/*.js.flow
|
||||
.*/build/.*
|
||||
.*/node_modules/electron-packager/test/fixtures/infer-malformed-json/.*
|
||||
|
||||
[include]
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { Conference } from '../../conference';
|
||||
import config from '../../config';
|
||||
import { Welcome } from '../../welcome';
|
||||
|
||||
/**
|
||||
* Main component encapsulating the entire application.
|
||||
|
@ -28,7 +32,19 @@ export default class App extends Component<*> {
|
|||
*/
|
||||
render() {
|
||||
return (
|
||||
<Conference />
|
||||
<AtlasKitThemeProvider mode = 'dark'>
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
component = { Welcome }
|
||||
path = '/' />
|
||||
<Route
|
||||
component = { Conference }
|
||||
path = '/:domain?/:room' />
|
||||
</Switch>
|
||||
</Router>
|
||||
</AtlasKitThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, *> {
|
||||
/**
|
||||
* Attach the script
|
||||
* Reference to the element of this component.
|
||||
*/
|
||||
_ref: Object;
|
||||
|
||||
/**
|
||||
* External API object.
|
||||
*/
|
||||
_api: Object;
|
||||
|
||||
/**
|
||||
* 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';
|
|
@ -3,8 +3,6 @@
|
|||
<head>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
body {
|
||||
|
|
|
@ -5,6 +5,11 @@ import { render } from 'react-dom';
|
|||
|
||||
import { App } from './features/app';
|
||||
|
||||
/**
|
||||
* AtlasKit components will deflect from appearance if css-reset is not present.
|
||||
*/
|
||||
import '@atlaskit/css-reset';
|
||||
|
||||
/**
|
||||
* Render the main / root application.
|
||||
* $FlowFixMe
|
||||
|
|
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
|
@ -30,10 +30,16 @@
|
|||
"readmeFilename": "README.md",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@atlaskit/button": "7.2.5",
|
||||
"@atlaskit/css-reset": "2.0.2",
|
||||
"@atlaskit/field-text": "5.1.0",
|
||||
"@atlaskit/theme": "3.2.2",
|
||||
"electron-is-dev": "0.3.0",
|
||||
"jitsi-meet-electron-utils": "jitsi/jitsi-meet-electron-utils",
|
||||
"react": "16.3.2",
|
||||
"react-dom": "16.3.2"
|
||||
"react-dom": "16.3.2",
|
||||
"react-router-dom": "4.2.2",
|
||||
"styled-components": "3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "6.26.3",
|
||||
|
@ -41,6 +47,7 @@
|
|||
"babel-loader": "7.1.4",
|
||||
"babel-preset-env": "1.7.0",
|
||||
"babel-preset-react": "6.24.1",
|
||||
"css-loader": "0.28.11",
|
||||
"electron": "2.0.0",
|
||||
"electron-packager": "12.0.2",
|
||||
"electron-rebuild": "1.7.3",
|
||||
|
@ -54,6 +61,7 @@
|
|||
"html-webpack-plugin": "3.2.0",
|
||||
"node-loader": "0.6.0",
|
||||
"precommit-hook": "3.0.0",
|
||||
"style-loader": "0.21.0",
|
||||
"webpack": "4.8.1",
|
||||
"webpack-cli": "2.1.3"
|
||||
}
|
||||
|
|
|
@ -25,6 +25,13 @@ const commonConfig = {
|
|||
},
|
||||
test: /\.js$/
|
||||
},
|
||||
{
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader' }
|
||||
],
|
||||
test: /\.css$/
|
||||
},
|
||||
{
|
||||
use: 'node-loader',
|
||||
test: /\.node$/
|
||||
|
|
Loading…
Reference in New Issue