diff --git a/android/app/build.gradle b/android/app/build.gradle
index 08e313c13462..0c3fc7afa2ee 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -96,8 +96,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001041114
- versionName "1.4.11-14"
+ versionCode 1001041123
+ versionName "1.4.11-23"
}
flavorDimensions "default"
diff --git a/desktop/package-lock.json b/desktop/package-lock.json
index 0ff280c4b9c6..bfeb58ceec05 100644
--- a/desktop/package-lock.json
+++ b/desktop/package-lock.json
@@ -10,7 +10,7 @@
"electron-context-menu": "^2.3.0",
"electron-log": "^4.4.7",
"electron-serve": "^1.0.0",
- "electron-updater": "^6.1.4",
+ "electron-updater": "^6.1.6",
"node-machine-id": "^1.1.12"
}
},
@@ -50,9 +50,9 @@
}
},
"node_modules/builder-util-runtime": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.1.tgz",
- "integrity": "sha512-2rLv/uQD2x+dJ0J3xtsmI12AlRyk7p45TEbE/6o/fbb633e/S3pPgm+ct+JHsoY7r39dKHnGEFk/AASRFdnXmA==",
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.2.tgz",
+ "integrity": "sha512-Or2/ycVYRGQ876hKMfiz2Ghgzh3WllgPW75jqt1Ta2a5wprpnziFrHpQ9eUq6/ScsVXMnG4PmQqlMsE9NFg8DQ==",
"dependencies": {
"debug": "^4.3.4",
"sax": "^1.2.4"
@@ -150,11 +150,11 @@
"integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q=="
},
"node_modules/electron-updater": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.4.tgz",
- "integrity": "sha512-yYAJc6RQjjV4WtInZVn+ZcLyXRhbVXoomKEfUUwDqIk5s2wxzLhWaor7lrNgxODyODhipjg4SVPMhJHi5EnsCA==",
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.6.tgz",
+ "integrity": "sha512-G2bO72i7kv+bVdBAjq6lQn8zkZ3wMRRjxBD4TGBjB77UiuMDUBeP45YAs4y08udPzttGW2qzpnbOUJY5RYWZfw==",
"dependencies": {
- "builder-util-runtime": "9.2.1",
+ "builder-util-runtime": "9.2.2",
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",
"lazy-val": "^1.0.5",
@@ -461,9 +461,9 @@
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="
},
"builder-util-runtime": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.1.tgz",
- "integrity": "sha512-2rLv/uQD2x+dJ0J3xtsmI12AlRyk7p45TEbE/6o/fbb633e/S3pPgm+ct+JHsoY7r39dKHnGEFk/AASRFdnXmA==",
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.2.tgz",
+ "integrity": "sha512-Or2/ycVYRGQ876hKMfiz2Ghgzh3WllgPW75jqt1Ta2a5wprpnziFrHpQ9eUq6/ScsVXMnG4PmQqlMsE9NFg8DQ==",
"requires": {
"debug": "^4.3.4",
"sax": "^1.2.4"
@@ -535,11 +535,11 @@
"integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q=="
},
"electron-updater": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.4.tgz",
- "integrity": "sha512-yYAJc6RQjjV4WtInZVn+ZcLyXRhbVXoomKEfUUwDqIk5s2wxzLhWaor7lrNgxODyODhipjg4SVPMhJHi5EnsCA==",
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.6.tgz",
+ "integrity": "sha512-G2bO72i7kv+bVdBAjq6lQn8zkZ3wMRRjxBD4TGBjB77UiuMDUBeP45YAs4y08udPzttGW2qzpnbOUJY5RYWZfw==",
"requires": {
- "builder-util-runtime": "9.2.1",
+ "builder-util-runtime": "9.2.2",
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",
"lazy-val": "^1.0.5",
diff --git a/desktop/package.json b/desktop/package.json
index bf49d93f1a7b..a6b92bde81c4 100644
--- a/desktop/package.json
+++ b/desktop/package.json
@@ -7,7 +7,7 @@
"electron-context-menu": "^2.3.0",
"electron-log": "^4.4.7",
"electron-serve": "^1.0.0",
- "electron-updater": "^6.1.4",
+ "electron-updater": "^6.1.6",
"node-machine-id": "^1.1.12"
},
"author": "Expensify, Inc.",
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 507543c84d41..e707e4c590b7 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.4.11.14
+ 1.4.11.23
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 6cb3c324fdee..f87a232a7454 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.4.11.14
+ 1.4.11.23
diff --git a/package-lock.json b/package-lock.json
index c4380a82ec12..f985d9383fba 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.4.11-14",
+ "version": "1.4.11-23",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.4.11-14",
+ "version": "1.4.11-23",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index c9c20d641402..817567dcb855 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.4.11-14",
+ "version": "1.4.11-23",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/CONST.ts b/src/CONST.ts
index d4208d51a78c..072f780b54ae 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1099,11 +1099,6 @@ const CONST = {
USER_CANCELLED: 'User canceled flow.',
USER_TAPPED_BACK: 'User exited by clicking the back button.',
USER_EXITED: 'User exited by manual action.',
- USER_CAMERA_DENINED: 'Onfido.OnfidoFlowError',
- USER_CAMERA_PERMISSION: 'Encountered an error: cameraPermission',
- // eslint-disable-next-line max-len
- USER_CAMERA_CONSENT_DENIED:
- 'Unexpected result Intent. It might be a result of incorrect integration, make sure you only pass Onfido intent to handleActivityResult. It might be due to unpredictable crash or error. Please report the problem to android-sdk@onfido.com. Intent: null \n resultCode: 0',
},
},
@@ -2731,17 +2726,125 @@ const CONST = {
EXPENSIFY_LOGO_SIZE_RATIO: 0.22,
EXPENSIFY_LOGO_MARGIN_RATIO: 0.03,
},
+ /**
+ * Acceptable values for the `accessibilityRole` prop on react native components.
+ *
+ * **IMPORTANT:** Do not use with the `role` prop as it can cause errors.
+ *
+ * @deprecated ACCESSIBILITY_ROLE is deprecated. Please use CONST.ROLE instead.
+ */
ACCESSIBILITY_ROLE: {
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
BUTTON: 'button',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
LINK: 'link',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
MENUITEM: 'menuitem',
- TEXT: 'presentation',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ TEXT: 'text',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
RADIO: 'radio',
- IMAGEBUTTON: 'img button',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ IMAGEBUTTON: 'imagebutton',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
CHECKBOX: 'checkbox',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ SWITCH: 'switch',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ ADJUSTABLE: 'adjustable',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ IMAGE: 'image',
+ },
+ /**
+ * Acceptable values for the `role` attribute on react native components.
+ *
+ * **IMPORTANT:** Not for use with the `accessibilityRole` prop, as it accepts different values, and new components
+ * should use the `role` prop instead.
+ */
+ ROLE: {
+ /** Use for elements with important, time-sensitive information. */
+ ALERT: 'alert',
+ /** Use for elements that act as buttons. */
+ BUTTON: 'button',
+ /** Use for elements representing checkboxes. */
+ CHECKBOX: 'checkbox',
+ /** Use for elements that allow a choice from multiple options. */
+ COMBOBOX: 'combobox',
+ /** Use with scrollable lists to represent a grid layout. */
+ GRID: 'grid',
+ /** Use for section headers or titles. */
+ HEADING: 'heading',
+ /** Use for image elements. */
+ IMG: 'img',
+ /** Use for elements that navigate to other pages or content. */
+ LINK: 'link',
+ /** Use to identify a list of items. */
+ LIST: 'list',
+ /** Use for a list of choices or options. */
+ MENU: 'menu',
+ /** Use for a container of multiple menus. */
+ MENUBAR: 'menubar',
+ /** Use for items within a menu. */
+ MENUITEM: 'menuitem',
+ /** Use when no specific role is needed. */
+ NONE: 'none',
+ /** Use for elements that don't require a specific role. */
+ PRESENTATION: 'presentation',
+ /** Use for elements showing progress of a task. */
+ PROGRESSBAR: 'progressbar',
+ /** Use for radio buttons. */
+ RADIO: 'radio',
+ /** Use for groups of radio buttons. */
+ RADIOGROUP: 'radiogroup',
+ /** Use for scrollbar elements. */
+ SCROLLBAR: 'scrollbar',
+ /** Use for text fields that are used for searching. */
+ SEARCHBOX: 'searchbox',
+ /** Use for adjustable elements like sliders. */
+ SLIDER: 'slider',
+ /** Use for a button that opens a list of choices. */
+ SPINBUTTON: 'spinbutton',
+ /** Use for elements providing a summary of app conditions. */
+ SUMMARY: 'summary',
+ /** Use for on/off switch elements. */
SWITCH: 'switch',
- ADJUSTABLE: 'slider',
- IMAGE: 'img',
+ /** Use for tab elements in a tab list. */
+ TAB: 'tab',
+ /** Use for a list of tabs. */
+ TABLIST: 'tablist',
+ /** Use for timer elements. */
+ TIMER: 'timer',
+ /** Use for toolbars containing action buttons or components. */
+ TOOLBAR: 'toolbar',
},
TRANSLATION_KEYS: {
ATTACHMENT: 'common.attachment',
diff --git a/src/Expensify.js b/src/Expensify.js
index aece93c0ff4d..756df5b79b88 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -112,6 +112,7 @@ function Expensify(props) {
}, [props.isCheckingPublicRoom]);
const isAuthenticated = useMemo(() => Boolean(lodashGet(props.session, 'authToken', null)), [props.session]);
+ const autoAuthState = useMemo(() => lodashGet(props.session, 'autoAuthState', ''), [props.session]);
const contextValue = useMemo(
() => ({
@@ -207,7 +208,10 @@ function Expensify(props) {
}
return (
-
+
{shouldInit && (
<>
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index a268c008cee8..933ae678da23 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -383,7 +383,7 @@ type OnyxValues = {
[ONYXKEYS.COUNTRY]: string;
[ONYXKEYS.USER]: OnyxTypes.User;
[ONYXKEYS.USER_LOCATION]: OnyxTypes.UserLocation;
- [ONYXKEYS.LOGIN_LIST]: Record;
+ [ONYXKEYS.LOGIN_LIST]: OnyxTypes.LoginList;
[ONYXKEYS.SESSION]: OnyxTypes.Session;
[ONYXKEYS.BETAS]: OnyxTypes.Beta[];
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf;
@@ -403,8 +403,8 @@ type OnyxValues = {
[ONYXKEYS.WALLET_ONFIDO]: OnyxTypes.WalletOnfido;
[ONYXKEYS.WALLET_ADDITIONAL_DETAILS]: OnyxTypes.WalletAdditionalDetails;
[ONYXKEYS.WALLET_TERMS]: OnyxTypes.WalletTerms;
- [ONYXKEYS.BANK_ACCOUNT_LIST]: Record;
- [ONYXKEYS.FUND_LIST]: Record;
+ [ONYXKEYS.BANK_ACCOUNT_LIST]: OnyxTypes.BankAccountList;
+ [ONYXKEYS.FUND_LIST]: OnyxTypes.FundList;
[ONYXKEYS.CARD_LIST]: Record;
[ONYXKEYS.WALLET_STATEMENT]: OnyxTypes.WalletStatement;
[ONYXKEYS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount;
@@ -440,7 +440,7 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy;
[ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory;
[ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags;
- [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMember;
+ [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories;
[ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers;
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 53763d6d7cd1..425ff73af56b 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -34,7 +34,7 @@ const ROUTES = {
VALIDATE_LOGIN: 'v/:accountID/:validateCode',
GET_ASSISTANCE: {
route: 'get-assistance/:taskID',
- getRoute: (taskID: string) => `get-assistance/${taskID}` as const,
+ getRoute: (taskID: string, backTo: string) => getUrlWithBackToParam(`get-assistance/${taskID}`, backTo),
},
UNLINK_LOGIN: 'u/:accountID/:validateCode',
APPLE_SIGN_IN: 'sign-in-with-apple',
diff --git a/src/components/AmountTextInput.js b/src/components/AmountTextInput.js
index bd88712432a8..5efcc003d853 100644
--- a/src/components/AmountTextInput.js
+++ b/src/components/AmountTextInput.js
@@ -55,7 +55,7 @@ function AmountTextInput(props) {
blurOnSubmit={false}
selection={props.selection}
onSelectionChange={props.onSelectionChange}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
onKeyPress={props.onKeyPress}
/>
);
diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
index 1e2d18bc4691..6161ba140726 100644
--- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
+++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
@@ -58,7 +58,7 @@ function BaseAnchorForAttachmentsOnly(props) {
onPressOut={props.onPressOut}
onLongPress={(event) => showContextMenuForReport(event, anchor, report.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))}
accessibilityLabel={fileName}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
(linkRef = el)}
style={StyleSheet.flatten([style, defaultTextStyle])}
- role={CONST.ACCESSIBILITY_ROLE.LINK}
+ role={CONST.ROLE.LINK}
hrefAttrs={{
rel,
target: isEmail || !linkProps.href ? '_self' : target,
diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
index fbc49590d5ae..1642fa32734a 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js
+++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
@@ -81,7 +81,7 @@ function CarouselItem({item, isFocused, onPress}) {
{children}
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
index 22bcf259ed77..3b080e47e4d1 100755
--- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
@@ -28,7 +28,7 @@ function AttachmentViewImage({source, file, isAuthTokenRequired, loadComplete, o
onPress={onPress}
disabled={loadComplete}
style={[styles.flex1, styles.flexRow, styles.alignSelfStretch]}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={file.name || translate('attachmentView.unknownFilename')}
>
{children}
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
index fc443e5ea17b..a61adcf04043 100755
--- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
@@ -36,7 +36,7 @@ function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, isUs
onPress={onPress}
disabled={loadComplete}
style={[styles.flex1, styles.flexRow, styles.alignSelfStretch]}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={file.name || translate('attachmentView.unknownFilename')}
>
{children}
diff --git a/src/components/AvatarCropModal/AvatarCropModal.js b/src/components/AvatarCropModal/AvatarCropModal.js
index 62141ecb38c7..6ad81cfb0c9b 100644
--- a/src/components/AvatarCropModal/AvatarCropModal.js
+++ b/src/components/AvatarCropModal/AvatarCropModal.js
@@ -414,7 +414,7 @@ function AvatarCropModal(props) {
onLayout={initializeSliderContainer}
onPressIn={(e) => runOnUI(sliderOnPress)(e.nativeEvent.locationX)}
accessibilityLabel="slider"
- role={CONST.ACCESSIBILITY_ROLE.ADJUSTABLE}
+ role={CONST.ROLE.SLIDER}
>
{shouldShowSubscriptAvatar ? (
ReportUtils.navigateToDetailsPage(report)}
style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}
accessibilityLabel={title}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{headerView}
diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js
index f19cf8a14b41..337725e91af9 100644
--- a/src/components/AvatarWithImagePicker.js
+++ b/src/components/AvatarWithImagePicker.js
@@ -298,7 +298,7 @@ function AvatarWithImagePicker({
setIsMenuVisible((prev) => !prev)}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={translate('avatarWithImagePicker.editImage')}
disabled={isAvatarCropModalOpen}
ref={anchorRef}
diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx
index 82212c66db04..b670921dff4c 100644
--- a/src/components/Badge.tsx
+++ b/src/components/Badge.tsx
@@ -47,7 +47,7 @@ function Badge({success = false, error = false, pressable = false, text, environ
{renderContent()}
diff --git a/src/components/CollapsibleSection/index.tsx b/src/components/CollapsibleSection/index.tsx
index cc854b625ee7..b7a3a0135360 100644
--- a/src/components/CollapsibleSection/index.tsx
+++ b/src/components/CollapsibleSection/index.tsx
@@ -34,7 +34,7 @@ function CollapsibleSection({title, children}: CollapsibleSectionProps) {
{currencySymbol}
diff --git a/src/components/DatePicker/index.js b/src/components/DatePicker/index.js
index 10a53dc25bbb..ac6454d25975 100644
--- a/src/components/DatePicker/index.js
+++ b/src/components/DatePicker/index.js
@@ -76,7 +76,7 @@ function DatePicker({containerStyles, defaultValue, disabled, errorText, inputID
icon={Expensicons.Calendar}
label={label}
accessibilityLabel={label}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
value={value || selectedDate || ''}
placeholder={placeholder || translate('common.dateFormat')}
errorText={errorText}
diff --git a/src/components/DeeplinkWrapper/index.website.js b/src/components/DeeplinkWrapper/index.website.js
index 166818e4ae27..d81c99657dd8 100644
--- a/src/components/DeeplinkWrapper/index.website.js
+++ b/src/components/DeeplinkWrapper/index.website.js
@@ -16,6 +16,8 @@ const propTypes = {
children: PropTypes.node.isRequired,
/** User authentication status */
isAuthenticated: PropTypes.bool.isRequired,
+ /** The auto authentication status */
+ autoAuthState: PropTypes.string,
};
function isMacOSWeb() {
@@ -36,7 +38,7 @@ function promptToOpenInDesktopApp() {
App.beginDeepLinkRedirect(!isMagicLink);
}
}
-function DeeplinkWrapper({children, isAuthenticated}) {
+function DeeplinkWrapper({children, isAuthenticated, autoAuthState}) {
const [currentScreen, setCurrentScreen] = useState();
const [hasShownPrompt, setHasShownPrompt] = useState(false);
const removeListener = useRef();
@@ -69,7 +71,7 @@ function DeeplinkWrapper({children, isAuthenticated}) {
return routeRegex.test(window.location.pathname);
});
// Making a few checks to exit early before checking authentication status
- if (!isMacOSWeb() || isUnsupportedDeeplinkRoute || CONFIG.ENVIRONMENT === CONST.ENVIRONMENT.DEV || hasShownPrompt) {
+ if (!isMacOSWeb() || isUnsupportedDeeplinkRoute || hasShownPrompt || CONFIG.ENVIRONMENT === CONST.ENVIRONMENT.DEV || autoAuthState === CONST.AUTO_AUTH_STATE.NOT_STARTED) {
return;
}
// We want to show the prompt immediately if the user is already authenticated.
@@ -92,7 +94,7 @@ function DeeplinkWrapper({children, isAuthenticated}) {
promptToOpenInDesktopApp();
setHasShownPrompt(true);
}
- }, [currentScreen, hasShownPrompt, isAuthenticated]);
+ }, [currentScreen, hasShownPrompt, isAuthenticated, autoAuthState]);
return children;
}
diff --git a/src/components/EmojiPicker/CategoryShortcutButton.js b/src/components/EmojiPicker/CategoryShortcutButton.js
index 2a9fdff91fb7..e4f48fbb1cc0 100644
--- a/src/components/EmojiPicker/CategoryShortcutButton.js
+++ b/src/components/EmojiPicker/CategoryShortcutButton.js
@@ -42,7 +42,7 @@ function CategoryShortcutButton(props) {
onHoverOut={() => setIsHighlighted(false)}
style={({pressed}) => [StyleUtils.getButtonBackgroundColorStyle(getButtonState(false, pressed)), styles.categoryShortcutButton, isHighlighted && styles.emojiItemHighlighted]}
accessibilityLabel={`emojiPicker.headers.${props.code}`}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{({hovered, pressed}) => (
diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js
index 95db6eb41167..263f5929d567 100755
--- a/src/components/EmojiPicker/EmojiPickerMenu/index.js
+++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js
@@ -485,7 +485,7 @@ function EmojiPickerMenu(props) {
0}
/>
diff --git a/src/components/EmojiPicker/EmojiPickerMenuItem/index.js b/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
index ae2cdf46dfc0..52d4a0db8812 100644
--- a/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
+++ b/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
@@ -103,7 +103,7 @@ class EmojiPickerMenuItem extends PureComponent {
this.props.themeStyles.emojiItem,
]}
accessibilityLabel={this.props.emoji}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{this.props.emoji}
diff --git a/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js b/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
index 7934cc0f03d4..1726ff5b6543 100644
--- a/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
+++ b/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
@@ -80,7 +80,7 @@ class EmojiPickerMenuItem extends PureComponent {
this.props.themeStyles.emojiItem,
]}
accessibilityLabel={this.props.emoji}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{this.props.emoji}
diff --git a/src/components/EmojiPicker/EmojiSkinToneList.js b/src/components/EmojiPicker/EmojiSkinToneList.js
index 25fc9ad0836a..69690fa882c9 100644
--- a/src/components/EmojiPicker/EmojiSkinToneList.js
+++ b/src/components/EmojiPicker/EmojiSkinToneList.js
@@ -49,7 +49,7 @@ function EmojiSkinToneList(props) {
onPress={toggleIsSkinToneListVisible}
style={[styles.flexRow, styles.alignSelfCenter, styles.justifyContentStart, styles.alignItemsCenter]}
accessibilityLabel={props.translate('emojiPicker.skinTonePickerLabel')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{currentSkinTone.code}
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
index 7cbdf8d69831..f5ecc106d629 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
@@ -77,7 +77,7 @@ function ImageRenderer(props) {
ReportUtils.isArchivedRoom(report),
)
}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={translate('accessibilityHints.viewAttachment')}
>
{
onPressIn={props.onPressIn}
onPressOut={props.onPressOut}
onLongPress={(event) => showContextMenuForReport(event, anchor, report.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
accessibilityLabel={props.translate('accessibilityHints.prestyledText')}
>
diff --git a/src/components/HeaderWithBackButton/index.js b/src/components/HeaderWithBackButton/index.js
index e97dd5889abd..7e1412f1f90b 100755
--- a/src/components/HeaderWithBackButton/index.js
+++ b/src/components/HeaderWithBackButton/index.js
@@ -143,7 +143,7 @@ function HeaderWithBackButton({
Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID))))}
+ onPress={singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID, Navigation.getActiveRoute()))))}
style={[styles.touchableButtonImage]}
role="button"
accessibilityLabel={translate('getAssistancePage.questionMarkButtonTooltip')}
@@ -170,7 +170,7 @@ function HeaderWithBackButton({
policy);
- const cleanAllPolicyMembers = _.pick(props.allPolicyMembers, (policyMembers) => policyMembers);
-
- const paymentCardList = props.fundList || {};
-
- // All of the error & info-checking methods are put into an array. This is so that using _.some() will return
- // early as soon as the first error / info condition is returned. This makes the checks very efficient since
- // we only care if a single error / info condition exists anywhere.
- const errorCheckingMethods = [
- () => !_.isEmpty(props.userWallet.errors),
- () => PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList),
- () => _.some(cleanPolicies, PolicyUtils.hasPolicyError),
- () => _.some(cleanPolicies, PolicyUtils.hasCustomUnitsError),
- () => _.some(cleanAllPolicyMembers, PolicyUtils.hasPolicyMemberError),
- () => !_.isEmpty(props.reimbursementAccount.errors),
- () => UserUtils.hasLoginListError(props.loginList),
-
- // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
- () => !_.isEmpty(props.walletTerms.errors) && !props.walletTerms.chatReportID,
- ];
- const infoCheckingMethods = [() => UserUtils.hasLoginListInfo(props.loginList)];
- const shouldShowErrorIndicator = _.some(errorCheckingMethods, (errorCheckingMethod) => errorCheckingMethod());
- const shouldShowInfoIndicator = !shouldShowErrorIndicator && _.some(infoCheckingMethods, (infoCheckingMethod) => infoCheckingMethod());
-
- const indicatorColor = shouldShowErrorIndicator ? theme.danger : theme.success;
- const indicatorStyles = [styles.alignItemsCenter, styles.justifyContentCenter, styles.statusIndicator(indicatorColor)];
-
- return (shouldShowErrorIndicator || shouldShowInfoIndicator) && ;
-}
-
-Indicator.defaultProps = defaultProps;
-Indicator.propTypes = propTypes;
-Indicator.displayName = 'Indicator';
-
-export default withOnyx({
- allPolicyMembers: {
- key: ONYXKEYS.COLLECTION.POLICY_MEMBERS,
- },
- policies: {
- key: ONYXKEYS.COLLECTION.POLICY,
- },
- bankAccountList: {
- key: ONYXKEYS.BANK_ACCOUNT_LIST,
- },
- reimbursementAccount: {
- key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
- },
- fundList: {
- key: ONYXKEYS.FUND_LIST,
- },
- userWallet: {
- key: ONYXKEYS.USER_WALLET,
- },
- walletTerms: {
- key: ONYXKEYS.WALLET_TERMS,
- },
- loginList: {
- key: ONYXKEYS.LOGIN_LIST,
- },
-})(Indicator);
diff --git a/src/components/Indicator.tsx b/src/components/Indicator.tsx
new file mode 100644
index 000000000000..5332c4bd984f
--- /dev/null
+++ b/src/components/Indicator.tsx
@@ -0,0 +1,104 @@
+import React from 'react';
+import {StyleSheet, View} from 'react-native';
+import {OnyxCollection, withOnyx} from 'react-native-onyx';
+import {OnyxEntry} from 'react-native-onyx/lib/types';
+import * as PolicyUtils from '@libs/PolicyUtils';
+import * as UserUtils from '@libs/UserUtils';
+import useTheme from '@styles/themes/useTheme';
+import useThemeStyles from '@styles/useThemeStyles';
+import * as PaymentMethods from '@userActions/PaymentMethods';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {BankAccountList, FundList, LoginList, Policy, PolicyMembers, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx';
+
+type CheckingMethod = () => boolean;
+
+type IndicatorOnyxProps = {
+ /** The employee list of all policies (coming from Onyx) */
+ allPolicyMembers: OnyxCollection;
+
+ /** All the user's policies (from Onyx via withFullPolicy) */
+ policies: OnyxCollection;
+
+ /** List of bank accounts */
+ bankAccountList: OnyxEntry;
+
+ /** List of user cards */
+ fundList: OnyxEntry;
+
+ /** The user's wallet (coming from Onyx) */
+ userWallet: OnyxEntry;
+
+ /** Bank account attached to free plan */
+ reimbursementAccount: OnyxEntry;
+
+ /** Information about the user accepting the terms for payments */
+ walletTerms: OnyxEntry;
+
+ /** Login list for the user that is signed in */
+ loginList: OnyxEntry;
+};
+
+type IndicatorProps = IndicatorOnyxProps;
+
+function Indicator({reimbursementAccount, allPolicyMembers, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) {
+ const theme = useTheme();
+ const styles = useThemeStyles();
+
+ // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and
+ // those should be cleaned out before doing any error checking
+ const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => !!policy));
+ const cleanAllPolicyMembers = Object.fromEntries(Object.entries(allPolicyMembers ?? {}).filter(([, policyMembers]) => !!policyMembers));
+
+ // All of the error & info-checking methods are put into an array. This is so that using _.some() will return
+ // early as soon as the first error / info condition is returned. This makes the checks very efficient since
+ // we only care if a single error / info condition exists anywhere.
+ const errorCheckingMethods: CheckingMethod[] = [
+ () => Object.keys(userWallet?.errors ?? {}).length > 0,
+ () => PaymentMethods.hasPaymentMethodError(bankAccountList, fundList),
+ () => Object.values(cleanPolicies).some(PolicyUtils.hasPolicyError),
+ () => Object.values(cleanPolicies).some(PolicyUtils.hasCustomUnitsError),
+ () => Object.values(cleanAllPolicyMembers).some(PolicyUtils.hasPolicyMemberError),
+ () => Object.keys(reimbursementAccount?.errors ?? {}).length > 0,
+ () => !!loginList && UserUtils.hasLoginListError(loginList),
+
+ // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
+ () => Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID,
+ ];
+ const infoCheckingMethods: CheckingMethod[] = [() => !!loginList && UserUtils.hasLoginListInfo(loginList)];
+ const shouldShowErrorIndicator = errorCheckingMethods.some((errorCheckingMethod) => errorCheckingMethod());
+ const shouldShowInfoIndicator = !shouldShowErrorIndicator && infoCheckingMethods.some((infoCheckingMethod) => infoCheckingMethod());
+
+ const indicatorColor = shouldShowErrorIndicator ? theme.danger : theme.success;
+ const indicatorStyles = [styles.alignItemsCenter, styles.justifyContentCenter, styles.statusIndicator(indicatorColor)];
+
+ return (shouldShowErrorIndicator || shouldShowInfoIndicator) && ;
+}
+
+Indicator.displayName = 'Indicator';
+
+export default withOnyx({
+ allPolicyMembers: {
+ key: ONYXKEYS.COLLECTION.POLICY_MEMBERS,
+ },
+ policies: {
+ key: ONYXKEYS.COLLECTION.POLICY,
+ },
+ bankAccountList: {
+ key: ONYXKEYS.BANK_ACCOUNT_LIST,
+ },
+ reimbursementAccount: {
+ key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
+ },
+ fundList: {
+ key: ONYXKEYS.FUND_LIST,
+ },
+ userWallet: {
+ key: ONYXKEYS.USER_WALLET,
+ },
+ walletTerms: {
+ key: ONYXKEYS.WALLET_TERMS,
+ },
+ loginList: {
+ key: ONYXKEYS.LOGIN_LIST,
+ },
+})(Indicator);
diff --git a/src/components/InlineCodeBlock/WrappedText.js b/src/components/InlineCodeBlock/WrappedText.js
deleted file mode 100644
index f00ec891116b..000000000000
--- a/src/components/InlineCodeBlock/WrappedText.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import PropTypes from 'prop-types';
-import React, {Fragment} from 'react';
-import {View} from 'react-native';
-import _ from 'underscore';
-import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
-import CONST from '@src/CONST';
-
-/**
- * Breaks the text into matrix
- * for eg: My Name is Rajat
- * [
- * [My,' ',Name,' ',' ',is,' ',Rajat],
- * ]
- *
- * @param {String} text
- * @returns {Array}
- */
-function getTextMatrix(text) {
- return _.map(text.split('\n'), (row) => _.without(row.split(CONST.REGEX.SPACE_OR_EMOJI), ''));
-}
-
-const propTypes = {
- /** Required text */
- children: PropTypes.string.isRequired,
-
- /** Style to be applied to Text */
- // eslint-disable-next-line react/forbid-prop-types
- textStyles: PropTypes.arrayOf(PropTypes.object),
-
- /** Style for each word(Token) in the text, remember that token also includes whitespaces among words */
- // eslint-disable-next-line react/forbid-prop-types
- wordStyles: PropTypes.arrayOf(PropTypes.object),
-};
-
-const defaultProps = {
- textStyles: [],
- wordStyles: [],
-};
-
-function WrappedText(props) {
- const styles = useThemeStyles();
- if (!_.isString(props.children)) {
- return null;
- }
-
- const textMatrix = getTextMatrix(props.children);
- return (
- <>
- {_.map(textMatrix, (rowText, rowIndex) => (
-
- {_.map(rowText, (colText, colIndex) => (
- // Outer View is important to vertically center the Text
-
-
- {colText}
-
-
- ))}
-
- ))}
- >
- );
-}
-
-WrappedText.propTypes = propTypes;
-WrappedText.defaultProps = defaultProps;
-WrappedText.displayName = 'WrappedText';
-
-export default WrappedText;
diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx
new file mode 100644
index 000000000000..6dbd17f18e2a
--- /dev/null
+++ b/src/components/InlineCodeBlock/WrappedText.tsx
@@ -0,0 +1,66 @@
+import React, {Fragment} from 'react';
+import {StyleProp, TextStyle, View, ViewStyle} from 'react-native';
+import Text from '@components/Text';
+import useThemeStyles from '@styles/useThemeStyles';
+import CONST from '@src/CONST';
+import type ChildrenProps from '@src/types/utils/ChildrenProps';
+
+type WrappedTextProps = ChildrenProps & {
+ /** Style to be applied to Text */
+ textStyles?: StyleProp;
+
+ /**
+ * Style for each individual word (token) in the text. Note that a token can also include whitespace characters between words.
+ */
+ wordStyles?: StyleProp;
+};
+
+/**
+ * Breaks the text into matrix
+ *
+ * @example
+ * const text = "My Name is Rajat";
+ * const resultMatrix = getTextMatrix(text);
+ * console.log(resultMatrix);
+ * // Output:
+ * // [
+ * // ['My', ' ', 'Name', ' ', 'is', ' ', 'Rajat'],
+ * // ]
+ */
+function getTextMatrix(text: string): string[][] {
+ return text.split('\n').map((row) => row.split(CONST.REGEX.SPACE_OR_EMOJI).filter((value) => value !== ''));
+}
+
+function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) {
+ const styles = useThemeStyles();
+
+ if (typeof children !== 'string') {
+ return null;
+ }
+
+ const textMatrix = getTextMatrix(children);
+
+ return textMatrix.map((rowText, rowIndex) => (
+
+ {rowText.map((colText, colIndex) => (
+ // Outer View is important to vertically center the Text
+
+
+ {colText}
+
+
+ ))}
+
+ ));
+}
+
+WrappedText.displayName = 'WrappedText';
+
+export default WrappedText;
diff --git a/src/components/InlineCodeBlock/index.js b/src/components/InlineCodeBlock/index.js
deleted file mode 100644
index 84666931d9b2..000000000000
--- a/src/components/InlineCodeBlock/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import Text from '@components/Text';
-import inlineCodeBlockPropTypes from './inlineCodeBlockPropTypes';
-
-function InlineCodeBlock(props) {
- const TDefaultRenderer = props.TDefaultRenderer;
- const textStyles = _.omit(props.textStyle, 'textDecorationLine');
-
- return (
-
- {props.defaultRendererProps.tnode.data}
-
- );
-}
-
-InlineCodeBlock.propTypes = inlineCodeBlockPropTypes;
-InlineCodeBlock.displayName = 'InlineCodeBlock';
-export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/index.native.js b/src/components/InlineCodeBlock/index.native.tsx
similarity index 50%
rename from src/components/InlineCodeBlock/index.native.js
rename to src/components/InlineCodeBlock/index.native.tsx
index 983463222532..308b88e76e88 100644
--- a/src/components/InlineCodeBlock/index.native.js
+++ b/src/components/InlineCodeBlock/index.native.tsx
@@ -1,26 +1,27 @@
import React from 'react';
+import type {TText} from 'react-native-render-html';
import useThemeStyles from '@styles/useThemeStyles';
-import inlineCodeBlockPropTypes from './inlineCodeBlockPropTypes';
+import type InlineCodeBlockProps from './types';
import WrappedText from './WrappedText';
-function InlineCodeBlock(props) {
+function InlineCodeBlock({TDefaultRenderer, defaultRendererProps, textStyle, boxModelStyle}: InlineCodeBlockProps) {
const styles = useThemeStyles();
- const TDefaultRenderer = props.TDefaultRenderer;
+
return (
- {props.defaultRendererProps.tnode.data}
+ {defaultRendererProps.tnode.data}
);
}
-InlineCodeBlock.propTypes = inlineCodeBlockPropTypes;
InlineCodeBlock.displayName = 'InlineCodeBlock';
+
export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/index.tsx b/src/components/InlineCodeBlock/index.tsx
new file mode 100644
index 000000000000..0802d4752661
--- /dev/null
+++ b/src/components/InlineCodeBlock/index.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import {StyleSheet} from 'react-native';
+import type {TText} from 'react-native-render-html';
+import Text from '@components/Text';
+import type InlineCodeBlockProps from './types';
+
+function InlineCodeBlock({TDefaultRenderer, textStyle, defaultRendererProps, boxModelStyle}: InlineCodeBlockProps) {
+ const flattenTextStyle = StyleSheet.flatten(textStyle);
+ const {textDecorationLine, ...textStyles} = flattenTextStyle;
+
+ return (
+
+ {defaultRendererProps.tnode.data}
+
+ );
+}
+
+InlineCodeBlock.displayName = 'InlineCodeBlock';
+
+export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js b/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js
deleted file mode 100644
index e8430d17d849..000000000000
--- a/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import PropTypes from 'prop-types';
-
-const inlineCodeBlockPropTypes = {
- TDefaultRenderer: PropTypes.func.isRequired,
- defaultRendererProps: PropTypes.object.isRequired,
- boxModelStyle: PropTypes.any.isRequired,
- textStyle: PropTypes.any.isRequired,
-};
-
-export default inlineCodeBlockPropTypes;
diff --git a/src/components/InlineCodeBlock/types.ts b/src/components/InlineCodeBlock/types.ts
new file mode 100644
index 000000000000..a100177e41a7
--- /dev/null
+++ b/src/components/InlineCodeBlock/types.ts
@@ -0,0 +1,11 @@
+import {StyleProp, TextStyle, ViewStyle} from 'react-native';
+import type {TDefaultRenderer, TDefaultRendererProps, TText} from 'react-native-render-html';
+
+type InlineCodeBlockProps = {
+ TDefaultRenderer: TDefaultRenderer;
+ textStyle: StyleProp;
+ defaultRendererProps: TDefaultRendererProps;
+ boxModelStyle: StyleProp;
+};
+
+export default InlineCodeBlockProps;
diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js
index fa96542e877d..af29e1481f9c 100644
--- a/src/components/LHNOptionsList/OptionRowLHN.js
+++ b/src/components/LHNOptionsList/OptionRowLHN.js
@@ -208,7 +208,7 @@ function OptionRowLHN(props) {
props.isFocused ? styles.sidebarLinkActive : null,
(hovered || isContextMenuActive) && !props.isFocused ? props.hoverStyle || styles.sidebarLinkHover : null,
]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('accessibilityHints.navigatesToChat')}
needsOffscreenAlphaCompositing={props.optionItem.icons.length >= 2}
>
diff --git a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js b/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
index a9472987a224..89ad869e9588 100644
--- a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
+++ b/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
@@ -66,7 +66,7 @@ function BaseLocationErrorMessage({onClose, onAllowLocationLinkPress, locationEr
onPress={onClose}
onMouseDown={(e) => e.preventDefault()}
style={[styles.touchableButtonImage]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.close')}
>
{
]}
disabled={props.disabled}
ref={ref}
- role={CONST.ACCESSIBILITY_ROLE.MENUITEM}
+ role={CONST.ROLE.MENUITEM}
accessibilityLabel={props.title ? props.title.toString() : ''}
>
{({pressed}) => (
diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx
index 1b87b95601f3..2e016ca7d416 100644
--- a/src/components/MessagesRow.tsx
+++ b/src/components/MessagesRow.tsx
@@ -50,7 +50,7 @@ function MessagesRow({messages = {}, type, onClose = () => {}, containerStyles,
onUserExit(),
- },
- {
- text: translate('common.settings'),
- onPress: () => {
- onUserExit();
- Linking.openSettings();
- },
- },
- ],
- {cancelable: false},
- );
- return;
- }
+ if (!_.isEmpty(errorMessage) && getPlatform() === CONST.PLATFORM.IOS) {
+ checkMultiple([PERMISSIONS.IOS.MICROPHONE, PERMISSIONS.IOS.CAMERA])
+ .then((statuses) => {
+ const isMicAllowed = statuses[PERMISSIONS.IOS.MICROPHONE] === RESULTS.GRANTED;
+ const isCameraAllowed = statuses[PERMISSIONS.IOS.CAMERA] === RESULTS.GRANTED;
+ let alertTitle = '';
+ let alertMessage = '';
+ if (!isCameraAllowed) {
+ alertTitle = 'onfidoStep.cameraPermissionsNotGranted';
+ alertMessage = 'onfidoStep.cameraRequestMessage';
+ } else if (!isMicAllowed) {
+ alertTitle = 'onfidoStep.microphonePermissionsNotGranted';
+ alertMessage = 'onfidoStep.microphoneRequestMessage';
+ }
- onError(errorMessage);
+ if (!_.isEmpty(alertTitle) && !_.isEmpty(alertMessage)) {
+ Alert.alert(
+ translate(alertTitle),
+ translate(alertMessage),
+ [
+ {
+ text: translate('common.cancel'),
+ onPress: () => onUserExit(),
+ },
+ {
+ text: translate('common.settings'),
+ onPress: () => {
+ onUserExit();
+ Linking.openSettings();
+ },
+ },
+ ],
+ {cancelable: false},
+ );
+ return;
+ }
+ onError(errorMessage);
+ })
+ .catch(() => {
+ onError(errorMessage);
+ });
+ } else {
+ onError(errorMessage);
+ }
});
// Onfido should be initialized only once on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js
index eaf3ccc7ead2..24f109112679 100644
--- a/src/components/OptionRow.js
+++ b/src/components/OptionRow.js
@@ -194,7 +194,7 @@ function OptionRow(props) {
!props.onSelectRow && !props.isDisabled ? styles.cursorDefault : null,
]}
accessibilityLabel={props.option.text}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
hoverDimmingValue={1}
hoverStyle={!props.optionIsFocused ? props.hoverStyle || styles.sidebarLinkHover : undefined}
needsOffscreenAlphaCompositing={lodashGet(props.option, 'icons.length', 0) >= 2}
@@ -270,7 +270,7 @@ function OptionRow(props) {
props.onSelectedStatePressed(props.option)}
disabled={isDisabled}
- role={CONST.ACCESSIBILITY_ROLE.CHECKBOX}
+ role={CONST.ROLE.CHECKBOX}
accessibilityLabel={CONST.ACCESSIBILITY_ROLE.CHECKBOX}
>
diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js
index 72bc5c032139..b054f9a1daea 100755
--- a/src/components/OptionsSelector/BaseOptionsSelector.js
+++ b/src/components/OptionsSelector/BaseOptionsSelector.js
@@ -471,7 +471,7 @@ class BaseOptionsSelector extends Component {
value={this.props.value}
label={this.props.textInputLabel}
accessibilityLabel={this.props.textInputLabel}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
onChangeText={this.updateSearchValue}
errorText={this.state.errorMessage}
onSubmitEditing={this.selectFocusedOption}
diff --git a/src/components/PDFView/PDFPasswordForm.js b/src/components/PDFView/PDFPasswordForm.js
index e20e2c44a76e..2c33d8d93a31 100644
--- a/src/components/PDFView/PDFPasswordForm.js
+++ b/src/components/PDFView/PDFPasswordForm.js
@@ -123,7 +123,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
ref={textInputRef}
label={translate('common.password')}
accessibilityLabel={translate('common.password')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
/**
* This is a workaround to bypass Safari's autofill odd behaviour.
* This tricks the browser not to fill the username somewhere else and still fill the password correctly.
diff --git a/src/components/PDFView/index.js b/src/components/PDFView/index.js
index 50e737ba54d3..e18c52b06972 100644
--- a/src/components/PDFView/index.js
+++ b/src/components/PDFView/index.js
@@ -329,7 +329,7 @@ class PDFView extends Component {
{this.renderPDFView()}
diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js
index 30d5e4c48d68..bfdb80131aa6 100644
--- a/src/components/PDFView/index.native.js
+++ b/src/components/PDFView/index.native.js
@@ -186,7 +186,7 @@ class PDFView extends Component {
{this.renderPDFView()}
diff --git a/src/components/ParentNavigationSubtitle.tsx b/src/components/ParentNavigationSubtitle.tsx
index e65a8617a996..c12cefe6bead 100644
--- a/src/components/ParentNavigationSubtitle.tsx
+++ b/src/components/ParentNavigationSubtitle.tsx
@@ -31,7 +31,7 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID));
}}
accessibilityLabel={translate('threads.parentNavigationSummary', {rootReportName, workspaceName})}
- role={CONST.ACCESSIBILITY_ROLE.LINK}
+ role={CONST.ROLE.LINK}
style={pressableStyles}
>
{isChecked && (
diff --git a/src/components/Reactions/AddReactionBubble.js b/src/components/Reactions/AddReactionBubble.js
index 994d467dfd6e..128eafd51ee8 100644
--- a/src/components/Reactions/AddReactionBubble.js
+++ b/src/components/Reactions/AddReactionBubble.js
@@ -100,7 +100,7 @@ function AddReactionBubble(props) {
e.preventDefault();
}}
accessibilityLabel={props.translate('emojiReactions.addReactionTooltip')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
// disable dimming
pressDimmingValue={1}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
diff --git a/src/components/Reactions/EmojiReactionBubble.js b/src/components/Reactions/EmojiReactionBubble.js
index 7fcdae8c0a5a..7ec72468ee91 100644
--- a/src/components/Reactions/EmojiReactionBubble.js
+++ b/src/components/Reactions/EmojiReactionBubble.js
@@ -83,7 +83,7 @@ function EmojiReactionBubble(props) {
// Prevent text input blur when emoji reaction is left clicked
e.preventDefault();
}}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.emojiCodes.join('')}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
>
diff --git a/src/components/ReportActionItem/ReportActionItemImage.js b/src/components/ReportActionItem/ReportActionItemImage.js
index 6fd322a24d3c..534a92dae830 100644
--- a/src/components/ReportActionItem/ReportActionItemImage.js
+++ b/src/components/ReportActionItem/ReportActionItemImage.js
@@ -94,7 +94,7 @@ function ReportActionItemImage({thumbnail, image, enablePreviewModal, transactio
{receiptImageComponent}
diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js
index c22181fec775..3b04364ee69a 100644
--- a/src/components/ReportActionItem/TaskPreview.js
+++ b/src/components/ReportActionItem/TaskPreview.js
@@ -108,7 +108,7 @@ function TaskPreview(props) {
onPressOut={() => ControlSelection.unblock()}
onLongPress={(event) => showContextMenuForReport(event, props.contextMenuAnchor, props.chatReportID, props.action, props.checkIfContextMenuActive)}
style={[styles.flexRow, styles.justifyContentBetween]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('task.task')}
>
diff --git a/src/components/ReportHeaderSkeletonView.tsx b/src/components/ReportHeaderSkeletonView.tsx
index 5ea83990431c..708cf3b930bb 100644
--- a/src/components/ReportHeaderSkeletonView.tsx
+++ b/src/components/ReportHeaderSkeletonView.tsx
@@ -30,7 +30,7 @@ function ReportHeaderSkeletonView({shouldAnimate = true, onBackButtonPress = ()
onSelectRow(item)}
disabled={isDisabled}
accessibilityLabel={item.text}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
hoverDimmingValue={1}
hoverStyle={styles.hoveredComponentBG}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js
index 79e38b304cdb..ce5d1945fd2a 100644
--- a/src/components/SelectionList/BaseSelectionList.js
+++ b/src/components/SelectionList/BaseSelectionList.js
@@ -152,7 +152,7 @@ function BaseSelectionList({
const [focusedIndex, setFocusedIndex] = useState(() => _.findIndex(flattenedSections.allOptions, (option) => option.keyForList === initiallyFocusedOptionKey));
// Disable `Enter` shortcut if the active element is a button or checkbox
- const disableEnterShortcut = activeElement && [CONST.ACCESSIBILITY_ROLE.BUTTON, CONST.ACCESSIBILITY_ROLE.CHECKBOX].includes(activeElement.role);
+ const disableEnterShortcut = activeElement && [CONST.ROLE.BUTTON, CONST.ROLE.CHECKBOX].includes(activeElement.role);
/**
* Scrolls to the desired item index in the section list
@@ -408,7 +408,7 @@ function BaseSelectionList({
}}
label={textInputLabel}
accessibilityLabel={textInputLabel}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
value={textInputValue}
placeholder={textInputPlaceholder}
maxLength={textInputMaxLength}
diff --git a/src/components/SignInButtons/GoogleSignIn/index.website.js b/src/components/SignInButtons/GoogleSignIn/index.website.js
index ac5018df8c15..7a909c5b1658 100644
--- a/src/components/SignInButtons/GoogleSignIn/index.website.js
+++ b/src/components/SignInButtons/GoogleSignIn/index.website.js
@@ -76,7 +76,7 @@ function GoogleSignIn({translate, isDesktopFlow}) {
@@ -84,7 +84,7 @@ function GoogleSignIn({translate, isDesktopFlow}) {
diff --git a/src/components/SignInButtons/IconButton.js b/src/components/SignInButtons/IconButton.js
index 706ceb2edc3f..ddfde61d6a07 100644
--- a/src/components/SignInButtons/IconButton.js
+++ b/src/components/SignInButtons/IconButton.js
@@ -38,7 +38,7 @@ function IconButton({onPress, translate, provider}) {
onSelectOption(option)}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityState={{checked: selectedOptionKey === option.key}}
aria-checked={selectedOptionKey === option.key}
accessibilityLabel={option.label}
diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx
index 2398f531628d..5195c0040add 100644
--- a/src/components/Switch.tsx
+++ b/src/components/Switch.tsx
@@ -38,7 +38,7 @@ function Switch({isOn, onToggle, accessibilityLabel}: SwitchProps) {
style={[styles.switchTrack, !isOn && styles.switchInactive]}
onPress={() => onToggle(!isOn)}
onLongPress={() => onToggle(!isOn)}
- role={CONST.ACCESSIBILITY_ROLE.SWITCH}
+ role={CONST.ROLE.SWITCH}
aria-checked={isOn}
accessibilityLabel={accessibilityLabel}
// disable hover dim for switch
diff --git a/src/components/TextInput/TextInputLabel/index.js b/src/components/TextInput/TextInputLabel/index.js
index 43dd1a0ef330..dbd6fa765503 100644
--- a/src/components/TextInput/TextInputLabel/index.js
+++ b/src/components/TextInput/TextInputLabel/index.js
@@ -19,7 +19,7 @@ function TextInputLabel({for: inputId, label, labelTranslateY, labelScale}) {
return (
{label}
diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js
index de145e63a9c7..2b4e3741368a 100644
--- a/src/components/ThreeDotsMenu/index.js
+++ b/src/components/ThreeDotsMenu/index.js
@@ -114,7 +114,7 @@ function ThreeDotsMenu({iconTooltip, icon, iconFill, iconStyles, onIconPress, me
}}
ref={buttonRef}
style={[styles.touchableButtonImage, ...iconStyles]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate(iconTooltip)}
>
New Expensify.',
+ microphonePermissionsNotGranted: 'Enable microphone access',
+ microphoneRequestMessage: 'We need access to your microphone to complete bank account verification. Please enable via Settings > New Expensify.',
originalDocumentNeeded: 'Please upload an original image of your ID rather than a screenshot or scanned image.',
documentNeedsBetterQuality: 'Your ID appears to be damaged or has missing security features. Please upload an original image of an undamaged ID that is entirely visible.',
imageNeedsBetterQuality: "There's an issue with the image quality of your ID. Please upload a new image where your entire ID can be seen clearly.",
@@ -1971,31 +1973,30 @@ export default {
buttonText1: 'Start a chat, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Start a chat, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `Get paid to talk to your friends! Start a chat with a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `Get paid to talk to your friends! Start a chat with a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST]: {
buttonText1: 'Request money, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Request money, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `It pays to get paid! Request money from a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `It pays to get paid! Request money from a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY]: {
buttonText1: 'Send money, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Send money, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `You gotta send money to make money! Send money to a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `You gotta send money to make money! Send money to a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
buttonText1: 'Invite a friend, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Invite a friend, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `Send your Expensify invite link to a friend or anyone else you know who spends too much time on expenses. When they start an annual subscription, you'll get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
+ body: 'Be the first to invite a friend (or anyone else) to Expensify and get $250 if they become an Expensify customer. Share your invite link by text, email, or post it on social media!',
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE]: {
buttonText1: `Get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Get $${CONST.REFERRAL_PROGRAM.REVENUE} for every referral`,
- body1: 'If you know anyone who’s spending too much time on expenses (literally anyone – your neighbor, your boss, your friend in accounting), send them your Expensify referral link:',
- body2: `When they start an annual subscription, you’ll get $${CONST.REFERRAL_PROGRAM.REVENUE}. Easy as that.`,
+ header: `Invite a friend, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Be the first to invite a friend (or anyone else) to Expensify and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer. Share your invite link by text, email, or post it on social media!`,
},
copyReferralLink: 'Copy invite link',
},
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 10401d4822f7..a91a8768a3ee 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1285,8 +1285,11 @@ export default {
tryAgain: 'Intentar otra vez',
verifyIdentity: 'Verificar identidad',
genericError: 'Hubo un error al procesar este paso. Inténtalo de nuevo.',
- cameraPermissionsNotGranted: 'No has habilitado los permisos para acceder a la cámara',
- cameraRequestMessage: 'No has habilitado los permisos para acceder a la cámara. Necesitamos acceso para completar la verificaciôn.',
+ cameraPermissionsNotGranted: 'Permiso para acceder a la cámara',
+ cameraRequestMessage: 'Necesitamos acceso a tu cámara para completar la verificación de tu cuenta de banco. Por favor habilita los permisos en Configuración > Nuevo Expensify.',
+ microphonePermissionsNotGranted: 'Permiso para acceder al micrófono',
+ microphoneRequestMessage:
+ 'Necesitamos acceso a tu micrófono para completar la verificación de tu cuenta de banco. Por favor habilita los permisos en Configuración > Nuevo Expensify.',
originalDocumentNeeded: 'Por favor, sube una imagen original de tu identificación en lugar de una captura de pantalla o imagen escaneada.',
documentNeedsBetterQuality:
'Parece que tu identificación esta dañado o le faltan caracterÃsticas de seguridad. Por favor, sube una imagen de tu documento sin daños y que se vea completamente.',
@@ -2457,31 +2460,30 @@ export default {
buttonText1: 'Inicia un chat y ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `Inicia un chat y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Gana dinero por hablar con tus amigos! Inicia un chat con una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Gana dinero por hablar con tus amigos! Inicia un chat con una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST]: {
buttonText1: 'Pide dinero, ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `Pide dinero y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Vale la pena cobrar! Pide dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Vale la pena cobrar! Pide dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY]: {
buttonText1: 'EnvÃa dinero, ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `EnvÃa dinero y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Hay que enviar dinero para ganar dinero! EnvÃa dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Hay que enviar dinero para ganar dinero! EnvÃa dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
buttonText1: 'Invita a un amigo y ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Invita a un amigo y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `EnvÃa tu enlace de invitación de Expensify a un amigo o a cualquier otra persona que conozcas que dedique demasiado tiempo a los gastos. Cuando comiencen una suscripción anual, obtendrás $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
+ header: `Invita a un amigo y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Sé el primero en invitar a un amigo (o a cualquier otra persona) a Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierte en cliente de Expensify. Comparte tu enlace de invitación por SMS, email o publÃcalo en las redes sociales.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE]: {
buttonText1: `Recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Recibe $${CONST.REFERRAL_PROGRAM.REVENUE} por cada recomendación`,
- body1: 'Si conoces a alguien que dedique demasiado tiempo a los gastos (literalmente cualquiera: tu vecino, tu jefe, tu amigo de contabilidad), envÃale tu enlace de invitación de Expensify:',
- body2: `Cuando comiencen una suscripción anual, obtendrás $${CONST.REFERRAL_PROGRAM.REVENUE}. Asà de fácil.`,
+ header: `Invita a un amigo y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Sé el primero en invitar a un amigo (o a cualquier otra persona) a Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierte en cliente de Expensify. Comparte tu enlace de invitación por SMS, email o publÃcalo en las redes sociales.`,
},
copyReferralLink: 'Copiar enlace de invitación',
},
diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts
index b0d426c9774a..9b2bd2616e8e 100644
--- a/src/libs/CardUtils.ts
+++ b/src/libs/CardUtils.ts
@@ -107,4 +107,23 @@ function findPhysicalCard(cards: Card[]) {
return cards.find((card) => !card.isVirtual);
}
-export {isExpensifyCard, isCorporateCard, getDomainCards, getMonthFromExpirationDateString, getYearFromExpirationDateString, maskCard, getCardDescription, findPhysicalCard};
+/**
+ * Checks if any of the cards in the list have detected fraud
+ *
+ * @param cardList - collection of assigned cards
+ */
+function hasDetectedFraud(cardList: Record): boolean {
+ return Object.values(cardList).some((card) => card.fraud !== CONST.EXPENSIFY_CARD.FRAUD_TYPES.NONE);
+}
+
+export {
+ isExpensifyCard,
+ isCorporateCard,
+ getDomainCards,
+ getMonthFromExpirationDateString,
+ getYearFromExpirationDateString,
+ maskCard,
+ getCardDescription,
+ findPhysicalCard,
+ hasDetectedFraud,
+};
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
index 5e8a9f502dc5..008015db7a90 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
@@ -147,7 +147,7 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom
const chatShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_CHAT;
const currentUrl = getCurrentUrl();
const isLoggingInAsNewUser = !!session?.email && SessionUtils.isLoggingInAsNewUser(currentUrl, session.email);
- const shouldGetAllData = !!isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession() || isLoggingInAsNewUser;
+ const shouldGetAllData = !!isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession();
// Sign out the current user if we're transitioning with a different user
const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS);
if (isLoggingInAsNewUser && isTransitioning) {
diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
index 31eb818b60dc..09099cb493f6 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
@@ -27,14 +27,14 @@ function Overlay({onPress}: OverlayProps) {
style={styles.draggableTopBar}
onPress={onPress}
accessibilityLabel={translate('common.close')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
nativeID={CONST.OVERLAY.TOP_BUTTON_NATIVE_ID}
/>
diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts
index acbc7c8f1702..e9e76f4a2e82 100644
--- a/src/libs/Navigation/linkingConfig.ts
+++ b/src/libs/Navigation/linkingConfig.ts
@@ -7,7 +7,15 @@ import SCREENS from '@src/SCREENS';
import {RootStackParamList} from './types';
const linkingConfig: LinkingOptions = {
- prefixes: ['new-expensify://', 'https://www.expensify.cash', 'https://staging.expensify.cash', 'https://dev.new.expensify.com', CONST.NEW_EXPENSIFY_URL, CONST.STAGING_NEW_EXPENSIFY_URL],
+ prefixes: [
+ 'app://-/',
+ 'new-expensify://',
+ 'https://www.expensify.cash',
+ 'https://staging.expensify.cash',
+ 'https://dev.new.expensify.com',
+ CONST.NEW_EXPENSIFY_URL,
+ CONST.STAGING_NEW_EXPENSIFY_URL,
+ ],
config: {
initialRouteName: SCREENS.HOME,
screens: {
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index ac7404689df2..d89d42e5775e 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -3695,8 +3695,8 @@ function getRouteFromLink(url: string | null): string {
// Get the reportID from URL
let route = url;
+ const localWebAndroidRegEx = /^(https:\/\/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}))/;
linkingConfig.prefixes.forEach((prefix) => {
- const localWebAndroidRegEx = /^(http:\/\/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}))/;
if (route.startsWith(prefix)) {
route = route.replace(prefix, '');
} else if (localWebAndroidRegEx.test(route)) {
diff --git a/src/libs/SessionUtils.ts b/src/libs/SessionUtils.ts
index 6cd20e0b56b2..1afa3a75e081 100644
--- a/src/libs/SessionUtils.ts
+++ b/src/libs/SessionUtils.ts
@@ -45,7 +45,7 @@ Onyx.connect({
});
function resetDidUserLogInDuringSession() {
- loggedInDuringSession = undefined;
+ loggedInDuringSession = true;
}
function didUserLogInDuringSession() {
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index 07b61e677b38..adf184729001 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -15,6 +15,7 @@ import * as Localize from '@libs/Localize';
import Navigation from '@libs/Navigation/Navigation';
import * as NumberUtils from '@libs/NumberUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
+import Permissions from '@libs/Permissions';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
@@ -25,6 +26,12 @@ import ROUTES from '@src/ROUTES';
import * as Policy from './Policy';
import * as Report from './Report';
+let betas;
+Onyx.connect({
+ key: ONYXKEYS.BETAS,
+ callback: (val) => (betas = val || []),
+});
+
let allPersonalDetails;
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
@@ -54,6 +61,29 @@ Onyx.connect({
},
});
+let allTransactionDrafts = {};
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
+ waitForCollectionCallback: true,
+ callback: (val) => {
+ allTransactionDrafts = val || {};
+ },
+});
+
+let allTransactionViolations;
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
+ waitForCollectionCallback: true,
+ callback: (val) => {
+ if (!val) {
+ allTransactionViolations = {};
+ return;
+ }
+
+ allTransactionViolations = val;
+ },
+});
+
let allDraftSplitTransactions;
Onyx.connect({
key: ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT,
@@ -640,11 +670,12 @@ function getMoneyRequestInformation(
// data. This is a big can of worms to change it to `Onyx.merge()` as explored in https://expensify.slack.com/archives/C05DWUDHVK7/p1692139468252109.
// I want to clean this up at some point, but it's possible this will live in the code for a while so I've created https://github.com/Expensify/App/issues/25417
// to remind me to do this.
- const existingTransaction = existingTransactionID && TransactionUtils.getTransaction(existingTransactionID);
- if (existingTransaction) {
+ const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`];
+ if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) {
optimisticTransaction = {
...optimisticTransaction,
...existingTransaction,
+ transactionID: optimisticTransaction.transactionID,
};
}
@@ -2149,6 +2180,7 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`];
const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID);
const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
+ const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`];
const transactionThreadID = reportAction.childReportID;
let transactionThread = null;
if (transactionThreadID) {
@@ -2229,6 +2261,15 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: null,
},
+ ...(Permissions.canUseViolations(betas)
+ ? [
+ {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
+ value: null,
+ },
+ ]
+ : []),
...(shouldDeleteTransactionThread
? [
{
@@ -2260,6 +2301,17 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
[reportPreviewAction.reportActionID]: updatedReportPreviewAction,
},
},
+ ...(!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0
+ ? [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ value: {
+ hasOutstandingChildRequest: false,
+ },
+ },
+ ]
+ : []),
...(shouldDeleteIOUReport
? [
{
@@ -2292,6 +2344,15 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: transaction,
},
+ ...(Permissions.canUseViolations(betas)
+ ? [
+ {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
+ value: transactionViolations,
+ },
+ ]
+ : []),
...(shouldDeleteTransactionThread
? [
{
@@ -2332,6 +2393,17 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
},
]
: []),
+ ...(!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0
+ ? [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ value: {
+ hasOutstandingChildRequest: true,
+ },
+ },
+ ]
+ : []),
];
// STEP 6: Make the API request
diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts
index b3d1e3e23a24..3547a3053a02 100644
--- a/src/libs/actions/PaymentMethods.ts
+++ b/src/libs/actions/PaymentMethods.ts
@@ -1,12 +1,14 @@
import {createRef} from 'react';
import Onyx, {OnyxUpdate} from 'react-native-onyx';
+import {OnyxEntry} from 'react-native-onyx/lib/types';
import {ValueOf} from 'type-fest';
import * as API from '@libs/API';
import * as CardUtils from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
-import ONYXKEYS, {OnyxValues} from '@src/ONYXKEYS';
+import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
+import type {BankAccountList, FundList} from '@src/types/onyx';
import PaymentMethod from '@src/types/onyx/PaymentMethod';
import {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer';
@@ -304,7 +306,7 @@ function dismissSuccessfulTransferBalancePage() {
* Looks through each payment method to see if there is an existing error
*
*/
-function hasPaymentMethodError(bankList: OnyxValues[typeof ONYXKEYS.BANK_ACCOUNT_LIST], fundList: OnyxValues[typeof ONYXKEYS.FUND_LIST]): boolean {
+function hasPaymentMethodError(bankList: OnyxEntry, fundList: OnyxEntry): boolean {
const combinedPaymentMethods = {...bankList, ...fundList};
return Object.values(combinedPaymentMethods).some((item) => Object.keys(item.errors ?? {}).length);
diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js
index 04f62ab0c393..f33e6637e2de 100644
--- a/src/libs/actions/Policy.js
+++ b/src/libs/actions/Policy.js
@@ -112,13 +112,6 @@ Onyx.connect({
callback: (val) => (allRecentlyUsedTags = val),
});
-let networkStatus = {};
-Onyx.connect({
- key: ONYXKEYS.NETWORK,
- waitForCollectionCallback: true,
- callback: (val) => (networkStatus = val),
-});
-
/**
* Stores in Onyx the policy ID of the last workspace that was accessed by the user
* @param {String|null} policyID
@@ -957,7 +950,7 @@ function updateWorkspaceCustomUnitAndRate(policyID, currentCustomUnit, newCustom
'UpdateWorkspaceCustomUnitAndRate',
{
policyID,
- ...(!networkStatus.isOffline && {lastModified}),
+ lastModified,
customUnit: JSON.stringify(newCustomUnitParam),
customUnitRate: JSON.stringify(newCustomUnitParam.rates),
},
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 134b78627c61..bea4ab8aed77 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -19,6 +19,7 @@ import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import LocalNotification from '@libs/Notification/LocalNotification';
import {ReportCommentParams} from '@libs/Notification/LocalNotification/types';
+import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as Pusher from '@libs/Pusher/pusher';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
@@ -2126,11 +2127,19 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record typeof accountID === 'number',
);
+ type PersonalDetailsOnyxData = {
+ optimisticData: OnyxUpdate[];
+ successData: OnyxUpdate[];
+ failureData: OnyxUpdate[];
+ };
+
+ const logins = inviteeEmails.map((memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin));
+ const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs) as PersonalDetailsOnyxData;
+
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
@@ -2139,8 +2148,11 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record
{
if (!el) {
return;
diff --git a/src/pages/EditRequestMerchantPage.js b/src/pages/EditRequestMerchantPage.js
index 53cb4946d640..af6ff89296f1 100644
--- a/src/pages/EditRequestMerchantPage.js
+++ b/src/pages/EditRequestMerchantPage.js
@@ -59,7 +59,7 @@ function EditRequestMerchantPage({defaultMerchant, onSubmit}) {
defaultValue={defaultMerchant}
label={translate('common.merchant')}
accessibilityLabel={translate('common.merchant')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(e) => (merchantInputRef.current = e)}
/>
diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js
index 6d01e601b901..9ed85447a3b3 100644
--- a/src/pages/EnablePayments/AdditionalDetailsStep.js
+++ b/src/pages/EnablePayments/AdditionalDetailsStep.js
@@ -193,7 +193,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys.legalFirstName)}
accessibilityLabel={translate(fieldNameTranslationKeys.legalFirstName)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={PersonalDetails.extractFirstAndLastNameFromAvailableDetails(currentUserPersonalDetails).firstName}
shouldSaveDraft
/>
@@ -203,7 +203,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys.legalLastName)}
accessibilityLabel={translate(fieldNameTranslationKeys.legalLastName)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={PersonalDetails.extractFirstAndLastNameFromAvailableDetails(currentUserPersonalDetails).lastName}
shouldSaveDraft
/>
@@ -225,7 +225,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
inputMode={CONST.INPUT_MODE.TEL}
label={translate(fieldNameTranslationKeys.phoneNumber)}
accessibilityLabel={translate(fieldNameTranslationKeys.phoneNumber)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={currentUserPersonalDetails.phoneNumber}
placeholder={translate('common.phoneNumberPlaceholder')}
shouldSaveDraft
@@ -245,7 +245,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys[shouldAskForFullSSN ? 'ssnFull9' : 'ssn'])}
accessibilityLabel={translate(fieldNameTranslationKeys[shouldAskForFullSSN ? 'ssnFull9' : 'ssn'])}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={shouldAskForFullSSN ? 9 : 4}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
diff --git a/src/pages/GetAssistancePage.js b/src/pages/GetAssistancePage.js
index 0cb0bbd36dc4..0ea213f2e0e1 100644
--- a/src/pages/GetAssistancePage.js
+++ b/src/pages/GetAssistancePage.js
@@ -45,6 +45,7 @@ const defaultProps = {
function GetAssistancePage(props) {
const styles = useThemeStyles();
+ const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.SETTINGS_CONTACT_METHODS);
const menuItems = [
{
title: props.translate('getAssistancePage.chatWithConcierge'),
@@ -83,7 +84,7 @@ function GetAssistancePage(props) {
Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)}
+ onBackButtonPress={() => Navigation.goBack(navigateBackTo)}
/>
- Navigation.goBack(getFallbackRoute())}
- />
-
+
- {contentHeader}
- {contentBody}
- {shouldShowClipboard && (
-
-
-
- )}
- {shouldShowBody2 && (
-
- {translate(`referralProgram.${CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE}.body2`)}
-
- )}
- {translate('requestorStep.learnMore')}
-
-
-
-
+ )}
+
+
{!requiresTwoFactorAuth && (
diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js
index c5e6bf43fa1d..fcc497111b92 100644
--- a/src/pages/ReportDetailsPage.js
+++ b/src/pages/ReportDetailsPage.js
@@ -105,7 +105,10 @@ function ReportDetailsPage(props) {
return items;
}
- if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && (!ReportUtils.isPublicRoom(props.report) || isPolicyMember))) {
+ // The Members page is only shown when:
+ // - The report is not a user created room with participants to show i.e. DM, Group Chat, etc
+ // - The report is a user created room and the room and the current user is a workspace member i.e. non-workspace members should not see this option.
+ if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && isPolicyMember)) {
items.push({
key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS,
translationKey: 'common.members',
@@ -212,7 +215,7 @@ function ReportDetailsPage(props) {
{
Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(props.report.policyID));
diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.js
index 957c3da9c86b..a17e1efe6a0c 100644
--- a/src/pages/ReportWelcomeMessagePage.js
+++ b/src/pages/ReportWelcomeMessagePage.js
@@ -101,7 +101,7 @@ function ReportWelcomeMessagePage(props) {
inputID="welcomeMessage"
label={props.translate('welcomeMessagePage.welcomeMessage')}
accessibilityLabel={props.translate('welcomeMessagePage.welcomeMessage')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
autoGrowHeight
maxLength={CONST.MAX_COMMENT_LENGTH}
ref={(el) => {
diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js
index 23722625b961..a48ab08408f2 100644
--- a/src/pages/RoomMembersPage.js
+++ b/src/pages/RoomMembersPage.js
@@ -237,7 +237,7 @@ function RoomMembersPage(props) {
testID={RoomMembersPage.displayName}
>
Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(props.report.reportID))}
>
diff --git a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
index e04b720e8365..f44356347273 100644
--- a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
+++ b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
@@ -107,7 +107,7 @@ function IntroSchoolPrincipalPage(props) {
name="firstName"
label={translate('teachersUnitePage.principalFirstName')}
accessibilityLabel={translate('teachersUnitePage.principalFirstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -119,7 +119,7 @@ function IntroSchoolPrincipalPage(props) {
name="lastName"
label={translate('teachersUnitePage.principalLastName')}
accessibilityLabel={translate('teachersUnitePage.principalLastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -131,7 +131,7 @@ function IntroSchoolPrincipalPage(props) {
name="partnerUserID"
label={translate('teachersUnitePage.principalWorkEmail')}
accessibilityLabel={translate('teachersUnitePage.principalWorkEmail')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.EMAIL}
autoCapitalize="none"
/>
diff --git a/src/pages/TeachersUnite/KnowATeacherPage.js b/src/pages/TeachersUnite/KnowATeacherPage.js
index 7c2b8f03f879..f2a5732b6a0a 100644
--- a/src/pages/TeachersUnite/KnowATeacherPage.js
+++ b/src/pages/TeachersUnite/KnowATeacherPage.js
@@ -117,7 +117,7 @@ function KnowATeacherPage(props) {
name="fname"
label={translate('common.firstName')}
accessibilityLabel={translate('common.firstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -129,7 +129,7 @@ function KnowATeacherPage(props) {
name="lname"
label={translate('common.lastName')}
accessibilityLabel={translate('common.lastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -141,7 +141,7 @@ function KnowATeacherPage(props) {
name="partnerUserID"
label={`${translate('common.email')}/${translate('common.phoneNumber')}`}
accessibilityLabel={`${translate('common.email')}/${translate('common.phoneNumber')}`}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.EMAIL}
autoCapitalize="none"
/>
diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js
index 996538c91e5a..b503727c1d58 100644
--- a/src/pages/home/HeaderView.js
+++ b/src/pages/home/HeaderView.js
@@ -206,7 +206,7 @@ function HeaderView(props) {
style={[styles.LHNToggle]}
accessibilityHint={translate('accessibilityHints.navigateToChatsList')}
accessibilityLabel={translate('common.back')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{shouldShowSubscript ? (
e.preventDefault()}
style={styles.composerSizeButton}
disabled={isBlockedFromConcierge || disabled}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('reportActionCompose.collapse')}
>
e.preventDefault()}
style={styles.composerSizeButton}
disabled={isBlockedFromConcierge || disabled}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('reportActionCompose.expand')}
>
{({pressed}) => (
diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js
index 01857e2f2f1c..633701f0b375 100644
--- a/src/pages/home/report/ReportActionItemCreated.js
+++ b/src/pages/home/report/ReportActionItemCreated.js
@@ -76,7 +76,7 @@ function ReportActionItemCreated(props) {
onPress={() => ReportUtils.navigateToDetailsPage(props.report)}
style={[styles.mh5, styles.mb3, styles.alignSelfStart]}
accessibilityLabel={props.translate('common.details')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
disabled={shouldDisableDetailPage}
>
- {children}
-
- );
-}
-
-ReportActionItemGrouped.propTypes = propTypes;
-ReportActionItemGrouped.defaultProps = defaultProps;
-ReportActionItemGrouped.displayName = 'ReportActionItemGrouped';
-export default ReportActionItemGrouped;
diff --git a/src/pages/home/report/ReportActionItemGrouped.tsx b/src/pages/home/report/ReportActionItemGrouped.tsx
new file mode 100644
index 000000000000..5e49f7af9d10
--- /dev/null
+++ b/src/pages/home/report/ReportActionItemGrouped.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import {StyleProp, View, ViewStyle} from 'react-native';
+import useThemeStyles from '@styles/useThemeStyles';
+import ChildrenProps from '@src/types/utils/ChildrenProps';
+
+type ReportActionItemGroupedProps = ChildrenProps & {
+ /** Styles for the outermost View */
+ wrapperStyle?: StyleProp;
+};
+
+function ReportActionItemGrouped({wrapperStyle, children}: ReportActionItemGroupedProps) {
+ const styles = useThemeStyles();
+ return (
+
+ {children}
+
+ );
+}
+
+ReportActionItemGrouped.displayName = 'ReportActionItemGrouped';
+
+export default ReportActionItemGrouped;
diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js
index 605aed6baab1..fdee403d6712 100644
--- a/src/pages/home/report/ReportActionItemMessageEdit.js
+++ b/src/pages/home/report/ReportActionItemMessageEdit.js
@@ -386,7 +386,7 @@ function ReportActionItemMessageEdit(props) {
{getAvatar()}
@@ -231,7 +231,7 @@ function ReportActionItemSingle(props) {
onPress={showActorDetails}
disabled={shouldDisableDetailPage}
accessibilityLabel={actorHint}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{_.map(personArray, (fragment, index) => (
{
Report.navigateToAndOpenChildReport(props.childReportID);
}}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={`${props.numberOfReplies} ${replyText}`}
onSecondaryInteraction={props.onSecondaryInteraction}
>
diff --git a/src/pages/home/sidebar/AvatarWithOptionalStatus.js b/src/pages/home/sidebar/AvatarWithOptionalStatus.js
index 4507b21a382c..20f9447f52ce 100644
--- a/src/pages/home/sidebar/AvatarWithOptionalStatus.js
+++ b/src/pages/home/sidebar/AvatarWithOptionalStatus.js
@@ -42,7 +42,7 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) {
diff --git a/src/pages/home/sidebar/PressableAvatarWithIndicator.js b/src/pages/home/sidebar/PressableAvatarWithIndicator.js
index ddf89321b680..d72aef2ef824 100644
--- a/src/pages/home/sidebar/PressableAvatarWithIndicator.js
+++ b/src/pages/home/sidebar/PressableAvatarWithIndicator.js
@@ -52,7 +52,7 @@ function PressableAvatarWithIndicator({isCreateMenuOpen, currentUserPersonalDeta
return (
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index 6cb8cbc24e72..4348881a680c 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -166,13 +166,13 @@ function SidebarLinks({onLinkClick, insets, optionListItems, isLoading, priority
contentFit="contain"
/>
}
- accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
shouldShowEnvironmentBadge
/>
diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
index 90c6fae49fe2..ae46f033e137 100644
--- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
+++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
@@ -242,7 +242,7 @@ function FloatingActionButtonAndPopover(props) {
/>
{
diff --git a/src/pages/home/sidebar/SignInButton.js b/src/pages/home/sidebar/SignInButton.js
index c42e56551200..f820298b0a22 100644
--- a/src/pages/home/sidebar/SignInButton.js
+++ b/src/pages/home/sidebar/SignInButton.js
@@ -15,7 +15,7 @@ function SignInButton() {
return (
diff --git a/src/pages/iou/MoneyRequestDescriptionPage.js b/src/pages/iou/MoneyRequestDescriptionPage.js
index 4bfcc7b5f12d..2d3e7d887e60 100644
--- a/src/pages/iou/MoneyRequestDescriptionPage.js
+++ b/src/pages/iou/MoneyRequestDescriptionPage.js
@@ -132,7 +132,7 @@ function MoneyRequestDescriptionPage({iou, route, selectedTab}) {
defaultValue={iou.comment}
label={translate('moneyRequestConfirmationList.whatsItFor')}
accessibilityLabel={translate('moneyRequestConfirmationList.whatsItFor')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(el) => {
if (!el) {
return;
diff --git a/src/pages/iou/MoneyRequestMerchantPage.js b/src/pages/iou/MoneyRequestMerchantPage.js
index 2c5869dfa7a3..be57f0b6c534 100644
--- a/src/pages/iou/MoneyRequestMerchantPage.js
+++ b/src/pages/iou/MoneyRequestMerchantPage.js
@@ -118,7 +118,7 @@ function MoneyRequestMerchantPage({iou, route}) {
maxLength={CONST.MERCHANT_NAME_MAX_LENGTH}
label={translate('common.merchant')}
accessibilityLabel={translate('common.merchant')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={inputCallbackRef}
/>
diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js
index af52ea1222ed..ee4ee88d7008 100644
--- a/src/pages/iou/MoneyRequestSelectorPage.js
+++ b/src/pages/iou/MoneyRequestSelectorPage.js
@@ -48,7 +48,7 @@ const propTypes = {
};
const defaultProps = {
- selectedTab: CONST.TAB.SCAN,
+ selectedTab: CONST.TAB_REQUEST.SCAN,
report: {},
};
@@ -100,7 +100,7 @@ function MoneyRequestSelectorPage(props) {
{({safeAreaPaddingBottomStyle}) => (
@@ -121,18 +121,18 @@ function MoneyRequestSelectorPage(props) {
)}
>
{shouldDisplayDistanceRequest && (
diff --git a/src/pages/iou/ReceiptSelector/index.js b/src/pages/iou/ReceiptSelector/index.js
index 561082c8b65a..71c06105fa93 100644
--- a/src/pages/iou/ReceiptSelector/index.js
+++ b/src/pages/iou/ReceiptSelector/index.js
@@ -210,7 +210,7 @@ function ReceiptSelector({route, transactionID, iou, report}) {
{({openPicker}) => (
{
openPicker({
onPicked: (file) => {
@@ -229,7 +229,7 @@ function ReceiptSelector({route, transactionID, iou, report}) {
)}
{({openPicker}) => (
{
@@ -258,7 +258,7 @@ function ReceiptSelector({route, report, iou, transactionID}) {
)}
`${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(route, 'params.transactionID')}`,
- selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
},
recentWaypoints: {
key: ONYXKEYS.NVP_RECENT_WAYPOINTS,
diff --git a/src/pages/iou/request/IOURequestStartPage.js b/src/pages/iou/request/IOURequestStartPage.js
index 48efc0bdd17c..c24e4f4e9e5f 100644
--- a/src/pages/iou/request/IOURequestStartPage.js
+++ b/src/pages/iou/request/IOURequestStartPage.js
@@ -6,6 +6,7 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TabSelector from '@components/TabSelector/TabSelector';
@@ -108,6 +109,12 @@ function IOURequestStartPage({
[previousIOURequestType, reportID, isFromGlobalCreate],
);
+ if (!transaction.transactionID) {
+ // The draft transaction is initialized only after the component is mounted,
+ // which will lead to briefly displaying the Not Found page without this loader.
+ return ;
+ }
+
return (
participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase())),
+ _.some(participants, (participant) => lodashGet(participant, 'searchText', '').toLowerCase().includes(searchTerm.trim().toLowerCase())),
);
const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails);
diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js
index 913912fcf05c..8f89703e6efd 100644
--- a/src/pages/iou/request/step/IOURequestStepAmount.js
+++ b/src/pages/iou/request/step/IOURequestStepAmount.js
@@ -99,6 +99,7 @@ function IOURequestStepAmount({
onBackButtonPress={navigateBack}
testID={IOURequestStepAmount.displayName}
shouldShowWrapper={Boolean(backTo)}
+ includeSafeAreaPaddingBottom
>
optionsSelectorRef.current && optionsSelectorRef.current.focus()}
+ includeSafeAreaPaddingBottom
>
(optionsSelectorRef.current = el)}
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.js b/src/pages/iou/request/step/IOURequestStepScan/index.js
index 5098401ddf79..e4c50ff25b5c 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.js
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.js
@@ -154,6 +154,11 @@ function IOURequestStepScan({
const fileSource = URL.createObjectURL(imageFile);
IOU.setMoneyRequestReceipt_temporaryForRefactor(transactionID, fileSource, imageFile.name);
+ if (backTo) {
+ Navigation.goBack(backTo);
+ return;
+ }
+
// When an existing transaction is being edited (eg. not the create transaction flow)
if (transactionID !== CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
IOU.replaceReceipt(transactionID, imageFile, fileSource);
@@ -171,7 +176,7 @@ function IOURequestStepScan({
}
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID));
- }, [cameraRef, report, iouType, transactionID, reportID]);
+ }, [cameraRef, report, iouType, transactionID, reportID, backTo]);
const panResponder = useRef(
PanResponder.create({
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.js b/src/pages/iou/request/step/IOURequestStepScan/index.native.js
index 65a0ffd7bf59..e80fbbce0676 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.native.js
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.js
@@ -214,14 +214,18 @@ function IOURequestStepScan({
)}
{cameraPermissionStatus === RESULTS.GRANTED && device != null && (
-
+
+
+
+
+
)}
@@ -239,6 +243,11 @@ function IOURequestStepScan({
const filePath = file.uri;
IOU.setMoneyRequestReceipt_temporaryForRefactor(transactionID, filePath, file.name);
+ if (backTo) {
+ Navigation.goBack(backTo);
+ return;
+ }
+
// When a transaction is being edited (eg. not in the creation flow)
if (transactionID !== CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
IOU.replaceReceipt(transactionID, file, filePath);
diff --git a/src/pages/iou/request/step/StepScreenWrapper.js b/src/pages/iou/request/step/StepScreenWrapper.js
index 000beb8432c5..5131a9c60dc6 100644
--- a/src/pages/iou/request/step/StepScreenWrapper.js
+++ b/src/pages/iou/request/step/StepScreenWrapper.js
@@ -25,13 +25,17 @@ const propTypes = {
/** An ID used for unit testing */
testID: PropTypes.string.isRequired,
+
+ /** Whether or not to include safe area padding */
+ includeSafeAreaPaddingBottom: PropTypes.bool,
};
const defaultProps = {
onEntryTransitionEnd: () => {},
+ includeSafeAreaPaddingBottom: false,
};
-function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTransitionEnd, children, shouldShowWrapper}) {
+function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTransitionEnd, children, shouldShowWrapper, includeSafeAreaPaddingBottom}) {
const styles = useThemeStyles();
if (!shouldShowWrapper) {
@@ -40,14 +44,13 @@ function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTrans
return (
{({insets, safeAreaPaddingBottomStyle, didScreenTransitionEnd}) => (
-
+
;
+ return ;
}
return (
diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js
index 6317fd09aa82..a8e56f7a41e8 100644
--- a/src/pages/iou/steps/MoneyRequestAmountForm.js
+++ b/src/pages/iou/steps/MoneyRequestAmountForm.js
@@ -46,7 +46,7 @@ const defaultProps = {
currency: CONST.CURRENCY.USD,
forwardedRef: null,
isEditing: false,
- selectedTab: CONST.TAB.MANUAL,
+ selectedTab: CONST.TAB_REQUEST.MANUAL,
};
/**
diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js
index d6000e4e48cc..03ebb9bdb562 100644
--- a/src/pages/iou/steps/MoneyRequestConfirmPage.js
+++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js
@@ -77,7 +77,7 @@ function MoneyRequestConfirmPage(props) {
[props.iou.participants, personalDetails],
);
const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(props.report)), [props.report]);
- const isManualRequestDM = props.selectedTab === CONST.TAB.MANUAL && iouType === CONST.IOU.TYPE.REQUEST;
+ const isManualRequestDM = props.selectedTab === CONST.TAB_REQUEST.MANUAL && iouType === CONST.IOU.TYPE.REQUEST;
useEffect(() => {
const policyExpenseChat = _.find(participants, (participant) => participant.isPolicyExpenseChat);
diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js
index 8ca1f96b3796..2af5b145caab 100755
--- a/src/pages/settings/InitialSettingsPage.js
+++ b/src/pages/settings/InitialSettingsPage.js
@@ -22,6 +22,7 @@ import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
import useSingleExecution from '@hooks/useSingleExecution';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
+import * as CardUtils from '@libs/CardUtils';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -43,6 +44,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
+import assignedCardPropTypes from './Wallet/assignedCardPropTypes';
const propTypes = {
/* Onyx Props */
@@ -102,6 +104,8 @@ const propTypes = {
}),
),
+ cardList: PropTypes.objectOf(assignedCardPropTypes),
+
/** Members keyed by accountID for all policies */
allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)),
@@ -120,6 +124,7 @@ const defaultProps = {
bankAccountList: {},
fundList: null,
loginList: {},
+ cardList: {},
allPolicyMembers: {},
...withCurrentUserPersonalDetailsDefaultProps,
};
@@ -235,7 +240,10 @@ function InitialSettingsPage(props) {
Navigation.navigate(ROUTES.SETTINGS_WALLET);
}),
brickRoadIndicator:
- PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList) || !_.isEmpty(props.userWallet.errors) || !_.isEmpty(props.walletTerms.errors)
+ PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList) ||
+ !_.isEmpty(props.userWallet.errors) ||
+ !_.isEmpty(props.walletTerms.errors) ||
+ CardUtils.hasDetectedFraud(props.cardList)
? 'error'
: null,
},
@@ -267,6 +275,7 @@ function InitialSettingsPage(props) {
}, [
props.allPolicyMembers,
props.bankAccountList,
+ props.cardList,
props.fundList,
props.loginList,
props.network.isOffline,
@@ -335,7 +344,7 @@ function InitialSettingsPage(props) {
disabled={isExecuting}
onPress={singleExecution(openProfileSettings)}
accessibilityLabel={translate('common.profile')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
(loginInputRef.current = el)}
inputID="phoneOrEmail"
diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
index fa1c17578126..60c9b46748f6 100644
--- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
+++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
@@ -207,7 +207,7 @@ function BaseValidateCodeForm(props) {
underlayColor={theme.componentBG}
hoverDimmingValue={1}
pressDimmingValue={0.2}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('validateCodeForm.magicCodeNotReceived')}
>
{props.translate('validateCodeForm.magicCodeNotReceived')}
diff --git a/src/pages/settings/Profile/CustomStatus/StatusSetPage.js b/src/pages/settings/Profile/CustomStatus/StatusSetPage.js
index 6c7a2d896aa9..b9ae9c8d2f51 100644
--- a/src/pages/settings/Profile/CustomStatus/StatusSetPage.js
+++ b/src/pages/settings/Profile/CustomStatus/StatusSetPage.js
@@ -76,7 +76,7 @@ function StatusSetPage({draftStatus, currentUserPersonalDetails}) {
inputID={INPUT_IDS.STATUS_TEXT}
label={translate('statusPage.message')}
aria-label={INPUT_IDS.STATUS_TEXT}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={defaultText}
maxLength={CONST.STATUS_TEXT_MAX_LENGTH}
autoFocus
diff --git a/src/pages/settings/Profile/DisplayNamePage.js b/src/pages/settings/Profile/DisplayNamePage.js
index 85f630a41212..5c13bfe72d5f 100644
--- a/src/pages/settings/Profile/DisplayNamePage.js
+++ b/src/pages/settings/Profile/DisplayNamePage.js
@@ -102,7 +102,7 @@ function DisplayNamePage(props) {
name="fname"
label={props.translate('common.firstName')}
aria-label={props.translate('common.firstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={lodashGet(currentUserDetails, 'firstName', '')}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
spellCheck={false}
@@ -115,7 +115,7 @@ function DisplayNamePage(props) {
name="lname"
label={props.translate('common.lastName')}
aria-label={props.translate('common.lastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={lodashGet(currentUserDetails, 'lastName', '')}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
spellCheck={false}
diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
index c6ad9f083114..a9005c39534d 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
@@ -104,7 +104,7 @@ function LegalNamePage(props) {
name="lfname"
label={props.translate('privatePersonalDetails.legalFirstName')}
aria-label={props.translate('privatePersonalDetails.legalFirstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={legalFirstName}
maxLength={CONST.LEGAL_NAME.MAX_LENGTH + CONST.SEARCH_MAX_LENGTH}
spellCheck={false}
@@ -117,7 +117,7 @@ function LegalNamePage(props) {
name="llname"
label={props.translate('privatePersonalDetails.legalLastName')}
aria-label={props.translate('privatePersonalDetails.legalLastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={legalLastName}
maxLength={CONST.LEGAL_NAME.MAX_LENGTH + CONST.SEARCH_MAX_LENGTH}
spellCheck={false}
diff --git a/src/pages/settings/Security/CloseAccountPage.js b/src/pages/settings/Security/CloseAccountPage.js
index 8c1b851ee176..2c55c5e73f0c 100644
--- a/src/pages/settings/Security/CloseAccountPage.js
+++ b/src/pages/settings/Security/CloseAccountPage.js
@@ -109,7 +109,7 @@ function CloseAccountPage(props) {
autoGrowHeight
label={props.translate('closeAccountPage.enterMessageHere')}
aria-label={props.translate('closeAccountPage.enterMessageHere')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt5, styles.autoGrowHeightMultilineInput]}
/>
@@ -121,7 +121,7 @@ function CloseAccountPage(props) {
autoCapitalize="none"
label={props.translate('closeAccountPage.enterDefaultContact')}
aria-label={props.translate('closeAccountPage.enterDefaultContact')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt5]}
autoCorrect={false}
inputMode={Str.isValidEmail(userEmailOrPhone) ? CONST.INPUT_MODE.EMAIL : CONST.INPUT_MODE.TEXT}
diff --git a/src/pages/settings/Wallet/AddDebitCardPage.js b/src/pages/settings/Wallet/AddDebitCardPage.js
index 872052067213..1f824fed5293 100644
--- a/src/pages/settings/Wallet/AddDebitCardPage.js
+++ b/src/pages/settings/Wallet/AddDebitCardPage.js
@@ -122,7 +122,7 @@ function DebitCardPage(props) {
inputID="nameOnCard"
label={translate('addDebitCardPage.nameOnCard')}
aria-label={translate('addDebitCardPage.nameOnCard')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={nameOnCardRef}
spellCheck={false}
/>
@@ -131,7 +131,7 @@ function DebitCardPage(props) {
inputID="cardNumber"
label={translate('addDebitCardPage.debitCardNumber')}
aria-label={translate('addDebitCardPage.debitCardNumber')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt4]}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
@@ -142,7 +142,7 @@ function DebitCardPage(props) {
inputID="expirationDate"
label={translate('addDebitCardPage.expiration')}
aria-label={translate('addDebitCardPage.expiration')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
placeholder={translate('addDebitCardPage.expirationDate')}
inputMode={CONST.INPUT_MODE.NUMERIC}
maxLength={4}
@@ -154,7 +154,7 @@ function DebitCardPage(props) {
inputID="securityCode"
label={translate('addDebitCardPage.cvv')}
aria-label={translate('addDebitCardPage.cvv')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={4}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
@@ -176,7 +176,7 @@ function DebitCardPage(props) {
inputID="addressZipCode"
label={translate('common.zip')}
aria-label={translate('common.zip')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.NUMERIC}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
hint={translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})}
diff --git a/src/pages/settings/Wallet/DangerCardSection.js b/src/pages/settings/Wallet/DangerCardSection.js
deleted file mode 100644
index 91add21b75ea..000000000000
--- a/src/pages/settings/Wallet/DangerCardSection.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import {View} from 'react-native';
-import * as Illustrations from '@components/Icon/Illustrations';
-import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
-
-const propTypes = {
- title: PropTypes.string.isRequired,
- description: PropTypes.string.isRequired,
-};
-
-function DangerCardSection({title, description}) {
- const styles = useThemeStyles();
- return (
-
-
-
- {title}
- {description}
-
-
-
-
-
-
- );
-}
-
-DangerCardSection.propTypes = propTypes;
-DangerCardSection.displayName = 'DangerCardSection';
-
-export default DangerCardSection;
diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.js b/src/pages/settings/Wallet/ExpensifyCardPage.js
index e92fca171817..b469027e6a57 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage.js
+++ b/src/pages/settings/Wallet/ExpensifyCardPage.js
@@ -19,7 +19,6 @@ import FormUtils from '@libs/FormUtils';
import * as GetPhysicalCardUtils from '@libs/GetPhysicalCardUtils';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import useTheme from '@styles/themes/useTheme';
import useThemeStyles from '@styles/useThemeStyles';
import * as Card from '@userActions/Card';
import * as Link from '@userActions/Link';
@@ -27,7 +26,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import assignedCardPropTypes from './assignedCardPropTypes';
-import DangerCardSection from './DangerCardSection';
+import RedDotCardSection from './RedDotCardSection';
import CardDetails from './WalletPage/CardDetails';
const propTypes = {
@@ -123,7 +122,6 @@ function ExpensifyCardPage({
params: {domain},
},
}) {
- const theme = useTheme();
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const {translate} = useLocalize();
@@ -184,8 +182,8 @@ function ExpensifyCardPage({
{hasDetectedDomainFraud ? (
@@ -193,17 +191,15 @@ function ExpensifyCardPage({
{hasDetectedIndividualFraud && !hasDetectedDomainFraud ? (
<>
-
- Link.openOldDotLink('inbox')}
/>
>
diff --git a/src/pages/settings/Wallet/RedDotCardSection.js b/src/pages/settings/Wallet/RedDotCardSection.js
new file mode 100644
index 000000000000..65c700575340
--- /dev/null
+++ b/src/pages/settings/Wallet/RedDotCardSection.js
@@ -0,0 +1,40 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import {View} from 'react-native';
+import Icon from '@components/Icon';
+import * as Expensicons from '@components/Icon/Expensicons';
+import Text from '@components/Text';
+import useTheme from '@styles/themes/useTheme';
+import useThemeStyles from '@styles/useThemeStyles';
+
+const propTypes = {
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string.isRequired,
+};
+
+function RedDotCardSection({title, description}) {
+ const theme = useTheme();
+ const styles = useThemeStyles();
+
+ return (
+
+
+
+
+
+
+ {title}
+ {description}
+
+
+
+ );
+}
+
+RedDotCardSection.propTypes = propTypes;
+RedDotCardSection.displayName = 'RedDotCardSection';
+
+export default RedDotCardSection;
diff --git a/src/pages/signin/ChangeExpensifyLoginLink.js b/src/pages/signin/ChangeExpensifyLoginLink.js
index 219085240459..0fee34f988a1 100755
--- a/src/pages/signin/ChangeExpensifyLoginLink.js
+++ b/src/pages/signin/ChangeExpensifyLoginLink.js
@@ -38,7 +38,7 @@ function ChangeExpensifyLoginLink(props) {
diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
index 3104042bf33b..4e9bf4c3b506 100755
--- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
+++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
@@ -340,7 +340,7 @@ function BaseValidateCodeForm(props) {
hoverDimmingValue={1}
pressDimmingValue={0.2}
disabled={isValidateCodeFormSubmitting}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.isUsingRecoveryCode ? props.translate('recoveryCodeForm.use2fa') : props.translate('recoveryCodeForm.useRecoveryCode')}
>
{props.isUsingRecoveryCode ? props.translate('recoveryCodeForm.use2fa') : props.translate('recoveryCodeForm.useRecoveryCode')}
@@ -376,7 +376,7 @@ function BaseValidateCodeForm(props) {
disabled={shouldDisableResendValidateCode}
hoverDimmingValue={1}
pressDimmingValue={0.2}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('validateCodeForm.magicCodeNotReceived')}
>
diff --git a/src/pages/tasks/NewTaskDescriptionPage.js b/src/pages/tasks/NewTaskDescriptionPage.js
index b9a569646148..30908b2de79b 100644
--- a/src/pages/tasks/NewTaskDescriptionPage.js
+++ b/src/pages/tasks/NewTaskDescriptionPage.js
@@ -73,7 +73,7 @@ function NewTaskDescriptionPage(props) {
inputID="taskDescription"
label={props.translate('newTaskPage.descriptionOptional')}
accessibilityLabel={props.translate('newTaskPage.descriptionOptional')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(el) => {
inputCallbackRef(el);
updateMultilineInputRange(el);
diff --git a/src/pages/tasks/NewTaskDetailsPage.js b/src/pages/tasks/NewTaskDetailsPage.js
index 94cb804a39e1..f04b837d85b6 100644
--- a/src/pages/tasks/NewTaskDetailsPage.js
+++ b/src/pages/tasks/NewTaskDetailsPage.js
@@ -94,7 +94,7 @@ function NewTaskDetailsPage(props) {
openEditor(policy.id)))}
accessibilityLabel={translate('workspace.common.settings')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
openEditor(policy.id)))}
accessibilityLabel={translate('workspace.common.settings')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
(this.welcomeMessageInputRef = el)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputID="welcomeMessage"
label={this.props.translate('workspace.inviteMessage.personalMessagePrompt')}
accessibilityLabel={this.props.translate('workspace.inviteMessage.personalMessagePrompt')}
diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js
index 7ddd78621d2d..c7fc9de2571f 100644
--- a/src/pages/workspace/WorkspaceNewRoomPage.js
+++ b/src/pages/workspace/WorkspaceNewRoomPage.js
@@ -261,7 +261,7 @@ function WorkspaceNewRoomPage(props) {
inputID="welcomeMessage"
label={translate('welcomeMessagePage.welcomeMessageOptional')}
accessibilityLabel={translate('welcomeMessagePage.welcomeMessageOptional')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
autoGrowHeight
maxLength={CONST.MAX_COMMENT_LENGTH}
autoCapitalize="none"
diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.js
index b51146cde7f3..d121134f26da 100644
--- a/src/pages/workspace/WorkspaceSettingsPage.js
+++ b/src/pages/workspace/WorkspaceSettingsPage.js
@@ -143,7 +143,7 @@ function WorkspaceSettingsPage({policy, currencyList, windowWidth, route}) {
;
- policyMembers: OnyxEntry;
+ policyMembers: OnyxEntry;
policyDraft: OnyxEntry;
policyMembersDraft: OnyxEntry;
};
diff --git a/src/stories/Form.stories.js b/src/stories/Form.stories.js
index 6473b1074f17..1edc860a4871 100644
--- a/src/stories/Form.stories.js
+++ b/src/stories/Form.stories.js
@@ -47,7 +47,7 @@ function Template(args) {
paddingBottom: 0,
},
- walletDangerSection: {
- backgroundColor: theme.dangerSection,
- color: theme.dangerSection,
- borderRadius: variables.componentBorderRadiusCard,
- width: 'auto',
- marginHorizontal: 20,
- marginBottom: 6,
- },
-
- walletDangerSectionTitle: {
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
+ walletRedDotSectionTitle: {
+ color: theme.text,
fontWeight: fontWeightBold,
+ fontSize: variables.fontSizeNormal,
lineHeight: variables.lineHeightXLarge,
},
- walletDangerSectionText: {
+ walletRedDotSectionText: {
+ color: theme.darkSupportingText,
fontSize: variables.fontSizeLabel,
lineHeight: variables.lineHeightNormal,
},
diff --git a/src/styles/themes/default.ts b/src/styles/themes/default.ts
index ee930b4a2a04..d46e94da87dd 100644
--- a/src/styles/themes/default.ts
+++ b/src/styles/themes/default.ts
@@ -34,7 +34,7 @@ const darkTheme = {
successPressed: colors.greenPressed,
transparent: colors.transparent,
signInPage: colors.green800,
- dangerSection: colors.tangerine800,
+ darkSupportingText: colors.productDark800,
// Additional keys
overlay: colors.productDark400,
@@ -127,6 +127,10 @@ const darkTheme = {
backgroundColor: colors.productDark200,
statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
},
+ [SCREENS.RIGHT_MODAL.REFERRAL]: {
+ backgroundColor: colors.pink800,
+ statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
+ },
},
statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
diff --git a/src/styles/themes/light.ts b/src/styles/themes/light.ts
index 0e4ca1c8a879..3c37ec4534d0 100644
--- a/src/styles/themes/light.ts
+++ b/src/styles/themes/light.ts
@@ -34,7 +34,7 @@ const lightTheme = {
successPressed: colors.greenPressed,
transparent: colors.transparent,
signInPage: colors.green800,
- dangerSection: colors.tangerine800,
+ darkSupportingText: colors.productDark800,
// Additional keys
overlay: colors.productLight400,
@@ -127,6 +127,10 @@ const lightTheme = {
backgroundColor: colors.productLight200,
statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT,
},
+ [SCREENS.RIGHT_MODAL.REFERRAL]: {
+ backgroundColor: colors.pink800,
+ statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
+ },
},
statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT,
diff --git a/src/styles/themes/types.ts b/src/styles/themes/types.ts
index c674b6057d0f..3a123419c384 100644
--- a/src/styles/themes/types.ts
+++ b/src/styles/themes/types.ts
@@ -37,7 +37,7 @@ type ThemeColors = {
successPressed: Color;
transparent: Color;
signInPage: Color;
- dangerSection: Color;
+ darkSupportingText: Color;
// Additional keys
overlay: Color;
diff --git a/src/types/onyx/BankAccount.ts b/src/types/onyx/BankAccount.ts
index 4dd46c82f800..8e26faf518cb 100644
--- a/src/types/onyx/BankAccount.ts
+++ b/src/types/onyx/BankAccount.ts
@@ -45,5 +45,7 @@ type BankAccount = {
pendingAction?: OnyxCommon.PendingAction;
};
+type BankAccountList = Record;
+
export default BankAccount;
-export type {AccountData, AdditionalData};
+export type {AccountData, AdditionalData, BankAccountList};
diff --git a/src/types/onyx/Fund.ts b/src/types/onyx/Fund.ts
index 82c15c5089d7..e889a414062e 100644
--- a/src/types/onyx/Fund.ts
+++ b/src/types/onyx/Fund.ts
@@ -37,4 +37,7 @@ type Fund = {
pendingAction?: OnyxCommon.PendingAction;
};
+type FundList = Record;
+
export default Fund;
+export type {FundList};
diff --git a/src/types/onyx/Login.ts b/src/types/onyx/Login.ts
index c770e2f81f90..bcf949eb95e6 100644
--- a/src/types/onyx/Login.ts
+++ b/src/types/onyx/Login.ts
@@ -17,4 +17,7 @@ type Login = {
pendingFields?: OnyxCommon.PendingFields;
};
+type LoginList = Record;
+
export default Login;
+export type {LoginList};
diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts
index 7d18f4d70c8d..110bdb024a8c 100644
--- a/src/types/onyx/index.ts
+++ b/src/types/onyx/index.ts
@@ -1,6 +1,6 @@
import Account from './Account';
import AccountData from './AccountData';
-import BankAccount from './BankAccount';
+import BankAccount, {BankAccountList} from './BankAccount';
import Beta from './Beta';
import BlockedFromConcierge from './BlockedFromConcierge';
import Card from './Card';
@@ -11,10 +11,10 @@ import DemoInfo from './DemoInfo';
import Download from './Download';
import Form, {AddDebitCardForm, DateOfBirthForm} from './Form';
import FrequentlyUsedEmoji from './FrequentlyUsedEmoji';
-import Fund from './Fund';
+import Fund, {FundList} from './Fund';
import IOU from './IOU';
import Locale from './Locale';
-import Login from './Login';
+import Login, {LoginList} from './Login';
import MapboxAccessToken from './MapboxAccessToken';
import Modal from './Modal';
import Network from './Network';
@@ -61,6 +61,7 @@ export type {
AccountData,
AddDebitCardForm,
BankAccount,
+ BankAccountList,
Beta,
BlockedFromConcierge,
Card,
@@ -73,9 +74,11 @@ export type {
Form,
FrequentlyUsedEmoji,
Fund,
+ FundList,
IOU,
Locale,
Login,
+ LoginList,
MapboxAccessToken,
Modal,
Network,