Skip to content

Commit

Permalink
Merge branch 'main' of github.com:kubabutkiewicz/expensify-app into t…
Browse files Browse the repository at this point in the history
…s-migration/ReportUtils-lib
  • Loading branch information
kubabutkiewicz committed Nov 27, 2023
2 parents 7ff0f22 + 0c125f9 commit aac1519
Show file tree
Hide file tree
Showing 16 changed files with 94 additions and 100 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.3.6</string>
<string>1.4.3.7</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.3.6</string>
<string>1.4.3.7</string>
</dict>
</plist>
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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.",
Expand Down
4 changes: 3 additions & 1 deletion src/components/AttachmentModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
? {
Expand Down Expand Up @@ -406,7 +408,7 @@ function AttachmentModal(props) {
<Modal
type={modalType}
onSubmit={submitAndClose}
onClose={closeModal}
onClose={isOverlayModalVisible ? closeConfirmModal : closeModal}
isVisible={isModalOpen}
backgroundColor={theme.componentBG}
onModalShow={() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
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';
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
Expand All @@ -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<TSuggestion>(
{
highlightedSuggestionIndex,
onSelect,
accessibilityLabelExtractor,
renderSuggestionMenuItem,
suggestions,
isSuggestionPickerLarge,
keyExtractor,
}: AutoCompleteSuggestionsProps<TSuggestion>,
ref: ForwardedRef<View | HTMLDivElement>,
) {
const styles = useThemeStyles();
const rowHeight = useSharedValue(0);
const scrollRef = useRef(null);
const scrollRef = useRef<FlashList<TSuggestion>>(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<TSuggestion>): ReactElement => (
<PressableWithFeedback
style={({hovered}) => StyleUtils.getAutoCompleteSuggestionItemStyle(highlightedSuggestionIndex, CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT, hovered, index)}
hoverDimmingValue={1}
Expand Down Expand Up @@ -84,7 +79,7 @@ function BaseAutoCompleteSuggestions({

return (
<Animated.View
ref={forwardedRef}
ref={viewForwardedRef(ref)}
style={[styles.autoCompleteSuggestionsContainer, animatedStyles]}
exiting={FadeOutDown.duration(100).easing(Easing.inOut(Easing.ease))}
>
Expand All @@ -104,17 +99,6 @@ function BaseAutoCompleteSuggestions({
);
}

BaseAutoCompleteSuggestions.propTypes = propTypes;
BaseAutoCompleteSuggestions.displayName = 'BaseAutoCompleteSuggestions';

const BaseAutoCompleteSuggestionsWithRef = React.forwardRef((props, ref) => (
<BaseAutoCompleteSuggestions
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
forwardedRef={ref}
/>
));

BaseAutoCompleteSuggestionsWithRef.displayName = 'BaseAutoCompleteSuggestionsWithRef';

export default BaseAutoCompleteSuggestionsWithRef;
export default forwardRef(BaseAutoCompleteSuggestions);

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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<TSuggestion>({measureParentContainer, ...props}: AutoCompleteSuggestionsProps<TSuggestion>) {
return (
<Portal hostName="suggestions">
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<BaseAutoCompleteSuggestions {...props} />
<BaseAutoCompleteSuggestions<TSuggestion> {...props} />
</Portal>
);
}

AutoCompleteSuggestions.propTypes = propTypes;
AutoCompleteSuggestions.displayName = 'AutoCompleteSuggestions';

export default AutoCompleteSuggestions;
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<TSuggestion>({measureParentContainer = () => {}, ...props}: AutoCompleteSuggestionsProps<TSuggestion>) {
const containerRef = React.useRef<HTMLDivElement>(null);
const {windowHeight, windowWidth} = useWindowDimensions();
const [{width, left, bottom}, setContainerState] = React.useState({
width: 0,
Expand All @@ -25,7 +25,7 @@ function AutoCompleteSuggestions({measureParentContainer, ...props}) {
React.useEffect(() => {
const container = containerRef.current;
if (!container) {
return;
return () => {};
}
container.onpointerdown = (e) => {
if (DeviceCapabilities.hasHoverSupport()) {
Expand All @@ -44,20 +44,20 @@ function AutoCompleteSuggestions({measureParentContainer, ...props}) {
}, [measureParentContainer, windowHeight, windowWidth]);

const componentToRender = (
<BaseAutoCompleteSuggestions
<BaseAutoCompleteSuggestions<TSuggestion>
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={containerRef}
/>
);

const bodyElement = document.querySelector('body');

return (
Boolean(width) &&
ReactDOM.createPortal(<View style={StyleUtils.getBaseAutoCompleteSuggestionContainerStyle({left, width, bottom})}>{componentToRender}</View>, document.querySelector('body'))
!!width && bodyElement && ReactDOM.createPortal(<View style={StyleUtils.getBaseAutoCompleteSuggestionContainerStyle({left, width, bottom})}>{componentToRender}</View>, bodyElement)
);
}

AutoCompleteSuggestions.propTypes = propTypes;
AutoCompleteSuggestions.displayName = 'AutoCompleteSuggestions';

export default AutoCompleteSuggestions;
38 changes: 38 additions & 0 deletions src/components/AutoCompleteSuggestions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {ReactElement} from 'react';

type MeasureParentContainerCallback = (x: number, y: number, width: number) => void;

type RenderSuggestionMenuItemProps<TSuggestion> = {
item: TSuggestion;
index: number;
};

type AutoCompleteSuggestionsProps<TSuggestion> = {
/** 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};
4 changes: 2 additions & 2 deletions src/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -110,7 +111,6 @@ type ButtonProps = (ButtonWithText | ChildrenProps) & {

/** Accessibility label for the component */
accessibilityLabel?: string;
isFocused: boolean;
};

function Button(
Expand Down Expand Up @@ -149,7 +149,6 @@ function Button(
shouldRemoveRightBorderRadius = false,
shouldRemoveLeftBorderRadius = false,
shouldEnableHapticFeedback = false,
isFocused,

id = '',
accessibilityLabel = '',
Expand All @@ -159,6 +158,7 @@ function Button(
) {
const theme = useTheme();
const styles = useThemeStyles();
const isFocused = useIsFocused();

const keyboardShortcutCallback = useCallback(
(event?: GestureResponderEvent | KeyboardEvent) => {
Expand Down
6 changes: 4 additions & 2 deletions src/components/ReportActionItem/MoneyRequestPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,17 @@ function MoneyRequestPreview(props) {
return childContainer;
}

const shouldDisableOnPress = props.isBillSplit && _.isEmpty(props.transaction);

return (
<PressableWithFeedback
onPress={props.onPreviewPressed}
onPress={shouldDisableOnPress ? undefined : props.onPreviewPressed}
onPressIn={() => 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}
</PressableWithFeedback>
Expand Down
3 changes: 1 addition & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2762,15 +2762,14 @@ 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,
newParentReportID,
movedReportID,
};

const policyName = getPolicyName(allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${newParentReportID}`]);
const movedActionMessage = [
{
html: `moved the report to the <a href='${CONST.NEW_EXPENSIFY_URL}r/${newParentReportID}' target='_blank' rel='noreferrer noopener'>${policyName}</a> workspace`,
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/Policy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
Loading

0 comments on commit aac1519

Please sign in to comment.