-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[Multi-Scan] Support Multi-Scan in Receipt page #63352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
cristipaval
merged 56 commits into
Expensify:main
from
callstack-internal:feature/multi-scan-wire-up
Jun 30, 2025
Merged
Changes from all commits
Commits
Show all changes
56 commits
Select commit
Hold shift + click to select a range
f9d1702
refactor: AttachmentCarousel, extract common UI
Swor71 21096e9
add: basic navigation setup for receipt view modal
Swor71 7b60797
add: draft ReceiptViewModal component and setup
Swor71 c246819
change: ReceiptViewModal to depend on local state instead of navigati…
Swor71 b7bafca
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 f79376b
Merge remote-tracking branch 'origin/VickyStash/feature/61179-update-…
Swor71 bff82d4
chore: adjustments to slack replies, general clean up
Swor71 d908473
change: reintroduced navigation with params due to mobile web require…
Swor71 837d8f2
Merge remote-tracking branch 'origin/VickyStash/feature/61179-update-…
Swor71 a99a584
add: switching between images in ReceiptViewModal with arrows, delete…
Swor71 8e92177
chore: minor clean up
Swor71 54e5d52
add: native initial implementation for ReceiptViewModal
Swor71 a1d4440
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 6ddc737
remove: not needed receiptID assignment
Swor71 6897997
add: confirmation modal on deleting receipt
Swor71 e28343c
chore: removed dependency on attachments from carousel buttons
Swor71 b602ef5
add: ReceiptViewModal independent of platform
Swor71 f9dfcc0
refactor: native versions of AttachmentCarousel and AttachmentCarouse…
Swor71 513d3b0
refactor: web versions of AttachmentCarousel and AttachmentCarouselView
Swor71 c5644ec
chore: clean up, extracted common types
Swor71 8e1635a
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 92001ab
chore: remove comment
Swor71 b1be0a4
fix: eslint CI error
Swor71 58cd754
fix: prettier CI error
Swor71 1e2622f
chore: removed duplicate of AttachmentCarousel for native platform
Swor71 9be12a4
fix: no found page after deleting a receipt
Swor71 5a14e1f
revert: CarouselButtons changes
Swor71 7056ebc
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 84e22c0
add: backTo param to handle correct navigation after reload
Swor71 ac069d7
add: check for localSource in AttachmentView
Swor71 b395fda
chore: moved check for local source next to if block responsible for …
Swor71 18670b8
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 739020b
fix: in native modal always opening on first image
Swor71 0f48f9f
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 df21be3
fix: ts error
Swor71 bbf5826
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 d62c855
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 1b20901
chore: change canUseMultiScan to true for ad hoc build
Swor71 8a92634
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 af47793
fix: disabled help button in header
Swor71 02f44f6
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 5395e1b
fix: double modal showing up on delete receipt press
Swor71 02d2171
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 4a82a0d
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 c3d400e
fix: icon size
Swor71 36c26ad
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 066f4f4
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 212ee5c
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 053056a
fix: incorrect spacing for photos on ios
Swor71 38d0752
Revert "fix: incorrect spacing for photos on ios"
Swor71 ea2aab3
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 d56ec80
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 fbcc345
fix: lint error
Swor71 12e556c
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 9d7ebfb
fix: confirm delete modal not showing up
Swor71 dd87582
Merge branch 'main' into feature/multi-scan-wire-up
Swor71 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/components/Attachments/AttachmentCarousel/AttachmentCarouselView/index.native.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| import React, {useCallback, useRef, useState} from 'react'; | ||
| import {Keyboard, View} from 'react-native'; | ||
| import CarouselButtons from '@components/Attachments/AttachmentCarousel/CarouselButtons'; | ||
| import AttachmentCarouselPager from '@components/Attachments/AttachmentCarousel/Pager'; | ||
| import type {AttachmentCarouselPagerHandle} from '@components/Attachments/AttachmentCarousel/Pager'; | ||
| import type {AttachmentSource} from '@components/Attachments/types'; | ||
| import BlockingView from '@components/BlockingViews/BlockingView'; | ||
| import * as Illustrations from '@components/Icon/Illustrations'; | ||
| import useLocalize from '@hooks/useLocalize'; | ||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||
| import {canUseTouchScreen as canUseTouchScreenUtil} from '@libs/DeviceCapabilities'; | ||
| import variables from '@styles/variables'; | ||
| import type AttachmentCarouselViewProps from './types'; | ||
|
|
||
| function AttachmentCarouselView({ | ||
| page, | ||
| attachments, | ||
| shouldShowArrows, | ||
| source, | ||
| report, | ||
| autoHideArrows, | ||
| cancelAutoHideArrow, | ||
| setShouldShowArrows, | ||
| onAttachmentError, | ||
| onNavigate, | ||
| onClose, | ||
| setPage, | ||
| attachmentID, | ||
| }: AttachmentCarouselViewProps) { | ||
| const {translate} = useLocalize(); | ||
| const canUseTouchScreen = canUseTouchScreenUtil(); | ||
| const styles = useThemeStyles(); | ||
| const [activeAttachmentID, setActiveAttachmentID] = useState<AttachmentSource>(attachmentID ?? source); | ||
|
|
||
| const pagerRef = useRef<AttachmentCarouselPagerHandle>(null); | ||
|
|
||
| /** Updates the page state when the user navigates between attachments */ | ||
| const updatePage = useCallback( | ||
| (newPageIndex: number) => { | ||
| Keyboard.dismiss(); | ||
| setShouldShowArrows(true); | ||
|
|
||
| const item = attachments.at(newPageIndex); | ||
|
|
||
| setPage(newPageIndex); | ||
| if (newPageIndex >= 0 && item) { | ||
| setActiveAttachmentID(item.attachmentID ?? item.source); | ||
| if (onNavigate) { | ||
| onNavigate(item); | ||
| } | ||
| onNavigate?.(item); | ||
| } | ||
| }, | ||
| [setShouldShowArrows, attachments, setPage, onNavigate], | ||
| ); | ||
|
|
||
| /** | ||
| * Increments or decrements the index to get another selected item | ||
| * @param {Number} deltaSlide | ||
| */ | ||
| const cycleThroughAttachments = useCallback( | ||
| (deltaSlide: number) => { | ||
| if (page === undefined) { | ||
| return; | ||
| } | ||
| const nextPageIndex = page + deltaSlide; | ||
| updatePage(nextPageIndex); | ||
| pagerRef.current?.setPage(nextPageIndex); | ||
|
|
||
| autoHideArrows(); | ||
| }, | ||
| [autoHideArrows, page, updatePage], | ||
| ); | ||
|
|
||
| return ( | ||
| <View | ||
| style={[styles.flex1, styles.attachmentCarouselContainer]} | ||
| onMouseEnter={() => !canUseTouchScreen && setShouldShowArrows(true)} | ||
| onMouseLeave={() => !canUseTouchScreen && setShouldShowArrows(false)} | ||
| > | ||
| {page === -1 ? ( | ||
| <BlockingView | ||
| icon={Illustrations.ToddBehindCloud} | ||
| iconWidth={variables.modalTopIconWidth} | ||
| iconHeight={variables.modalTopIconHeight} | ||
| title={translate('notFound.notHere')} | ||
| /> | ||
| ) : ( | ||
| <> | ||
| <CarouselButtons | ||
| page={page} | ||
| attachments={attachments} | ||
| shouldShowArrows={shouldShowArrows} | ||
| onBack={() => cycleThroughAttachments(-1)} | ||
| onForward={() => cycleThroughAttachments(1)} | ||
| autoHideArrow={autoHideArrows} | ||
| cancelAutoHideArrow={cancelAutoHideArrow} | ||
| /> | ||
| <AttachmentCarouselPager | ||
| items={attachments} | ||
| initialPage={page} | ||
| onAttachmentError={onAttachmentError} | ||
| activeAttachmentID={activeAttachmentID} | ||
| setShouldShowArrows={setShouldShowArrows} | ||
| onPageSelected={({nativeEvent: {position: newPage}}) => updatePage(newPage)} | ||
| onClose={onClose} | ||
| ref={pagerRef} | ||
| reportID={report?.reportID} | ||
| /> | ||
| </> | ||
| )} | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| AttachmentCarouselView.displayName = 'AttachmentCarouselView'; | ||
|
|
||
| export default AttachmentCarouselView; | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code caused #80949:
onNavigateis called twice per page change — once via theif (onNavigate)guard and again viaonNavigate?.(item)on the next line. This double call causes double route navigation per swipe, destabilizing video initialization and causing the play/pause button to blink. Combined with extraneoususeEffectdependencies inAttachmentViewand an unstableupdateCurrentURLAndReportIDcallback inPlaybackContext(from #81732), this created a feedback loop preventing video playback when navigating via the carousel. Fixed in #84739.