Add Dialog utilities

In order to accommodate the requirements of the work on supporting XMPP
authentication on mobile/react-native, make dealing with Dialog a
little more generic and a little easier.
This commit is contained in:
Lyubo Marinov 2017-09-18 15:52:10 -05:00
parent 088fe87e31
commit 9c47a7e972
5 changed files with 75 additions and 26 deletions

View File

@ -1,15 +1,24 @@
/* @flow */
import { HIDE_DIALOG, OPEN_DIALOG } from './actionTypes';
import { isDialogOpen } from './functions';
/**
* Signals Dialog to close its dialog.
*
* @param {Object} [component] - The <tt>Dialog</tt> component to close/hide. If
* <tt>undefined</tt>, closes/hides <tt>Dialog</tt> regardless of which
* component it's rendering; otherwise, closes/hides <tt>Dialog</tt> only if
* it's rendering the specified <tt>component</tt>.
* @returns {{
* type: HIDE_DIALOG
* type: HIDE_DIALOG,
* component: (React.Component | undefined)
* }}
*/
export function hideDialog() {
export function hideDialog(component: ?Object) {
return {
type: HIDE_DIALOG
type: HIDE_DIALOG,
component
};
}
@ -19,9 +28,13 @@ export function hideDialog() {
* @param {Object} component - The component to display as dialog.
* @param {Object} [componentProps] - The React <tt>Component</tt> props of the
* specified <tt>component</tt>.
* @returns {Object}
* @returns {{
* type: OPEN_DIALOG,
* component: React.Component,
* componentProps: (Object | undefined)
* }}
*/
export function openDialog(component, componentProps) {
export function openDialog(component: Object, componentProps: ?Object) {
return {
type: OPEN_DIALOG,
component,
@ -37,12 +50,12 @@ export function openDialog(component, componentProps) {
* @param {Object} component - The component to display as dialog.
* @param {Object} [componentProps] - The React <tt>Component</tt> props of the
* specified <tt>component</tt>.
* @returns {Object}
* @returns {Function}
*/
export function toggleDialog(component, componentProps) {
return (dispatch, getState) => {
if (getState()['features/base/dialog'].component === component) {
dispatch(hideDialog());
export function toggleDialog(component: Object, componentProps: ?Object) {
return (dispatch: Dispatch, getState: Function) => {
if (isDialogOpen(getState, component)) {
dispatch(hideDialog(component));
} else {
dispatch(openDialog(component, componentProps));
}

View File

@ -0,0 +1,17 @@
/* @flow */
import { toState } from '../redux';
/**
* Checks if a <tt>Dialog</tt> with a specific <tt>component</tt> is currently
* open.
*
* @param {Function|Object} stateful - The redux store, the redux
* <tt>getState</tt> function, or the redux state itself.
* @param {React.Component} component - The <tt>component</tt> of a
* <tt>Dialog</tt> to be checked.
* @returns {boolean}
*/
export function isDialogOpen(stateful: Function | Object, component: Object) {
return toState(stateful)['features/base/dialog'].component === component;
}

View File

@ -1,5 +1,6 @@
export * from './actions';
export * from './actionTypes';
export * from './components';
export * from './functions';
import './reducer';

View File

@ -1,3 +1,5 @@
/* @flow */
import { assign, ReducerRegistry } from '../redux';
import { HIDE_DIALOG, OPEN_DIALOG } from './actionTypes';
@ -13,11 +15,17 @@ import { HIDE_DIALOG, OPEN_DIALOG } from './actionTypes';
*/
ReducerRegistry.register('features/base/dialog', (state = {}, action) => {
switch (action.type) {
case HIDE_DIALOG:
return assign(state, {
component: undefined,
componentProps: undefined
});
case HIDE_DIALOG: {
const { component } = action;
if (typeof component === 'undefined' || state.component === component) {
return assign(state, {
component: undefined,
componentProps: undefined
});
}
break;
}
case OPEN_DIALOG:
return assign(state, {

View File

@ -112,18 +112,28 @@ function _set(
/* eslint-enable max-params */
/**
* If the specified <tt>stateOrGetState</tt> is a function, it is presumed to be
* the redux {@link getState} function, it is invoked, and its return value is
* returned; otherwise, <tt>stateOrGetState</tt> is presumed to be the redux
* state and is returned.
* Returns redux state from the specified <tt>stateful</tt> which is presumed to
* be related to the redux state (e.g. the redux store, the redux
* <tt>getState</tt> function).
*
* @param {Object|Function} stateOrGetState - The redux state or
* {@link getState} function.
* @param {Function|Object} stateful - The entity such as the redux store or the
* redux <tt>getState</tt> function from which the redux state is to be
* returned.
* @returns {Object} The redux state.
*/
export function toState(stateOrGetState: Object | Function) {
return (
typeof stateOrGetState === 'function'
? stateOrGetState()
: stateOrGetState);
export function toState(stateful: Function | Object) {
if (stateful) {
if (typeof stateful === 'function') {
return stateful();
}
const { getState } = stateful;
if (typeof getState === 'function'
&& typeof stateful.dispatch === 'function') {
return getState();
}
}
return stateful;
}