Apply setNavigatorStyles to all navigation components (#3122)
This commit is contained in:
parent
90dba40a92
commit
c1957ac6a0
10 changed files with 79 additions and 29 deletions
|
|
@ -291,7 +291,11 @@ export function dismissModal(options = {}) {
|
|||
return () => {
|
||||
const componentId = EphemeralStore.getNavigationTopComponentId();
|
||||
|
||||
Navigation.dismissModal(componentId, options);
|
||||
Navigation.dismissModal(componentId, options).catch(() => {
|
||||
// RNN returns a promise rejection if there is no modal to
|
||||
// dismiss. We'll do nothing in this case but we will catch
|
||||
// the rejection here so that the caller doesn't have to.
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {
|
||||
Platform,
|
||||
|
|
@ -20,7 +19,6 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
|||
export default class DisplaySettings extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
applyTheme: PropTypes.func.isRequired,
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
|
|
@ -37,15 +35,6 @@ export default class DisplaySettings extends PureComponent {
|
|||
showClockDisplaySettings: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.navigationEventListener = Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidAppear() {
|
||||
const {actions, componentId} = this.props;
|
||||
actions.applyTheme(componentId);
|
||||
}
|
||||
|
||||
closeClockDisplaySettings = () => {
|
||||
this.setState({showClockDisplaySettings: false});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ jest.mock('react-intl');
|
|||
describe('DisplaySettings', () => {
|
||||
const baseProps = {
|
||||
actions: {
|
||||
applyTheme: jest.fn(),
|
||||
goToScreen: jest.fn(),
|
||||
},
|
||||
theme: Preferences.THEMES.default,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {connect} from 'react-redux';
|
|||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isTimezoneEnabled} from 'mattermost-redux/selectors/entities/timezone';
|
||||
|
||||
import {applyTheme, goToScreen} from 'app/actions/navigation';
|
||||
import {goToScreen} from 'app/actions/navigation';
|
||||
import {getAllowedThemes} from 'app/selectors/theme';
|
||||
import {isThemeSwitchingEnabled} from 'app/utils/theme';
|
||||
|
||||
|
|
@ -28,7 +28,6 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
goToScreen,
|
||||
applyTheme,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {getCurrentUrl, getConfig} from 'mattermost-redux/selectors/entities/gene
|
|||
import {getJoinableTeams} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {applyTheme, goToScreen, dismissModal} from 'app/actions/navigation';
|
||||
import {goToScreen, dismissModal} from 'app/actions/navigation';
|
||||
import {purgeOfflineStore} from 'app/actions/views/root';
|
||||
import {removeProtocol} from 'app/utils/url';
|
||||
|
||||
|
|
@ -32,7 +32,6 @@ function mapStateToProps(state) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
applyTheme,
|
||||
clearErrors,
|
||||
purgeOfflineStore,
|
||||
goToScreen,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import LocalConfig from 'assets/config';
|
|||
class Settings extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
applyTheme: PropTypes.func.isRequired,
|
||||
clearErrors: PropTypes.func.isRequired,
|
||||
purgeOfflineStore: PropTypes.func.isRequired,
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
|
|
@ -51,11 +50,6 @@ class Settings extends PureComponent {
|
|||
this.navigationEventListener = Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidAppear() {
|
||||
const {actions, componentId} = this.props;
|
||||
actions.applyTheme(componentId, true);
|
||||
}
|
||||
|
||||
navigationButtonPressed({buttonId}) {
|
||||
if (buttonId === 'close-settings') {
|
||||
this.props.actions.dismissModal();
|
||||
|
|
|
|||
|
|
@ -6,14 +6,16 @@ import {Text, View} from 'react-native';
|
|||
import PropTypes from 'prop-types';
|
||||
import {intlShape} from 'react-intl';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import Section from 'app/screens/settings/section';
|
||||
import SectionItem from 'app/screens/settings/section_item';
|
||||
import ThemeTile from './theme_tile';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
|
||||
import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme';
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
import EphemeralStore from 'app/store/ephemeral_store';
|
||||
|
||||
import ThemeTile from './theme_tile';
|
||||
|
||||
const thumbnailImages = {
|
||||
default: require('assets/images/themes/mattermost.png'),
|
||||
|
|
@ -56,7 +58,9 @@ export default class Theme extends React.PureComponent {
|
|||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.theme !== this.props.theme) {
|
||||
setNavigatorStyles(this.props.componentId, this.props.theme);
|
||||
EphemeralStore.allNavigationComponentIds.forEach((componentId) => {
|
||||
setNavigatorStyles(componentId, this.props.theme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,23 @@
|
|||
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
import EphemeralStore from 'app/store/ephemeral_store';
|
||||
|
||||
import Theme from './theme';
|
||||
import ThemeTile from './theme_tile';
|
||||
|
||||
jest.mock('react-intl');
|
||||
|
||||
jest.mock('react-native-navigation', () => ({
|
||||
Navigation: {
|
||||
mergeOptions: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const allowedThemes = [
|
||||
{
|
||||
type: 'Mattermost',
|
||||
|
|
@ -143,4 +152,43 @@ describe('Theme', () => {
|
|||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
expect(wrapper.find(ThemeTile)).toHaveLength(4);
|
||||
});
|
||||
|
||||
test('should call Navigation.mergeOptions on all navigation components when theme changes', () => {
|
||||
const componentIds = ['component-1', 'component-2', 'component-3'];
|
||||
componentIds.forEach((componentId) => {
|
||||
EphemeralStore.addNavigationComponentId(componentId);
|
||||
});
|
||||
|
||||
const wrapper = shallow(
|
||||
<Theme {...baseProps}/>,
|
||||
);
|
||||
|
||||
const newTheme = allowedThemes[1];
|
||||
wrapper.setProps({theme: newTheme});
|
||||
|
||||
const options = {
|
||||
topBar: {
|
||||
backButton: {
|
||||
color: newTheme.sidebarHeaderTextColor,
|
||||
},
|
||||
background: {
|
||||
color: newTheme.sidebarHeaderBg,
|
||||
},
|
||||
title: {
|
||||
color: newTheme.sidebarHeaderTextColor,
|
||||
},
|
||||
leftButtonColor: newTheme.sidebarHeaderTextColor,
|
||||
rightButtonColor: newTheme.sidebarHeaderTextColor,
|
||||
},
|
||||
layout: {
|
||||
backgroundColor: newTheme.centerChannelBg,
|
||||
},
|
||||
};
|
||||
|
||||
expect(Navigation.mergeOptions.mock.calls).toEqual([
|
||||
[componentIds[2], options],
|
||||
[componentIds[1], options],
|
||||
[componentIds[0], options],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,20 +7,31 @@ class EphemeralStore {
|
|||
this.appStartedFromPushNotification = false;
|
||||
this.deviceToken = null;
|
||||
this.navigationComponentIdStack = [];
|
||||
this.allNavigationComponentIds = [];
|
||||
this.currentServerUrl = null;
|
||||
}
|
||||
|
||||
getNavigationTopComponentId = () => this.navigationComponentIdStack[0];
|
||||
getNavigationComponentIds = () => this.navigationComponentIdStack;
|
||||
|
||||
addNavigationComponentId = (componentId) => {
|
||||
this.addToNavigationComponentIdStack(componentId);
|
||||
this.addToAllNavigationComponentIds(componentId);
|
||||
};
|
||||
|
||||
addToNavigationComponentIdStack = (componentId) => {
|
||||
const index = this.navigationComponentIdStack.indexOf(componentId);
|
||||
if (index > 0) {
|
||||
this.navigationComponentIdStack.slice(index, 1);
|
||||
}
|
||||
|
||||
this.navigationComponentIdStack.unshift(componentId);
|
||||
};
|
||||
}
|
||||
|
||||
addToAllNavigationComponentIds = (componentId) => {
|
||||
if (!this.allNavigationComponentIds.includes(componentId)) {
|
||||
this.allNavigationComponentIds.unshift(componentId);
|
||||
}
|
||||
}
|
||||
|
||||
removeNavigationComponentId = (componentId) => {
|
||||
const index = this.navigationComponentIdStack.indexOf(componentId);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ export function setNavigatorStyles(componentId, theme) {
|
|||
},
|
||||
leftButtonColor: theme.sidebarHeaderTextColor,
|
||||
rightButtonColor: theme.sidebarHeaderTextColor,
|
||||
backButton: {
|
||||
color: theme.sidebarHeaderTextColor,
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
|
|
|
|||
Loading…
Reference in a new issue