diff --git a/android/app/build.gradle b/android/app/build.gradle
index e11f938a9a8e..c7dd40eaeae3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -91,8 +91,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001040306
- versionName "1.4.3-6"
+ versionCode 1001040307
+ versionName "1.4.3-7"
}
flavorDimensions "default"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 2d89178b271b..ce615bf345c0 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.4.3.6
+ 1.4.3.7
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 2f053575ff3b..5721e8644981 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.4.3.6
+ 1.4.3.7
diff --git a/package-lock.json b/package-lock.json
index 9dd6974b12c5..a60d1d129895 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.4.3-6",
+ "version": "1.4.3-7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.4.3-6",
+ "version": "1.4.3-7",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index eb1b725eea10..ab8e6da87446 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.4.3-6",
+ "version": "1.4.3-7",
"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/components/AttachmentModal.js b/src/components/AttachmentModal.js
index 4ab81ae462c9..d346f271b36d 100755
--- a/src/components/AttachmentModal.js
+++ b/src/components/AttachmentModal.js
@@ -128,6 +128,8 @@ function AttachmentModal(props) {
const [isDownloadButtonReadyToBeShown, setIsDownloadButtonReadyToBeShown] = React.useState(true);
const {windowWidth} = useWindowDimensions();
+ const isOverlayModalVisible = (isAttachmentReceipt && isDeleteReceiptConfirmModalVisible) || (!isAttachmentReceipt && isAttachmentInvalid);
+
const [file, setFile] = useState(
props.originalFileName
? {
@@ -406,7 +408,7 @@ function AttachmentModal(props) {
{
diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
similarity index 77%
rename from src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js
rename to src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
index ec53507d4d8e..3e5e7b4fdd9a 100644
--- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js
+++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
@@ -1,5 +1,6 @@
import {FlashList} from '@shopify/flash-list';
-import React, {useCallback, useEffect, useRef} from 'react';
+import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useRef} from 'react';
+import {View} from 'react-native';
// We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another
import {ScrollView} from 'react-native-gesture-handler';
import Animated, {Easing, FadeOutDown, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
@@ -7,14 +8,10 @@ import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import * as StyleUtils from '@styles/StyleUtils';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
-import {propTypes} from './autoCompleteSuggestionsPropTypes';
+import viewForwardedRef from '@src/types/utils/viewForwardedRef';
+import type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps} from './types';
-/**
- * @param {Number} numRows
- * @param {Boolean} isSuggestionPickerLarge
- * @returns {Number}
- */
-const measureHeightOfSuggestionRows = (numRows, isSuggestionPickerLarge) => {
+const measureHeightOfSuggestionRows = (numRows: number, isSuggestionPickerLarge: boolean): number => {
if (isSuggestionPickerLarge) {
if (numRows > CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_VISIBLE_SUGGESTIONS_IN_CONTAINER) {
// On large screens, if there are more than 5 suggestions, we display a scrollable window with a height of 5 items, indicating that there are more items available
@@ -29,28 +26,26 @@ const measureHeightOfSuggestionRows = (numRows, isSuggestionPickerLarge) => {
return numRows * CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT;
};
-function BaseAutoCompleteSuggestions({
- highlightedSuggestionIndex,
- onSelect,
- renderSuggestionMenuItem,
- suggestions,
- accessibilityLabelExtractor,
- keyExtractor,
- isSuggestionPickerLarge,
- forwardedRef,
-}) {
+function BaseAutoCompleteSuggestions(
+ {
+ highlightedSuggestionIndex,
+ onSelect,
+ accessibilityLabelExtractor,
+ renderSuggestionMenuItem,
+ suggestions,
+ isSuggestionPickerLarge,
+ keyExtractor,
+ }: AutoCompleteSuggestionsProps,
+ ref: ForwardedRef,
+) {
const styles = useThemeStyles();
const rowHeight = useSharedValue(0);
- const scrollRef = useRef(null);
+ const scrollRef = useRef>(null);
/**
* Render a suggestion menu item component.
- * @param {Object} params
- * @param {Object} params.item
- * @param {Number} params.index
- * @returns {JSX.Element}
*/
const renderItem = useCallback(
- ({item, index}) => (
+ ({item, index}: RenderSuggestionMenuItemProps): ReactElement => (
StyleUtils.getAutoCompleteSuggestionItemStyle(highlightedSuggestionIndex, CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT, hovered, index)}
hoverDimmingValue={1}
@@ -84,7 +79,7 @@ function BaseAutoCompleteSuggestions({
return (
@@ -104,17 +99,6 @@ function BaseAutoCompleteSuggestions({
);
}
-BaseAutoCompleteSuggestions.propTypes = propTypes;
BaseAutoCompleteSuggestions.displayName = 'BaseAutoCompleteSuggestions';
-const BaseAutoCompleteSuggestionsWithRef = React.forwardRef((props, ref) => (
-
-));
-
-BaseAutoCompleteSuggestionsWithRef.displayName = 'BaseAutoCompleteSuggestionsWithRef';
-
-export default BaseAutoCompleteSuggestionsWithRef;
+export default forwardRef(BaseAutoCompleteSuggestions);
diff --git a/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js b/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js
deleted file mode 100644
index 8c6dca1902c5..000000000000
--- a/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import PropTypes from 'prop-types';
-
-const propTypes = {
- /** Array of suggestions */
- // eslint-disable-next-line react/forbid-prop-types
- suggestions: PropTypes.arrayOf(PropTypes.object).isRequired,
-
- /** Function used to render each suggestion, returned JSX will be enclosed inside a Pressable component */
- renderSuggestionMenuItem: PropTypes.func.isRequired,
-
- /** Create unique keys for each suggestion item */
- keyExtractor: PropTypes.func.isRequired,
-
- /** The index of the highlighted suggestion */
- highlightedSuggestionIndex: PropTypes.number.isRequired,
-
- /** Fired when the user selects a suggestion */
- onSelect: PropTypes.func.isRequired,
-
- /** Show that we can use large auto-complete suggestion picker.
- * Depending on available space and whether the input is expanded, we can have a small or large mention suggester.
- * When this value is false, the suggester will have a height of 2.5 items. When this value is true, the height can be up to 5 items. */
- isSuggestionPickerLarge: PropTypes.bool.isRequired,
-
- /** create accessibility label for each item */
- accessibilityLabelExtractor: PropTypes.func.isRequired,
-
- /** Meaures the parent container's position and dimensions. */
- measureParentContainer: PropTypes.func,
-};
-
-const defaultProps = {
- measureParentContainer: () => {},
-};
-
-export {propTypes, defaultProps};
diff --git a/src/components/AutoCompleteSuggestions/index.native.js b/src/components/AutoCompleteSuggestions/index.native.tsx
similarity index 61%
rename from src/components/AutoCompleteSuggestions/index.native.js
rename to src/components/AutoCompleteSuggestions/index.native.tsx
index 439fa45eae78..fbfa7d953581 100644
--- a/src/components/AutoCompleteSuggestions/index.native.js
+++ b/src/components/AutoCompleteSuggestions/index.native.tsx
@@ -1,18 +1,17 @@
import {Portal} from '@gorhom/portal';
import React from 'react';
-import {propTypes} from './autoCompleteSuggestionsPropTypes';
import BaseAutoCompleteSuggestions from './BaseAutoCompleteSuggestions';
+import type {AutoCompleteSuggestionsProps} from './types';
-function AutoCompleteSuggestions({measureParentContainer, ...props}) {
+function AutoCompleteSuggestions({measureParentContainer, ...props}: AutoCompleteSuggestionsProps) {
return (
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
-
+ {...props} />
);
}
-AutoCompleteSuggestions.propTypes = propTypes;
AutoCompleteSuggestions.displayName = 'AutoCompleteSuggestions';
export default AutoCompleteSuggestions;
diff --git a/src/components/AutoCompleteSuggestions/index.js b/src/components/AutoCompleteSuggestions/index.tsx
similarity index 76%
rename from src/components/AutoCompleteSuggestions/index.js
rename to src/components/AutoCompleteSuggestions/index.tsx
index 30654caf5708..24b846c265a9 100644
--- a/src/components/AutoCompleteSuggestions/index.js
+++ b/src/components/AutoCompleteSuggestions/index.tsx
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as StyleUtils from '@styles/StyleUtils';
-import {propTypes} from './autoCompleteSuggestionsPropTypes';
import BaseAutoCompleteSuggestions from './BaseAutoCompleteSuggestions';
+import type {AutoCompleteSuggestionsProps} from './types';
/**
* On the mobile-web platform, when long-pressing on auto-complete suggestions,
@@ -14,8 +14,8 @@ import BaseAutoCompleteSuggestions from './BaseAutoCompleteSuggestions';
* On the native platform, tapping on auto-complete suggestions will not blur the main input.
*/
-function AutoCompleteSuggestions({measureParentContainer, ...props}) {
- const containerRef = React.useRef(null);
+function AutoCompleteSuggestions({measureParentContainer = () => {}, ...props}: AutoCompleteSuggestionsProps) {
+ const containerRef = React.useRef(null);
const {windowHeight, windowWidth} = useWindowDimensions();
const [{width, left, bottom}, setContainerState] = React.useState({
width: 0,
@@ -25,7 +25,7 @@ function AutoCompleteSuggestions({measureParentContainer, ...props}) {
React.useEffect(() => {
const container = containerRef.current;
if (!container) {
- return;
+ return () => {};
}
container.onpointerdown = (e) => {
if (DeviceCapabilities.hasHoverSupport()) {
@@ -44,20 +44,20 @@ function AutoCompleteSuggestions({measureParentContainer, ...props}) {
}, [measureParentContainer, windowHeight, windowWidth]);
const componentToRender = (
-
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={containerRef}
/>
);
+ const bodyElement = document.querySelector('body');
+
return (
- Boolean(width) &&
- ReactDOM.createPortal({componentToRender}, document.querySelector('body'))
+ !!width && bodyElement && ReactDOM.createPortal({componentToRender}, bodyElement)
);
}
-AutoCompleteSuggestions.propTypes = propTypes;
AutoCompleteSuggestions.displayName = 'AutoCompleteSuggestions';
export default AutoCompleteSuggestions;
diff --git a/src/components/AutoCompleteSuggestions/types.ts b/src/components/AutoCompleteSuggestions/types.ts
new file mode 100644
index 000000000000..9130f5139d71
--- /dev/null
+++ b/src/components/AutoCompleteSuggestions/types.ts
@@ -0,0 +1,38 @@
+import {ReactElement} from 'react';
+
+type MeasureParentContainerCallback = (x: number, y: number, width: number) => void;
+
+type RenderSuggestionMenuItemProps = {
+ item: TSuggestion;
+ index: number;
+};
+
+type AutoCompleteSuggestionsProps = {
+ /** Array of suggestions */
+ suggestions: TSuggestion[];
+
+ /** Function used to render each suggestion, returned JSX will be enclosed inside a Pressable component */
+ renderSuggestionMenuItem: (item: TSuggestion, index: number) => ReactElement;
+
+ /** Create unique keys for each suggestion item */
+ keyExtractor: (item: TSuggestion, index: number) => string;
+
+ /** The index of the highlighted suggestion */
+ highlightedSuggestionIndex: number;
+
+ /** Fired when the user selects a suggestion */
+ onSelect: (index: number) => void;
+
+ /** Show that we can use large auto-complete suggestion picker.
+ * Depending on available space and whether the input is expanded, we can have a small or large mention suggester.
+ * When this value is false, the suggester will have a height of 2.5 items. When this value is true, the height can be up to 5 items. */
+ isSuggestionPickerLarge: boolean;
+
+ /** create accessibility label for each item */
+ accessibilityLabelExtractor: (item: TSuggestion, index: number) => string;
+
+ /** Meaures the parent container's position and dimensions. */
+ measureParentContainer?: (callback: MeasureParentContainerCallback) => void;
+};
+
+export type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps};
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index 02f743b6a1b6..71bce9777174 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -1,3 +1,4 @@
+import {useIsFocused} from '@react-navigation/native';
import React, {ForwardedRef, useCallback} from 'react';
import {ActivityIndicator, GestureResponderEvent, StyleProp, TextStyle, View, ViewStyle} from 'react-native';
import {SvgProps} from 'react-native-svg';
@@ -110,7 +111,6 @@ type ButtonProps = (ButtonWithText | ChildrenProps) & {
/** Accessibility label for the component */
accessibilityLabel?: string;
- isFocused: boolean;
};
function Button(
@@ -149,7 +149,6 @@ function Button(
shouldRemoveRightBorderRadius = false,
shouldRemoveLeftBorderRadius = false,
shouldEnableHapticFeedback = false,
- isFocused,
id = '',
accessibilityLabel = '',
@@ -159,6 +158,7 @@ function Button(
) {
const theme = useTheme();
const styles = useThemeStyles();
+ const isFocused = useIsFocused();
const keyboardShortcutCallback = useCallback(
(event?: GestureResponderEvent | KeyboardEvent) => {
diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js
index 07aba132be0e..466a5a6eec51 100644
--- a/src/components/ReportActionItem/MoneyRequestPreview.js
+++ b/src/components/ReportActionItem/MoneyRequestPreview.js
@@ -358,15 +358,17 @@ function MoneyRequestPreview(props) {
return childContainer;
}
+ const shouldDisableOnPress = props.isBillSplit && _.isEmpty(props.transaction);
+
return (
DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()}
onPressOut={() => ControlSelection.unblock()}
onLongPress={showContextMenu}
accessibilityLabel={props.isBillSplit ? props.translate('iou.split') : props.translate('iou.cash')}
accessibilityHint={CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency)}
- style={[styles.moneyRequestPreviewBox, ...props.containerStyles]}
+ style={[styles.moneyRequestPreviewBox, ...props.containerStyles, shouldDisableOnPress && styles.cursorDefault]}
>
{childContainer}
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 9ebd2ff0a089..d93661778b83 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -2762,7 +2762,7 @@ function buildOptimisticApprovedReportAction(amount: number, currency: string, e
* Builds an optimistic MOVED report action with a randomly generated reportActionID.
* This action is used when we move reports across workspaces.
*/
-function buildOptimisticMovedReportAction(fromPolicyID: string, toPolicyID: string, newParentReportID: string, movedReportID: string): ReportAction {
+function buildOptimisticMovedReportAction(fromPolicyID: string, toPolicyID: string, newParentReportID: string, movedReportID: string, policyName: string): ReportAction {
const originalMessage = {
fromPolicyID,
toPolicyID,
@@ -2770,7 +2770,6 @@ function buildOptimisticMovedReportAction(fromPolicyID: string, toPolicyID: stri
movedReportID,
};
- const policyName = getPolicyName(allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${newParentReportID}`]);
const movedActionMessage = [
{
html: `moved the report to the ${policyName} workspace`,
diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js
index ebc1cdf9a2e1..b993b4a5dd8b 100644
--- a/src/libs/actions/Policy.js
+++ b/src/libs/actions/Policy.js
@@ -1812,7 +1812,7 @@ function createWorkspaceFromIOUPayment(iouReport) {
});
// Create the MOVED report action and add it to the DM chat which indicates to the user where the report has been moved
- const movedReportAction = ReportUtils.buildOptimisticMovedReportAction(oldPersonalPolicyID, policyID, memberData.workspaceChatReportID, iouReportID);
+ const movedReportAction = ReportUtils.buildOptimisticMovedReportAction(oldPersonalPolicyID, policyID, memberData.workspaceChatReportID, iouReportID, workspaceName);
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`,
diff --git a/src/types/utils/viewForwardedRef.ts b/src/types/utils/viewForwardedRef.ts
new file mode 100644
index 000000000000..3bc18495b153
--- /dev/null
+++ b/src/types/utils/viewForwardedRef.ts
@@ -0,0 +1,6 @@
+import {ForwardedRef} from 'react';
+import {View} from 'react-native';
+
+const viewForwardedRef = (ref: ForwardedRef) => ref as ForwardedRef;
+
+export default viewForwardedRef;