From c1957ac6a0ac42da13a13f02a06627488f4fcb05 Mon Sep 17 00:00:00 2001 From: Mattermost Build Date: Wed, 14 Aug 2019 20:06:57 +0200 Subject: [PATCH] Apply setNavigatorStyles to all navigation components (#3122) --- app/actions/navigation.js | 6 ++- .../display_settings/display_settings.js | 11 ----- .../display_settings/display_settings.test.js | 1 - .../settings/display_settings/index.js | 3 +- app/screens/settings/general/index.js | 3 +- app/screens/settings/general/settings.js | 6 --- app/screens/settings/theme/theme.js | 12 +++-- app/screens/settings/theme/theme.test.js | 48 +++++++++++++++++++ app/store/ephemeral_store.js | 15 +++++- app/utils/theme.js | 3 ++ 10 files changed, 79 insertions(+), 29 deletions(-) diff --git a/app/actions/navigation.js b/app/actions/navigation.js index 219bb26a7..11a186b89 100644 --- a/app/actions/navigation.js +++ b/app/actions/navigation.js @@ -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. + }); }; } diff --git a/app/screens/settings/display_settings/display_settings.js b/app/screens/settings/display_settings/display_settings.js index c134f7997..268cfc41c 100644 --- a/app/screens/settings/display_settings/display_settings.js +++ b/app/screens/settings/display_settings/display_settings.js @@ -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}); }; diff --git a/app/screens/settings/display_settings/display_settings.test.js b/app/screens/settings/display_settings/display_settings.test.js index 8f485108d..4d91bf1c8 100644 --- a/app/screens/settings/display_settings/display_settings.test.js +++ b/app/screens/settings/display_settings/display_settings.test.js @@ -16,7 +16,6 @@ jest.mock('react-intl'); describe('DisplaySettings', () => { const baseProps = { actions: { - applyTheme: jest.fn(), goToScreen: jest.fn(), }, theme: Preferences.THEMES.default, diff --git a/app/screens/settings/display_settings/index.js b/app/screens/settings/display_settings/index.js index ab325072a..12d4b321f 100644 --- a/app/screens/settings/display_settings/index.js +++ b/app/screens/settings/display_settings/index.js @@ -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), }; } diff --git a/app/screens/settings/general/index.js b/app/screens/settings/general/index.js index 146d2b866..09cc293ab 100644 --- a/app/screens/settings/general/index.js +++ b/app/screens/settings/general/index.js @@ -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, diff --git a/app/screens/settings/general/settings.js b/app/screens/settings/general/settings.js index fe7ed1637..94cbdba27 100644 --- a/app/screens/settings/general/settings.js +++ b/app/screens/settings/general/settings.js @@ -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(); diff --git a/app/screens/settings/theme/theme.js b/app/screens/settings/theme/theme.js index 152132345..75cb5e39e 100644 --- a/app/screens/settings/theme/theme.js +++ b/app/screens/settings/theme/theme.js @@ -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); + }); } } diff --git a/app/screens/settings/theme/theme.test.js b/app/screens/settings/theme/theme.test.js index 38dc10bce..53318bc99 100644 --- a/app/screens/settings/theme/theme.test.js +++ b/app/screens/settings/theme/theme.test.js @@ -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( + , + ); + + 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], + ]); + }); }); diff --git a/app/store/ephemeral_store.js b/app/store/ephemeral_store.js index eeb451f44..574fb029f 100644 --- a/app/store/ephemeral_store.js +++ b/app/store/ephemeral_store.js @@ -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); diff --git a/app/utils/theme.js b/app/utils/theme.js index c8c751371..c34157796 100644 --- a/app/utils/theme.js +++ b/app/utils/theme.js @@ -31,6 +31,9 @@ export function setNavigatorStyles(componentId, theme) { }, leftButtonColor: theme.sidebarHeaderTextColor, rightButtonColor: theme.sidebarHeaderTextColor, + backButton: { + color: theme.sidebarHeaderTextColor, + }, }, layout: { backgroundColor: theme.centerChannelBg,