diff --git a/package.json b/package.json index a8dac1bfe67f4..a5a0097aa2a73 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure", "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc", "typecheck-tsgo": "tsgo --project tsconfig.tsgo.json", - "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=334 --cache --cache-location=node_modules/.cache/eslint --cache-strategy content --concurrency=auto", + "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=316 --cache --cache-location=node_modules/.cache/eslint --cache-strategy content --concurrency=auto", "lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 ./scripts/lintChanged.sh", "check-lazy-loading": "ts-node scripts/checkLazyLoading.ts", "lint-watch": "npx eslint-watch --watch --changed", diff --git a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.native.tsx b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.native.tsx index 0c5c095ab96f3..cfedd87c414db 100644 --- a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.native.tsx @@ -33,9 +33,9 @@ import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import CameraPermission from '@pages/iou/request/step/IOURequestStepScan/CameraPermission'; +import NavigationAwareCamera from '@pages/iou/request/step/IOURequestStepScan/components/NavigationAwareCamera/Camera'; import {cropImageToAspectRatio} from '@pages/iou/request/step/IOURequestStepScan/cropImageToAspectRatio'; import type {ImageObject} from '@pages/iou/request/step/IOURequestStepScan/cropImageToAspectRatio'; -import NavigationAwareCamera from '@pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/Camera'; import StepScreenWrapper from '@pages/iou/request/step/StepScreenWrapper'; import withFullTransactionOrNotFound from '@pages/iou/request/step/withFullTransactionOrNotFound'; import type {WithFullTransactionOrNotFoundProps} from '@pages/iou/request/step/withFullTransactionOrNotFound'; diff --git a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx index 4efd0282eab84..2abeaa55a5f36 100644 --- a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx @@ -25,9 +25,9 @@ import {shouldUseTransactionDraft} from '@libs/IOUUtils'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; +import NavigationAwareCamera from '@pages/iou/request/step/IOURequestStepScan/components/NavigationAwareCamera/WebCamera'; import {cropImageToAspectRatio} from '@pages/iou/request/step/IOURequestStepScan/cropImageToAspectRatio'; import type {ImageObject} from '@pages/iou/request/step/IOURequestStepScan/cropImageToAspectRatio'; -import NavigationAwareCamera from '@pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/WebCamera'; import StepScreenDragAndDropWrapper from '@pages/iou/request/step/StepScreenDragAndDropWrapper'; import withFullTransactionOrNotFound from '@pages/iou/request/step/withFullTransactionOrNotFound'; import type {WithFullTransactionOrNotFoundProps} from '@pages/iou/request/step/withFullTransactionOrNotFound'; diff --git a/src/pages/iou/request/step/IOURequestStepScan/components/DesktopWebUploadView.tsx b/src/pages/iou/request/step/IOURequestStepScan/components/DesktopWebUploadView.tsx new file mode 100644 index 0000000000000..8c8fce4f8a860 --- /dev/null +++ b/src/pages/iou/request/step/IOURequestStepScan/components/DesktopWebUploadView.tsx @@ -0,0 +1,145 @@ +import React, {useRef, useState} from 'react'; +import {PanResponder, View} from 'react-native'; +import AttachmentPicker from '@components/AttachmentPicker'; +import Button from '@components/Button'; +import DragAndDropConsumer from '@components/DragAndDrop/Consumer'; +import {useDragAndDropState} from '@components/DragAndDrop/Provider'; +import DropZoneUI from '@components/DropZone/DropZoneUI'; +import Icon from '@components/Icon'; +import ReceiptAlternativeMethods from '@components/ReceiptAlternativeMethods'; +import Text from '@components/Text'; +import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import StepScreenDragAndDropWrapper from '@pages/iou/request/step/StepScreenDragAndDropWrapper'; +import CONST from '@src/CONST'; +import type {FileObject} from '@src/types/utils/Attachment'; + +type DesktopWebUploadViewProps = { + PDFValidationComponent: React.ReactNode; + shouldAcceptMultipleFiles: boolean; + isReplacingReceipt: boolean; + onLayout: () => void; + validateFiles: (files: FileObject[], items?: DataTransferItem[]) => void; + onBackButtonPress: () => void; + shouldShowWrapper: boolean; +}; + +function DesktopWebUploadView({ + PDFValidationComponent, + shouldAcceptMultipleFiles, + isReplacingReceipt, + onLayout, + validateFiles, + onBackButtonPress, + shouldShowWrapper, +}: DesktopWebUploadViewProps) { + const theme = useTheme(); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const lazyIllustrations = useMemoizedLazyIllustrations(['ReceiptStack']); + const lazyIcons = useMemoizedLazyExpensifyIcons(['ReplaceReceipt', 'SmartScan']); + const panResponder = useRef( + PanResponder.create({ + onPanResponderTerminationRequest: () => false, + }), + ).current; + + const {isDraggingOver} = useDragAndDropState(); + const [containerHeight, setContainerHeight] = useState(0); + const [desktopUploadViewHeight, setDesktopUploadViewHeight] = useState(0); + const [alternativeMethodsHeight, setAlternativeMethodsHeight] = useState(0); + const chooseFilesPaddingVertical = Number(styles.chooseFilesView(false).paddingVertical); + const shouldHideAlternativeMethods = alternativeMethodsHeight + desktopUploadViewHeight + chooseFilesPaddingVertical * 2 > containerHeight; + + const handleDropReceipt = (e: DragEvent) => { + const files = Array.from(e?.dataTransfer?.files ?? []); + if (files.length === 0) { + return; + } + for (const file of files) { + // eslint-disable-next-line no-param-reassign + file.uri = URL.createObjectURL(file); + } + + validateFiles(files, Array.from(e.dataTransfer?.items ?? [])); + }; + + return ( + + {(isDraggingOverWrapper) => ( + { + setContainerHeight(event.nativeEvent.layout.height); + onLayout(); + }} + style={[styles.flex1, styles.chooseFilesView(false)]} + > + + {!(isDraggingOver ?? isDraggingOverWrapper) && ( + { + setDesktopUploadViewHeight(e.nativeEvent.layout.height); + }} + > + {PDFValidationComponent} + + + {translate(shouldAcceptMultipleFiles ? 'receipt.uploadMultiple' : 'receipt.upload')} + + {translate(shouldAcceptMultipleFiles ? 'receipt.desktopSubtitleMultiple' : 'receipt.desktopSubtitleSingle')} + + + + + {({openPicker}) => ( +