Skip to content

Commit

Permalink
Merge branch 'main' into expo-image
Browse files Browse the repository at this point in the history
  • Loading branch information
WojtekBoman committed Dec 12, 2023
2 parents 221fe4e + 4239252 commit c483c8a
Show file tree
Hide file tree
Showing 75 changed files with 1,561 additions and 1,376 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001041102
versionName "1.4.11-2"
versionCode 1001041106
versionName "1.4.11-6"
}

flavorDimensions "default"
Expand Down
8 changes: 8 additions & 0 deletions assets/images/thumbs-up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 33 additions & 3 deletions docs/articles/new-expensify/get-paid-back/Request-Money.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
---
title: Request Money
description: Request Money
title: Request Money and Split Bills with Friends
description: Everything you need to know about Requesting Money and Splitting Bills with Friends!
redirect_from: articles/request-money/Request-and-Split-Bills/
---
## Resource Coming Soon!

<!-- The lines above are required by Jekyll to process the .md file -->

# How do these Payment Features work?
Our suite of money movement features enables you to request money owed by an individual or split a bill with a group.

**Request Money** lets your friends pay you back directly in Expensify. When you send a payment request to a friend, Expensify will display the amount owed and the option to pay the corresponding request in a chat between you.

**Split Bill** allows you to split payments between friends and ensures the person who settled the tab gets paid back.

These two features ensure you can live in the moment and settle up afterward.

# How to Request Money
- Select the Green **+** button and choose **Request Money**
- Enter the amount **$** they owe and click **Next**
- Search for the user or enter their email!
- Enter a reason for the request (optional)
- Click **Request!**
- If you change your mind, all you have to do is click **Cancel**
- The user will be able to **Settle up outside of Expensify** or pay you via **Venmo** or **PayPal.me**

# How to Split a Bill
- Select the Green **+** button and choose **Split Bill**
- Enter the total amount for the bill and click **Next**
- Search for users or enter their emails and **Select**
- Enter a reason for the split
- The split is then shared equally between the attendees

# FAQs
## Can I request money from more than one person at a time?
If you need to request money for more than one person at a time, you’ll want to use the Split Bill feature. The Request Money option is for one-to-one payments between two people.
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.11.2</string>
<string>1.4.11.6</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.11.2</string>
<string>1.4.11.6</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.11-2",
"version": "1.4.11-6",
"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: 4 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,9 @@ const CONST = {
OWNER_ACCOUNT_ID_FAKE: 0,
DEFAULT_REPORT_NAME: 'Chat Report',
},
NEXT_STEP: {
FINISHED: 'Finished!',
},
COMPOSER: {
MAX_LINES: 16,
MAX_LINES_SMALL_SCREEN: 6,
Expand Down Expand Up @@ -1167,6 +1170,7 @@ const CONST = {
DECLINE: 'decline',
CANCEL: 'cancel',
DELETE: 'delete',
APPROVE: 'approve',
},
AMOUNT_MAX_LENGTH: 10,
RECEIPT_STATE: {
Expand Down
3 changes: 2 additions & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,12 +453,13 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT]: string;
[ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES]: number;
[ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE]: boolean;
[ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: boolean;
[ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: OnyxTypes.ReportUserIsTyping;
[ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM]: boolean;
[ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup;
[ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags;
[ONYXKEYS.COLLECTION.SELECTED_TAB]: string;
[ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string;

// Forms
[ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM]: OnyxTypes.AddDebitCardForm;
Expand Down
4 changes: 2 additions & 2 deletions src/components/ArchivedReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import * as ReportUtils from '@libs/ReportUtils';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, Report, ReportAction} from '@src/types/onyx';
import type {PersonalDetailsList, Report, ReportAction} from '@src/types/onyx';
import Banner from './Banner';

type ArchivedReportFooterOnyxProps = {
/** The reason this report was archived */
reportClosedAction: OnyxEntry<ReportAction>;

/** Personal details of all users */
personalDetails: OnyxEntry<Record<string, PersonalDetails>>;
personalDetails: OnyxEntry<PersonalDetailsList>;
};

type ArchivedReportFooterProps = ArchivedReportFooterOnyxProps & {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ButtonWithDropdownMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function ButtonWithDropdownMenu(props) {
const [popoverAnchorPosition, setPopoverAnchorPosition] = useState(null);
const {windowWidth, windowHeight} = useWindowDimensions();
const caretButton = useRef(null);
const selectedItem = props.options[selectedItemIndex];
const selectedItem = props.options[selectedItemIndex] || _.first(props.options);
const innerStyleDropButton = StyleUtils.getDropDownButtonHeight(props.buttonSize);
const isButtonSizeLarge = props.buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE;

Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import Youtube from '@assets/images/social-youtube.svg';
import Sync from '@assets/images/sync.svg';
import Task from '@assets/images/task.svg';
import ThreeDots from '@assets/images/three-dots.svg';
import ThumbsUp from '@assets/images/thumbs-up.svg';
import Transfer from '@assets/images/transfer.svg';
import Trashcan from '@assets/images/trashcan.svg';
import Unlock from '@assets/images/unlock.svg';
Expand Down Expand Up @@ -242,6 +243,7 @@ export {
Shield,
Sync,
Task,
ThumbsUp,
ThreeDots,
Transfer,
Trashcan,
Expand Down
39 changes: 13 additions & 26 deletions src/components/MoneyReportHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,24 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const policyType = lodashGet(policy, 'type');
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && lodashGet(policy, 'role') === CONST.POLICY.ROLE.ADMIN;
const isGroupPolicy = _.contains([CONST.POLICY.TYPE.CORPORATE, CONST.POLICY.TYPE.TEAM], policyType);
const isManager = ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID;
const isPayer = policyType === CONST.POLICY.TYPE.CORPORATE ? isPolicyAdmin && isApproved : isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager);
const isPayer = isGroupPolicy
? // In a group policy, the admin approver can pay the report directly by skipping the approval step
isPolicyAdmin && (isApproved || isManager)
: isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager);
const isDraft = ReportUtils.isDraftExpenseReport(moneyRequestReport);
const shouldShowSettlementButton = useMemo(
const shouldShowPayButton = useMemo(
() => isPayer && !isDraft && !isSettled && !moneyRequestReport.isWaitingOnBankAccount && reimbursableTotal !== 0 && !ReportUtils.isArchivedRoom(chatReport),
[isPayer, isDraft, isSettled, moneyRequestReport, reimbursableTotal, chatReport],
);
const shouldShowApproveButton = useMemo(() => {
if (policyType !== CONST.POLICY.TYPE.CORPORATE) {
if (!isGroupPolicy) {
return false;
}
return isManager && !isDraft && !isApproved && !isSettled;
}, [policyType, isManager, isDraft, isApproved, isSettled]);
}, [isGroupPolicy, isManager, isDraft, isApproved, isSettled]);
const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton;
const shouldShowSubmitButton = isDraft && reimbursableTotal !== 0;
const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE;
const shouldShowNextSteps = isFromPaidPolicy && nextStep && !_.isEmpty(nextStep.message);
Expand Down Expand Up @@ -120,22 +125,13 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
style={[styles.pv2]}
formattedAmount={formattedAmount}
/>
</View>
)}
{shouldShowApproveButton && !isSmallScreenWidth && (
<View style={styles.pv2}>
<Button
success
medium
text={translate('iou.approve')}
style={[styles.mnw120, styles.pv2, styles.pr0]}
onPress={() => IOU.approveMoneyRequest(moneyRequestReport)}
/>
</View>
)}
{shouldShowSubmitButton && !isSmallScreenWidth && (
<View style={styles.pv2}>
<Button
Expand All @@ -159,21 +155,12 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
formattedAmount={formattedAmount}
/>
</View>
)}
{shouldShowApproveButton && isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2]}>
<Button
success
medium
text={translate('iou.approve')}
style={[styles.w100, styles.pr0]}
onPress={() => IOU.approveMoneyRequest(moneyRequestReport)}
/>
</View>
)}
{shouldShowSubmitButton && isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2]}>
<Button
Expand Down
3 changes: 2 additions & 1 deletion src/components/MoneyReportHeaderStatusBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useLocalize from '@hooks/useLocalize';
import * as NextStepUtils from '@libs/NextStepUtils';
import nextStepPropTypes from '@pages/nextStepPropTypes';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import RenderHTML from './RenderHTML';

const propTypes = {
Expand All @@ -27,7 +28,7 @@ function MoneyReportHeaderStatusBar({nextStep}) {
return (
<View style={[styles.dFlex, styles.flexRow, styles.alignItemsCenter, styles.overflowHidden, styles.w100]}>
<View style={styles.moneyRequestHeaderStatusBarBadge}>
<Text style={[styles.textLabel, styles.textMicroBold]}>{translate('iou.nextSteps')}</Text>
<Text style={[styles.textLabel, styles.textMicroBold]}>{translate(nextStep.title === CONST.NEXT_STEP.FINISHED ? 'iou.finished' : 'iou.nextSteps')}</Text>
</View>
<View style={[styles.dFlex, styles.flexRow, styles.flexShrink1]}>
<RenderHTML html={messageContent} />
Expand Down
29 changes: 15 additions & 14 deletions src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
receiptPath,
reportActionID,
reportID,
selectedParticipants,
selectedParticipants: pickedParticipants,
session: {accountID},
shouldShowSmartScanFields,
transaction,
Expand Down Expand Up @@ -358,7 +358,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
];
}, [isTypeSplit, isTypeRequest, iouType, iouAmount, receiptPath, formattedAmount, isDistanceRequestWithoutRoute, translate]);

const selectedParticipantsFiltered = useMemo(() => _.filter(selectedParticipants, (participant) => participant.selected), [selectedParticipants]);
const selectedParticipants = useMemo(() => _.filter(pickedParticipants, (participant) => participant.selected), [pickedParticipants]);
const personalDetailsOfPayee = useMemo(() => payeePersonalDetails || currentUserPersonalDetails, [payeePersonalDetails, currentUserPersonalDetails]);
const userCanModifyParticipants = useRef(!isReadOnly && canModifyParticipants && hasMultipleParticipants);
useEffect(() => {
Expand All @@ -368,9 +368,9 @@ function MoneyTemporaryForRefactorRequestConfirmationList({

const optionSelectorSections = useMemo(() => {
const sections = [];
const unselectedParticipants = _.filter(selectedParticipantsFiltered, (participant) => !participant.selected);
const unselectedParticipants = _.filter(pickedParticipants, (participant) => !participant.selected);
if (hasMultipleParticipants) {
const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipantsFiltered);
const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants);
let formattedParticipantsList = _.union(formattedSelectedParticipants, unselectedParticipants);

if (!userCanModifyParticipants.current) {
Expand All @@ -380,7 +380,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
}));
}

const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsFiltered.length, iouAmount, iouCurrencyCode, true);
const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, iouAmount, iouCurrencyCode, true);
const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(
personalDetailsOfPayee,
iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '',
Expand All @@ -402,7 +402,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
},
);
} else {
const formattedSelectedParticipants = _.map(selectedParticipantsFiltered, (participant) => ({
const formattedSelectedParticipants = _.map(selectedParticipants, (participant) => ({
...participant,
isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID),
}));
Expand All @@ -415,7 +415,8 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
}
return sections;
}, [
selectedParticipantsFiltered,
selectedParticipants,
pickedParticipants,
hasMultipleParticipants,
iouAmount,
iouCurrencyCode,
Expand All @@ -430,8 +431,8 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
if (!hasMultipleParticipants) {
return [];
}
return [...selectedParticipantsFiltered, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetailsOfPayee)];
}, [selectedParticipantsFiltered, hasMultipleParticipants, personalDetailsOfPayee]);
return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetailsOfPayee)];
}, [selectedParticipants, hasMultipleParticipants, personalDetailsOfPayee]);

useEffect(() => {
if (!isDistanceRequest) {
Expand Down Expand Up @@ -474,7 +475,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
*/
const confirm = useCallback(
(paymentMethod) => {
if (_.isEmpty(selectedParticipantsFiltered)) {
if (_.isEmpty(selectedParticipants)) {
return;
}

Expand Down Expand Up @@ -502,10 +503,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
}

setDidConfirm(true);
onConfirm(selectedParticipantsFiltered);
onConfirm(selectedParticipants);
}
},
[selectedParticipantsFiltered, onSendMoney, onConfirm, isEditingSplitBill, iouType, isDistanceRequest, isDistanceRequestWithoutRoute, iouCurrencyCode, iouAmount, transaction],
[selectedParticipants, onSendMoney, onConfirm, isEditingSplitBill, iouType, isDistanceRequest, isDistanceRequestWithoutRoute, iouCurrencyCode, iouAmount, transaction],
);

const footerContent = useMemo(() => {
Expand All @@ -514,7 +515,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
}

const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND;
const shouldDisableButton = selectedParticipantsFiltered.length === 0;
const shouldDisableButton = selectedParticipants.length === 0;

const button = shouldShowSettlementButton ? (
<SettlementButton
Expand Down Expand Up @@ -558,7 +559,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
{button}
</>
);
}, [confirm, bankAccountRoute, iouCurrencyCode, iouType, isReadOnly, policyID, selectedParticipantsFiltered, splitOrRequestOptions, translate, formError, styles.ph1, styles.mb2]);
}, [confirm, bankAccountRoute, iouCurrencyCode, iouType, isReadOnly, policyID, selectedParticipants, splitOrRequestOptions, translate, formError, styles.ph1, styles.mb2]);

const {image: receiptImage, thumbnail: receiptThumbnail} = receiptPath && receiptFilename ? ReceiptUtils.getThumbnailAndImageURIs(transaction, receiptPath, receiptFilename) : {};
return (
Expand Down
Loading

0 comments on commit c483c8a

Please sign in to comment.