From 5fba56b6ce442a28d56c479af477752b6e4d3d71 Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Thu, 24 Sep 2020 22:24:50 -0700 Subject: [PATCH] nav: Tell all screens on AppNavigator that they get the `navigation` prop. This has been done on an as-needed basis in the past, but in a few different ways, and it would be good to be consistent. With #3804 approaching, it makes sense to proactively furnish all these components with the knowledge that they have the `navigation` prop if they ever need it. In doing so, we're making an unchecked assumption: that the components will in fact be passed the `navigation` prop, in the shape we say it will take. It's unchecked because of the `$FlowFixMe` from aaaf847fe on the route config passed to `createStackNavigator` [0]. ----- There is a doc for doing this in TypeScript [1], but it's clearly wrong about how to handle it in Flow (and I believe it's also wrong about TypeScript in ways that would matter to us if we were using TypeScript). In particular, `NavigationStackScreenProps` is marketed (under "Type checking all props for a screen") as something you can spread in your `Props` type to get `theme` and `screenProps` along with `navigation`. Sounds great. But it doesn't exist in the Flow libdef, and I haven't found a clear alternative. In #4127, a demo PR branch that informed 17f73d88d -- in particular, f48282752 [FOR DISCUSSION] One way to get `sharedData` into ShareToStream, ShareToPm -- I seemed [2] to have favored something called `NavigationNavigatorProps` for this purpose. But it has at least two points against it: 1. I don't see documentation that we're supposed to use it, or how. 2. It's not tailored (or conveniently tailorable) to screens that get put on a particular type of navigator (stack, drawer, tabs, etc.) So, be conservative and just type the `navigation` prop, and in a way that says we know it comes from a stack navigator. The main example in the TypeScript doc is the following: ``` type Props = { navigation: NavigationStackProp<{ userId: string }>; }; ``` We find `NavigationStackProp` is a good thing to use [3], and it exists in the Flow libdef, but `{ userId: string }` is bad for a couple of reasons: - It's off by a level of nesting; surely they mean to describe `navigation.state.params`. To do that, the type needs to look something like `{ params: { userId: string } }`. This is also the case in the TypeScript. - It leaves out all the other things on `navigation.state` including `key` and `routeName`, which might be nice to have someday. Experimentally, these are conveniently filled in by saying `NavigationStackProp` [4]. So, account for those deficiencies straightforwardly. [0] Initial thoughts on this were written in a36814e80, but see https://github.com/zulip/zulip-mobile/pull/4114#issuecomment-634255590 for more recent concerns about typing our component classes with a static `navigationOptions` property. I'm inclined to not revisit these suppressions until we're on React Navigation v5, which has quite a different, component-based API, and a particular guide for type-checking the route config and the screen components in a unified way; that's at https://reactnavigation.org/docs/typescript/. [1] https://reactnavigation.org/docs/4.x/typescript/ [2] Possibly following a train of thought from https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/react-navigation.20types/near/878262. [3] In one or two places, we've been using `NavigationScreenProp` -- the doc for upgrading from v3 (which we did in f3b6c1f9e) says to replace that with `NavigationStackProp` for stack navigators. This didn't catch my eye at the time because it's under the "TypeScript" heading and we don't use TypeScript. That doc is at https://reactnavigation.org/docs/4.x/upgrading-from-3.x/#typescript. [4] Like at https://github.com/react-navigation/react-navigation/issues/3643#issuecomment-370044086, but with `NavigationStackProp` instead of `NavigationScreenProp`. --- src/account-info/AccountDetailsScreen.js | 8 ++++++-- src/account/AccountPickScreen.js | 7 +++++++ src/chat/ChatScreen.js | 8 ++++++-- src/chat/GroupDetailsScreen.js | 12 ++++++++++-- src/diagnostics/DiagnosticsScreen.js | 8 +++++++- src/diagnostics/StorageScreen.js | 7 +++++++ src/diagnostics/TimingScreen.js | 11 ++++++++++- src/diagnostics/VariablesScreen.js | 11 ++++++++++- src/emoji/EmojiPickerScreen.js | 9 +++++++-- src/lightbox/LightboxScreen.js | 11 +++++++++-- src/main/MainScreenWithTabs.js | 8 ++++++-- src/reactions/MessageReactionList.js | 11 +++++++++-- src/search/SearchMessagesScreen.js | 7 +++++++ src/settings/DebugScreen.js | 7 +++++++ src/settings/LanguageScreen.js | 7 +++++++ src/settings/LegalScreen.js | 7 +++++++ src/settings/NotificationsScreen.js | 7 +++++++ src/sharing/SharingScreen.js | 13 +++++++++++-- src/start/AuthScreen.js | 12 ++++++++++-- src/start/DevAuthScreen.js | 7 +++++++ src/start/LoadingScreen.js | 11 ++++++++++- src/start/PasswordAuthScreen.js | 12 ++++++++++-- src/start/RealmScreen.js | 2 +- src/streams/CreateStreamScreen.js | 7 +++++++ src/streams/EditStreamScreen.js | 11 +++++++++-- src/streams/InviteUsersScreen.js | 11 +++++++++-- src/streams/StreamScreen.js | 11 +++++++++-- src/topics/TopicListScreen.js | 11 +++++++++-- src/user-groups/CreateGroupScreen.js | 7 +++++++ src/user-status/UserStatusScreen.js | 7 +++++++ src/users/UsersScreen.js | 9 ++++++++- 31 files changed, 243 insertions(+), 34 deletions(-) diff --git a/src/account-info/AccountDetailsScreen.js b/src/account-info/AccountDetailsScreen.js index c969c8028e3..eb2ecc49a81 100644 --- a/src/account-info/AccountDetailsScreen.js +++ b/src/account-info/AccountDetailsScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; -import type { NavigationScreenProp } from 'react-navigation'; import type { Dispatch, UserOrBot } from '../types'; import { createStyleSheet } from '../styles'; import { connect } from '../react-redux'; @@ -30,7 +30,11 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| userId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| ...NavigationStateRoute, params: {| userId: number |} |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/account/AccountPickScreen.js b/src/account/AccountPickScreen.js index 148e9daf166..e620be5f937 100644 --- a/src/account/AccountPickScreen.js +++ b/src/account/AccountPickScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -11,6 +12,12 @@ import AccountList from './AccountList'; import { navigateToRealmScreen, accountSwitch, removeAccount } from '../actions'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + accounts: AccountStatus[], dispatch: Dispatch, hasAuth: boolean, diff --git a/src/chat/ChatScreen.js b/src/chat/ChatScreen.js index 5b683228417..87054039535 100644 --- a/src/chat/ChatScreen.js +++ b/src/chat/ChatScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { withNavigationFocus } from 'react-navigation'; import { ActionSheetProvider } from '@expo/react-native-action-sheet'; import { compose } from 'redux'; @@ -34,7 +34,11 @@ type SelectorProps = {| |}; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| narrow: Narrow |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| ...NavigationStateRoute, params: {| narrow: Narrow |} |}>, dispatch: Dispatch, // From React Navigation's `withNavigationFocus` HOC. Type copied diff --git a/src/chat/GroupDetailsScreen.js b/src/chat/GroupDetailsScreen.js index f087aa336b8..4a821f00e91 100644 --- a/src/chat/GroupDetailsScreen.js +++ b/src/chat/GroupDetailsScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { FlatList } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch, UserOrBot } from '../types'; import { connect } from '../react-redux'; @@ -10,7 +10,15 @@ import UserItem from '../users/UserItem'; import { navigateToAccountDetails } from '../actions'; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| recipients: UserOrBot[] |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| recipients: UserOrBot[] |}, + |}>, + dispatch: Dispatch, |}>; diff --git a/src/diagnostics/DiagnosticsScreen.js b/src/diagnostics/DiagnosticsScreen.js index f29cbbed1d8..f3f1c121efb 100644 --- a/src/diagnostics/DiagnosticsScreen.js +++ b/src/diagnostics/DiagnosticsScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; - +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { nativeApplicationVersion } from 'expo-application'; import type { Dispatch } from '../types'; @@ -23,6 +23,12 @@ const styles = createStyleSheet({ }); type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, |}>; diff --git a/src/diagnostics/StorageScreen.js b/src/diagnostics/StorageScreen.js index 6a330aec39d..eea73f5b3fc 100644 --- a/src/diagnostics/StorageScreen.js +++ b/src/diagnostics/StorageScreen.js @@ -2,6 +2,7 @@ import React, { PureComponent } from 'react'; import { FlatList } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { GlobalState, Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -17,6 +18,12 @@ const calculateKeyStorageSizes = obj => .sort((a, b) => b.size - a.size); type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, state: GlobalState, |}>; diff --git a/src/diagnostics/TimingScreen.js b/src/diagnostics/TimingScreen.js index d57188e21f9..c46c9089ad7 100644 --- a/src/diagnostics/TimingScreen.js +++ b/src/diagnostics/TimingScreen.js @@ -1,12 +1,21 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { FlatList } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { Screen } from '../common'; import TimeItem from './TimeItem'; import timing from '../utils/timing'; -export default class TimingScreen extends PureComponent<{||}> { +type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, +|}>; + +export default class TimingScreen extends PureComponent { render() { return ( diff --git a/src/diagnostics/VariablesScreen.js b/src/diagnostics/VariablesScreen.js index ddcf5eec749..2d37696bb3c 100644 --- a/src/diagnostics/VariablesScreen.js +++ b/src/diagnostics/VariablesScreen.js @@ -1,12 +1,21 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { FlatList } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import config from '../config'; import { Screen } from '../common'; import InfoItem from './InfoItem'; -export default class VariablesScreen extends PureComponent<{||}> { +type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, +|}>; + +export default class VariablesScreen extends PureComponent { render() { const variables = { enableReduxLogging: config.enableReduxLogging, diff --git a/src/emoji/EmojiPickerScreen.js b/src/emoji/EmojiPickerScreen.js index e27826a932e..797dc1cf02d 100644 --- a/src/emoji/EmojiPickerScreen.js +++ b/src/emoji/EmojiPickerScreen.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { FlatList } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import * as api from '../api'; import { unicodeCodeByName } from './codePointMap'; @@ -16,10 +16,15 @@ import { navigateBack } from '../nav/navActions'; import zulipExtraEmojiMap from './zulipExtraEmojiMap'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| ...NavigationStateRoute, params: {| messageId: number |} |}>, + activeImageEmojiByName: RealmEmojiById, auth: Auth, dispatch: Dispatch, - navigation: NavigationScreenProp<{ params: {| messageId: number |} }>, |}>; type State = {| diff --git a/src/lightbox/LightboxScreen.js b/src/lightbox/LightboxScreen.js index bfe25e8636c..5674e890994 100644 --- a/src/lightbox/LightboxScreen.js +++ b/src/lightbox/LightboxScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { ActionSheetProvider } from '@expo/react-native-action-sheet'; import { ZulipStatusBar } from '../common'; @@ -19,7 +19,14 @@ const styles = createStyleSheet({ }); type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| src: string, message: Message |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| src: string, message: Message |}, + |}>, |}>; export default class LightboxScreen extends PureComponent { diff --git a/src/main/MainScreenWithTabs.js b/src/main/MainScreenWithTabs.js index e44598888f6..f743222544c 100644 --- a/src/main/MainScreenWithTabs.js +++ b/src/main/MainScreenWithTabs.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { ThemeData } from '../styles'; import styles, { ThemeContext } from '../styles'; @@ -9,7 +9,11 @@ import { OfflineNotice, ZulipStatusBar } from '../common'; import MainTabs from './MainTabs'; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, |}>; export default class MainScreenWithTabs extends PureComponent { diff --git a/src/reactions/MessageReactionList.js b/src/reactions/MessageReactionList.js index fcd68559bb1..18a4bc413dd 100644 --- a/src/reactions/MessageReactionList.js +++ b/src/reactions/MessageReactionList.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { View } from 'react-native'; import { createAppContainer } from 'react-navigation'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { createMaterialTopTabNavigator } from 'react-navigation-tabs'; import * as logging from '../utils/logging'; @@ -111,7 +111,14 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| reactionName?: string, messageId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| reactionName?: string, messageId: number |}, + |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/search/SearchMessagesScreen.js b/src/search/SearchMessagesScreen.js index 164c5fa2dad..fd45ae96a29 100644 --- a/src/search/SearchMessagesScreen.js +++ b/src/search/SearchMessagesScreen.js @@ -1,5 +1,6 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Auth, Dispatch, Message } from '../types'; import { Screen } from '../common'; @@ -12,6 +13,12 @@ import { getAuth } from '../account/accountsSelectors'; import { fetchMessages } from '../message/fetchActions'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + auth: Auth, dispatch: Dispatch, // Warning: do not add new props without considering their effect on the diff --git a/src/settings/DebugScreen.js b/src/settings/DebugScreen.js index 27f03728f7c..beb0f0e4176 100644 --- a/src/settings/DebugScreen.js +++ b/src/settings/DebugScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Debug, Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -9,6 +10,12 @@ import { OptionRow, Screen } from '../common'; import { debugFlagToggle } from '../actions'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + debug: Debug, dispatch: Dispatch, |}>; diff --git a/src/settings/LanguageScreen.js b/src/settings/LanguageScreen.js index a72c721076a..ddb5eaa5c7d 100644 --- a/src/settings/LanguageScreen.js +++ b/src/settings/LanguageScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -10,6 +11,12 @@ import { getSettings } from '../selectors'; import { settingsChange } from '../actions'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, locale: string, |}>; diff --git a/src/settings/LegalScreen.js b/src/settings/LegalScreen.js index b0a49a65131..2c468c98825 100644 --- a/src/settings/LegalScreen.js +++ b/src/settings/LegalScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -9,6 +10,12 @@ import openLink from '../utils/openLink'; import { getCurrentRealm } from '../selectors'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, realm: URL, |}>; diff --git a/src/settings/NotificationsScreen.js b/src/settings/NotificationsScreen.js index 8261c377f82..b982654c7cd 100644 --- a/src/settings/NotificationsScreen.js +++ b/src/settings/NotificationsScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Auth, Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -10,6 +11,12 @@ import * as api from '../api'; import { settingsChange } from '../actions'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + auth: Auth, dispatch: Dispatch, offlineNotification: boolean, diff --git a/src/sharing/SharingScreen.js b/src/sharing/SharingScreen.js index 1e14b159e28..25b4d9888cf 100644 --- a/src/sharing/SharingScreen.js +++ b/src/sharing/SharingScreen.js @@ -1,9 +1,10 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { Text } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { createMaterialTopTabNavigator } from 'react-navigation-tabs'; import { FormattedMessage } from 'react-intl'; + import type { Dispatch, SharedData, Auth, TabNavigationOptionsPropsType } from '../types'; import { createStyleSheet } from '../styles'; import { materialTopTabNavigatorConfig } from '../styles/tabs'; @@ -15,7 +16,15 @@ import ShareToStream from './ShareToStream'; import ShareToPm from './ShareToPm'; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| sharedData: SharedData |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| sharedData: SharedData |}, + |}>, + auth: Auth | void, dispatch: Dispatch, |}>; diff --git a/src/start/AuthScreen.js b/src/start/AuthScreen.js index 8774e49ce79..b8267ef8721 100644 --- a/src/start/AuthScreen.js +++ b/src/start/AuthScreen.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { Linking, Platform } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { AppleAuthenticationCredential } from 'expo-apple-authentication'; import * as AppleAuthentication from 'expo-apple-authentication'; @@ -167,9 +167,17 @@ export const activeAuthentications = ( }; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| serverSettings: ApiResponseServerSettings |}, + |}>, + dispatch: Dispatch, realm: URL, - navigation: NavigationScreenProp<{ params: {| serverSettings: ApiResponseServerSettings |} }>, |}>; let otp = ''; diff --git a/src/start/DevAuthScreen.js b/src/start/DevAuthScreen.js index 10259c570a8..5ee27a46740 100644 --- a/src/start/DevAuthScreen.js +++ b/src/start/DevAuthScreen.js @@ -2,6 +2,7 @@ import React, { PureComponent } from 'react'; import { ActivityIndicator, View, FlatList } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Auth, DevUser, Dispatch } from '../types'; import styles, { createStyleSheet } from '../styles'; @@ -27,6 +28,12 @@ const componentStyles = createStyleSheet({ }); type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + partialAuth: Auth, dispatch: Dispatch, |}>; diff --git a/src/start/LoadingScreen.js b/src/start/LoadingScreen.js index 4aa560c9417..6dccd316df1 100644 --- a/src/start/LoadingScreen.js +++ b/src/start/LoadingScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { BRAND_COLOR, createStyleSheet } from '../styles'; import { LoadingIndicator, ZulipStatusBar } from '../common'; @@ -14,7 +15,15 @@ const styles = createStyleSheet({ }, }); -export default class LoadingScreen extends PureComponent<{||}> { +type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, +|}>; + +export default class LoadingScreen extends PureComponent { render() { return ( diff --git a/src/start/PasswordAuthScreen.js b/src/start/PasswordAuthScreen.js index 21a4c7d4b52..7c7af34dbe0 100644 --- a/src/start/PasswordAuthScreen.js +++ b/src/start/PasswordAuthScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Auth, Dispatch } from '../types'; import { createStyleSheet } from '../styles'; @@ -27,9 +27,17 @@ const styles = createStyleSheet({ }); type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| requireEmailFormat: boolean |}, + |}>, + partialAuth: Auth, dispatch: Dispatch, - navigation: NavigationScreenProp<{ params: {| requireEmailFormat: boolean |} }>, |}>; type State = {| diff --git a/src/start/RealmScreen.js b/src/start/RealmScreen.js index 46afb3cad3f..6ed2c2e3169 100644 --- a/src/start/RealmScreen.js +++ b/src/start/RealmScreen.js @@ -19,7 +19,7 @@ type Props = $ReadOnly<{| // Since we've put this screen in a stack-nav route config, and we // don't invoke it without type-checking anywhere else (in fact, we // don't invoke it anywhere else at all), we know it gets the - // `navigation` prop for free. + // `navigation` prop for free, with the stack-nav shape. navigation: NavigationStackProp<{| ...NavigationStateRoute, params: {| diff --git a/src/streams/CreateStreamScreen.js b/src/streams/CreateStreamScreen.js index fdc559afabf..61b5c634549 100644 --- a/src/streams/CreateStreamScreen.js +++ b/src/streams/CreateStreamScreen.js @@ -1,5 +1,6 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch } from '../types'; import { connect } from '../react-redux'; @@ -9,6 +10,12 @@ import { Screen } from '../common'; import EditStreamCard from './EditStreamCard'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, ownEmail: string, |}>; diff --git a/src/streams/EditStreamScreen.js b/src/streams/EditStreamScreen.js index 0b03d60811c..b01dce2a58e 100644 --- a/src/streams/EditStreamScreen.js +++ b/src/streams/EditStreamScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; -import type { NavigationScreenProp } from 'react-navigation'; import type { Dispatch, Stream } from '../types'; import { connect } from '../react-redux'; import { updateExistingStream, navigateBack } from '../actions'; @@ -14,7 +14,14 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| streamId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| streamId: number |}, + |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/streams/InviteUsersScreen.js b/src/streams/InviteUsersScreen.js index 645c1c5e1f1..0a37edbe099 100644 --- a/src/streams/InviteUsersScreen.js +++ b/src/streams/InviteUsersScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; -import type { NavigationScreenProp } from 'react-navigation'; import type { Auth, Dispatch, Stream, User } from '../types'; import { connect } from '../react-redux'; import { Screen } from '../common'; @@ -16,7 +16,14 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| streamId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| streamId: number |}, + |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/streams/StreamScreen.js b/src/streams/StreamScreen.js index 9e60cf4aa70..eb8cad8c6dd 100644 --- a/src/streams/StreamScreen.js +++ b/src/streams/StreamScreen.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { View } from 'react-native'; -import type { NavigationScreenProp } from 'react-navigation'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch, Stream, Subscription } from '../types'; import { connect } from '../react-redux'; @@ -30,7 +30,14 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| streamId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| streamId: number |}, + |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/topics/TopicListScreen.js b/src/topics/TopicListScreen.js index e6de39f29a6..a126e38419d 100644 --- a/src/topics/TopicListScreen.js +++ b/src/topics/TopicListScreen.js @@ -1,8 +1,8 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; -import type { NavigationScreenProp } from 'react-navigation'; import type { Dispatch, Stream, TopicExtended } from '../types'; import { connect } from '../react-redux'; import { Screen } from '../common'; @@ -18,7 +18,14 @@ type SelectorProps = $ReadOnly<{| |}>; type Props = $ReadOnly<{| - navigation: NavigationScreenProp<{ params: {| streamId: number |} }>, + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp<{| + ...NavigationStateRoute, + params: {| streamId: number |}, + |}>, dispatch: Dispatch, ...SelectorProps, diff --git a/src/user-groups/CreateGroupScreen.js b/src/user-groups/CreateGroupScreen.js index 64c6cbd8560..cd928c8a216 100644 --- a/src/user-groups/CreateGroupScreen.js +++ b/src/user-groups/CreateGroupScreen.js @@ -1,5 +1,6 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import type { Dispatch, User } from '../types'; import { connect } from '../react-redux'; @@ -9,6 +10,12 @@ import { groupNarrow } from '../utils/narrow'; import UserPickerCard from '../user-picker/UserPickerCard'; type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, |}>; diff --git a/src/user-status/UserStatusScreen.js b/src/user-status/UserStatusScreen.js index a139a1206dc..990f6f61932 100644 --- a/src/user-status/UserStatusScreen.js +++ b/src/user-status/UserStatusScreen.js @@ -1,6 +1,7 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; import { FlatList, View } from 'react-native'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { TranslationContext } from '../boot/TranslationProvider'; import { createStyleSheet } from '../styles'; @@ -27,6 +28,12 @@ const styles = createStyleSheet({ }); type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, + dispatch: Dispatch, userStatusText: string, |}>; diff --git a/src/users/UsersScreen.js b/src/users/UsersScreen.js index b7031295ee3..5c97f7aad84 100644 --- a/src/users/UsersScreen.js +++ b/src/users/UsersScreen.js @@ -1,10 +1,17 @@ /* @flow strict-local */ import React, { PureComponent } from 'react'; +import type { NavigationStackProp, NavigationStateRoute } from 'react-navigation-stack'; import { Screen } from '../common'; import UsersCard from './UsersCard'; -type Props = $ReadOnly<{||}>; +type Props = $ReadOnly<{| + // Since we've put this screen in a stack-nav route config, and we + // don't invoke it without type-checking anywhere else (in fact, we + // don't invoke it anywhere else at all), we know it gets the + // `navigation` prop for free, with the stack-nav shape. + navigation: NavigationStackProp, +|}>; type State = {| filter: string,