From df364c5fe9c13b3e8c39c51b2f85d6f798ad54b3 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Thu, 18 Apr 2024 17:50:35 +0530 Subject: [PATCH 01/12] fix: IOU Scan - In dark mode, the damaged PDF - file is barely visible. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.tsx | 8 ++++++-- src/components/PDFThumbnail/types.ts | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index a5b911deb6ff..8663357fb508 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -4,6 +4,8 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import {Document, pdfjs, Thumbnail} from 'react-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import type PDFThumbnailProps from './types'; @@ -12,8 +14,9 @@ if (!pdfjs.GlobalWorkerOptions.workerSrc) { pdfjs.GlobalWorkerOptions.workerSrc = URL.createObjectURL(new Blob([pdfWorkerSource], {type: 'text/javascript'})); } -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, errorLabelStyles}: PDFThumbnailProps) { const styles = useThemeStyles(); + const {translate} = useLocalize(); const thumbnail = useMemo( () => ( @@ -26,13 +29,14 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena }} externalLinkTarget="_blank" onPassword={onPassword} + error={{translate('attachmentView.failedToLoadPDF')}} > ), - [isAuthTokenRequired, previewSourceURL, onPassword], + [isAuthTokenRequired, previewSourceURL, onPassword, errorLabelStyles, translate, styles.textLabel], ); return ( diff --git a/src/components/PDFThumbnail/types.ts b/src/components/PDFThumbnail/types.ts index 11253e462aca..5891ac133da1 100644 --- a/src/components/PDFThumbnail/types.ts +++ b/src/components/PDFThumbnail/types.ts @@ -1,4 +1,4 @@ -import type {StyleProp, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; type PDFThumbnailProps = { /** Source URL for the preview PDF */ @@ -15,6 +15,9 @@ type PDFThumbnailProps = { /** Callback to call if PDF is password protected */ onPassword?: () => void; + + /** Styles for the error label */ + errorLabelStyles?: StyleProp; }; export default PDFThumbnailProps; From 1e046d8530b62a4c0defc37e1b20e411d6ebb91c Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Mon, 22 Apr 2024 18:35:09 +0530 Subject: [PATCH 02/12] fix: show corrupted pdf alert for native devices. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.native.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index 0232dba99f05..3da6d5b4fa6e 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -1,19 +1,24 @@ -import React from 'react'; +import React, {useState} from 'react'; import {View} from 'react-native'; import Pdf from 'react-native-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import type PDFThumbnailProps from './types'; -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, errorLabelStyles}: PDFThumbnailProps) { const styles = useThemeStyles(); const sizeStyles = [styles.w100, styles.h100]; + const {translate} = useLocalize(); + + const [isCorrupted, setIsCorrupted] = useState(false); return ( - {enabled && ( + {enabled && !isCorrupted && ( { + if ('message' in error && typeof error.message === 'string' && error.message.match(/corrupted/i)) { + setIsCorrupted(true); + } + if (!('message' in error && typeof error.message === 'string' && error.message.match(/password/i))) { return; } + if (!onPassword) { return; } @@ -32,6 +42,7 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena }} /> )} + {isCorrupted && {translate('attachmentView.failedToLoadPDF')}} ); From 2288b186406b8eac3351a9aca5f4972584efe6d6 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Mon, 22 Apr 2024 18:36:34 +0530 Subject: [PATCH 03/12] spacing improvement. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.native.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index 3da6d5b4fa6e..c008d6823a00 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -12,7 +12,6 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena const styles = useThemeStyles(); const sizeStyles = [styles.w100, styles.h100]; const {translate} = useLocalize(); - const [isCorrupted, setIsCorrupted] = useState(false); return ( @@ -30,11 +29,9 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena if ('message' in error && typeof error.message === 'string' && error.message.match(/corrupted/i)) { setIsCorrupted(true); } - if (!('message' in error && typeof error.message === 'string' && error.message.match(/password/i))) { return; } - if (!onPassword) { return; } From f258c08c6fe2f9609341f27c585396212c3f7f03 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Wed, 8 May 2024 17:42:55 +0530 Subject: [PATCH 04/12] add ReceiptSlash icon for corrupt pdf's. Signed-off-by: Krishna Gupta --- src/components/Icon/Expensicons.ts | 2 ++ src/components/PDFThumbnail/index.native.tsx | 29 +++++++++++------ src/components/PDFThumbnail/index.tsx | 33 +++++++++++++++----- src/components/PDFThumbnail/types.ts | 5 +-- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index 74dbf8622a24..d052dead7366 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -128,6 +128,7 @@ import QrCode from '@assets/images/qrcode.svg'; import QuestionMark from '@assets/images/question-mark-circle.svg'; import ReceiptScan from '@assets/images/receipt-scan.svg'; import ReceiptSearch from '@assets/images/receipt-search.svg'; +import ReceiptSlash from '@assets/images/receipt-slash.svg'; import Receipt from '@assets/images/receipt.svg'; import RemoveMembers from '@assets/images/remove-members.svg'; import Rotate from '@assets/images/rotate-image.svg'; @@ -296,6 +297,7 @@ export { QuestionMark, Receipt, ReceiptScan, + ReceiptSlash, RemoveMembers, ReceiptSearch, Rotate, diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index c008d6823a00..7498fb4597b5 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -2,22 +2,24 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import Pdf from 'react-native-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import type PDFThumbnailProps from './types'; -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, errorLabelStyles}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { const styles = useThemeStyles(); + const theme = useTheme(); const sizeStyles = [styles.w100, styles.h100]; - const {translate} = useLocalize(); - const [isCorrupted, setIsCorrupted] = useState(false); + + const [hasError, setHasError] = useState(false); return ( - - {enabled && !isCorrupted && ( + + {enabled && !hasError && ( { if ('message' in error && typeof error.message === 'string' && error.message.match(/corrupted/i)) { - setIsCorrupted(true); + setHasError(true); } if (!('message' in error && typeof error.message === 'string' && error.message.match(/password/i))) { return; @@ -39,7 +41,16 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena }} /> )} - {isCorrupted && {translate('attachmentView.failedToLoadPDF')}} + {hasError && ( + + + + )} ); diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index 8663357fb508..41098a8b77b9 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -1,11 +1,12 @@ // @ts-expect-error - This line imports a module from 'pdfjs-dist' package which lacks TypeScript typings. import pdfWorkerSource from 'pdfjs-dist/legacy/build/pdf.worker'; -import React, {useMemo} from 'react'; +import React, {useMemo, useState} from 'react'; import {View} from 'react-native'; import {Document, pdfjs, Thumbnail} from 'react-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import type PDFThumbnailProps from './types'; @@ -14,9 +15,10 @@ if (!pdfjs.GlobalWorkerOptions.workerSrc) { pdfjs.GlobalWorkerOptions.workerSrc = URL.createObjectURL(new Blob([pdfWorkerSource], {type: 'text/javascript'})); } -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, errorLabelStyles}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { const styles = useThemeStyles(); - const {translate} = useLocalize(); + const theme = useTheme(); + const [hasError, setHasError] = useState(false); const thumbnail = useMemo( () => ( @@ -29,19 +31,34 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena }} externalLinkTarget="_blank" onPassword={onPassword} - error={{translate('attachmentView.failedToLoadPDF')}} + onLoad={() => { + setHasError(false); + }} + onLoadError={() => { + setHasError(true); + }} + error={ + + + + } > ), - [isAuthTokenRequired, previewSourceURL, onPassword, errorLabelStyles, translate, styles.textLabel], + [isAuthTokenRequired, previewSourceURL, onPassword, styles, theme], ); return ( - {enabled && thumbnail} + {enabled && thumbnail} ); } diff --git a/src/components/PDFThumbnail/types.ts b/src/components/PDFThumbnail/types.ts index 5891ac133da1..11253e462aca 100644 --- a/src/components/PDFThumbnail/types.ts +++ b/src/components/PDFThumbnail/types.ts @@ -1,4 +1,4 @@ -import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; type PDFThumbnailProps = { /** Source URL for the preview PDF */ @@ -15,9 +15,6 @@ type PDFThumbnailProps = { /** Callback to call if PDF is password protected */ onPassword?: () => void; - - /** Styles for the error label */ - errorLabelStyles?: StyleProp; }; export default PDFThumbnailProps; From d6a166b50a036de297c7740b479e65b9a68e5019 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Thu, 9 May 2024 09:04:55 +0530 Subject: [PATCH 05/12] receipt slash icon size update. Signed-off-by: Krishna Gupta --- assets/images/receipt-slash.svg | 12 ++++++++++++ src/components/PDFThumbnail/index.native.tsx | 5 +++-- src/components/PDFThumbnail/index.tsx | 5 +++-- src/styles/variables.ts | 2 ++ 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 assets/images/receipt-slash.svg diff --git a/assets/images/receipt-slash.svg b/assets/images/receipt-slash.svg new file mode 100644 index 000000000000..2af3fcbc60e6 --- /dev/null +++ b/assets/images/receipt-slash.svg @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index 7498fb4597b5..b5e2cb887507 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -7,6 +7,7 @@ import * as Expensicons from '@components/Icon/Expensicons'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; +import variables from '@styles/variables'; import type PDFThumbnailProps from './types'; function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { @@ -45,8 +46,8 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index 41098a8b77b9..8cd84934655f 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -9,6 +9,7 @@ import * as Expensicons from '@components/Icon/Expensicons'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; +import variables from '@styles/variables'; import type PDFThumbnailProps from './types'; if (!pdfjs.GlobalWorkerOptions.workerSrc) { @@ -41,8 +42,8 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 7ab469af9533..381de09b48a1 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -187,6 +187,8 @@ export default { eReceiptBGHeight: 540, eReceiptBGHWidth: 335, eReceiptTextContainerWidth: 263, + receiptPlaceholderIconWidth: 80, + receiptPlaceholderIconHeight: 80, reportPreviewMaxWidth: 335, reportActionImagesSingleImageHeight: 147, reportActionImagesDoubleImageHeight: 138, From 8745bc8d651741c11ae5d1b5ce3d634f097bb856 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Thu, 9 May 2024 12:12:38 +0530 Subject: [PATCH 06/12] fix stylings. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.native.tsx | 5 ++-- src/components/PDFThumbnail/index.tsx | 29 +++++++++++--------- src/styles/index.ts | 11 ++++++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index b5e2cb887507..fb28689a6c7b 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -14,7 +14,6 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena const styles = useThemeStyles(); const theme = useTheme(); const sizeStyles = [styles.w100, styles.h100]; - const [hasError, setHasError] = useState(false); return ( @@ -29,7 +28,7 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena singlePage style={sizeStyles} onError={(error) => { - if ('message' in error && typeof error.message === 'string' && error.message.match(/corrupted/i)) { + if ('message' in error && typeof error.message === 'string' && error.message.match(/Load pdf failed/i)) { setHasError(true); } if (!('message' in error && typeof error.message === 'string' && error.message.match(/password/i))) { @@ -43,7 +42,7 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena /> )} {hasError && ( - + { setHasError(true); }} - error={ - - - - } + error={() => null} > ), - [isAuthTokenRequired, previewSourceURL, onPassword, styles, theme], + [isAuthTokenRequired, previewSourceURL, onPassword], ); return ( - - {enabled && thumbnail} + + + {enabled && thumbnail} + {hasError && ( + + + + )} + ); } diff --git a/src/styles/index.ts b/src/styles/index.ts index 060fb1c5ba90..c5cc1e920bdf 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4215,6 +4215,7 @@ const styles = (theme: ThemeColors) => borderRadius: 16, margin: 20, overflow: 'hidden', + justifyContent: 'center', }, reportPreviewBox: { @@ -4373,6 +4374,16 @@ const styles = (theme: ThemeColors) => maxWidth: 400, }, + pdfErrorPlaceholder: { + overflow: 'hidden', + borderWidth: 2, + borderColor: theme.cardBG, + borderRadius: variables.componentBorderRadiusLarge, + maxWidth: 400, + height: '100%', + backgroundColor: theme.highlightBG, + }, + moneyRequestAttachReceipt: { backgroundColor: theme.highlightBG, borderColor: theme.border, From bbcea3c4a39be48b9a709b36fe9f3b8bf3769d48 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Thu, 9 May 2024 12:57:53 +0530 Subject: [PATCH 07/12] feat: prevent uploading corrupt pdf's. Signed-off-by: Krishna Gupta --- src/components/AttachmentPicker/index.native.tsx | 2 +- src/components/MoneyRequestConfirmationList.tsx | 15 ++++++++++++--- src/components/PDFThumbnail/index.native.tsx | 14 ++++++-------- src/components/PDFThumbnail/index.tsx | 7 +++++-- src/components/PDFThumbnail/types.ts | 3 +++ src/languages/en.ts | 2 +- src/languages/es.ts | 2 +- .../iou/request/step/IOURequestStepScan/index.tsx | 2 +- 8 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index ad4cf023c096..431698b3567c 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -212,7 +212,7 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s * An attachment error dialog when user selected malformed images */ const showImageCorruptionAlert = useCallback(() => { - Alert.alert(translate('attachmentPicker.attachmentError'), translate('attachmentPicker.errorWhileSelectingCorruptedImage')); + Alert.alert(translate('attachmentPicker.attachmentError'), translate('attachmentPicker.errorWhileSelectingCorruptedAttachment')); }, [translate]); /** diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 2c592c20f4c6..9639d8a3f919 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -332,6 +332,7 @@ function MoneyRequestConfirmationList({ const [didConfirmSplit, setDidConfirmSplit] = useState(false); const [isAttachmentInvalid, setIsAttachmentInvalid] = useState(false); + const [invalidAttachmentPromt, setInvalidAttachmentPromt] = useState(translate('attachmentPicker.protectedPDFNotSupported')); const navigateBack = () => { Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); @@ -1050,7 +1051,14 @@ function MoneyRequestConfirmationList({ previewSourceURL={resolvedReceiptImage as string} // We don't support scaning password protected PDF receipt enabled={!isAttachmentInvalid} - onPassword={() => setIsAttachmentInvalid(true)} + onPassword={() => { + setIsAttachmentInvalid(true); + setInvalidAttachmentPromt(translate('attachmentPicker.protectedPDFNotSupported')); + }} + onLoadError={() => { + setInvalidAttachmentPromt(translate('attachmentPicker.errorWhileSelectingCorruptedAttachment')); + setIsAttachmentInvalid(true); + }} /> ) : ( diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index fb28689a6c7b..7c4709e45435 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -10,7 +10,7 @@ import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import variables from '@styles/variables'; import type PDFThumbnailProps from './types'; -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, onLoadError}: PDFThumbnailProps) { const styles = useThemeStyles(); const theme = useTheme(); const sizeStyles = [styles.w100, styles.h100]; @@ -28,16 +28,14 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena singlePage style={sizeStyles} onError={(error) => { - if ('message' in error && typeof error.message === 'string' && error.message.match(/Load pdf failed/i)) { - setHasError(true); + if (onLoadError) { + onLoadError(); } - if (!('message' in error && typeof error.message === 'string' && error.message.match(/password/i))) { + if ('message' in error && typeof error.message === 'string' && error.message.match(/password/i) && onPassword) { + onPassword(); return; } - if (!onPassword) { - return; - } - onPassword(); + setHasError(true); }} /> )} diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index 27b950f5394c..f06158275ade 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -16,7 +16,7 @@ if (!pdfjs.GlobalWorkerOptions.workerSrc) { pdfjs.GlobalWorkerOptions.workerSrc = URL.createObjectURL(new Blob([pdfWorkerSource], {type: 'text/javascript'})); } -function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword}: PDFThumbnailProps) { +function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, onLoadError}: PDFThumbnailProps) { const styles = useThemeStyles(); const theme = useTheme(); const [hasError, setHasError] = useState(false); @@ -36,6 +36,9 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena setHasError(false); }} onLoadError={() => { + if (onLoadError) { + onLoadError(); + } setHasError(true); }} error={() => null} @@ -45,7 +48,7 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena ), - [isAuthTokenRequired, previewSourceURL, onPassword], + [isAuthTokenRequired, previewSourceURL, onPassword, onLoadError], ); return ( diff --git a/src/components/PDFThumbnail/types.ts b/src/components/PDFThumbnail/types.ts index 11253e462aca..349669ecc33e 100644 --- a/src/components/PDFThumbnail/types.ts +++ b/src/components/PDFThumbnail/types.ts @@ -15,6 +15,9 @@ type PDFThumbnailProps = { /** Callback to call if PDF is password protected */ onPassword?: () => void; + + /** Callback to call if PDF can't be loaded(corrupted) */ + onLoadError?: () => void; }; export default PDFThumbnailProps; diff --git a/src/languages/en.ts b/src/languages/en.ts index a822e1c5c3c8..98b186fccbf7 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -348,7 +348,7 @@ export default { expensifyDoesntHaveAccessToCamera: "Expensify can't take photos without access to your camera. Tap Settings to update permissions.", attachmentError: 'Attachment error', errorWhileSelectingAttachment: 'An error occurred while selecting an attachment, please try again.', - errorWhileSelectingCorruptedImage: 'An error occurred while selecting a corrupted attachment, please try another file.', + errorWhileSelectingCorruptedAttachment: 'An error occurred while selecting a corrupted attachment, please try another file.', takePhoto: 'Take photo', chooseFromGallery: 'Choose from gallery', chooseDocument: 'Choose document', diff --git a/src/languages/es.ts b/src/languages/es.ts index b2f02708bbe2..3ebf4324f9b0 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -342,7 +342,7 @@ export default { expensifyDoesntHaveAccessToCamera: 'Expensify no puede tomar fotos sin acceso a la cámara. Haz click en Configuración para actualizar los permisos.', attachmentError: 'Error al adjuntar archivo', errorWhileSelectingAttachment: 'Ha ocurrido un error al seleccionar un archivo adjunto. Por favor, inténtalo de nuevo.', - errorWhileSelectingCorruptedImage: 'Ha ocurrido un error al seleccionar un archivo adjunto corrupto. Por favor, inténtalo con otro archivo.', + errorWhileSelectingCorruptedAttachment: 'Ha ocurrido un error al seleccionar un archivo adjunto corrupto. Por favor, inténtalo con otro archivo.', takePhoto: 'Hacer una foto', chooseFromGallery: 'Elegir de la galería', chooseDocument: 'Elegir documento', diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 44b32754113a..53b68ed5307e 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -212,7 +212,7 @@ function IOURequestStepScan({ return true; }) .catch(() => { - setUploadReceiptError(true, 'attachmentPicker.attachmentError', 'attachmentPicker.errorWhileSelectingCorruptedImage'); + setUploadReceiptError(true, 'attachmentPicker.attachmentError', 'attachmentPicker.errorWhileSelectingCorruptedAttachment'); return false; }); } From eb014587bf2ed5385749f860ebe9cdf50e7c0c03 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Tue, 14 May 2024 17:58:34 +0530 Subject: [PATCH 08/12] remove changes from MoneyRequestConfirmationList. Signed-off-by: Krishna Gupta --- src/components/MoneyRequestConfirmationList.tsx | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 9639d8a3f919..2c592c20f4c6 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -332,7 +332,6 @@ function MoneyRequestConfirmationList({ const [didConfirmSplit, setDidConfirmSplit] = useState(false); const [isAttachmentInvalid, setIsAttachmentInvalid] = useState(false); - const [invalidAttachmentPromt, setInvalidAttachmentPromt] = useState(translate('attachmentPicker.protectedPDFNotSupported')); const navigateBack = () => { Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); @@ -1051,14 +1050,7 @@ function MoneyRequestConfirmationList({ previewSourceURL={resolvedReceiptImage as string} // We don't support scaning password protected PDF receipt enabled={!isAttachmentInvalid} - onPassword={() => { - setIsAttachmentInvalid(true); - setInvalidAttachmentPromt(translate('attachmentPicker.protectedPDFNotSupported')); - }} - onLoadError={() => { - setInvalidAttachmentPromt(translate('attachmentPicker.errorWhileSelectingCorruptedAttachment')); - setIsAttachmentInvalid(true); - }} + onPassword={() => setIsAttachmentInvalid(true)} /> ) : ( From 31caba2c668877e26dc40a8d91c17d369df24403 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Tue, 14 May 2024 18:01:03 +0530 Subject: [PATCH 09/12] update MoneyRequestConfirmationList. Signed-off-by: Krishna Gupta --- src/components/MoneyRequestConfirmationList.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 086580d60e57..f94bba4031f2 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -325,6 +325,7 @@ function MoneyRequestConfirmationList({ const [didConfirmSplit, setDidConfirmSplit] = useState(false); const [isAttachmentInvalid, setIsAttachmentInvalid] = useState(false); + const [invalidAttachmentPromt, setInvalidAttachmentPromt] = useState(translate('attachmentPicker.protectedPDFNotSupported')); const navigateBack = useCallback( () => Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)), @@ -1096,7 +1097,14 @@ function MoneyRequestConfirmationList({ previewSourceURL={resolvedReceiptImage as string} // We don't support scanning password protected PDF receipt enabled={!isAttachmentInvalid} - onPassword={() => setIsAttachmentInvalid(true)} + onPassword={() => { + setIsAttachmentInvalid(true); + setInvalidAttachmentPromt(translate('attachmentPicker.protectedPDFNotSupported')); + }} + onLoadError={() => { + setInvalidAttachmentPromt(translate('attachmentPicker.errorWhileSelectingCorruptedAttachment')); + setIsAttachmentInvalid(true); + }} /> ) : ( {shouldShowAllFields && supplementaryFields} @@ -1220,6 +1229,7 @@ function MoneyRequestConfirmationList({ transaction, transactionID, translate, + invalidAttachmentPromt, ], ); From 075868d8d3ac4c16cc9f7ce3689b6ed58d00e87b Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Fri, 17 May 2024 12:24:31 +0530 Subject: [PATCH 10/12] minor updates and refactoring. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.native.tsx | 25 +++++------------- src/components/PDFThumbnail/index.tsx | 27 +++++--------------- 2 files changed, 13 insertions(+), 39 deletions(-) diff --git a/src/components/PDFThumbnail/index.native.tsx b/src/components/PDFThumbnail/index.native.tsx index 7c4709e45435..27d41ede3263 100644 --- a/src/components/PDFThumbnail/index.native.tsx +++ b/src/components/PDFThumbnail/index.native.tsx @@ -2,24 +2,20 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import Pdf from 'react-native-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; -import variables from '@styles/variables'; +import PDFThumbnailError from './PDFThumbnailError'; import type PDFThumbnailProps from './types'; function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, onLoadError}: PDFThumbnailProps) { const styles = useThemeStyles(); - const theme = useTheme(); const sizeStyles = [styles.w100, styles.h100]; - const [hasError, setHasError] = useState(false); + const [failedToLoad, setFailedToLoad] = useState(false); return ( - - {enabled && !hasError && ( + + {enabled && !failedToLoad && ( )} - {hasError && ( - - - - )} + {failedToLoad && } ); diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index f4dc4727657a..99ae95f34c6b 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -3,12 +3,9 @@ import React, {useMemo, useState} from 'react'; import {View} from 'react-native'; import {Document, pdfjs, Thumbnail} from 'react-pdf'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; -import variables from '@styles/variables'; +import PDFThumbnailError from './PDFThumbnailError'; import type PDFThumbnailProps from './types'; if (!pdfjs.GlobalWorkerOptions.workerSrc) { @@ -17,8 +14,7 @@ if (!pdfjs.GlobalWorkerOptions.workerSrc) { function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, enabled = true, onPassword, onLoadError}: PDFThumbnailProps) { const styles = useThemeStyles(); - const theme = useTheme(); - const [hasError, setHasError] = useState(false); + const [failedToLoad, setFailedToLoad] = useState(false); const thumbnail = useMemo( () => ( @@ -32,13 +28,13 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena externalLinkTarget="_blank" onPassword={onPassword} onLoad={() => { - setHasError(false); + setFailedToLoad(false); }} onLoadError={() => { if (onLoadError) { onLoadError(); } - setHasError(true); + setFailedToLoad(true); }} error={() => null} > @@ -52,18 +48,9 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena return ( - - {enabled && thumbnail} - {hasError && ( - - - - )} + + {enabled && failedToLoad && thumbnail} + {failedToLoad && } ); From dc778d7c880028f187b6fc36a8908ecf538989e6 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Fri, 17 May 2024 12:25:19 +0530 Subject: [PATCH 11/12] add PDFThumbnailError component. Signed-off-by: Krishna Gupta --- .../PDFThumbnail/PDFThumbnailError.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/components/PDFThumbnail/PDFThumbnailError.tsx diff --git a/src/components/PDFThumbnail/PDFThumbnailError.tsx b/src/components/PDFThumbnail/PDFThumbnailError.tsx new file mode 100644 index 000000000000..0598a995e030 --- /dev/null +++ b/src/components/PDFThumbnail/PDFThumbnailError.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import {View} from 'react-native'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import variables from '@styles/variables'; + +function PDFThumbnailError() { + const styles = useThemeStyles(); + const theme = useTheme(); + + return ( + + + + ); +} + +export default PDFThumbnailError; From 1f93a1ee1db81f5b41e6dd55b4df586d8c7db432 Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Mon, 20 May 2024 13:20:32 +0530 Subject: [PATCH 12/12] fix styling issues. Signed-off-by: Krishna Gupta --- src/components/PDFThumbnail/index.tsx | 4 ++-- src/styles/index.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index 99ae95f34c6b..8e79c027cf03 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -47,9 +47,9 @@ function PDFThumbnail({previewSourceURL, style, isAuthTokenRequired = false, ena ); return ( - + - {enabled && failedToLoad && thumbnail} + {enabled && !failedToLoad && thumbnail} {failedToLoad && } diff --git a/src/styles/index.ts b/src/styles/index.ts index 97d491790c96..6c69e12f34d0 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4225,7 +4225,6 @@ const styles = (theme: ThemeColors) => borderRadius: 16, margin: 20, overflow: 'hidden', - justifyContent: 'center', }, reportPreviewBox: {