Skip to content

Commit 34f5451

Browse files
authored
Merge branch 'Expensify:main' into krishna2323/issue/87734-fix
2 parents 369d5e2 + 5000a57 commit 34f5451

61 files changed

Lines changed: 2009 additions & 118 deletions

Some content is hidden

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

src/ONYXKEYS.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,10 @@ const ONYXKEYS = {
11261126
ADD_AGENT_FORM_DRAFT: 'addAgentFormDraft',
11271127
CREATE_DOMAIN_GROUP_FORM: 'createDomainGroupForm',
11281128
CREATE_DOMAIN_GROUP_FORM_DRAFT: 'createDomainGroupFormDraft',
1129+
EDIT_AGENT_NAME_FORM: 'editAgentNameForm',
1130+
EDIT_AGENT_NAME_FORM_DRAFT: 'editAgentNameFormDraft',
1131+
EDIT_AGENT_PROMPT_FORM: 'editAgentPromptForm',
1132+
EDIT_AGENT_PROMPT_FORM_DRAFT: 'editAgentPromptFormDraft',
11291133
},
11301134
DERIVED: {
11311135
REPORT_ATTRIBUTES: 'reportAttributes',
@@ -1273,6 +1277,8 @@ type OnyxFormValuesMapping = {
12731277
[ONYXKEYS.FORMS.EDIT_DOMAIN_GROUP_NAME_FORM]: FormTypes.DomainGroupEditNameForm;
12741278
[ONYXKEYS.FORMS.ADD_AGENT_FORM]: FormTypes.AddAgentForm;
12751279
[ONYXKEYS.FORMS.CREATE_DOMAIN_GROUP_FORM]: FormTypes.DomainGroupCreateForm;
1280+
[ONYXKEYS.FORMS.EDIT_AGENT_NAME_FORM]: FormTypes.EditAgentNameForm;
1281+
[ONYXKEYS.FORMS.EDIT_AGENT_PROMPT_FORM]: FormTypes.EditAgentPromptForm;
12761282
};
12771283

12781284
type OnyxFormDraftValuesMapping = {

src/ROUTES.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,18 @@ const ROUTES = {
10611061
SETTINGS_WALLET_TRAVEL_CVV_VERIFY_ACCOUNT: `settings/wallet/travel-cvv/${VERIFY_ACCOUNT}`,
10621062
SETTINGS_AGENTS: 'settings/agents',
10631063
SETTINGS_AGENTS_ADD: 'settings/agents/new',
1064+
SETTINGS_AGENTS_EDIT: {
1065+
route: 'settings/agents/:accountID/edit',
1066+
getRoute: (accountID: number) => `settings/agents/${accountID}/edit` as const,
1067+
},
1068+
SETTINGS_AGENTS_EDIT_NAME: {
1069+
route: 'settings/agents/:accountID/edit/name',
1070+
getRoute: (accountID: number) => `settings/agents/${accountID}/edit/name` as const,
1071+
},
1072+
SETTINGS_AGENTS_EDIT_PROMPT: {
1073+
route: 'settings/agents/:accountID/edit/prompt',
1074+
getRoute: (accountID: number) => `settings/agents/${accountID}/edit/prompt` as const,
1075+
},
10641076
SETTINGS_RULES: 'settings/rules',
10651077
SETTINGS_RULES_ADD: {
10661078
route: 'settings/rules/new/:field?/:index?',

src/SCREENS.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ const SCREENS = {
177177
AGENTS: {
178178
ROOT: 'Settings_Agents',
179179
ADD: 'Settings_Agents_Add',
180+
EDIT: 'Settings_Agents_Edit',
181+
EDIT_NAME: 'Settings_Agents_Edit_Name',
182+
EDIT_PROMPT: 'Settings_Agents_Edit_Prompt',
180183
},
181184

182185
RULES: {

src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [
1212
SCREENS.SETTINGS.PREFERENCES.ROOT,
1313
SCREENS.SETTINGS.SECURITY,
1414
SCREENS.SETTINGS.WALLET.ROOT,
15+
SCREENS.SETTINGS.AGENTS.ROOT,
1516
SCREENS.SETTINGS.RULES.ROOT,
1617
SCREENS.SETTINGS.HELP,
1718
SCREENS.SETTINGS.ABOUT,

src/components/MenuItem.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type {ImageContentFit} from 'expo-image';
22
import type {ReactElement, ReactNode, Ref} from 'react';
3-
import React, {useMemo, useRef} from 'react';
3+
import React, {useEffect, useMemo, useRef} from 'react';
44
import type {GestureResponderEvent, Role, StyleProp, TextStyle, ViewStyle} from 'react-native';
55
import {View} from 'react-native';
66
import type {ValueOf} from 'type-fest';
@@ -618,6 +618,18 @@ function MenuItem({
618618
const {isExecuting} = useMenuItemGroupState() ?? {};
619619
const {singleExecution, waitForNavigate} = useMenuItemGroupActions() ?? {};
620620
const popoverAnchor = useRef<View>(null);
621+
const pressableRef = useRef<View>(null);
622+
useEffect(() => {
623+
const element = pressableRef.current;
624+
if (interactive || !element || typeof HTMLElement === 'undefined' || !(element instanceof HTMLElement) || typeof element.onclick === 'undefined') {
625+
return;
626+
}
627+
// React Native Web's Pressable always attaches an onClick handler to the DOM element.
628+
// TalkBack on Android web uses the presence of a click event listener to determine whether
629+
// an element is clickable and announces "double tap to activate" even for non-interactive elements.
630+
// Removing the onclick property prevents TalkBack from treating the element as clickable.
631+
element.onclick = null;
632+
}, [interactive]);
621633
const deviceHasHoverSupport = hasHoverSupport();
622634
const isCompactMenu = useIsCompactMenu();
623635
const isCompactPopoverItem = isCompactMenu && !isSmallScreenWidth && !shouldIgnoreCompactStyle;
@@ -861,7 +873,7 @@ function MenuItem({
861873
}
862874
disabledStyle={shouldUseDefaultCursorWhenDisabled && [styles.cursorDefault]}
863875
disabled={disabled || isExecuting}
864-
ref={mergeRefs(ref, popoverAnchor)}
876+
ref={mergeRefs(ref, popoverAnchor, pressableRef)}
865877
role={interactive ? role : undefined}
866878
accessibilityLabel={accessibilityLabelWithContextMenuHint}
867879
accessibilityHint={accessibilityHint}
@@ -1122,7 +1134,7 @@ function MenuItem({
11221134
</View>
11231135
)}
11241136
{!!brickRoadIndicator && (
1125-
<View style={[styles.alignItemsCenter, styles.justifyContentCenter, styles.ml1, styles.mr2]}>
1137+
<View style={[styles.alignItemsCenter, styles.justifyContentCenter, styles.ml1, badgeText ? undefined : styles.mr2]}>
11261138
<Icon
11271139
src={icons.DotIndicator}
11281140
fill={brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR ? theme.danger : theme.success}

src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableHeaderButtons.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ function WorkspaceCompanyCardsTableHeaderButtons({policyID, feedName, isLoading,
6666
const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY);
6767
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
6868

69-
const {cardFeedErrors} = useCardFeedErrors();
69+
const {cardFeedErrors, shouldShowRbrForFeedNameWithDomainID} = useCardFeedErrors();
7070
const feedErrors = cardFeedErrors[feedName];
7171
const hasFeedErrors = feedErrors?.hasFeedErrors;
7272
const isFeedConnectionBroken = feedErrors?.isFeedConnectionBroken;
73-
const shouldShowRBR = feedErrors?.shouldShowRBR;
73+
const hasOtherFeedWithRBR = Object.keys(companyFeeds ?? {}).some((feed) => feed !== feedName && shouldShowRbrForFeedNameWithDomainID[feed]);
74+
const shouldShowFeedSelectorRBR = hasOtherFeedWithRBR || !!feedErrors?.hasWorkspaceErrors;
7475

7576
const openBankConnection = () => {
7677
if (!feedName) {
@@ -144,7 +145,7 @@ function WorkspaceCompanyCardsTableHeaderButtons({policyID, feedName, isLoading,
144145
CardFeedIcon={CardFeedIcon}
145146
feedName={formattedFeedName}
146147
supportingText={supportingText}
147-
shouldShowRBR={shouldShowRBR}
148+
shouldShowRBR={shouldShowFeedSelectorRBR}
148149
/>
149150
)}
150151

src/hooks/useRestoreWorkspacesTabOnNavigate.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ function useRestoreWorkspacesTabOnNavigate() {
5959
}
6060

6161
// Fall back to session storage when no workspace route exists anywhere in the navigation tree.
62-
const sessionRoute = getWorkspacesTabStateFromSessionStorage()
62+
// getStateFromPath returns state rooted at TAB_NAVIGATOR, so we must drill into it first.
63+
const sessionTabNavigatorRoute = getWorkspacesTabStateFromSessionStorage()?.routes?.findLast((route) => route.name === NAVIGATORS.TAB_NAVIGATOR);
64+
const sessionRoute = getTabState(sessionTabNavigatorRoute)
6365
?.routes?.findLast((route) => route.name === NAVIGATORS.WORKSPACE_NAVIGATOR)
6466
?.state?.routes?.findLast((route) => isWorkspaceNavigatorRouteName(route.name));
6567
if (sessionRoute) {

src/hooks/useSearchTypeMenuSections.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,12 @@ const useSearchTypeMenuSections = (queryParams?: UseSearchTypeMenuSectionsParams
168168
return -1;
169169
}, [typeMenuSections, savedSearches, hash, similarSearchHash, sortBy, sortOrder, type]);
170170

171+
const activeKey = activeItemIndex < 0 ? undefined : typeMenuSections.flatMap((section) => section.menuItems).at(activeItemIndex)?.key;
172+
171173
return {
172174
typeMenuSections,
173175
activeItemIndex,
176+
activeKey,
174177
};
175178
};
176179

src/languages/de.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,6 +2476,7 @@ const translations: TranslationDeepObject<typeof en> = {
24762476
revealDetails: 'Details anzeigen',
24772477
revealCvv: 'CVV anzeigen',
24782478
copyCardNumber: 'Kartennummer kopieren',
2479+
copyCvv: 'CVV kopieren',
24792480
updateAddress: 'Adresse aktualisieren',
24802481
},
24812482
cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Zu ${platform} Wallet hinzugefügt`,
@@ -2742,6 +2743,9 @@ ${amount} für ${merchant} – ${date}`,
27422743
emptyAgents: {title: 'Keine Agenten erstellt', subtitle: 'Hör auf, Dinge manuell zu erledigen. Weise stattdessen eine:n Agent:in an und spare dir eine Menge Zeit.'},
27432744
error: {
27442745
genericAdd: 'Beim Hinzufügen dieses Agenten ist ein Problem aufgetreten',
2746+
genericUpdate: 'Beim Aktualisieren dieses Agents ist ein Problem aufgetreten',
2747+
updateName: 'Beim Aktualisieren des Namens dieses Agents ist ein Problem aufgetreten',
2748+
updatePrompt: 'Beim Aktualisieren der Anweisungen dieses Agenten ist ein Problem aufgetreten',
27452749
},
27462750
},
27472751
addAgentPage: {
@@ -2754,6 +2758,16 @@ ${amount} für ${merchant} – ${date}`,
27542758
defaultPrompt:
27552759
'Lehne Ausgaben ab, die für Glücksspiele, Kinobesuche oder andere offensichtlich nicht geschäftliche Zwecke sind.\n\nErinnere den:die Nutzer:in daran, immer ein Belegfoto beizufügen, auf dem das Trinkgeld klar erkennbar ist.\n\nGenehmige den Bericht, wenn er früheren Berichten derselben Person sehr ähnlich ist.\n\nLehne Berichte mit mehr als 500 $ an Reisekosten ab.',
27562760
},
2761+
editAgentPage: {
2762+
title: 'Agent bearbeiten',
2763+
agentName: 'Agentenname',
2764+
instructions: 'Eigene Anweisungen schreiben',
2765+
deleteAgent: 'Agent löschen',
2766+
deleteAgentTitle: 'Agent löschen?',
2767+
deleteAgentMessage: 'Sind Sie sicher, dass Sie diese Ansprechperson löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.',
2768+
},
2769+
editAgentNamePage: {title: 'Agentenname'},
2770+
editAgentPromptPage: {title: 'Eigene Anweisungen schreiben', error: {emptyPrompt: 'Bitte gib Anweisungen für deine Agentin/deinen Agenten ein.'}},
27572771
expenseRulesPage: {
27582772
title: 'Ausgabenregeln',
27592773
findRule: 'Regel finden',

src/languages/en.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2546,6 +2546,7 @@ const translations = {
25462546
revealDetails: 'Reveal details',
25472547
revealCvv: 'Reveal CVV',
25482548
copyCardNumber: 'Copy card number',
2549+
copyCvv: 'Copy CVV',
25492550
updateAddress: 'Update address',
25502551
},
25512552
cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Added to ${platform} Wallet`,
@@ -2798,6 +2799,9 @@ const translations = {
27982799
},
27992800
error: {
28002801
genericAdd: 'There was a problem adding this agent',
2802+
genericUpdate: 'There was a problem updating this agent',
2803+
updateName: "There was a problem updating this agent's name",
2804+
updatePrompt: "There was a problem updating this agent's instructions",
28012805
},
28022806
},
28032807
addAgentPage: {
@@ -2810,6 +2814,23 @@ const translations = {
28102814
defaultPrompt:
28112815
"Reject expenses that are for gambling, movies, or other obvious non-business reasons.\n\nRemind the user to always include a receipt image that makes the tip clear.\n\nApprove the report if it's very similar to previous reports from the same user.\n\nReject reports with more than $500 in travel expenses.",
28122816
},
2817+
editAgentPage: {
2818+
title: 'Edit agent',
2819+
agentName: 'Agent name',
2820+
instructions: 'Write custom instructions',
2821+
deleteAgent: 'Delete agent',
2822+
deleteAgentTitle: 'Delete agent?',
2823+
deleteAgentMessage: 'Are you sure you want to delete this agent? This action cannot be undone.',
2824+
},
2825+
editAgentNamePage: {
2826+
title: 'Agent name',
2827+
},
2828+
editAgentPromptPage: {
2829+
title: 'Write custom instructions',
2830+
error: {
2831+
emptyPrompt: 'Please enter instructions for your agent.',
2832+
},
2833+
},
28132834
expenseRulesPage: {
28142835
title: 'Expense rules',
28152836
subtitle: 'These rules will apply to your expenses.',

0 commit comments

Comments
 (0)