From d4f014f911934bfecf41981326411aed2d6db210 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 17 Jan 2024 19:22:08 +0100 Subject: [PATCH 1/3] [TS migration] Migrate 'ReportWelcomeMessage' page --- src/libs/updateMultilineInputRange/types.ts | 2 +- ...gePage.js => ReportWelcomeMessagePage.tsx} | 92 +++++++++---------- .../home/report/withReportOrNotFound.tsx | 7 +- 3 files changed, 49 insertions(+), 52 deletions(-) rename src/pages/{ReportWelcomeMessagePage.js => ReportWelcomeMessagePage.tsx} (59%) diff --git a/src/libs/updateMultilineInputRange/types.ts b/src/libs/updateMultilineInputRange/types.ts index d1b134b09a99..ce8f553c51f8 100644 --- a/src/libs/updateMultilineInputRange/types.ts +++ b/src/libs/updateMultilineInputRange/types.ts @@ -1,5 +1,5 @@ import type {TextInput} from 'react-native'; -type UpdateMultilineInputRange = (input: HTMLInputElement | TextInput, shouldAutoFocus?: boolean) => void; +type UpdateMultilineInputRange = (input: HTMLInputElement | TextInput | null, shouldAutoFocus?: boolean) => void; export default UpdateMultilineInputRange; diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.tsx similarity index 59% rename from src/pages/ReportWelcomeMessagePage.js rename to src/pages/ReportWelcomeMessagePage.tsx index ae8a4635a98e..f3be0d52930f 100644 --- a/src/pages/ReportWelcomeMessagePage.js +++ b/src/pages/ReportWelcomeMessagePage.tsx @@ -1,8 +1,10 @@ import {useFocusEffect} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; -import PropTypes from 'prop-types'; import React, {useCallback, useRef, useState} from 'react'; import {View} from 'react-native'; +import type {TextInput as RNTextInput} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FormProvider from '@components/Form/FormProvider'; @@ -11,54 +13,50 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; +import type {ReportWelcomeMessageNavigatorParamList} from '@navigation/types'; import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import type {Policy} from '@src/types/onyx'; +import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound'; import withReportOrNotFound from './home/report/withReportOrNotFound'; -import reportPropTypes from './reportPropTypes'; -import {policyDefaultProps, policyPropTypes} from './workspace/withPolicy'; -const propTypes = { - ...withLocalizePropTypes, - ...policyPropTypes, - - /** The report currently being looked at */ - report: reportPropTypes.isRequired, - - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** Report ID passed via route r/:reportID/welcomeMessage */ - reportID: PropTypes.string, - }), - }).isRequired, +type ReportWelcomeMessagePageOnyxProps = { + /** The policy object for the current route */ + policy: OnyxEntry; }; -const defaultProps = { - ...policyDefaultProps, -}; +type ReportWelcomeMessagePageProps = ReportWelcomeMessagePageOnyxProps & + WithReportOrNotFoundProps & + StackScreenProps; -function ReportWelcomeMessagePage(props) { +function ReportWelcomeMessagePage({report, policy}: ReportWelcomeMessagePageProps) { const styles = useThemeStyles(); + const {translate} = useLocalize(); + const parser = new ExpensiMark(); - const [welcomeMessage, setWelcomeMessage] = useState(() => parser.htmlToMarkdown(props.report.welcomeMessage)); - const welcomeMessageInputRef = useRef(null); - const focusTimeoutRef = useRef(null); + const [welcomeMessage, setWelcomeMessage] = useState(() => parser.htmlToMarkdown(report?.welcomeMessage ?? '')); + const welcomeMessageInputRef = useRef(null); + const focusTimeoutRef = useRef(null); - const handleWelcomeMessageChange = useCallback((value) => { + const handleWelcomeMessageChange = useCallback((value: string) => { setWelcomeMessage(value); }, []); const submitForm = useCallback(() => { - Report.updateWelcomeMessage(props.report.reportID, props.report.welcomeMessage, welcomeMessage.trim()); - }, [props.report.reportID, props.report.welcomeMessage, welcomeMessage]); + if (!report?.reportID) { + return; + } + + Report.updateWelcomeMessage(report.reportID, report.welcomeMessage ?? '', welcomeMessage.trim()); + }, [report?.reportID, report?.welcomeMessage, welcomeMessage]); useFocusEffect( useCallback(() => { @@ -82,33 +80,35 @@ function ReportWelcomeMessagePage(props) { includeSafeAreaPaddingBottom={false} testID={ReportWelcomeMessagePage.displayName} > - + Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(props.report.reportID))} + title={translate('welcomeMessagePage.welcomeMessage')} + onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? ''))} /> + {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. */} - {props.translate('welcomeMessagePage.explainerText')} + {translate('welcomeMessagePage.explainerText')} { - if (!el) { + ref={(element) => { + if (!element) { return; } - welcomeMessageInputRef.current = el; + welcomeMessageInputRef.current = element; updateMultilineInputRange(welcomeMessageInputRef.current); }} value={welcomeMessage} @@ -124,15 +124,11 @@ function ReportWelcomeMessagePage(props) { } ReportWelcomeMessagePage.displayName = 'ReportWelcomeMessagePage'; -ReportWelcomeMessagePage.propTypes = propTypes; -ReportWelcomeMessagePage.defaultProps = defaultProps; -export default compose( - withLocalize, - withReportOrNotFound(), - withOnyx({ +export default withReportOrNotFound()( + withOnyx({ policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, }, - }), -)(ReportWelcomeMessagePage); + })(ReportWelcomeMessagePage), +); diff --git a/src/pages/home/report/withReportOrNotFound.tsx b/src/pages/home/report/withReportOrNotFound.tsx index 7613bafeacdc..8e8e2b645fdc 100644 --- a/src/pages/home/report/withReportOrNotFound.tsx +++ b/src/pages/home/report/withReportOrNotFound.tsx @@ -22,16 +22,16 @@ type OnyxProps = { isLoadingReportData: OnyxEntry; }; -type ComponentProps = OnyxProps & { +type WithReportOrNotFoundProps = OnyxProps & { route: RouteProp<{params: {reportID: string}}>; }; export default function ( shouldRequireReportID = true, -): ( +): ( WrappedComponent: React.ComponentType>, ) => React.ComponentType, keyof OnyxProps>> { - return function (WrappedComponent: ComponentType>) { + return function (WrappedComponent: ComponentType>) { function WithReportOrNotFound(props: TProps, ref: ForwardedRef) { const contentShown = React.useRef(false); @@ -89,3 +89,4 @@ export default function ( })(React.forwardRef(WithReportOrNotFound)); }; } +export type {WithReportOrNotFoundProps}; From 1e1423643709469797a1f4c187a13c94002ef1d8 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 18 Jan 2024 08:34:25 +0100 Subject: [PATCH 2/3] Remove extra condition --- src/pages/ReportWelcomeMessagePage.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pages/ReportWelcomeMessagePage.tsx b/src/pages/ReportWelcomeMessagePage.tsx index f3be0d52930f..b57a3d573bb8 100644 --- a/src/pages/ReportWelcomeMessagePage.tsx +++ b/src/pages/ReportWelcomeMessagePage.tsx @@ -51,11 +51,7 @@ function ReportWelcomeMessagePage({report, policy}: ReportWelcomeMessagePageProp }, []); const submitForm = useCallback(() => { - if (!report?.reportID) { - return; - } - - Report.updateWelcomeMessage(report.reportID, report.welcomeMessage ?? '', welcomeMessage.trim()); + Report.updateWelcomeMessage(report?.reportID ?? '', report?.welcomeMessage ?? '', welcomeMessage.trim()); }, [report?.reportID, report?.welcomeMessage, welcomeMessage]); useFocusEffect( From bef7dd98e6984fd51ba88bdeb28752c8092d08f2 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 25 Jan 2024 16:45:13 +0100 Subject: [PATCH 3/3] Remove extra TODOs, update ref type --- src/pages/ReportWelcomeMessagePage.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/pages/ReportWelcomeMessagePage.tsx b/src/pages/ReportWelcomeMessagePage.tsx index b57a3d573bb8..53f3e7fcadda 100644 --- a/src/pages/ReportWelcomeMessagePage.tsx +++ b/src/pages/ReportWelcomeMessagePage.tsx @@ -3,13 +3,13 @@ import type {StackScreenProps} from '@react-navigation/stack'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import React, {useCallback, useRef, useState} from 'react'; import {View} from 'react-native'; -import type {TextInput as RNTextInput} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import type {AnimatedTextInputRef} from '@components/RNTextInput'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; @@ -43,7 +43,7 @@ function ReportWelcomeMessagePage({report, policy}: ReportWelcomeMessagePageProp const parser = new ExpensiMark(); const [welcomeMessage, setWelcomeMessage] = useState(() => parser.htmlToMarkdown(report?.welcomeMessage ?? '')); - const welcomeMessageInputRef = useRef(null); + const welcomeMessageInputRef = useRef(null); const focusTimeoutRef = useRef(null); const handleWelcomeMessageChange = useCallback((value: string) => { @@ -81,7 +81,6 @@ function ReportWelcomeMessagePage({report, policy}: ReportWelcomeMessagePageProp title={translate('welcomeMessagePage.welcomeMessage')} onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? ''))} /> - {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. */} {translate('welcomeMessagePage.explainerText')} { + ref={(element: AnimatedTextInputRef) => { if (!element) { return; }