Skip to content

Commit e8e808d

Browse files
committed
navActions: Stop dispatching all actions via Redux.
Instead, dispatch them via our recently added `NavigationService`. Add a few notes in `InitialNavigationDispatcher` about why we expect `NavigationService` to be ready in time. We chose to do the initial navigation here, rather than in a descendant of the `NavigationService`'s `ref`fed component for those reasons [1]. [1] #4274 (comment)
1 parent dcfc3c7 commit e8e808d

24 files changed

+100
-72
lines changed

src/account-info/ProfileCard.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { PureComponent } from 'react';
33
import { ScrollView, View } from 'react-native';
44
import type { NavigationTabProp, NavigationStateRoute } from 'react-navigation-tabs';
55

6+
import NavigationService from '../nav/NavigationService';
67
import type { Dispatch, User } from '../types';
78
import { createStyleSheet } from '../styles';
89
import { connect } from '../react-redux';
@@ -28,10 +29,9 @@ const styles = createStyleSheet({
2829
},
2930
});
3031

31-
class SetStatusButton extends PureComponent<{| +dispatch: Dispatch |}> {
32+
class SetStatusButton extends PureComponent<{||}> {
3233
onPress = () => {
33-
const { dispatch } = this.props;
34-
dispatch(navigateToUserStatus());
34+
NavigationService.dispatch(navigateToUserStatus());
3535
};
3636

3737
render() {
@@ -41,9 +41,9 @@ class SetStatusButton extends PureComponent<{| +dispatch: Dispatch |}> {
4141
}
4242
}
4343

44-
class SwitchAccountButton extends PureComponent<{| +dispatch: Dispatch |}> {
44+
class SwitchAccountButton extends PureComponent<{||}> {
4545
onPress = () => {
46-
this.props.dispatch(navigateToAccountPicker());
46+
NavigationService.dispatch(navigateToAccountPicker());
4747
};
4848

4949
render() {
@@ -91,10 +91,10 @@ class ProfileCard extends PureComponent<Props> {
9191
<AccountDetails user={selfUserDetail} />
9292
<AwayStatusSwitch />
9393
<View style={styles.buttonRow}>
94-
<SetStatusButton dispatch={this.props.dispatch} />
94+
<SetStatusButton />
9595
</View>
9696
<View style={styles.buttonRow}>
97-
<SwitchAccountButton dispatch={this.props.dispatch} />
97+
<SwitchAccountButton />
9898
<LogoutButton dispatch={this.props.dispatch} />
9999
</View>
100100
</ScrollView>

src/account/AccountPickScreen.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import React, { PureComponent } from 'react';
44
import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack';
55

6+
import NavigationService from '../nav/NavigationService';
67
import type { Dispatch } from '../types';
78
import { connect } from '../react-redux';
89
import { hasAuth, getAccountStatuses } from '../selectors';
@@ -32,7 +33,7 @@ class AccountPickScreen extends PureComponent<Props> {
3233
dispatch(accountSwitch(index));
3334
});
3435
} else {
35-
dispatch(navigateToRealmScreen({ realm }));
36+
NavigationService.dispatch(navigateToRealmScreen({ realm }));
3637
}
3738
};
3839

@@ -53,7 +54,7 @@ class AccountPickScreen extends PureComponent<Props> {
5354
canGoBack = this.props.hasAuth;
5455

5556
render() {
56-
const { accounts, dispatch } = this.props;
57+
const { accounts } = this.props;
5758

5859
return (
5960
<Screen
@@ -74,7 +75,7 @@ class AccountPickScreen extends PureComponent<Props> {
7475
<ZulipButton
7576
text="Add new account"
7677
onPress={() => {
77-
dispatch(navigateToRealmScreen());
78+
NavigationService.dispatch(navigateToRealmScreen());
7879
}}
7980
/>
8081
</Centerer>

src/account/accountActions.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* @flow strict-local */
2+
import NavigationService from '../nav/NavigationService';
23
import type { Action, Dispatch, GetState } from '../types';
34
import {
45
ACCOUNT_SWITCH,
@@ -16,7 +17,7 @@ const accountSwitchPlain = (index: number): Action => ({
1617
});
1718

1819
export const accountSwitch = (index: number) => (dispatch: Dispatch, getState: GetState) => {
19-
dispatch(resetToLoading());
20+
NavigationService.dispatch(resetToLoading());
2021
dispatch(accountSwitchPlain(index));
2122
};
2223

@@ -47,7 +48,7 @@ export const loginSuccess = (realm: URL, email: string, apiKey: string) => (
4748
dispatch: Dispatch,
4849
getState: GetState,
4950
) => {
50-
dispatch(resetToLoading());
51+
NavigationService.dispatch(resetToLoading());
5152
dispatch(loginSuccessPlain(realm, email, apiKey));
5253
};
5354

@@ -56,6 +57,6 @@ const logoutPlain = (): Action => ({
5657
});
5758

5859
export const logout = () => async (dispatch: Dispatch, getState: GetState) => {
59-
dispatch(resetToAccountPicker());
60+
NavigationService.dispatch(resetToAccountPicker());
6061
dispatch(logoutPlain());
6162
};

src/compose/ComposeMenu.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Platform, View } from 'react-native';
44
import type { DocumentPickerResponse } from 'react-native-document-picker';
55
import ImagePicker from 'react-native-image-picker';
66

7+
import NavigationService from '../nav/NavigationService';
78
import type { Dispatch, Narrow } from '../types';
89
import { connect } from '../react-redux';
910
import { showErrorAlert } from '../utils/info';
@@ -154,7 +155,7 @@ class ComposeMenu extends PureComponent<Props> {
154155
});
155156

156157
render() {
157-
const { dispatch, expanded, insertVideoCallLink, onExpandContract } = this.props;
158+
const { expanded, insertVideoCallLink, onExpandContract } = this.props;
158159
const numIcons =
159160
3 + (Platform.OS === 'android' ? 1 : 0) + (insertVideoCallLink !== null ? 1 : 0);
160161

@@ -171,7 +172,7 @@ class ComposeMenu extends PureComponent<Props> {
171172
style={this.styles.composeMenuButton}
172173
size={24}
173174
onPress={() => {
174-
dispatch(navigateToCreateGroup());
175+
NavigationService.dispatch(navigateToCreateGroup());
175176
}}
176177
/>
177178
{Platform.OS === 'android' && (

src/diagnostics/DiagnosticsScreen.js

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import React, { PureComponent } from 'react';
44
import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack';
55
import { nativeApplicationVersion } from 'expo-application';
66

7-
import type { Dispatch } from '../types';
7+
import NavigationService from '../nav/NavigationService';
88
import { createStyleSheet } from '../styles';
9-
import { connect } from '../react-redux';
109
import { OptionButton, OptionDivider, Screen, RawLabel } from '../common';
1110
import {
1211
navigateToDebug,
@@ -28,45 +27,39 @@ type Props = $ReadOnly<{|
2827
// don't invoke it anywhere else at all), we know it gets the
2928
// `navigation` prop for free, with the stack-nav shape.
3029
navigation: NavigationStackProp<NavigationStateRoute>,
31-
32-
dispatch: Dispatch,
3330
|}>;
3431

35-
class DiagnosticsScreen extends PureComponent<Props> {
32+
export default class DiagnosticsScreen extends PureComponent<Props> {
3633
render() {
37-
const { dispatch } = this.props;
38-
3934
return (
4035
<Screen title="Diagnostics">
4136
<RawLabel style={styles.versionLabel} text={`v${nativeApplicationVersion ?? '?.?.?'}`} />
4237
<OptionDivider />
4338
<OptionButton
4439
label="Variables"
4540
onPress={() => {
46-
dispatch(navigateToVariables());
41+
NavigationService.dispatch(navigateToVariables());
4742
}}
4843
/>
4944
<OptionButton
5045
label="Timing"
5146
onPress={() => {
52-
dispatch(navigateToTiming());
47+
NavigationService.dispatch(navigateToTiming());
5348
}}
5449
/>
5550
<OptionButton
5651
label="Storage"
5752
onPress={() => {
58-
dispatch(navigateToStorage());
53+
NavigationService.dispatch(navigateToStorage());
5954
}}
6055
/>
6156
<OptionButton
6257
label="Debug"
6358
onPress={() => {
64-
dispatch(navigateToDebug());
59+
NavigationService.dispatch(navigateToDebug());
6560
}}
6661
/>
6762
</Screen>
6863
);
6964
}
7065
}
71-
72-
export default connect<{||}, _, _>()(DiagnosticsScreen);

src/main/HomeTab.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, { PureComponent } from 'react';
44
import { View } from 'react-native';
55
import type { NavigationTabProp, NavigationStateRoute } from 'react-navigation-tabs';
66

7+
import NavigationService from '../nav/NavigationService';
78
import type { Dispatch } from '../types';
89
import { connect } from '../react-redux';
910
import { HOME_NARROW, MENTIONED_NARROW, STARRED_NARROW } from '../utils/narrow';
@@ -65,7 +66,7 @@ class HomeTab extends PureComponent<Props> {
6566
<NavButton
6667
name="search"
6768
onPress={() => {
68-
dispatch(navigateToSearch());
69+
NavigationService.dispatch(navigateToSearch());
6970
}}
7071
/>
7172
</View>

src/message/__tests__/messageActions-test.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import configureStore from 'redux-mock-store';
33
import thunk from 'redux-thunk';
44

5+
import { navigateToChat } from '../../nav/navActions';
6+
import NavigationService from '../../nav/NavigationService';
57
import { doNarrow } from '../messagesActions';
68
import { streamNarrow } from '../../utils/narrow';
79
import * as eg from '../../__tests__/lib/exampleData';
@@ -15,6 +17,8 @@ const streamNarrowObj = streamNarrow('some stream');
1517
describe('messageActions', () => {
1618
describe('doNarrow', () => {
1719
test('action to push to nav dispatched', () => {
20+
NavigationService.dispatch = jest.fn();
21+
1822
const store = mockStore<GlobalState, Action>(
1923
eg.reduxState({
2024
accounts: [eg.selfAccount],
@@ -24,11 +28,8 @@ describe('messageActions', () => {
2428
);
2529

2630
store.dispatch(doNarrow(streamNarrowObj));
27-
const actions = store.getActions();
2831

29-
expect(actions).toHaveLength(1);
30-
const [action0] = actions;
31-
expect(action0.type).toBe('Navigation/PUSH');
32+
expect(NavigationService.dispatch).toHaveBeenCalledWith(navigateToChat(streamNarrowObj));
3233
});
3334
});
3435
});

src/message/fetchActions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* @flow strict-local */
2+
import NavigationService from '../nav/NavigationService';
23
import type {
34
Narrow,
45
Dispatch,
@@ -173,7 +174,7 @@ export const initialFetchComplete = () => async (dispatch: Dispatch, getState: G
173174
// conditional accordingly, if we found out we're not depending on
174175
// the more general condition; see
175176
// https://github.com/zulip/zulip-mobile/pull/4274#discussion_r505941875
176-
dispatch(resetToMainTabs());
177+
NavigationService.dispatch(resetToMainTabs());
177178
}
178179
dispatch(initialFetchCompletePlain());
179180
};

src/message/messageActionSheet.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/* @flow strict-local */
22
import { Clipboard, Share, Alert } from 'react-native';
3+
4+
import NavigationService from '../nav/NavigationService';
35
import type {
46
Auth,
57
Dispatch,
@@ -185,13 +187,13 @@ shareMessage.title = 'Share';
185187
shareMessage.errorMessage = 'Failed to share message';
186188

187189
const addReaction = ({ message, dispatch }) => {
188-
dispatch(navigateToEmojiPicker(message.id));
190+
NavigationService.dispatch(navigateToEmojiPicker(message.id));
189191
};
190192
addReaction.title = 'Add a reaction';
191193
addReaction.errorMessage = 'Failed to add reaction';
192194

193195
const showReactions = ({ message, dispatch }) => {
194-
dispatch(navigateToMessageReactionScreen(message.id));
196+
NavigationService.dispatch(navigateToMessageReactionScreen(message.id));
195197
};
196198
showReactions.title = 'See who reacted';
197199
showReactions.errorMessage = 'Failed to show reactions';

src/message/messagesActions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* @flow strict-local */
2+
import NavigationService from '../nav/NavigationService';
23
import type { Narrow, Dispatch, GetState } from '../types';
34
import { getAuth, getUsersById } from '../selectors';
45
import { getMessageIdFromLink, getNarrowFromLink } from '../utils/internalLinks';
@@ -18,7 +19,7 @@ export const doNarrow = (narrow: Narrow, anchor: number = FIRST_UNREAD_ANCHOR) =
1819
getState: GetState,
1920
) => {
2021
// TODO: Use `anchor` to open the message list to a particular message.
21-
dispatch(navigateToChat(narrow));
22+
NavigationService.dispatch(navigateToChat(narrow));
2223
};
2324

2425
export const messageLinkPress = (href: string) => async (

0 commit comments

Comments
 (0)