Browse Source

Add initial welcome page

fix-builder
Akshit Kr Nagpal 4 years ago committed by Saúl Ibarra Corretgé
parent
commit
4773b12a3b
  1. 3
      .flowconfig
  2. 18
      app/features/app/components/App.js
  3. 97
      app/features/conference/components/Conference.js
  4. 2
      app/features/conference/index.js
  5. 7
      app/features/conference/styled/Wrapper.js
  6. 1
      app/features/conference/styled/index.js
  7. 124
      app/features/welcome/components/Welcome.js
  8. 1
      app/features/welcome/components/index.js
  9. 2
      app/features/welcome/index.js
  10. 10
      app/features/welcome/styled/Content.js
  11. 8
      app/features/welcome/styled/Form.js
  12. 9
      app/features/welcome/styled/WelcomeWrapper.js
  13. 3
      app/features/welcome/styled/index.js
  14. 2
      app/index.html
  15. 5
      app/index.js
  16. 1340
      package-lock.json
  17. 10
      package.json
  18. 7
      webpack.config.js

3
.flowconfig

@ -1,6 +1,7 @@
[ignore]
.*/node_modules/.*
.*/node_modules/@atlaskit/.*/*.js.flow
.*/build/.*
.*/node_modules/electron-packager/test/fixtures/infer-malformed-json/.*
[include]

18
app/features/app/components/App.js

@ -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>
);
}
}

97
app/features/conference/components/Conference.js

@ -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());
}
}

2
app/features/conference/index.js

@ -1 +1,3 @@
export * from './components';
export * from './styled';

7
app/features/conference/styled/Wrapper.js

@ -0,0 +1,7 @@
// @flow
import styled from 'styled-components';
export default styled.div`
height: 100vh;
`;

1
app/features/conference/styled/index.js

@ -0,0 +1 @@
export { default as Wrapper } from './Wrapper';

124
app/features/welcome/components/Welcome.js

@ -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
});
}
}

1
app/features/welcome/components/index.js

@ -0,0 +1 @@
export { default as Welcome } from './Welcome';

2
app/features/welcome/index.js

@ -0,0 +1,2 @@
export * from './components';
export * from './styled';

10
app/features/welcome/styled/Content.js

@ -0,0 +1,10 @@
// @flow
import styled from 'styled-components';
export default styled.div`
align-items: center;
display: flex;
margin: 0 auto;
padding: 30px;
`;

8
app/features/welcome/styled/Form.js

@ -0,0 +1,8 @@
// Flow
import styled from 'styled-components';
export default styled.form`
width: 350px;
margin: 0 15px;
`;

9
app/features/welcome/styled/WelcomeWrapper.js

@ -0,0 +1,9 @@
// @flow
import styled from 'styled-components';
export default styled.div`
background: linear-gradient(#165ecc,#44A5FF);
display: flex;
height: 100vh;
`;

3
app/features/welcome/styled/index.js

@ -0,0 +1,3 @@
export { default as Content } from './Content';
export { default as Form } from './Form';
export { default as WelcomeWrapper } from './WelcomeWrapper';

2
app/index.html

@ -3,8 +3,6 @@
<head>
<style>
body, html {
margin: 0;
height: 100%;
overflow: hidden;
}
body {

5
app/index.js

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

1340
package-lock.json generated

File diff suppressed because it is too large Load Diff

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"
}

7
webpack.config.js

@ -25,6 +25,13 @@ const commonConfig = {
},
test: /\.js$/
},
{
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
],
test: /\.css$/
},
{
use: 'node-loader',
test: /\.node$/

Loading…
Cancel
Save