Skip to content

Commit

Permalink
Merge branch 'main' into fix/40316
Browse files Browse the repository at this point in the history
  • Loading branch information
nkdengineer committed Jun 17, 2024
2 parents febcc44 + df9689f commit 248662d
Show file tree
Hide file tree
Showing 101 changed files with 818 additions and 603 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const restrictedImportPaths = [
name: 'date-fns/locale',
message: "Do not import 'date-fns/locale' directly. Please use the submodule import instead, like 'date-fns/locale/en-GB'.",
},
{
name: 'expensify-common',
importNames: ['Device'],
message: "Do not import Device directly, it's known to make VSCode's IntelliSense crash. Please import the desired module from `expensify-common/dist/Device` instead.",
},
];

const restrictedImportPatterns = [
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001048301
versionName "1.4.83-1"
versionCode 1001048400
versionName "1.4.84-0"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
46 changes: 0 additions & 46 deletions contributingGuides/STYLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
- [Forwarding refs](#forwarding-refs)
- [Hooks and HOCs](#hooks-and-hocs)
- [Stateless components vs Pure Components vs Class based components vs Render Props](#stateless-components-vs-pure-components-vs-class-based-components-vs-render-props---when-to-use-what)
- [Composition](#composition)
- [Use Refs Appropriately](#use-refs-appropriately)
- [Are we allowed to use [insert brand new React feature]?](#are-we-allowed-to-use-insert-brand-new-react-feature-why-or-why-not)
- [React Hooks: Frequently Asked Questions](#react-hooks-frequently-asked-questions)
Expand Down Expand Up @@ -1094,51 +1093,6 @@ Class components are DEPRECATED. Use function components and React hooks.

[https://react.dev/reference/react/Component#migrating-a-component-with-lifecycle-methods-from-a-class-to-a-function](https://react.dev/reference/react/Component#migrating-a-component-with-lifecycle-methods-from-a-class-to-a-function)

### Composition

Avoid the usage of `compose` function to compose HOCs in TypeScript files. Use nesting instead.

> Why? `compose` function doesn't work well with TypeScript when dealing with several HOCs being used in a component, many times resulting in wrong types and errors. Instead, nesting can be used to allow a seamless use of multiple HOCs and result in a correct return type of the compoment. Also, you can use [hooks instead of HOCs](#hooks-instead-of-hocs) whenever possible to minimize or even remove the need of HOCs in the component.

From React's documentation -
>Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.
>If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or a class, without extending it.

```ts
// BAD
export default compose(
withCurrentUserPersonalDetails,
withReportOrNotFound(),
withOnyx<ComponentProps, ComponentOnyxProps>({
session: {
key: ONYXKEYS.SESSION,
},
}),
)(Component);

// GOOD
export default withCurrentUserPersonalDetails(
withReportOrNotFound()(
withOnyx<ComponentProps, ComponentOnyxProps>({
session: {
key: ONYXKEYS.SESSION,
},
})(Component),
),
);

// GOOD - alternative to HOC nesting
const ComponentWithOnyx = withOnyx<ComponentProps, ComponentOnyxProps>({
session: {
key: ONYXKEYS.SESSION,
},
})(Component);
const ComponentWithReportOrNotFound = withReportOrNotFound()(ComponentWithOnyx);
export default withCurrentUserPersonalDetails(ComponentWithReportOrNotFound);
```

**Note:** If you find that none of these approaches work for you, please ask an Expensify engineer for guidance via Slack or GitHub.

### Use Refs Appropriately

React's documentation explains refs in [detail](https://reactjs.org/docs/refs-and-the-dom.html). It's important to understand when to use them and how to use them to avoid bugs and hard to maintain code.
Expand Down
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.83</string>
<string>1.4.84</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.83.1</string>
<string>1.4.84.0</string>
<key>FullStory</key>
<dict>
<key>OrgId</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.83</string>
<string>1.4.84</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.83.1</string>
<string>1.4.84.0</string>
</dict>
</plist>
4 changes: 2 additions & 2 deletions ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.83</string>
<string>1.4.84</string>
<key>CFBundleVersion</key>
<string>1.4.83.1</string>
<string>1.4.84.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
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.83-1",
"version": "1.4.84-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
5 changes: 4 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ const ROUTES = {
SETTINGS_PRONOUNS: 'settings/profile/pronouns',
SETTINGS_PREFERENCES: 'settings/preferences',
SETTINGS_SUBSCRIPTION: 'settings/subscription',
SETTINGS_SUBSCRIPTION_SIZE: 'settings/subscription/subscription-size',
SETTINGS_SUBSCRIPTION_SIZE: {
route: 'settings/subscription/subscription-size',
getRoute: (canChangeSize: 0 | 1) => `settings/subscription/subscription-size?canChangeSize=${canChangeSize}` as const,
},
SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD: 'settings/subscription/add-payment-card',
SETTINGS_SUBSCRIPTION_DISABLE_AUTO_RENEW_SURVEY: 'settings/subscription/disable-auto-renew-survey',
SETTINGS_PRIORITY_MODE: 'settings/preferences/priority-mode',
Expand Down
12 changes: 6 additions & 6 deletions src/components/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ type AvatarProps = {
/** Used to locate fallback icon in end-to-end tests. */
fallbackIconTestID?: string;

/** Denotes whether it is an avatar or a workspace avatar */
type?: AvatarType;

/** Owner of the avatar. If user, displayName. If workspace, policy name */
name?: string;

/** Denotes whether it is an avatar or a workspace avatar */
type: AvatarType;

/** Optional account id if it's user avatar or policy id if it's workspace avatar */
avatarID?: number | string;
};
Expand All @@ -64,7 +64,7 @@ function Avatar({
fill,
fallbackIcon = Expensicons.FallbackAvatar,
fallbackIconTestID = '',
type = CONST.ICON_TYPE_AVATAR,
type,
name = '',
avatarID,
}: AvatarProps) {
Expand All @@ -80,9 +80,9 @@ function Avatar({
}, [originalSource]);

const isWorkspace = type === CONST.ICON_TYPE_WORKSPACE;
const userAccountID = isWorkspace ? undefined : (avatarID as number);

// If it's user avatar then accountID will be a number
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, avatarID as number);
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, userAccountID);
const useFallBackAvatar = imageError || !source || source === Expensicons.FallbackAvatar;
const fallbackAvatar = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatar(name) : fallbackIcon || Expensicons.FallbackAvatar;
const fallbackAvatarTestID = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatarTestID(name) : fallbackIconTestID || 'SvgFallbackAvatar Icon';
Expand Down
1 change: 1 addition & 0 deletions src/components/AvatarWithIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function AvatarWithIndicator({source, accountID, tooltipText = '', fallbackIcon
source={UserUtils.getSmallSizeAvatar(source, accountID)}
fallbackIcon={fallbackIcon}
avatarID={accountID}
type={CONST.ICON_TYPE_AVATAR}
/>
<Indicator />
</>
Expand Down
5 changes: 0 additions & 5 deletions src/components/CustomStatusBarAndBackground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,6 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
[prevIsRootStatusBarEnabled, isRootStatusBarEnabled, statusBarAnimation, statusBarStyle, theme.PAGE_THEMES, theme.appBG, theme.statusBarStyle],
);

useEffect(() => {
updateStatusBarAppearance({backgroundColor: theme.appBG});
// eslint-disable-next-line react-hooks/exhaustive-deps -- we only want this to run on first render
}, []);

useEffect(() => {
didForceUpdateStatusBarRef.current = false;
}, [isRootStatusBarEnabled]);
Expand Down
2 changes: 1 addition & 1 deletion src/components/FocusTrap/FocusTrapForModal/index.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function FocusTrapForModal({children, active}: FocusTrapForModalProps) {
focusTrapOptions={{
trapStack: sharedTrapStack,
allowOutsideClick: true,
fallbackFocus: document.body,
initialFocus: false,
}}
>
{children}
Expand Down
1 change: 1 addition & 0 deletions src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [
SCREENS.SETTINGS.WALLET.ROOT,
SCREENS.SETTINGS.ABOUT,
SCREENS.SETTINGS.WORKSPACES,
SCREENS.SETTINGS.SUBSCRIPTION.ROOT,
SCREENS.WORKSPACE.INITIAL,
SCREENS.WORKSPACE.PROFILE,
SCREENS.WORKSPACE.CARD,
Expand Down
74 changes: 45 additions & 29 deletions src/components/LHNOptionsList/LHNOptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import LottieAnimations from '@components/LottieAnimations';
import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
import Text from '@components/Text';
import TextBlock from '@components/TextBlock';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import usePrevious from '@hooks/usePrevious';
Expand Down Expand Up @@ -61,36 +61,52 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio

const emptyLHNSubtitle = useMemo(
() => (
<View>
<Text
color={theme.placeholderText}
style={[styles.textAlignCenter]}
>
{translate('common.emptyLHN.subtitleText1')}
<Icon
src={Expensicons.MagnifyingGlass}
width={variables.emptyLHNIconWidth}
height={variables.emptyLHNIconHeight}
small
inline
fill={theme.icon}
additionalStyles={styles.alignItemsCenter}
/>
{translate('common.emptyLHN.subtitleText2')}
<Icon
src={Expensicons.Plus}
width={variables.emptyLHNIconWidth}
height={variables.emptyLHNIconHeight}
small
inline
fill={theme.icon}
additionalStyles={styles.alignItemsCenter}
/>
{translate('common.emptyLHN.subtitleText3')}
</Text>
<View style={[styles.alignItemsCenter, styles.flexRow, styles.justifyContentCenter, styles.flexWrap, styles.textAlignCenter]}>
<TextBlock
color={theme.textSupporting}
textStyles={[styles.textAlignCenter, styles.textNormal]}
text={translate('common.emptyLHN.subtitleText1')}
/>
<Icon
src={Expensicons.MagnifyingGlass}
width={variables.emptyLHNIconWidth}
height={variables.emptyLHNIconHeight}
fill={theme.icon}
small
additionalStyles={styles.mh1}
/>
<TextBlock
color={theme.textSupporting}
textStyles={[styles.textAlignCenter, styles.textNormal]}
text={translate('common.emptyLHN.subtitleText2')}
/>
<Icon
src={Expensicons.Plus}
width={variables.emptyLHNIconWidth}
height={variables.emptyLHNIconHeight}
fill={theme.icon}
small
additionalStyles={styles.mh1}
/>
<TextBlock
color={theme.textSupporting}
textStyles={[styles.textAlignCenter, styles.textNormal]}
text={translate('common.emptyLHN.subtitleText3')}
/>
</View>
),
[theme, styles.alignItemsCenter, styles.textAlignCenter, translate],
[
styles.alignItemsCenter,
styles.flexRow,
styles.justifyContentCenter,
styles.flexWrap,
styles.textAlignCenter,
styles.mh1,
theme.icon,
theme.textSupporting,
styles.textNormal,
translate,
],
);

/**
Expand Down
14 changes: 6 additions & 8 deletions src/components/LHNOptionsList/OptionRowLHN.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {useFocusEffect} from '@react-navigation/native';
import {ExpensiMark} from 'expensify-common';
import React, {useCallback, useRef, useState} from 'react';
import type {GestureResponderEvent, ViewStyle} from 'react-native';
import {StyleSheet, View} from 'react-native';
Expand All @@ -21,6 +20,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
import DomUtils from '@libs/DomUtils';
import {parseHtmlToText} from '@libs/OnyxAwareParser';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import Performance from '@libs/Performance';
import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
Expand All @@ -31,8 +31,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {OptionRowLHNProps} from './types';

const parser = new ExpensiMark();

function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', style, onLayout = () => {}, hasDraftComment}: OptionRowLHNProps) {
const theme = useTheme();
const styles = useThemeStyles();
Expand Down Expand Up @@ -187,17 +185,17 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
>
<View style={sidebarInnerRowStyle}>
<View style={[styles.flexRow, styles.alignItemsCenter]}>
{(optionItem.icons?.length ?? 0) > 0 &&
{!!optionItem.icons?.length &&
(optionItem.shouldShowSubscript ? (
<SubscriptAvatar
backgroundColor={hovered && !isFocused ? hoveredBackgroundColor : subscriptAvatarBorderColor}
mainAvatar={optionItem.icons?.[0]}
secondaryAvatar={optionItem.icons?.[1]}
mainAvatar={optionItem.icons[0]}
secondaryAvatar={optionItem.icons[1]}
size={isInFocusMode ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT}
/>
) : (
<MultipleAvatars
icons={optionItem.icons ?? []}
icons={optionItem.icons}
isFocusMode={isInFocusMode}
size={isInFocusMode ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT}
secondAvatarStyle={[
Expand Down Expand Up @@ -243,7 +241,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
numberOfLines={1}
accessibilityLabel={translate('accessibilityHints.lastChatMessagePreview')}
>
{parser.htmlToText(optionItem.alternateText)}
{parseHtmlToText(optionItem.alternateText)}
</Text>
) : null}
</View>
Expand Down
Loading

0 comments on commit 248662d

Please sign in to comment.