Skip to content

Commit

Permalink
Merge branch 'main' into fix/30296
Browse files Browse the repository at this point in the history
  • Loading branch information
dukenv0307 committed Dec 4, 2023
2 parents 98fc1ea + 7fef24c commit 397a4f4
Show file tree
Hide file tree
Showing 65 changed files with 768 additions and 502 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ const restrictedImportPaths = [
importNames: ['TouchableOpacity', 'TouchableWithoutFeedback', 'TouchableNativeFeedback', 'TouchableHighlight'],
message: "Please use 'PressableWithFeedback' and/or 'PressableWithoutFeedback' from 'src/components/Pressable' instead.",
},
{
name: 'react-native-safe-area-context',
importNames: ['useSafeAreaInsets', 'SafeAreaConsumer', 'SafeAreaInsetsContext'],
message: "Please use 'useSafeAreaInsets' from 'src/hooks/useSafeAreaInset' and/or 'SafeAreaConsumer' from 'src/components/SafeAreaConsumer' instead.",
},
];

const restrictedImportPatterns = [
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/platformDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ jobs:
if: ${{ failure() }}
needs: [android, desktop, iOS, web]
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Post Slack message on failure
uses: ./.github/actions/composite/announceFailedWorkflowInSlack
with:
Expand Down
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 1001040602
versionName "1.4.6-2"
versionCode 1001040700
versionName "1.4.7-0"
}

flavorDimensions "default"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,30 @@ description: Get the most out of your Expensify Card with exclusive perks!


# Overview
The Expensify Card is packed with perks, both native to our Card program and through exclusive discounts with partnering solutions. Below, we’ll cover all of our exclusive offers in more detail and how to claim discounts with our partners.
The Expensify Card is packed with perks, both native to our Card program and through exclusive discounts with partnering solutions. The Expensify Card’s primary perks include:
- Swipe to Win, where every swipe has a chance to win fun personalized gifts for you and your closest friends and family members
- Unbeatable cash back incentive with each swipe
Below, we’ll cover all of our exclusive offers in more detail and how to claim discounts with our partners.

# Expensify Card Perks

## Swipe to Win
Swipe to Win is a new [Expensify Card](https://use.expensify.com/company-credit-card) perk that gives cardholders the chance to send a gift to a friend, family member, or essential worker on the frontlines!

Winners can choose to _Send a Smile_ or _Send a Laugh_. To start, we’re offering one gift per option:

- **Send A Smile:** Champagne by Expensify
- **Send a Laugh:** Jenga Set

**How to Participate**
It’s easy! Once you have an Expensify Card, you just need to start using it. With each swipe, you're automatically entered to win and have a 1 in 250 chance of getting a prize!

**How will I know if I’ve won?**
Winners will be notified immediately via the Expensify app, and receive additional instructions on how to choose and send their desired gift.

If you don't have Expensify notifications turned on yet, here are some helpful guides:
- [Apple Notification Preferences](https://support.apple.com/en-us/HT201925)
- [Android Notification Preferences](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fsupport.google.com%2Fandroid%2Fanswer%2F9079661%3Fhl%3Den)

# Partner Specific Perks

Expand Down Expand Up @@ -188,4 +211,3 @@ Stripe Atlas helps removes obstacles typically associated with starting a busine
**Receive $100 off Stripe Atlas and get access to a startup toolkit and special offers on additional Strip Atlas services.**

**How to redeem:** Sign up with your Expensify Card.

This file was deleted.

This file was deleted.

4 changes: 2 additions & 2 deletions ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.6</string>
<string>1.4.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.6.2</string>
<string>1.4.7.0</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.6</string>
<string>1.4.7</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.6.2</string>
<string>1.4.7.0</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.6-2",
"version": "1.4.7-0",
"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 @@ -497,6 +497,7 @@ const CONST = {
MODIFIEDEXPENSE: 'MODIFIEDEXPENSE',
MOVED: 'MOVED',
REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED',
REIMBURSEMENTDEQUEUED: 'REIMBURSEMENTDEQUEUED',
RENAMED: 'RENAMED',
REPORTPREVIEW: 'REPORTPREVIEW',
SUBMITTED: 'SUBMITTED',
Expand Down Expand Up @@ -1165,6 +1166,9 @@ const CONST = {
SVG: 'svg',
},
RECEIPT_ERROR: 'receiptError',
CANCEL_REASON: {
PAYMENT_EXPIRED: 'CANCEL_REASON_PAYMENT_EXPIRED',
},
},

GROWL: {
Expand Down
118 changes: 64 additions & 54 deletions src/components/AvatarWithDisplayName.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';
import React, {useCallback, useEffect, useRef} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
import * as StyleUtils from '@styles/StyleUtils';
import useTheme from '@styles/themes/useTheme';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import DisplayNames from './DisplayNames';
import MultipleAvatars from './MultipleAvatars';
Expand All @@ -21,8 +22,6 @@ import participantPropTypes from './participantPropTypes';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import SubscriptAvatar from './SubscriptAvatar';
import Text from './Text';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';

const propTypes = {
/** The report currently being looked at */
Expand All @@ -45,70 +44,76 @@ const propTypes = {

shouldEnableDetailPageNavigation: PropTypes.bool,

...windowDimensionsPropTypes,
...withLocalizePropTypes,
/* Onyx Props */
/** All of the actions of the report */
parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)),
};

const defaultProps = {
personalDetails: {},
policy: {},
report: {},
parentReportActions: {},
isAnonymous: false,
size: CONST.AVATAR_SIZE.DEFAULT,
shouldEnableDetailPageNavigation: false,
};

const showActorDetails = (report, shouldEnableDetailPageNavigation = false) => {
// We should navigate to the details page if the report is a IOU/expense report
if (shouldEnableDetailPageNavigation) {
return ReportUtils.navigateToDetailsPage(report);
}

if (ReportUtils.isExpenseReport(report)) {
Navigation.navigate(ROUTES.PROFILE.getRoute(report.ownerAccountID));
return;
}
function AvatarWithDisplayName({report, policy, size, isAnonymous, parentReportActions, personalDetails, shouldEnableDetailPageNavigation}) {
const theme = useTheme();
const styles = useThemeStyles();
const title = ReportUtils.getReportName(report);
const subtitle = ReportUtils.getChatRoomSubtitle(report);
const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(report);
const isMoneyRequestOrReport = ReportUtils.isMoneyRequestReport(report) || ReportUtils.isMoneyRequest(report);
const icons = ReportUtils.getIcons(report, personalDetails, policy);
const ownerPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs([report.ownerAccountID], personalDetails);
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(_.values(ownerPersonalDetails), false);
const shouldShowSubscriptAvatar = ReportUtils.shouldReportShowSubscript(report);
const isExpenseRequest = ReportUtils.isExpenseRequest(report);
const defaultSubscriptSize = isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : size;
const avatarBorderColor = isAnonymous ? theme.highlightBG : theme.componentBG;

const actorAccountID = useRef(null);
useEffect(() => {
const parentReportAction = lodashGet(parentReportActions, [report.parentReportActionID], {});
actorAccountID.current = lodashGet(parentReportAction, 'actorAccountID', -1);
}, [parentReportActions, report]);

const showActorDetails = useCallback(() => {
// We should navigate to the details page if the report is a IOU/expense report
if (shouldEnableDetailPageNavigation) {
return ReportUtils.navigateToDetailsPage(report);
}

if (ReportUtils.isIOUReport(report)) {
Navigation.navigate(ROUTES.REPORT_PARTICIPANTS.getRoute(report.reportID));
return;
}
if (ReportUtils.isExpenseReport(report)) {
Navigation.navigate(ROUTES.PROFILE.getRoute(report.ownerAccountID));
return;
}

if (ReportUtils.isChatThread(report)) {
const parentReportAction = ReportActionsUtils.getParentReportAction(report);
const actorAccountID = lodashGet(parentReportAction, 'actorAccountID', -1);
// in an ideal situation account ID won't be 0
if (actorAccountID > 0) {
Navigation.navigate(ROUTES.PROFILE.getRoute(actorAccountID));
if (ReportUtils.isIOUReport(report)) {
Navigation.navigate(ROUTES.REPORT_PARTICIPANTS.getRoute(report.reportID));
return;
}
}

// report detail route is added as fallback but based on the current implementation this route won't be executed
Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID));
};
if (ReportUtils.isChatThread(report)) {
// In an ideal situation account ID won't be 0
if (actorAccountID.current > 0) {
Navigation.navigate(ROUTES.PROFILE.getRoute(actorAccountID.current));
return;
}
}

function AvatarWithDisplayName(props) {
const theme = useTheme();
const styles = useThemeStyles();
const title = ReportUtils.getReportName(props.report);
const subtitle = ReportUtils.getChatRoomSubtitle(props.report);
const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(props.report);
const isMoneyRequestOrReport = ReportUtils.isMoneyRequestReport(props.report) || ReportUtils.isMoneyRequest(props.report);
const icons = ReportUtils.getIcons(props.report, props.personalDetails, props.policy);
const ownerPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs([props.report.ownerAccountID], props.personalDetails);
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(_.values(ownerPersonalDetails), false);
const shouldShowSubscriptAvatar = ReportUtils.shouldReportShowSubscript(props.report);
const isExpenseRequest = ReportUtils.isExpenseRequest(props.report);
const defaultSubscriptSize = isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : props.size;
const avatarBorderColor = props.isAnonymous ? theme.highlightBG : theme.componentBG;
// Report detail route is added as fallback but based on the current implementation this route won't be executed
Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID));
}, [report, shouldEnableDetailPageNavigation]);

const headerView = (
<View style={[styles.appContentHeaderTitle, styles.flex1]}>
{Boolean(props.report && title) && (
{Boolean(report && title) && (
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween]}>
<PressableWithoutFeedback
onPress={() => showActorDetails(props.report, props.shouldEnableDetailPageNavigation)}
onPress={showActorDetails}
accessibilityLabel={title}
role={CONST.ACCESSIBILITY_ROLE.BUTTON}
>
Expand All @@ -122,7 +127,7 @@ function AvatarWithDisplayName(props) {
) : (
<MultipleAvatars
icons={icons}
size={props.size}
size={size}
secondAvatarStyle={[StyleUtils.getBackgroundAndBorderStyle(avatarBorderColor)]}
/>
)}
Expand All @@ -133,13 +138,13 @@ function AvatarWithDisplayName(props) {
displayNamesWithTooltips={displayNamesWithTooltips}
tooltipEnabled
numberOfLines={1}
textStyles={[props.isAnonymous ? styles.headerAnonymousFooter : styles.headerText, styles.pre]}
shouldUseFullTitle={isMoneyRequestOrReport || props.isAnonymous}
textStyles={[isAnonymous ? styles.headerAnonymousFooter : styles.headerText, styles.pre]}
shouldUseFullTitle={isMoneyRequestOrReport || isAnonymous}
/>
{!_.isEmpty(parentNavigationSubtitleData) && (
<ParentNavigationSubtitle
parentNavigationSubtitleData={parentNavigationSubtitleData}
parentReportID={props.report.parentReportID}
parentReportID={report.parentReportID}
/>
)}
{!_.isEmpty(subtitle) && (
Expand All @@ -156,13 +161,13 @@ function AvatarWithDisplayName(props) {
</View>
);

if (!props.shouldEnableDetailPageNavigation) {
if (!shouldEnableDetailPageNavigation) {
return headerView;
}

return (
<PressableWithoutFeedback
onPress={() => ReportUtils.navigateToDetailsPage(props.report)}
onPress={() => ReportUtils.navigateToDetailsPage(report)}
style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}
accessibilityLabel={title}
role={CONST.ACCESSIBILITY_ROLE.BUTTON}
Expand All @@ -175,4 +180,9 @@ AvatarWithDisplayName.propTypes = propTypes;
AvatarWithDisplayName.displayName = 'AvatarWithDisplayName';
AvatarWithDisplayName.defaultProps = defaultProps;

export default compose(withWindowDimensions, withLocalize)(AvatarWithDisplayName);
export default withOnyx({
parentReportActions: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`,
canEvict: false,
},
})(AvatarWithDisplayName);
Loading

0 comments on commit 397a4f4

Please sign in to comment.