Skip to content

Commit

Permalink
Merge pull request #39011 from callstack-internal/pac-guerreiro/refac…
Browse files Browse the repository at this point in the history
…tor/migrate-pdfview-to-typescript

[TS migration] Migrate 'PDFView' component to TypeScript
  • Loading branch information
AndrewGable authored Apr 4, 2024
2 parents 90ac4ef + 3eab96f commit 709fb40
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ function BaseAttachmentViewPdf({

return (
<PDFView
// @ts-expect-error waiting for https://github.com/Expensify/App/issues/16186 merge
onPress={onPress}
isFocused={isFocused}
sourceURL={encryptedSourceUrl}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type AttachmentViewPdfProps from './types';
function AttachmentViewPdf({file, encryptedSourceUrl, isFocused, onPress, onToggleKeyboard, onLoadComplete, errorLabelStyles, style}: AttachmentViewPdfProps) {
return (
<PDFView
// @ts-expect-error waiting for https://github.com/Expensify/App/issues/16186 merge
onPress={onPress}
isFocused={isFocused}
sourceURL={encryptedSourceUrl}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {StyleProp, ViewStyle} from 'react-native';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import type {AttachmentViewProps} from '..';

type AttachmentViewPdfProps = Pick<AttachmentViewProps, 'file' | 'onPress' | 'isUsedInCarousel' | 'isFocused' | 'onToggleKeyboard'> & {
Expand All @@ -9,7 +9,7 @@ type AttachmentViewPdfProps = Pick<AttachmentViewProps, 'file' | 'onPress' | 'is
style?: StyleProp<ViewStyle>;

/** Styles for the error label */
errorLabelStyles?: StyleProp<ViewStyle>;
errorLabelStyles?: StyleProp<TextStyle>;

/** Triggered when the PDF's onScaleChanged event is triggered */
onScaleChanged?: (scale: number) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import PropTypes from 'prop-types';
import type {KeyboardEvent} from 'react';
import React from 'react';
import type {GestureResponderEvent} from 'react-native';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';

const propTypes = {
type PDFInfoMessageProps = {
/** Callback function to indicate that PDF password form should be shown */
onShowForm: PropTypes.func.isRequired,

...withLocalizePropTypes,
onShowForm: (event: GestureResponderEvent | KeyboardEvent) => void;
};

function PDFInfoMessage(props) {
function PDFInfoMessage({onShowForm}: PDFInfoMessageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();

return (
<View style={styles.alignItemsCenter}>
<Icon
Expand All @@ -28,18 +29,17 @@ function PDFInfoMessage(props) {
width={variables.iconSizeSuperLarge}
height={variables.iconSizeSuperLarge}
/>
<Text style={[styles.textHeadline, styles.mb3, styles.mt3]}>{props.translate('attachmentView.pdfPasswordForm.title')}</Text>
<Text>{props.translate('attachmentView.pdfPasswordForm.infoText')}</Text>
<Text style={[styles.textHeadline, styles.mb3, styles.mt3]}>{translate('attachmentView.pdfPasswordForm.title')}</Text>
<Text>{translate('attachmentView.pdfPasswordForm.infoText')}</Text>
<Text>
{props.translate('attachmentView.pdfPasswordForm.beforeLinkText')}
<TextLink onPress={props.onShowForm}>{` ${props.translate('attachmentView.pdfPasswordForm.linkText')} `}</TextLink>
{props.translate('attachmentView.pdfPasswordForm.afterLinkText')}
{translate('attachmentView.pdfPasswordForm.beforeLinkText')}
<TextLink onPress={onShowForm}>{` ${translate('attachmentView.pdfPasswordForm.linkText')} `}</TextLink>
{translate('attachmentView.pdfPasswordForm.afterLinkText')}
</Text>
</View>
);
}

PDFInfoMessage.propTypes = propTypes;
PDFInfoMessage.displayName = 'PDFInfoMessage';

export default withLocalize(PDFInfoMessage);
export default PDFInfoMessage;
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import PropTypes from 'prop-types';
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import Button from '@components/Button';
import ScrollView from '@components/ScrollView';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
Expand All @@ -14,51 +13,43 @@ import shouldDelayFocus from '@libs/shouldDelayFocus';
import CONST from '@src/CONST';
import PDFInfoMessage from './PDFInfoMessage';

const propTypes = {
type PDFPasswordFormProps = {
/** If the submitted password is invalid (show an error message) */
isPasswordInvalid: PropTypes.bool,
isPasswordInvalid?: boolean;

/** If loading indicator should be shown */
shouldShowLoadingIndicator: PropTypes.bool,
shouldShowLoadingIndicator?: boolean;

/** Notify parent that the password form has been submitted */
onSubmit: PropTypes.func,
onSubmit?: (password: string) => void;

/** Notify parent that the password has been updated/edited */
onPasswordUpdated: PropTypes.func,
onPasswordUpdated?: (newPassword: string) => void;

/** Notify parent that a text field has been focused or blurred */
onPasswordFieldFocused: PropTypes.func,
onPasswordFieldFocused?: (isFocused: boolean) => void;

/** Should focus to the password input */
isFocused: PropTypes.bool.isRequired,
isFocused: boolean;
};

const defaultProps = {
isPasswordInvalid: false,
shouldShowLoadingIndicator: false,
onSubmit: () => {},
onPasswordUpdated: () => {},
onPasswordFieldFocused: () => {},
};

function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicator, onSubmit, onPasswordUpdated, onPasswordFieldFocused}) {
function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadingIndicator = false, onSubmit, onPasswordUpdated, onPasswordFieldFocused}: PDFPasswordFormProps) {
const styles = useThemeStyles();
const {isSmallScreenWidth} = useWindowDimensions();
const {translate} = useLocalize();

const [password, setPassword] = useState('');
const [validationErrorText, setValidationErrorText] = useState('');
const [shouldShowForm, setShouldShowForm] = useState(false);
const textInputRef = useRef(null);
const textInputRef = useRef<BaseTextInputRef>(null);

const focusTimeoutRef = useRef(null);
const focusTimeoutRef = useRef<NodeJS.Timeout>();

const errorText = useMemo(() => {
if (isPasswordInvalid) {
return 'attachmentView.passwordIncorrect';
}
if (!_.isEmpty(validationErrorText)) {
if (validationErrorText) {
return validationErrorText;
}
return '';
Expand All @@ -76,7 +67,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
* Relevant thread: https://expensify.slack.com/archives/C01GTK53T8Q/p1694660990479979
*/
focusTimeoutRef.current = setTimeout(() => {
textInputRef.current.focus();
textInputRef.current?.focus();
}, CONST.ANIMATED_TRANSITION);
return () => {
if (!focusTimeoutRef.current) {
Expand All @@ -86,19 +77,19 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
};
}, [isFocused]);

const updatePassword = (newPassword) => {
onPasswordUpdated(newPassword);
if (!_.isEmpty(newPassword) && validationErrorText) {
const updatePassword = (newPassword: string) => {
onPasswordUpdated?.(newPassword);
if (newPassword && validationErrorText) {
setValidationErrorText('');
}
setPassword(newPassword);
};

const validate = () => {
if (!isPasswordInvalid && !_.isEmpty(password)) {
if (!isPasswordInvalid && password) {
return true;
}
if (_.isEmpty(password)) {
if (!password) {
setValidationErrorText('attachmentView.passwordRequired');
}
return false;
Expand All @@ -108,7 +99,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
if (!validate()) {
return;
}
onSubmit(password);
onSubmit?.(password);
};

return shouldShowForm ? (
Expand Down Expand Up @@ -136,8 +127,8 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
enterKeyHint="done"
onSubmitEditing={submitPassword}
errorText={errorText}
onFocus={() => onPasswordFieldFocused(true)}
onBlur={() => onPasswordFieldFocused(false)}
onFocus={() => onPasswordFieldFocused?.(true)}
onBlur={() => onPasswordFieldFocused?.(false)}
autoFocus
shouldDelayFocus={shouldDelayFocus}
secureTextEntry
Expand All @@ -160,8 +151,6 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
);
}

PDFPasswordForm.propTypes = propTypes;
PDFPasswordForm.defaultProps = defaultProps;
PDFPasswordForm.displayName = 'PDFPasswordForm';

export default PDFPasswordForm;
147 changes: 0 additions & 147 deletions src/components/PDFView/index.js

This file was deleted.

Loading

0 comments on commit 709fb40

Please sign in to comment.