rn: refactor aspect ratio and reduced UI detectors

This commit is contained in:
Saúl Ibarra Corretgé 2019-11-08 17:42:39 +01:00 committed by Saúl Ibarra Corretgé
parent 17c1f50fc3
commit fe2b1f3d9f
11 changed files with 97 additions and 186 deletions

View File

@ -9,10 +9,7 @@ import { DialogContainer } from '../../base/dialog';
import { CALL_INTEGRATION_ENABLED, updateFlags } from '../../base/flags';
import '../../base/jwt';
import { Platform } from '../../base/react';
import {
AspectRatioDetector,
ReducedUIDetector
} from '../../base/responsive-ui';
import '../../base/responsive-ui';
import { updateSettings } from '../../base/settings';
import '../../google-api';
import '../../mobile/audio-mode';
@ -110,22 +107,6 @@ export class App extends AbstractApp {
});
}
/**
* Injects {@link AspectRatioDetector} in order to detect the aspect ratio
* of this {@code App}'s user interface and afford {@link AspectRatioAware}.
*
* @override
*/
_createMainElement(component, props) {
return (
<AspectRatioDetector>
<ReducedUIDetector>
{ super._createMainElement(component, props) }
</ReducedUIDetector>
</AspectRatioDetector>
);
}
/**
* Attempts to disable the use of React Native
* {@link ExceptionsManager#handleException} on platforms and in

View File

@ -5,7 +5,6 @@ import React from 'react';
import { DialogContainer } from '../../base/dialog';
import '../../base/user-interaction';
import '../../base/responsive-ui';
import '../../chat';
import '../../external-api';
import '../../power-monitor';

View File

@ -12,9 +12,7 @@ import type { Dispatch } from 'redux';
* very brittle because it's completely disconnected from the UI which wants to
* be rendered and, naturally, it broke on iPad where even the secondary Toolbar
* didn't fit in the height. We do need to measure the actual UI at runtime and
* determine whether and how to render it. I'm bumping from 240 to 300 because I
* don't have the time now to refactor {@code ReducedUIDetector} or rip it out
* completely.
* determine whether and how to render it.
*/
const REDUCED_UI_THRESHOLD = 300;

View File

@ -1,73 +0,0 @@
// @flow
import React, { Component, type Node } from 'react';
import { type Dispatch } from 'redux';
import { connect } from '../../redux';
import { setAspectRatio } from '../actions';
import DimensionsDetector from './DimensionsDetector';
/**
* AspectRatioDetector component's property types.
*/
type Props = {
/**
* The "onDimensionsHandler" handler.
*/
_onDimensionsChanged: Function,
/**
* Any nested components.
*/
children: Node
};
/**
* A root {@link View} which captures the 'onLayout' event and figures out
* the aspect ratio of the app.
*/
class AspectRatioDetector 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 aspect ratio actions to React component props.
*
* @param {Function} dispatch - Redux action dispatcher.
* @private
* @returns {{
* _onDimensionsChanged: Function
* }}
*/
function _mapDispatchToProps(dispatch: Dispatch<any>) {
return {
/**
* Handles the "on dimensions changed" event and dispatches aspect ratio
* changed 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(setAspectRatio(width, height));
}
};
}
export default connect(undefined, _mapDispatchToProps)(AspectRatioDetector);

View File

@ -1,6 +1,6 @@
// @flow
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import { View } from 'react-native';
import styles from './styles';
@ -25,7 +25,7 @@ type Props = {
* A {@link View} which captures the 'onLayout' event and calls a prop with the
* component size.
*/
export default class DimensionsDetector extends Component<Props> {
export default class DimensionsDetector extends PureComponent<Props> {
/**
* Initializes a new DimensionsDetector instance.
*

View File

@ -1,74 +0,0 @@
// @flow
import React, { Component, type Node } from 'react';
import { type Dispatch } from 'redux';
import { connect } from '../../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: 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: Dispatch<any>) {
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,4 +1,2 @@
export * from './AspectRatioAware';
export { default as AspectRatioDetector } from './AspectRatioDetector';
export { default as DimensionsDetector } from './DimensionsDetector';
export { default as ReducedUIDetector } from './ReducedUIDetector';

View File

@ -3,4 +3,5 @@ export * from './actionTypes';
export * from './components';
export * from './constants';
import './middleware';
import './reducer';

View File

@ -0,0 +1,83 @@
// @flow
import { Dimensions } from 'react-native';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app';
import { MiddlewareRegistry } from '../../base/redux';
import { setAspectRatio, setReducedUI } from './actions';
/**
* Dimensions change handler.
*/
let handler;
/**
* Middleware that handles widnow dimension changes and updates the aspect ratio and
* reduced UI modes accordingly.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
const result = next(action);
switch (action.type) {
case APP_WILL_UNMOUNT: {
_appWillUnmount();
break;
}
case APP_WILL_MOUNT:
_appWillMount(store);
break;
}
return result;
});
/**
* Notifies this feature that the action {@link APP_WILL_MOUNT} is being
* dispatched within a specific redux {@code store}.
*
* @param {Store} store - The redux store in which the specified {@code action}
* is being dispatched.
* @private
* @returns {void}
*/
function _appWillMount(store) {
handler = dim => {
_onDimensionsChange(dim, store);
};
Dimensions.addEventListener('change', handler);
}
/**
* Notifies this feature that the action {@link APP_WILL_UNMOUNT} is being
* dispatched within a specific redux {@code store}.
*
* @private
* @returns {void}
*/
function _appWillUnmount() {
Dimensions.removeEventListener('change', handler);
handler = undefined;
}
/**
* Handles window dimension changes.
*
* @param {Object} dimensions - The new dimensions.
* @param {Store} store - The redux store.
* @private
* @returns {void}
*/
function _onDimensionsChange(dimensions, store) {
const { width, height } = dimensions.window;
const { dispatch } = store;
dispatch(setAspectRatio(width, height));
dispatch(setReducedUI(width, height));
}

View File

@ -13,16 +13,14 @@ const DEFAULT_STATE = {
reducedUI: false
};
ReducerRegistry.register(
'features/base/responsive-ui',
(state = DEFAULT_STATE, action) => {
switch (action.type) {
case SET_ASPECT_RATIO:
return set(state, 'aspectRatio', action.aspectRatio);
ReducerRegistry.register('features/base/responsive-ui', (state = DEFAULT_STATE, action) => {
switch (action.type) {
case SET_ASPECT_RATIO:
return set(state, 'aspectRatio', action.aspectRatio);
case SET_REDUCED_UI:
return set(state, 'reducedUI', action.reducedUI);
}
case SET_REDUCED_UI:
return set(state, 'reducedUI', action.reducedUI);
}
return state;
});
return state;
});