[RN] Add a "reduced UI" mode

It's detected based on a size threshold.
This commit is contained in:
Saúl Ibarra Corretgé 2018-02-02 14:39:27 +01:00 committed by Lyubo Marinov
parent c9d8b5c827
commit 5305557ce5
7 changed files with 130 additions and 5 deletions

View File

@ -7,7 +7,10 @@ import { Linking } from 'react-native';
import '../../analytics';
import '../../authentication';
import { Platform } from '../../base/react';
import { AspectRatioDetector } from '../../base/responsive-ui';
import {
AspectRatioDetector,
ReducedUIDetector
} from '../../base/responsive-ui';
import '../../mobile/audio-mode';
import '../../mobile/background';
import '../../mobile/callkit';
@ -97,7 +100,9 @@ export class App extends AbstractApp {
_createElement(component, props) {
return (
<AspectRatioDetector>
{ super._createElement(component, props) }
<ReducedUIDetector>
{ super._createElement(component, props) }
</ReducedUIDetector>
</AspectRatioDetector>
);
}

View File

@ -1,6 +1,7 @@
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import React from 'react';
import '../../base/responsive-ui';
import { getLocationContextRoot } from '../../base/util';
import '../../room-lock';

View File

@ -8,3 +8,16 @@
* }
*/
export const SET_ASPECT_RATIO = Symbol('SET_ASPECT_RATIO');
/**
* The type of redux action which signals that the reduces UI mode was enabled
* or disabled.
*
* {
* type: SET_REDUCED_UI,
* reducedUI: boolean
* }
*
* @public
*/
export const SET_REDUCED_UI = Symbol('SET_REDUCED_UI');

View File

@ -1,10 +1,15 @@
// @flow
import { SET_ASPECT_RATIO } from './actionTypes';
import { SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes';
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants';
import type { Dispatch } from 'redux';
/**
* Size threshold for determining if we are in reduced UI mode or not.
*/
const REDUCED_UI_THRESHOLD = 240;
/**
* Sets the aspect ratio of the app's user interface based on specific width and
* height.
@ -34,3 +39,27 @@ export function setAspectRatio(width: number, height: number): Object {
}
};
}
/**
* Sets the "reduced UI" property. In reduced UI mode some components will
* be hidden if there is no space to render them.
*
* @param {number} width - Current usable width.
* @param {number} height - Current usable height.
* @returns {{
* type: SET_REDUCED_UI,
* reducedUI: boolean
* }}
*/
export function setReducedUI(width: number, height: number) {
return (dispatch: Dispatch<*>, getState: Function) => {
const reducedUI = Math.min(width, height) < REDUCED_UI_THRESHOLD;
if (reducedUI !== getState()['features/base/responsive-ui'].reducedUI) {
return dispatch({
type: SET_REDUCED_UI,
reducedUI
});
}
};
}

View File

@ -0,0 +1,72 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setReducedUI } from '../actions';
import DimensionsDetector from './DimensionsDetector';
/**
* ReducedUIDetector component's property types.
*/
type Props = {
/**
* The "onDimensionsHandler" handler.
*/
_onDimensionsChanged: Function,
/**
* Any nested components.
*/
children: React$Node
};
/**
* A root {@link View} which captures the 'onLayout' event and figures out
* if the UI is reduced.
*/
class ReducedUIDetector extends Component<Props> {
/**
* Renders the root view and it's children.
*
* @returns {Component}
*/
render() {
return (
<DimensionsDetector
onDimensionsChanged = { this.props._onDimensionsChanged } >
{ this.props.children }
</DimensionsDetector>
);
}
}
/**
* Maps dispatching of the reduced UI actions to React component props.
*
* @param {Function} dispatch - Redux action dispatcher.
* @private
* @returns {{
* _onDimensionsChanged: Function
* }}
*/
function _mapDispatchToProps(dispatch) {
return {
/**
* Handles the "on dimensions changed" event and dispatches the
* reduced UI action.
*
* @param {number} width - The new width for the component.
* @param {number} height - The new height for the component.
* @private
* @returns {void}
*/
_onDimensionsChanged(width: number, height: number) {
dispatch(setReducedUI(width, height));
}
};
}
export default connect(undefined, _mapDispatchToProps)(ReducedUIDetector);

View File

@ -1,3 +1,4 @@
export * from './AspectRatioAware';
export { default as AspectRatioDetector } from './AspectRatioDetector';
export { default as DimensionsDetector } from './DimensionsDetector';
export { default as ReducedUIDetector } from './ReducedUIDetector';

View File

@ -1,13 +1,14 @@
import { ReducerRegistry, set } from '../redux';
import { SET_ASPECT_RATIO } from './actionTypes';
import { SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes';
import { ASPECT_RATIO_NARROW } from './constants';
/**
* The initial redux state of the feature base/responsive-ui.
*/
const _INITIAL_STATE = {
aspectRatio: ASPECT_RATIO_NARROW
aspectRatio: ASPECT_RATIO_NARROW,
reducedUI: false
};
ReducerRegistry.register(
@ -16,6 +17,9 @@ ReducerRegistry.register(
switch (action.type) {
case SET_ASPECT_RATIO:
return set(state, 'aspectRatio', action.aspectRatio);
case SET_REDUCED_UI:
return set(state, 'reducedUI', action.reducedUI);
}
return state;