From cf3c28719c2ec593a82120256e6a6eb07a5aa133 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 12 Oct 2023 13:57:53 +0200 Subject: [PATCH 1/5] [TS migration] Migrate 'withNavigationFocus.js' HOC to TypeScript: --- .eslintrc.js | 2 +- src/components/AvatarWithImagePicker.js | 5 ++- .../OptionsSelector/BaseOptionsSelector.js | 4 +- .../RoomNameInput/roomNameInputPropTypes.js | 3 +- src/components/withNavigationFocus.js | 40 ------------------- src/components/withNavigationFocus.tsx | 31 ++++++++++++++ src/libs/getComponentDisplayName.ts | 2 +- src/pages/signin/LoginForm/BaseLoginForm.js | 6 +-- src/pages/workspace/WorkspaceNewRoomPage.js | 4 +- 9 files changed, 44 insertions(+), 53 deletions(-) delete mode 100644 src/components/withNavigationFocus.js create mode 100644 src/components/withNavigationFocus.tsx diff --git a/.eslintrc.js b/.eslintrc.js index 75a74ed371c4..83e9479ce0c4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -116,7 +116,7 @@ module.exports = { }, { selector: ['parameter', 'method'], - format: ['camelCase'], + format: ['camelCase', 'PascalCase'], }, ], '@typescript-eslint/ban-types': [ diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index a44d1841bbb6..06d1e8a2f187 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -24,7 +24,7 @@ import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import AttachmentModal from './AttachmentModal'; import DotIndicatorMessage from './DotIndicatorMessage'; import * as Browser from '../libs/Browser'; -import withNavigationFocus, {withNavigationFocusPropTypes} from './withNavigationFocus'; +import withNavigationFocus from './withNavigationFocus'; import compose from '../libs/compose'; const propTypes = { @@ -91,8 +91,9 @@ const propTypes = { /** File name of the avatar */ originalFileName: PropTypes.string, + isFocused: PropTypes.bool.isRequired, + ...withLocalizePropTypes, - ...withNavigationFocusPropTypes, }; const defaultProps = { diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index e72bb7ef4b8e..dca9804573bf 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -9,7 +9,7 @@ import OptionsList from '../OptionsList'; import CONST from '../../CONST'; import styles from '../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; -import withNavigationFocus, {withNavigationFocusPropTypes} from '../withNavigationFocus'; +import withNavigationFocus from '../withNavigationFocus'; import TextInput from '../TextInput'; import ArrowKeyFocusManager from '../ArrowKeyFocusManager'; import KeyboardShortcut from '../../libs/KeyboardShortcut'; @@ -30,10 +30,10 @@ const propTypes = { /** List styles for OptionsList */ listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + isFocused: PropTypes.bool.isRequired, ...optionsSelectorPropTypes, ...withLocalizePropTypes, - ...withNavigationFocusPropTypes, }; const defaultProps = { diff --git a/src/components/RoomNameInput/roomNameInputPropTypes.js b/src/components/RoomNameInput/roomNameInputPropTypes.js index ab1ac37d32c8..34262575af01 100644 --- a/src/components/RoomNameInput/roomNameInputPropTypes.js +++ b/src/components/RoomNameInput/roomNameInputPropTypes.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import {withNavigationFocusPropTypes} from '../withNavigationFocus'; const propTypes = { /** Callback to execute when the text input is modified correctly */ @@ -29,7 +28,7 @@ const propTypes = { /** Whether we should wait before focusing the TextInput, useful when using transitions on Android */ shouldDelayFocus: PropTypes.bool, - ...withNavigationFocusPropTypes, + isFocused: PropTypes.bool.isRequired, }; const defaultProps = { diff --git a/src/components/withNavigationFocus.js b/src/components/withNavigationFocus.js deleted file mode 100644 index f934f038e311..000000000000 --- a/src/components/withNavigationFocus.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import {useIsFocused} from '@react-navigation/native'; -import getComponentDisplayName from '../libs/getComponentDisplayName'; -import refPropTypes from './refPropTypes'; - -const withNavigationFocusPropTypes = { - isFocused: PropTypes.bool.isRequired, -}; - -export default function withNavigationFocus(WrappedComponent) { - function WithNavigationFocus(props) { - const isFocused = useIsFocused(); - return ( - - ); - } - - WithNavigationFocus.displayName = `withNavigationFocus(${getComponentDisplayName(WrappedComponent)})`; - WithNavigationFocus.propTypes = { - forwardedRef: refPropTypes, - }; - WithNavigationFocus.defaultProps = { - forwardedRef: undefined, - }; - return React.forwardRef((props, ref) => ( - - )); -} - -export {withNavigationFocusPropTypes}; diff --git a/src/components/withNavigationFocus.tsx b/src/components/withNavigationFocus.tsx new file mode 100644 index 000000000000..3e97a39b36ac --- /dev/null +++ b/src/components/withNavigationFocus.tsx @@ -0,0 +1,31 @@ +import React, {ComponentType, ForwardedRef, RefAttributes} from 'react'; +import PropTypes from 'prop-types'; +import {useIsFocused} from '@react-navigation/native'; +import getComponentDisplayName from '../libs/getComponentDisplayName'; + +const withNavigationFocusPropTypes = { + isFocused: PropTypes.bool.isRequired, +}; + +type WithNavigationFocusProps = { + isFocused: boolean; +}; + +export default function withNavigationFocus(WrappedComponent: ComponentType>) { + function WithNavigationFocus(props: Omit, ref: ForwardedRef) { + const isFocused = useIsFocused(); + return ( + + ); + } + + WithNavigationFocus.displayName = `withNavigationFocus(${getComponentDisplayName(WrappedComponent as ComponentType)})`; + return React.forwardRef(WithNavigationFocus); +} + +export {withNavigationFocusPropTypes}; diff --git a/src/libs/getComponentDisplayName.ts b/src/libs/getComponentDisplayName.ts index fd1bbcaea521..0bf52d543a84 100644 --- a/src/libs/getComponentDisplayName.ts +++ b/src/libs/getComponentDisplayName.ts @@ -1,6 +1,6 @@ import {ComponentType} from 'react'; /** Returns the display name of a component */ -export default function getComponentDisplayName(component: ComponentType): string { +export default function getComponentDisplayName(component: ComponentType): string { return component.displayName ?? component.name ?? 'Component'; } diff --git a/src/pages/signin/LoginForm/BaseLoginForm.js b/src/pages/signin/LoginForm/BaseLoginForm.js index 2c65b5ff5d37..1fb4955da218 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.js +++ b/src/pages/signin/LoginForm/BaseLoginForm.js @@ -30,7 +30,7 @@ import GoogleSignIn from '../../../components/SignInButtons/GoogleSignIn'; import isInputAutoFilled from '../../../libs/isInputAutoFilled'; import * as PolicyUtils from '../../../libs/PolicyUtils'; import Log from '../../../libs/Log'; -import withNavigationFocus, {withNavigationFocusPropTypes} from '../../../components/withNavigationFocus'; +import withNavigationFocus from '../../../components/withNavigationFocus'; import usePrevious from '../../../hooks/usePrevious'; import * as MemoryOnlyKeys from '../../../libs/actions/MemoryOnlyKeys/MemoryOnlyKeys'; @@ -66,13 +66,13 @@ const propTypes = { /** Whether or not the sign in page is being rendered in the RHP modal */ isInModal: PropTypes.bool, + isFocused: PropTypes.bool.isRequired, + ...windowDimensionsPropTypes, ...withLocalizePropTypes, ...toggleVisibilityViewPropTypes, - - ...withNavigationFocusPropTypes, }; const defaultProps = { diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index e1fbab65486b..60b73218e6e7 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -3,7 +3,7 @@ import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; -import withNavigationFocus, {withNavigationFocusPropTypes} from '../../components/withNavigationFocus'; +import withNavigationFocus from '../../components/withNavigationFocus'; import * as Report from '../../libs/actions/Report'; import * as App from '../../libs/actions/App'; import useLocalize from '../../hooks/useLocalize'; @@ -60,7 +60,7 @@ const propTypes = { /** A collection of objects for all policies which key policy member objects by accountIDs */ allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)), - ...withNavigationFocusPropTypes, + isFocused: PropTypes.bool.isRequired, }; const defaultProps = { betas: [], From 3e593c395455a0c2d8d287f302325b7e92bfc52f Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 12 Oct 2023 14:20:05 +0200 Subject: [PATCH 2/5] Rename generic --- src/components/withNavigationFocus.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/withNavigationFocus.tsx b/src/components/withNavigationFocus.tsx index 3e97a39b36ac..88a0e2fd67a4 100644 --- a/src/components/withNavigationFocus.tsx +++ b/src/components/withNavigationFocus.tsx @@ -11,13 +11,13 @@ type WithNavigationFocusProps = { isFocused: boolean; }; -export default function withNavigationFocus(WrappedComponent: ComponentType>) { - function WithNavigationFocus(props: Omit, ref: ForwardedRef) { +export default function withNavigationFocus(WrappedComponent: ComponentType>) { + function WithNavigationFocus(props: Omit, ref: ForwardedRef) { const isFocused = useIsFocused(); return ( From ae4d24aa0db16e4dbf8061618e23517476d9dec7 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 12 Oct 2023 14:24:59 +0200 Subject: [PATCH 3/5] remove prop-types --- src/components/withNavigationFocus.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/withNavigationFocus.tsx b/src/components/withNavigationFocus.tsx index 88a0e2fd67a4..e71ef361c0b4 100644 --- a/src/components/withNavigationFocus.tsx +++ b/src/components/withNavigationFocus.tsx @@ -1,12 +1,7 @@ import React, {ComponentType, ForwardedRef, RefAttributes} from 'react'; -import PropTypes from 'prop-types'; import {useIsFocused} from '@react-navigation/native'; import getComponentDisplayName from '../libs/getComponentDisplayName'; -const withNavigationFocusPropTypes = { - isFocused: PropTypes.bool.isRequired, -}; - type WithNavigationFocusProps = { isFocused: boolean; }; @@ -27,5 +22,3 @@ export default function withNavigationFocus Date: Mon, 16 Oct 2023 10:25:43 +0200 Subject: [PATCH 4/5] Add return type to withNavigationFocus --- src/components/withNavigationFocus.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/withNavigationFocus.tsx b/src/components/withNavigationFocus.tsx index e71ef361c0b4..f3f1d3561d9c 100644 --- a/src/components/withNavigationFocus.tsx +++ b/src/components/withNavigationFocus.tsx @@ -6,7 +6,9 @@ type WithNavigationFocusProps = { isFocused: boolean; }; -export default function withNavigationFocus(WrappedComponent: ComponentType>) { +export default function withNavigationFocus( + WrappedComponent: ComponentType>, +): (props: Omit & React.RefAttributes) => React.ReactElement | null { function WithNavigationFocus(props: Omit, ref: ForwardedRef) { const isFocused = useIsFocused(); return ( @@ -19,6 +21,6 @@ export default function withNavigationFocus Date: Mon, 23 Oct 2023 15:26:19 +0200 Subject: [PATCH 5/5] Add comments to prop types --- src/components/AvatarWithImagePicker.js | 1 + src/components/OptionsSelector/BaseOptionsSelector.js | 2 ++ src/components/RoomNameInput/roomNameInputPropTypes.js | 1 + src/pages/signin/LoginForm/BaseLoginForm.js | 1 + src/pages/workspace/WorkspaceNewRoomPage.js | 1 + 5 files changed, 6 insertions(+) diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index 06d1e8a2f187..3b6fdccc57a4 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -91,6 +91,7 @@ const propTypes = { /** File name of the avatar */ originalFileName: PropTypes.string, + /** Whether navigation is focused */ isFocused: PropTypes.bool.isRequired, ...withLocalizePropTypes, diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 24e5630f2669..0125fc8e178e 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -31,6 +31,8 @@ const propTypes = { /** List styles for OptionsList */ listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + + /** Whether navigation is focused */ isFocused: PropTypes.bool.isRequired, ...optionsSelectorPropTypes, diff --git a/src/components/RoomNameInput/roomNameInputPropTypes.js b/src/components/RoomNameInput/roomNameInputPropTypes.js index 34262575af01..7f8292f0123e 100644 --- a/src/components/RoomNameInput/roomNameInputPropTypes.js +++ b/src/components/RoomNameInput/roomNameInputPropTypes.js @@ -28,6 +28,7 @@ const propTypes = { /** Whether we should wait before focusing the TextInput, useful when using transitions on Android */ shouldDelayFocus: PropTypes.bool, + /** Whether navigation is focused */ isFocused: PropTypes.bool.isRequired, }; diff --git a/src/pages/signin/LoginForm/BaseLoginForm.js b/src/pages/signin/LoginForm/BaseLoginForm.js index 3f815827dd1c..e92844468a52 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.js +++ b/src/pages/signin/LoginForm/BaseLoginForm.js @@ -66,6 +66,7 @@ const propTypes = { /** Whether or not the sign in page is being rendered in the RHP modal */ isInModal: PropTypes.bool, + /** Whether navigation is focused */ isFocused: PropTypes.bool.isRequired, ...windowDimensionsPropTypes, diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 80d1d93d74bd..80c1a13731bd 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -61,6 +61,7 @@ const propTypes = { /** A collection of objects for all policies which key policy member objects by accountIDs */ allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)), + /** Whether navigation is focused */ isFocused: PropTypes.bool.isRequired, }; const defaultProps = {