diff --git a/__mocks__/react-native-blob-util.js b/__mocks__/react-native-blob-util.js deleted file mode 100644 index ff8b4c56321a..000000000000 --- a/__mocks__/react-native-blob-util.js +++ /dev/null @@ -1 +0,0 @@ -export default {}; diff --git a/__mocks__/react-native-blob-util.ts b/__mocks__/react-native-blob-util.ts new file mode 100644 index 000000000000..bdaa0ae3ded5 --- /dev/null +++ b/__mocks__/react-native-blob-util.ts @@ -0,0 +1,5 @@ +import type RNFetchBlob from 'react-native-blob-util'; + +const ReactNativeBlobUtilMock: Partial = {}; + +export default ReactNativeBlobUtilMock; diff --git a/__mocks__/react-native-device-info.js b/__mocks__/react-native-device-info.js deleted file mode 100644 index 2ba5b6ef85b3..000000000000 --- a/__mocks__/react-native-device-info.js +++ /dev/null @@ -1,3 +0,0 @@ -import MockDeviceInfo from 'react-native-device-info/jest/react-native-device-info-mock'; - -export default MockDeviceInfo; diff --git a/__mocks__/react-native-device-info.ts b/__mocks__/react-native-device-info.ts new file mode 100644 index 000000000000..bb04f1a176b2 --- /dev/null +++ b/__mocks__/react-native-device-info.ts @@ -0,0 +1,6 @@ +import type DeviceInfoModule from 'react-native-device-info'; +import MockDeviceInfo from 'react-native-device-info/jest/react-native-device-info-mock'; + +const DeviceInfo: typeof DeviceInfoModule = MockDeviceInfo; + +export default DeviceInfo; diff --git a/android/app/build.gradle b/android/app/build.gradle index c0d157da2afd..cbfdb4b0b0a5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001043900 - versionName "1.4.39-0" + versionCode 1001043902 + versionName "1.4.39-2" } flavorDimensions "default" diff --git a/desktop/main.js b/desktop/main.js index e53f03530b57..4b38c5d36ab3 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -410,6 +410,14 @@ const mainWindow = () => { browserWindow.webContents.goBack(); }, }, + { + role: 'back', + visible: false, + accelerator: process.platform === 'darwin' ? 'Cmd+Left' : 'Shift+Left', + click: () => { + browserWindow.webContents.goBack(); + }, + }, { id: 'forward', role: 'forward', @@ -418,6 +426,14 @@ const mainWindow = () => { browserWindow.webContents.goForward(); }, }, + { + role: 'forward', + visible: false, + accelerator: process.platform === 'darwin' ? 'Cmd+Right' : 'Shift+Right', + click: () => { + browserWindow.webContents.goForward(); + }, + }, ], }, { diff --git a/docs/redirects.csv b/docs/redirects.csv index 648f3ad6612f..674e5c32ab04 100644 --- a/docs/redirects.csv +++ b/docs/redirects.csv @@ -48,6 +48,7 @@ https://community.expensify.com/discussion/4463/how-to-remove-or-manage-settings https://community.expensify.com/discussion/5793/how-to-connect-your-personal-card-to-import-expenses,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/Personal-Credit-Cards https://community.expensify.com/discussion/4826/how-to-set-your-annual-subscription-size,https://help.expensify.com/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription https://community.expensify.com/discussion/5667/deep-dive-how-does-the-annual-subscription-billing-work,https://help.expensify.com/articles/expensify-classic/billing-and-subscriptions/Annual-Subscription +https://help.expensify.com/articles/expensify-classic/getting-started/approved-accountants/Your-Expensify-Partner-Manager,https://help.expensify.com/articles/expensify-classic/expensify-partner-program/Your-Expensify-Partner-Manager https://help.expensify.com/expensify-classic/hubs/getting-started/plan-types,https://use.expensify.com/ https://help.expensify.com/articles/expensify-classic/getting-started/Employees,https://help.expensify.com/articles/expensify-classic/getting-started/Join-your-company's-workspace https://help.expensify.com/articles/expensify-classic/getting-started/Using-The-App,https://help.expensify.com/articles/expensify-classic/getting-started/Join-your-company's-workspace diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index c23bcfef9657..0c53a62c88a6 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.39.0 + 1.4.39.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 61cf39e17bc7..ed74e6865d2f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.39.0 + 1.4.39.2 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 27ca75150241..94c770eaf29f 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.39 CFBundleVersion - 1.4.39.0 + 1.4.39.2 NSExtension NSExtensionPointIdentifier diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1664c982ce50..2c05bf4175d8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1178,10 +1178,6 @@ PODS: - React-Core - react-native-launch-arguments (4.0.2): - React - - react-native-live-markdown (0.1.0): - - glog - - RCT-Folly (= 2022.05.16.00) - - React-Core - react-native-netinfo (11.2.1): - React-Core - react-native-pager-view (6.2.2): @@ -1412,6 +1408,10 @@ PODS: - RNGoogleSignin (10.0.1): - GoogleSignIn (~> 7.0) - React-Core + - RNLiveMarkdown (0.1.5): + - glog + - RCT-Folly (= 2022.05.16.00) + - React-Core - RNLocalize (2.2.6): - React-Core - rnmapbox-maps (10.0.11): @@ -1529,7 +1529,6 @@ DEPENDENCIES: - react-native-image-picker (from `../node_modules/react-native-image-picker`) - react-native-key-command (from `../node_modules/react-native-key-command`) - react-native-launch-arguments (from `../node_modules/react-native-launch-arguments`) - - "react-native-live-markdown (from `../node_modules/@expensify/react-native-live-markdown`)" - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" - react-native-pager-view (from `../node_modules/react-native-pager-view`) - react-native-pdf (from `../node_modules/react-native-pdf`) @@ -1574,6 +1573,7 @@ DEPENDENCIES: - RNFS (from `../node_modules/react-native-fs`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - "RNGoogleSignin (from `../node_modules/@react-native-google-signin/google-signin`)" + - "RNLiveMarkdown (from `../node_modules/@expensify/react-native-live-markdown`)" - RNLocalize (from `../node_modules/react-native-localize`) - "rnmapbox-maps (from `../node_modules/@rnmapbox/maps`)" - RNPermissions (from `../node_modules/react-native-permissions`) @@ -1725,8 +1725,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-key-command" react-native-launch-arguments: :path: "../node_modules/react-native-launch-arguments" - react-native-live-markdown: - :path: "../node_modules/@expensify/react-native-live-markdown" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" react-native-pager-view: @@ -1815,6 +1813,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-gesture-handler" RNGoogleSignin: :path: "../node_modules/@react-native-google-signin/google-signin" + RNLiveMarkdown: + :path: "../node_modules/@expensify/react-native-live-markdown" RNLocalize: :path: "../node_modules/react-native-localize" rnmapbox-maps: @@ -1922,7 +1922,6 @@ SPEC CHECKSUMS: react-native-image-picker: c33d4e79f0a14a2b66e5065e14946ae63749660b react-native-key-command: 5af6ee30ff4932f78da6a2109017549042932aa5 react-native-launch-arguments: 5f41e0abf88a15e3c5309b8875d6fd5ac43df49d - react-native-live-markdown: 81ac491b913cb8541a06586adcdc159ab1b86fb5 react-native-netinfo: 8a7fd3f7130ef4ad2fb4276d5c9f8d3f28d2df3d react-native-pager-view: 02a5c4962530f7efc10dd51ee9cdabeff5e6c631 react-native-pdf: b4ca3d37a9a86d9165287741c8b2ef4d8940c00e @@ -1967,6 +1966,7 @@ SPEC CHECKSUMS: RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 25b969a1ffc806b9f9ad2e170d4a3b049c6af85e RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 + RNLiveMarkdown: 35eeecf7e57eb26fdc279d5d4815982a9a9f7beb RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: 6f638ec002aa6e906a6f766d69cd45f968d98e64 RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa diff --git a/package-lock.json b/package-lock.json index a7b27a7f0332..694646334480 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "new.expensify", - "version": "1.4.39-0", + "version": "1.4.39-2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.39-0", + "version": "1.4.39-2", "hasInstallScript": true, "license": "MIT", "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "git+ssh://git@github.com/Expensify/react-native-live-markdown.git#77f85a5265043c6100f1fa65edd58901724faf08", + "@expensify/react-native-live-markdown": "0.1.5", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-getcanonicallocales": "^2.2.0", @@ -3374,13 +3374,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.0", - "resolved": "git+ssh://git@github.com/Expensify/react-native-live-markdown.git#77f85a5265043c6100f1fa65edd58901724faf08", - "integrity": "sha512-EpXjQ+JBR3pRuYuT5iFzQw45hrCcr5ZmX/lji4i3Un/BOQ14JbTkQjjwo4hYX3EdOvfrAUSJs0ZVqeCEIMo3YQ==", - "license": "MIT", - "workspaces": [ - "example" - ], + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.5.tgz", + "integrity": "sha512-Z1tduU1C2BDgZNMrDvXtiWUhQoroMasvwucLBdLSypAMB4Kls4G038A/yZEbD00YVXjXv2tBUiqvUmCMuRdlqw==", "engines": { "node": ">= 18.0.0" }, diff --git a/package.json b/package.json index 6626baf86ad5..0f856afb44e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.39-0", + "version": "1.4.39-2", "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.", @@ -59,7 +59,7 @@ }, "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "git+ssh://git@github.com/Expensify/react-native-live-markdown.git#77f85a5265043c6100f1fa65edd58901724faf08", + "@expensify/react-native-live-markdown": "0.1.5", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-getcanonicallocales": "^2.2.0", diff --git a/src/CONST.ts b/src/CONST.ts index be78f257a44b..79895d20aa57 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -736,7 +736,6 @@ const CONST = { REPORT_INITIAL_RENDER: 'report_initial_render', SWITCH_REPORT: 'switch_report', SIDEBAR_LOADED: 'sidebar_loaded', - OPEN_SEARCH: 'open_search', LOAD_SEARCH_OPTIONS: 'load_search_options', COLD: 'cold', WARM: 'warm', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 9fed8b69db79..b46d3db8b60d 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -424,7 +424,7 @@ type OnyxValues = { [ONYXKEYS.WALLET_TERMS]: OnyxTypes.WalletTerms; [ONYXKEYS.BANK_ACCOUNT_LIST]: OnyxTypes.BankAccountList; [ONYXKEYS.FUND_LIST]: OnyxTypes.FundList; - [ONYXKEYS.CARD_LIST]: Record; + [ONYXKEYS.CARD_LIST]: OnyxTypes.CardList; [ONYXKEYS.WALLET_STATEMENT]: OnyxTypes.WalletStatement; [ONYXKEYS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount; [ONYXKEYS.REIMBURSEMENT_ACCOUNT]: OnyxTypes.ReimbursementAccount; @@ -465,7 +465,8 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; [ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS]: OnyxTypes.PolicyReportFields; [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers; - [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: Record; + [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: OnyxTypes.InvitedEmailsToAccountIDs | undefined; + [ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MESSAGE_DRAFT]: string | undefined; [ONYXKEYS.COLLECTION.REPORT]: OnyxTypes.Report; [ONYXKEYS.COLLECTION.REPORT_METADATA]: OnyxTypes.ReportMetadata; [ONYXKEYS.COLLECTION.REPORT_ACTIONS]: OnyxTypes.ReportActions; @@ -547,8 +548,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM]: OnyxTypes.Form; [ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form; - [ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM]: OnyxTypes.Form; - [ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form; + [ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM]: OnyxTypes.GetPhysicalCardForm; + [ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.GetPhysicalCardForm; [ONYXKEYS.FORMS.REPORT_FIELD_EDIT_FORM]: OnyxTypes.ReportFieldEditForm; [ONYXKEYS.FORMS.REPORT_FIELD_EDIT_FORM_DRAFT]: OnyxTypes.Form; // @ts-expect-error Different values are defined under the same key: ReimbursementAccount and ReimbursementAccountForm diff --git a/src/components/AmountTextInput.tsx b/src/components/AmountTextInput.tsx index 245aa2126d08..05080fcdd21c 100644 --- a/src/components/AmountTextInput.tsx +++ b/src/components/AmountTextInput.tsx @@ -43,7 +43,6 @@ function AmountTextInput( disableKeyboard autoGrow hideFocusedState - shouldInterceptSwipe inputStyle={[styles.iouAmountTextInput, styles.p0, styles.noLeftBorderRadius, styles.noRightBorderRadius, style]} textInputContainerStyles={[styles.borderNone, styles.noLeftBorderRadius, styles.noRightBorderRadius]} onChangeText={onChangeAmount} diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index a5c9e8952905..516de55c73ba 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -1,4 +1,3 @@ -import {MarkdownTextInput} from '@expensify/react-native-live-markdown'; import type {BaseSyntheticEvent, ForwardedRef} from 'react'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {flushSync} from 'react-dom'; @@ -6,10 +5,10 @@ import {flushSync} from 'react-dom'; import type {DimensionValue, NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputSelectionChangeEventData} from 'react-native'; import {StyleSheet, View} from 'react-native'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; +import RNTextInput from '@components/RNTextInput'; import Text from '@components/Text'; import useHtmlPaste from '@hooks/useHtmlPaste'; import useIsScrollBarVisible from '@hooks/useIsScrollBarVisible'; -import useMarkdownStyle from '@hooks/useMarkdownStyle'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -81,7 +80,6 @@ function Composer( const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const markdownStyle = useMarkdownStyle(); const {windowWidth} = useWindowDimensions(); const textRef = useRef(null); const textInput = useRef(null); @@ -170,7 +168,7 @@ function Composer( // To make sure the composer does not capture paste events from other inputs, we check where the event originated // If it did originate in another input, we return early to prevent the composer from handling the paste - const isTargetInput = ['INPUT', 'TEXTAREA', 'SPAN'].includes(eventTarget?.nodeName ?? '') || eventTarget?.contentEditable === 'true'; + const isTargetInput = eventTarget?.nodeName === 'INPUT' || eventTarget?.nodeName === 'TEXTAREA' || eventTarget?.contentEditable === 'true'; if (isTargetInput) { return true; } @@ -329,14 +327,13 @@ function Composer( return ( <> - (textInput.current = el as AnimatedTextInputRef)} + ref={(el) => (textInput.current = el)} selection={selection} style={inputStyleMemo} - markdownStyle={markdownStyle} value={value} defaultValue={defaultValue} autoFocus={autoFocus} diff --git a/src/components/ConnectBankAccountButton.js b/src/components/ConnectBankAccountButton.js deleted file mode 100644 index f036918d9429..000000000000 --- a/src/components/ConnectBankAccountButton.js +++ /dev/null @@ -1,57 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {View} from 'react-native'; -import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; -import Navigation from '@libs/Navigation/Navigation'; -import * as ReimbursementAccount from '@userActions/ReimbursementAccount'; -import Button from './Button'; -import * as Expensicons from './Icon/Expensicons'; -import networkPropTypes from './networkPropTypes'; -import {withNetwork} from './OnyxProvider'; -import Text from './Text'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; - -const propTypes = { - ...withLocalizePropTypes, - - /** Information about the network */ - network: networkPropTypes.isRequired, - - /** PolicyID for navigating to bank account route of that policy */ - policyID: PropTypes.string.isRequired, - - /** Button styles, also applied for offline message wrapper */ - style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), -}; - -const defaultProps = { - style: [], -}; - -function ConnectBankAccountButton(props) { - const styles = useThemeStyles(); - const activeRoute = Navigation.getActiveRouteWithoutParams(); - return props.network.isOffline ? ( - - {`${props.translate('common.youAppearToBeOffline')} ${props.translate('common.thisFeatureRequiresInternet')}`} - - ) : ( -