Skip to content

Commit 2ef8043

Browse files
committed
Merge branch 'main' into @OlGierd03/migrate-AddUnreportedExpense
2 parents 408e215 + 68d4da3 commit 2ef8043

87 files changed

Lines changed: 873 additions & 362 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ jobs:
554554
else
555555
npm run build-staging
556556
fi
557+
env:
558+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
557559

558560
- name: Build storybook docs
559561
continue-on-error: true

.github/workflows/testBuild.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ jobs:
260260

261261
- name: Build web for testing
262262
run: npm run build-adhoc
263+
env:
264+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
263265

264266
- name: Deploy to S3 for internal testing
265267
run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://ad-hoc-expensify-cash/web/"$PULL_REQUEST_NUMBER"

__mocks__/reportData/transactions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const transactionR14932: Transaction = {
3030
reimbursable: true,
3131
hasEReceipt: true,
3232
cardID: 0,
33-
modifiedAmount: 0,
33+
modifiedAmount: '',
3434
originalAmount: 0,
3535
comment: {},
3636
bank: '',
@@ -59,7 +59,7 @@ const transactionR98765: Transaction = {
5959
hasEReceipt: true,
6060
managedCard: false,
6161
billable: false,
62-
modifiedAmount: 0,
62+
modifiedAmount: '',
6363
cardID: 0,
6464
originalAmount: 0,
6565
comment: {},

package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@
189189
"react-native-localize": "^3.5.4",
190190
"react-native-nitro-modules": "0.29.4",
191191
"react-native-nitro-sqlite": "9.2.0",
192-
"react-native-onyx": "3.0.15",
192+
"react-native-onyx": "3.0.19",
193193
"react-native-pager-view": "6.9.1",
194194
"react-native-pdf": "7.0.2",
195195
"react-native-performance": "^6.0.0",

src/CONST/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ const CONST = {
710710
NO_OPTIMISTIC_TRANSACTION_THREADS: 'noOptimisticTransactionThreads',
711711
UBER_FOR_BUSINESS: 'uberForBusiness',
712712
CUSTOM_REPORT_NAMES: 'newExpensifyCustomReportNames',
713+
ZERO_EXPENSES: 'zeroExpenses',
713714
},
714715
BUTTON_STATES: {
715716
DEFAULT: 'default',
@@ -1684,6 +1685,7 @@ const CONST = {
16841685
SPAN_OPEN_SEARCH_ROUTER: 'ManualOpenSearchRouter',
16851686
SPAN_OPEN_CREATE_EXPENSE: 'ManualOpenCreateExpense',
16861687
SPAN_SEND_MESSAGE: 'ManualSendMessage',
1688+
SPAN_SKELETON: 'ManualSkeleton',
16871689
SPAN_BOOTSPLASH: {
16881690
ROOT: 'BootsplashVisible',
16891691
NAVIGATION: 'BootsplashVisibleNavigation',
@@ -1699,6 +1701,11 @@ const CONST = {
16991701
ATTRIBUTE_CANCELED: 'canceled',
17001702
ATTRIBUTE_ROUTE_FROM: 'route_from',
17011703
ATTRIBUTE_ROUTE_TO: 'route_to',
1704+
ATTRIBUTE_MIN_DURATION: 'min_duration',
1705+
ATTRIBUTE_FINISHED_MANUALLY: 'finished_manually',
1706+
CONFIG: {
1707+
SKELETON_MIN_DURATION: 10_000,
1708+
},
17021709
},
17031710
PRIORITY_MODE: {
17041711
GSD: 'gsd',

src/components/AccountSwitcherSkeletonView/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader';
66
import useStyleUtils from '@hooks/useStyleUtils';
77
import useTheme from '@hooks/useTheme';
88
import useThemeStyles from '@hooks/useThemeStyles';
9+
import useSkeletonSpan from '@libs/telemetry/useSkeletonSpan';
910
import CONST from '@src/CONST';
1011

1112
type AccountSwitcherSkeletonViewProps = {
@@ -20,9 +21,11 @@ function AccountSwitcherSkeletonView({shouldAnimate = true, avatarSize = CONST.A
2021
const theme = useTheme();
2122
const styles = useThemeStyles();
2223
const StyleUtils = useStyleUtils();
24+
useSkeletonSpan('AccountSwitcherSkeletonView');
2325
const avatarPlaceholderSize = StyleUtils.getAvatarSize(avatarSize);
2426
const avatarPlaceholderRadius = avatarPlaceholderSize / 2;
2527
const startPositionX = avatarPlaceholderRadius;
28+
const rectXTranslation = startPositionX + avatarPlaceholderRadius + styles.gap3.gap;
2629

2730
return (
2831
<View style={styles.avatarSectionWrapperSkeleton}>
@@ -38,14 +41,12 @@ function AccountSwitcherSkeletonView({shouldAnimate = true, avatarSize = CONST.A
3841
r={avatarPlaceholderRadius}
3942
/>
4043
<Rect
41-
x={startPositionX + avatarPlaceholderRadius + styles.gap3.gap}
42-
y="6"
44+
transform={[{translateX: rectXTranslation}, {translateY: 6}]}
4345
width="45%"
4446
height="8"
4547
/>
4648
<Rect
47-
x={startPositionX + avatarPlaceholderRadius + styles.gap3.gap}
48-
y="26"
49+
transform={[{translateX: rectXTranslation}, {translateY: 26}]}
4950
width="55%"
5051
height="8"
5152
/>

src/components/ApproverSelectionList.tsx

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, {useMemo} from 'react';
2-
import type {SectionListData} from 'react-native';
32
import useDebouncedState from '@hooks/useDebouncedState';
43
import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
54
import useLocalize from '@hooks/useLocalize';
@@ -13,15 +12,14 @@ import variables from '@styles/variables';
1312
import CONST from '@src/CONST';
1413
import ONYXKEYS from '@src/ONYXKEYS';
1514
import type {Policy} from '@src/types/onyx';
16-
import type {Icon} from '@src/types/onyx/OnyxCommon';
1715
import {isEmptyObject} from '@src/types/utils/EmptyObject';
1816
import BlockingView from './BlockingViews/BlockingView';
1917
import FullPageNotFoundView from './BlockingViews/FullPageNotFoundView';
2018
import HeaderWithBackButton from './HeaderWithBackButton';
2119
import ScreenWrapper from './ScreenWrapper';
22-
import SelectionList from './SelectionListWithSections';
23-
import InviteMemberListItem from './SelectionListWithSections/InviteMemberListItem';
24-
import type {Section} from './SelectionListWithSections/types';
20+
import SelectionList from './SelectionList';
21+
import InviteMemberListItem from './SelectionList/ListItem/InviteMemberListItem';
22+
import type {ListItem} from './SelectionList/types';
2523

2624
type ApproverSelectionListPageProps = {
2725
testID: string;
@@ -42,21 +40,13 @@ type ApproverSelectionListPageProps = {
4240
onSelectApprover?: (approvers: SelectionListApprover[]) => void;
4341
shouldShowLoadingPlaceholder?: boolean;
4442
shouldEnableHeaderMaxHeight?: boolean;
43+
shouldUpdateFocusedIndex?: boolean;
4544
};
4645

47-
type SelectionListApprover = {
48-
text: string;
49-
alternateText: string;
50-
keyForList: string;
51-
isSelected: boolean;
52-
login: string;
53-
rightElement?: React.ReactNode;
54-
icons: Icon[];
46+
type SelectionListApprover = ListItem & {
5547
value?: number;
5648
};
5749

58-
type ApproverSection = SectionListData<SelectionListApprover, Section<SelectionListApprover>>;
59-
6050
function ApproverSelectionList({
6151
testID,
6252
headerTitle,
@@ -76,6 +66,7 @@ function ApproverSelectionList({
7666
onSelectApprover,
7767
shouldShowLoadingPlaceholder,
7868
shouldEnableHeaderMaxHeight,
69+
shouldUpdateFocusedIndex = true,
7970
}: ApproverSelectionListPageProps) {
8071
const styles = useThemeStyles();
8172
const {translate, localeCompare} = useLocalize();
@@ -89,23 +80,16 @@ function ApproverSelectionList({
8980
// eslint-disable-next-line rulesdir/no-negated-variables
9081
const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy) || shouldShowNotFoundViewProp;
9182

92-
const sections: ApproverSection[] = useMemo(() => {
83+
const data = useMemo(() => {
9384
const filteredApprovers =
9485
debouncedSearchTerm !== ''
9586
? tokenizedSearch(allApprovers, getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode), (option) => [option.text ?? '', option.login ?? ''])
9687
: allApprovers;
9788

98-
const data = sortAlphabetically(filteredApprovers, 'text', localeCompare);
99-
return [
100-
{
101-
title: undefined,
102-
data,
103-
shouldShow: true,
104-
},
105-
];
89+
return sortAlphabetically(filteredApprovers, 'text', localeCompare);
10690
}, [allApprovers, debouncedSearchTerm, countryCode, localeCompare]);
10791

108-
const shouldShowListEmptyContent = !debouncedSearchTerm && !sections.at(0)?.data.length && shouldShowListEmptyContentProp;
92+
const shouldShowListEmptyContent = !debouncedSearchTerm && !data.length && shouldShowListEmptyContentProp;
10993

11094
const toggleApprover = (member: SelectionListApprover) => {
11195
const isAlreadySelected = selectedMembers.some((selectedOption) => selectedOption.login === member.login);
@@ -122,8 +106,6 @@ function ApproverSelectionList({
122106
}
123107
};
124108

125-
const headerMessage = useMemo(() => (searchTerm && !sections.at(0)?.data?.length ? translate('common.noResultsFound') : ''), [searchTerm, sections, translate]);
126-
127109
const listEmptyContent = useMemo(
128110
() => (
129111
<BlockingView
@@ -140,6 +122,16 @@ function ApproverSelectionList({
140122
[translate, listEmptyContentSubtitle, styles.textSupporting, styles.pb10, lazyIllustrations.TurtleInShell],
141123
);
142124

125+
const textInputOptions = useMemo(
126+
() => ({
127+
label: shouldShowListEmptyContent ? undefined : translate('selectionList.findMember'),
128+
value: searchTerm,
129+
onChangeText: setSearchTerm,
130+
headerMessage: searchTerm && !data?.length ? translate('common.noResultsFound') : '',
131+
}),
132+
[shouldShowListEmptyContent, translate, searchTerm, setSearchTerm, data?.length],
133+
);
134+
143135
return (
144136
<ScreenWrapper
145137
testID={testID}
@@ -160,24 +152,21 @@ function ApproverSelectionList({
160152
/>
161153
{subtitle}
162154
<SelectionList
163-
canSelectMultiple={allowMultipleSelection}
164-
sections={sections}
165-
ListItem={InviteMemberListItem}
166-
textInputLabel={shouldShowListEmptyContent ? undefined : translate('selectionList.findMember')}
167-
textInputValue={searchTerm}
168-
onChangeText={setSearchTerm}
169-
headerMessage={headerMessage}
155+
data={data}
170156
onSelectRow={toggleApprover}
171-
showScrollIndicator
157+
ListItem={InviteMemberListItem}
158+
textInputOptions={textInputOptions}
159+
canSelectMultiple={allowMultipleSelection}
172160
shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
173161
listEmptyContent={listEmptyContent}
174-
shouldShowListEmptyContent={shouldShowListEmptyContent}
175-
initiallyFocusedOptionKey={initiallyFocusedOptionKey}
176-
shouldUpdateFocusedIndex
162+
showListEmptyContent={shouldShowListEmptyContent}
163+
initiallyFocusedItemKey={initiallyFocusedOptionKey}
177164
shouldShowTextInput={shouldShowTextInput}
178-
addBottomSafeAreaPadding
179165
showLoadingPlaceholder={shouldShowLoadingPlaceholder}
180166
footerContent={footerContent}
167+
addBottomSafeAreaPadding
168+
shouldUpdateFocusedIndex={shouldUpdateFocusedIndex}
169+
showScrollIndicator
181170
/>
182171
</FullPageNotFoundView>
183172
</ScreenWrapper>

src/components/AvatarSelector.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type AvatarSelectorProps = {
2929
label?: string;
3030
};
3131

32+
const SPACER_SIZE = 10;
33+
3234
/**
3335
* AvatarSelector — renders a grid of selectable avatars.
3436
*/
@@ -39,6 +41,8 @@ function AvatarSelector({selectedID, onSelect, label, name, size = CONST.AVATAR_
3941
const StyleUtils = useStyleUtils();
4042
const {avatarList} = useLetterAvatars(name, size);
4143

44+
const iconSize = StyleUtils.getAvatarSize(size);
45+
4246
return (
4347
<>
4448
{!!label && avatarList?.length > 0 && (
@@ -89,6 +93,15 @@ function AvatarSelector({selectedID, onSelect, label, name, size = CONST.AVATAR_
8993
</PressableWithFeedback>
9094
);
9195
})}
96+
{/* We need to add several invisible items at the end of the avatar list to guarantee that the last row avatars are aligned properly */}
97+
{[...Array(SPACER_SIZE).keys()].map((i) => (
98+
<View
99+
key={`spacer-${i}`}
100+
style={[styles.avatarSelectorWrapper]}
101+
>
102+
<View style={{width: iconSize, height: iconSize}} />
103+
</View>
104+
))}
92105
</View>
93106
</>
94107
);

src/components/AvatarSkeleton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import {Circle} from 'react-native-svg';
33
import type {ValueOf} from 'type-fest';
44
import useStyleUtils from '@hooks/useStyleUtils';
55
import useTheme from '@hooks/useTheme';
6+
import useSkeletonSpan from '@libs/telemetry/useSkeletonSpan';
67
import CONST from '@src/CONST';
78
import SkeletonViewContentLoader from './SkeletonViewContentLoader';
89

910
function AvatarSkeleton({size = CONST.AVATAR_SIZE.SMALL}: {size?: ValueOf<typeof CONST.AVATAR_SIZE>}) {
1011
const theme = useTheme();
11-
12+
useSkeletonSpan('AvatarSkeleton');
1213
const StyleUtils = useStyleUtils();
1314
const avatarSize = StyleUtils.getAvatarSize(size);
1415
const skeletonCircleRadius = avatarSize / 2;

0 commit comments

Comments
 (0)