Introduce Platform in React
React Native provides a Platform abstraction which React does not provide.
This commit is contained in:
parent
7de5c9c1d2
commit
62bafcaf63
|
@ -1,16 +1,5 @@
|
||||||
import { Symbol } from '../base/react';
|
import { Symbol } from '../base/react';
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of this action sets the platform of user agent in order to decide to
|
|
||||||
* show the landing or not.
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* type: APP_SET_PLATFORM,
|
|
||||||
* platform: string
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export const APP_SET_PLATFORM = Symbol('APP_SET_PLATFORM');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the actions which signals that a specific App will mount (in the
|
* The type of the actions which signals that a specific App will mount (in the
|
||||||
* terms of React).
|
* terms of React).
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
import { setRoom } from '../base/conference';
|
import { setRoom } from '../base/conference';
|
||||||
import { getDomain, setDomain } from '../base/connection';
|
import { getDomain, setDomain } from '../base/connection';
|
||||||
import { loadConfig, setConfig } from '../base/lib-jitsi-meet';
|
import { loadConfig, setConfig } from '../base/lib-jitsi-meet';
|
||||||
import {
|
import { Platform } from '../base/react';
|
||||||
detectAndroid,
|
|
||||||
detectIOS
|
|
||||||
} from '../base/util';
|
|
||||||
|
|
||||||
import {
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
|
||||||
APP_WILL_MOUNT,
|
|
||||||
APP_WILL_UNMOUNT,
|
|
||||||
APP_SET_PLATFORM
|
|
||||||
} from './actionTypes';
|
|
||||||
import {
|
import {
|
||||||
_getRoomAndDomainFromUrlString,
|
_getRoomAndDomainFromUrlString,
|
||||||
_getRouteToRender,
|
_getRouteToRender,
|
||||||
|
@ -134,21 +127,6 @@ export function appWillUnmount(app) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects the platform of user agent and signals that platform detected.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function detectPlatform() {
|
|
||||||
return dispatch => {
|
|
||||||
if (detectAndroid()) {
|
|
||||||
dispatch(_setPlatform('android'));
|
|
||||||
} else if (detectIOS()) {
|
|
||||||
dispatch(_setPlatform('ios'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigates to route corresponding to current room name.
|
* Navigates to route corresponding to current room name.
|
||||||
*
|
*
|
||||||
|
@ -163,23 +141,6 @@ function _navigate(state) {
|
||||||
app._navigate(routeToRender);
|
app._navigate(routeToRender);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals that user agent platform is mobile and it has been already detected.
|
|
||||||
*
|
|
||||||
* @param {string} platform - Mobile user agent platform.
|
|
||||||
* @returns {{
|
|
||||||
* type: APP_SET_PLATFORM,
|
|
||||||
* platform: string
|
|
||||||
* }}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _setPlatform(platform) {
|
|
||||||
return {
|
|
||||||
type: APP_SET_PLATFORM,
|
|
||||||
platform
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets room and navigates to new route if needed.
|
* Sets room and navigates to new route if needed.
|
||||||
*
|
*
|
||||||
|
@ -194,13 +155,15 @@ function _setRoomAndNavigate(newRoom) {
|
||||||
dispatch(setRoom(newRoom));
|
dispatch(setRoom(newRoom));
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { platform } = state['features/app'];
|
|
||||||
const { room } = state['features/base/conference'];
|
const { room } = state['features/base/conference'];
|
||||||
const { landingIsShown } = state['features/landing'];
|
const { landingIsShown } = state['features/unsupported-browser'];
|
||||||
|
|
||||||
// If user agent is mobile browser and landing wasn't shown we
|
// If the user agent is a mobile browser and landing hasn't been shown
|
||||||
// should recheck which component to render.
|
// yet, we should recheck which component to render.
|
||||||
if ((platform && !landingIsShown) || room !== oldRoom) {
|
const OS = Platform.OS;
|
||||||
|
|
||||||
|
if (((OS === 'android' || OS === 'ios') && !landingIsShown)
|
||||||
|
|| room !== oldRoom) {
|
||||||
_navigate(state);
|
_navigate(state);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { appInit, detectPlatform } from '../actions';
|
import { appInit } from '../actions';
|
||||||
import { AbstractApp } from './AbstractApp';
|
import { AbstractApp } from './AbstractApp';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,6 @@ export class App extends AbstractApp {
|
||||||
componentWillMount(...args) {
|
componentWillMount(...args) {
|
||||||
super.componentWillMount(...args);
|
super.componentWillMount(...args);
|
||||||
|
|
||||||
this.props.store.dispatch(detectPlatform());
|
|
||||||
this.props.store.dispatch(appInit());
|
this.props.store.dispatch(appInit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
/* global APP, JitsiMeetJS, loggingConfig */
|
/* global APP, JitsiMeetJS, loggingConfig */
|
||||||
|
|
||||||
|
import { isRoomValid } from '../base/conference';
|
||||||
|
import { RouteRegistry } from '../base/navigator';
|
||||||
|
import { Platform } from '../base/react';
|
||||||
|
import { Conference } from '../conference';
|
||||||
|
import { Landing } from '../unsupported-browser';
|
||||||
|
import { WelcomePage } from '../welcome';
|
||||||
|
|
||||||
import URLProcessor from '../../../modules/config/URLProcessor';
|
import URLProcessor from '../../../modules/config/URLProcessor';
|
||||||
import KeyboardShortcut
|
import KeyboardShortcut
|
||||||
from '../../../modules/keyboardshortcut/keyboardshortcut';
|
from '../../../modules/keyboardshortcut/keyboardshortcut';
|
||||||
|
@ -7,13 +14,6 @@ import settings from '../../../modules/settings/Settings';
|
||||||
import getTokenData from '../../../modules/tokendata/TokenData';
|
import getTokenData from '../../../modules/tokendata/TokenData';
|
||||||
import JitsiMeetLogStorage from '../../../modules/util/JitsiMeetLogStorage';
|
import JitsiMeetLogStorage from '../../../modules/util/JitsiMeetLogStorage';
|
||||||
|
|
||||||
import { detectIOS, detectAndroid } from '../base/util';
|
|
||||||
|
|
||||||
// XXX We should import landing feature here in order to update router registry.
|
|
||||||
import { Landing } from '../landing';
|
|
||||||
import { Conference } from '../conference';
|
|
||||||
import { WelcomePage } from '../welcome';
|
|
||||||
|
|
||||||
const Logger = require('jitsi-meet-logger');
|
const Logger = require('jitsi-meet-logger');
|
||||||
|
|
||||||
export { _getRoomAndDomainFromUrlString } from './functions.native';
|
export { _getRoomAndDomainFromUrlString } from './functions.native';
|
||||||
|
@ -27,20 +27,22 @@ export { _getRoomAndDomainFromUrlString } from './functions.native';
|
||||||
* @returns {Route}
|
* @returns {Route}
|
||||||
*/
|
*/
|
||||||
export function _getRouteToRender(stateOrGetState) {
|
export function _getRouteToRender(stateOrGetState) {
|
||||||
|
const OS = Platform.OS;
|
||||||
const state
|
const state
|
||||||
= typeof stateOrGetState === 'function'
|
= typeof stateOrGetState === 'function'
|
||||||
? stateOrGetState()
|
? stateOrGetState()
|
||||||
: stateOrGetState;
|
: stateOrGetState;
|
||||||
|
|
||||||
const { platform } = state['features/app'];
|
// If landing was shown, there is no need to show it again.
|
||||||
const { room } = state['features/base/conference'];
|
const { landingIsShown } = state['features/unsupported-browser'];
|
||||||
const { landingIsShown } = state['features/landing'];
|
let component;
|
||||||
|
|
||||||
let component = isRoomValid(room) ? Conference : WelcomePage;
|
if ((OS === 'android' || OS === 'ios') && !landingIsShown) {
|
||||||
|
component = Landing;
|
||||||
|
} else {
|
||||||
|
const { room } = state['features/base/conference'];
|
||||||
|
|
||||||
// If landing was shown there is no need to show it again.
|
component = isRoomValid(room) ? Conference : WelcomePage;
|
||||||
if (platform && !landingIsShown) {
|
|
||||||
component = detectAndroid() || detectIOS() ? Landing : component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return RouteRegistry.getRouteByComponent(component);
|
return RouteRegistry.getRouteByComponent(component);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import { ReducerRegistry } from '../base/redux';
|
import { ReducerRegistry } from '../base/redux';
|
||||||
|
|
||||||
import {
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
|
||||||
APP_WILL_MOUNT,
|
|
||||||
APP_WILL_UNMOUNT,
|
|
||||||
APP_SET_PLATFORM
|
|
||||||
} from './actionTypes';
|
|
||||||
|
|
||||||
ReducerRegistry.register('features/app', (state = {}, action) => {
|
ReducerRegistry.register('features/app', (state = {}, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
@ -32,13 +28,6 @@ ReducerRegistry.register('features/app', (state = {}, action) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APP_SET_PLATFORM:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
platform: action.platform
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
* Returns true if user agent is run on Android.
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function detectAndroid() {
|
|
||||||
return Boolean(navigator.userAgent.match(/Android/i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if user agent is run on iOS.
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function detectIOS() {
|
|
||||||
return Boolean(navigator.userAgent.match(/iP(ad|hone|od)/i));
|
|
||||||
}
|
|
|
@ -1,3 +1,2 @@
|
||||||
export * from './detectDevices';
|
|
||||||
export * from './loadScript';
|
export * from './loadScript';
|
||||||
export * from './roomnameGenerator';
|
export * from './roomnameGenerator';
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { ReducerRegistry } from '../base/redux';
|
|
||||||
|
|
||||||
import { LANDING_IS_SHOWN } from './actionTypes';
|
|
||||||
|
|
||||||
ReducerRegistry.register('features/landing', (state = {}, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case LANDING_IS_SHOWN:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag that shows that mobile landing is shown.
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
landingIsShown: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
});
|
|
|
@ -2,11 +2,17 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
|
||||||
|
import { Platform } from '../../base/react';
|
||||||
|
|
||||||
import { landingIsShown } from '../actions';
|
import { landingIsShown } from '../actions';
|
||||||
|
|
||||||
const LINKS = {
|
/**
|
||||||
'android': 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
|
* The map of platforms to URLs at which the mobile app for the associated
|
||||||
'ios': 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905'
|
* platform is available for download.
|
||||||
|
*/
|
||||||
|
const URLS = {
|
||||||
|
android: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
|
||||||
|
ios: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,9 +21,13 @@ const LINKS = {
|
||||||
* @class Landing
|
* @class Landing
|
||||||
*/
|
*/
|
||||||
class Landing extends Component {
|
class Landing extends Component {
|
||||||
|
/**
|
||||||
|
* Landing component's property types.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: React.PropTypes.func,
|
dispatch: React.PropTypes.func,
|
||||||
platform: React.PropTypes.string,
|
|
||||||
room: React.PropTypes.string
|
room: React.PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +69,6 @@ class Landing extends Component {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { platform } = this.props;
|
|
||||||
const { btnText, link } = this.state;
|
const { btnText, link } = this.state;
|
||||||
const primaryButtonClasses = 'landing__button landing__button_primary';
|
const primaryButtonClasses = 'landing__button landing__button_primary';
|
||||||
|
|
||||||
|
@ -70,22 +79,23 @@ class Landing extends Component {
|
||||||
className = 'landing__logo'
|
className = 'landing__logo'
|
||||||
src = '/images/logo-blue.svg' />
|
src = '/images/logo-blue.svg' />
|
||||||
<p className = 'landing__text'>
|
<p className = 'landing__text'>
|
||||||
You need <strong>Jitsi Meet</strong> to join a
|
You need <strong>Jitsi Meet</strong> to join a
|
||||||
conversation on your mobile
|
conversation on your mobile
|
||||||
</p>
|
</p>
|
||||||
<a href = { LINKS[platform] }>
|
<a href = { URLS[Platform.OS] }>
|
||||||
<button
|
<button className = { primaryButtonClasses }>
|
||||||
className = { primaryButtonClasses }>
|
|
||||||
Download the App
|
Download the App
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<p className = 'landing__text landing__text_small'>
|
<p className = 'landing__text landing__text_small'>
|
||||||
or if you already have it
|
or if you already have it
|
||||||
<br /><strong>then</strong>
|
<br />
|
||||||
|
<strong>then</strong>
|
||||||
</p>
|
</p>
|
||||||
<Link to = { link }>
|
<Link to = { link }>
|
||||||
<button
|
<button className = 'landing__button'>
|
||||||
className = 'landing__button'>{ btnText }</button>
|
{ btnText }
|
||||||
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,13 +108,11 @@ class Landing extends Component {
|
||||||
*
|
*
|
||||||
* @param {Object} state - Redux state.
|
* @param {Object} state - Redux state.
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* platform: string,
|
|
||||||
* room: string
|
* room: string
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
platform: state['features/app'].platform,
|
|
||||||
room: state['features/base/conference'].room
|
room: state['features/base/conference'].room
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ReducerRegistry } from '../base/redux';
|
||||||
|
|
||||||
|
import { LANDING_IS_SHOWN } from './actionTypes';
|
||||||
|
|
||||||
|
ReducerRegistry.register(
|
||||||
|
'features/unsupported-browser',
|
||||||
|
(state = {}, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case LANDING_IS_SHOWN:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag that shows that mobile landing is shown.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
landingIsShown: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
});
|
Loading…
Reference in New Issue