Skip to content

Commit

Permalink
Merge branch 'main' into ci/hash-branch-name
Browse files Browse the repository at this point in the history
  • Loading branch information
staszekscp committed Dec 13, 2022
2 parents e8c8d4f + 07e37a7 commit 5662cd6
Show file tree
Hide file tree
Showing 73 changed files with 887 additions and 390 deletions.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ This is a checklist for PR authors. Please make sure to complete all tasks and c
- [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/StyleUtils.js) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG`)
- [ ] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases)
- [ ] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
- [ ] If a new page is added, I verified it's using the `ScrollView` component to make it scrollable when more elements are added to the page.
- [ ] I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

### Screenshots/Videos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,11 @@ function getMergeLogsAsJSON(fromRef, toRef) {
sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '');

// Then format as JSON and convert to a proper JS object
const json = `[${sanitizedOutput}]`.replace('},]', '}]');
const json = `[${sanitizedOutput}]`.replace('},]', '}]')

// Escape backslashes in commit messages that end with a backslash
.replace('\\"}', '\\\\"}');

return JSON.parse(json);
});
}
Expand Down
6 changes: 5 additions & 1 deletion .github/actions/javascript/getDeployPullRequestList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ function getMergeLogsAsJSON(fromRef, toRef) {
sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '');

// Then format as JSON and convert to a proper JS object
const json = `[${sanitizedOutput}]`.replace('},]', '}]');
const json = `[${sanitizedOutput}]`.replace('},]', '}]')

// Escape backslashes in commit messages that end with a backslash
.replace('\\"}', '\\\\"}');

return JSON.parse(json);
});
}
Expand Down
6 changes: 5 additions & 1 deletion .github/libs/GitUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ function getMergeLogsAsJSON(fromRef, toRef) {
sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '');

// Then format as JSON and convert to a proper JS object
const json = `[${sanitizedOutput}]`.replace('},]', '}]');
const json = `[${sanitizedOutput}]`.replace('},]', '}]')

// Escape backslashes in commit messages that end with a backslash
.replace('\\"}', '\\\\"}');

return JSON.parse(json);
});
}
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/buildActions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do

# Build the action in the background
ncc build "$ACTION" -o "$ACTION_DIR" &
ASYNC_BUILDS[$i]=$!
ASYNC_BUILDS[i]=$!
done

for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do
ACTION=${GITHUB_ACTIONS[$i]}
ACTION_DIR=$(dirname "$ACTION")

# Wait for the background build to finish
wait ${ASYNC_BUILDS[$i]}
wait "${ASYNC_BUILDS[$i]}"

# Prepend the warning note to the top of the compiled file
OUTPUT_FILE="$ACTION_DIR/index.js"
Expand Down
6 changes: 3 additions & 3 deletions .github/scripts/validateActionsAndWorkflows.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ info 'Validating actions and workflows against their JSON schemas...'
for ((i=0; i < ${#ACTIONS[@]}; i++)); do
ACTION=${ACTIONS[$i]}
ajv -s ./tempSchemas/github-action.json -d "$ACTION" --strict=false &
ASYNC_PROCESSES[$i]=$!
ASYNC_PROCESSES[i]=$!
done

for ((i=0; i < ${#WORKFLOWS[@]}; i++)); do
Expand All @@ -48,12 +48,12 @@ for ((i=0; i < ${#WORKFLOWS[@]}; i++)); do
fi

ajv -s ./tempSchemas/github-workflow.json -d "$WORKFLOW" --strict=false &
ASYNC_PROCESSES[${#ACTIONS[@]} + $i]=$!
ASYNC_PROCESSES[${#ACTIONS[@]} + i]=$!
done

# Wait for the background builds to finish
for PID in "${ASYNC_PROCESSES[@]}"; do
wait $PID
wait "$PID"
RESULT=$?
if [[ $RESULT != 0 ]]; then
EXIT_CODE=$RESULT
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001023700
versionName "1.2.37-0"
versionCode 1001023806
versionName "1.2.38-6"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()

if (isNewArchitectureEnabled()) {
Expand Down
2 changes: 1 addition & 1 deletion contributingGuides/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ This is the most common scenario for contributors. The Expensify team posts new
#### Proposing a job that Expensify hasn't posted
It’s possible that you found a new bug or new feature that we haven’t posted as a job to the [GitHub repository](https://github.com/Expensify/App/issues?q=is%3Aissue). This is an opportunity to propose a job, and (optionally) a solution for that job. If it's a valid job proposal that we choose to implement by deploying it to production — either internally or via an external contributor — then we will compensate you $250 for identifying and proposing the bug or feature. If the bug or feature is fixed by a PR that is not associated with your proposal, then you will not be eligible for the corresponding compensation unless you can find the PR that fixed it and prove your proposal came first.
- Note: If you get assigned the job you proposed **and** you complete the job, this $250 for identifying the improvement is *in addition to* the reward you will be paid for completing the job.
- Note about proposed bugs or features: Expensify has the right not to pay the $250 reward if the suggested bug or feature is already planned. Currently, Expensify plans to implement all features of the old Expensify app in New Expensify.
- Note about proposed bugs or features: Expensify has the right not to pay the $250 reward if the suggested bug has already been reported or the feature request is already planned. Following, if more than one contributor proposes the same bug, the contributor who posted it first is the one who is eligible for the bonus.
- Note: whilst you may optionally propose a solution for that job on Slack, solutions are ultimately reviewed in GitHub. The onus is on you to propose the solution on GitHub, and/or ensure the issue creator will include a link to your proposal.

Please follow these steps to propose a job:
Expand Down
1 change: 1 addition & 0 deletions contributingGuides/REVIEWER_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/StyleUtils.js) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG`)
- [ ] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases)
- [ ] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
- [ ] If a new page is added, I verified it's using the `ScrollView` component to make it scrollable when more elements are added to the page.
- [ ] I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

### Screenshots/Videos
Expand Down
4 changes: 2 additions & 2 deletions ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.2.37</string>
<string>1.2.38</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -30,7 +30,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.2.37.0</string>
<string>1.2.38.6</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.2.37</string>
<string>1.2.38</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.2.37.0</string>
<string>1.2.38.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.2.37-0",
"version": "1.2.38-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
2 changes: 1 addition & 1 deletion src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ const CONST = {
},
RESERVED_ROOM_NAMES: ['#admins', '#announce'],
MAX_PREVIEW_AVATARS: 4,
MAX_ROOM_NAME_LENGTH: 80,
MAX_ROOM_NAME_LENGTH: 79,
LAST_MESSAGE_TEXT_MAX_LENGTH: 200,
OWNER_EMAIL_FAKE: '__FAKE__',
DEFAULT_REPORT_NAME: 'Chat Report',
Expand Down
4 changes: 4 additions & 0 deletions src/components/AttachmentPicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class AttachmentPicker extends React.Component {
// Cleanup after selecting a file to start from a fresh state
this.fileInput.value = null;
}}

// We are stopping the event propagation because triggering the `click()` on the hidden input
// causes the event to unexpectedly bubble up to anything wrapping this component e.g. Pressable
onClick={e => e.stopPropagation()}
accept={getAcceptableFileTypes(this.props.type)}
/>
{this.props.children({
Expand Down
15 changes: 14 additions & 1 deletion src/components/Avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import CONST from '../CONST';
import * as StyleUtils from '../styles/StyleUtils';
import * as Expensicons from './Icon/Expensicons';
import getAvatarDefaultSource from '../libs/getAvatarDefaultSource';
import {withNetwork} from './OnyxProvider';
import networkPropTypes from './networkPropTypes';
import styles from '../styles/styles';

const propTypes = {
Expand All @@ -30,6 +32,9 @@ const propTypes = {

/** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */
fallbackIcon: PropTypes.func,

/** Props to detect online status */
network: networkPropTypes.isRequired,
};

const defaultProps = {
Expand All @@ -49,6 +54,14 @@ class Avatar extends PureComponent {
};
}

componentDidUpdate(prevProps) {
const isReconnecting = prevProps.network.isOffline && !this.props.network.isOffline;
if (!this.state.imageError || !isReconnecting) {
return;
}
this.setState({imageError: false});
}

render() {
if (!this.props.source) {
return null;
Expand Down Expand Up @@ -94,4 +107,4 @@ class Avatar extends PureComponent {

Avatar.defaultProps = defaultProps;
Avatar.propTypes = propTypes;
export default Avatar;
export default withNetwork()(Avatar);
2 changes: 1 addition & 1 deletion src/components/AvatarCropModal/AvatarCropModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ const AvatarCropModal = (props) => {
translateX={translateX}
rotation={rotation}
/>
<View style={[styles.mt5, styles.justifyContentBetween, styles.alignItemsCenter, styles.flexRow, StyleUtils.getWidthAndHeightStyle(imageContainerSize)]}>
<View style={[styles.mt5, styles.justifyContentBetween, styles.alignItemsCenter, styles.flexRow, StyleUtils.getWidthStyle(imageContainerSize)]}>
<Icon src={Expensicons.Zoom} fill={themeColors.icons} />
<Pressable
style={[styles.mh5, styles.flex1]}
Expand Down
14 changes: 9 additions & 5 deletions src/components/ContextMenuItem.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Pressable} from 'react-native';
import {Pressable, View} from 'react-native';
import MenuItem from './MenuItem';
import Tooltip from './Tooltip';
import Icon from './Icon';
import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import getButtonState from '../libs/getButtonState';
import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState';
import variables from '../styles/variables';

const propTypes = {
/** Icon Component */
Expand Down Expand Up @@ -87,10 +88,13 @@ class ContextMenuItem extends Component {
}
>
{({hovered, pressed}) => (
<Icon
src={icon}
fill={StyleUtils.getIconFillColor(getButtonState(hovered, pressed, this.props.isDelayButtonStateComplete))}
/>
<View style={[StyleUtils.getWidthAndHeightStyle(variables.iconSizeNormal), styles.alignItemsCenter, styles.justifyContentCenter]}>
<Icon
small
src={icon}
fill={StyleUtils.getIconFillColor(getButtonState(hovered, pressed, this.props.isDelayButtonStateComplete))}
/>
</View>
)}
</Pressable>
</Tooltip>
Expand Down
14 changes: 10 additions & 4 deletions src/components/CurrencySymbolButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,30 @@ import {TouchableOpacity} from 'react-native';
import PropTypes from 'prop-types';
import Text from './Text';
import styles from '../styles/styles';
import Tooltip from './Tooltip';
import withLocalize, {withLocalizePropTypes} from './withLocalize';

const propTypes = {
/** Currency symbol of selected currency */
currencySymbol: PropTypes.string.isRequired,

/** Function to call when currency button is pressed */
onCurrencyButtonPress: PropTypes.func.isRequired,

...withLocalizePropTypes,
};

function CurrencySymbolButton(props) {
return (
<TouchableOpacity onPress={props.onCurrencyButtonPress}>
<Text style={styles.iouAmountText}>{props.currencySymbol}</Text>
</TouchableOpacity>
<Tooltip text={props.translate('iOUCurrencySelection.selectCurrency')}>
<TouchableOpacity onPress={props.onCurrencyButtonPress}>
<Text style={styles.iouAmountText}>{props.currencySymbol}</Text>
</TouchableOpacity>
</Tooltip>
);
}

CurrencySymbolButton.propTypes = propTypes;
CurrencySymbolButton.displayName = 'CurrencySymbolButton';

export default CurrencySymbolButton;
export default withLocalize(CurrencySymbolButton);
35 changes: 7 additions & 28 deletions src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ class Form extends React.Component {

this.inputRefs = {};
this.touchedInputs = {};
this.childPosition = {};

this.setTouchedInput = this.setTouchedInput.bind(this);
this.validate = this.validate.bind(this);
Expand Down Expand Up @@ -109,21 +108,6 @@ class Form extends React.Component {
return _.first(_.keys(hasStateErrors ? this.state.erorrs : this.props.formState.errorFields));
}

setPosition(element, position) {
// Some elements might not have props defined, e.g. Text
if (!element.props) {
return;
}

if (!element.props.inputID && element.props.children) {
_.forEach(element.props.children, (child) => {
this.setPosition(child, position);
});
} else {
this.childPosition[element.props.inputID] = position;
}
}

submit() {
// Return early if the form is already submitting to avoid duplicate submission
if (this.props.formState.isLoading) {
Expand Down Expand Up @@ -268,16 +252,7 @@ class Form extends React.Component {
ref={el => this.form = el}
>
<View style={[this.props.style]}>
{_.map(this.childrenWrapperWithProps(this.props.children), child => (
<View
key={child.key}
onLayout={(event) => {
this.setPosition(child, event.nativeEvent.layout.y);
}}
>
{child}
</View>
))}
{this.childrenWrapperWithProps(this.props.children)}
{this.props.isSubmitButtonVisible && (
<FormAlertWithSubmitButton
buttonText={this.props.submitButtonText}
Expand All @@ -289,12 +264,16 @@ class Form extends React.Component {
const errors = !_.isEmpty(this.state.errors) ? this.state.errors : this.props.formState.errorFields;
const focusKey = _.find(_.keys(this.inputRefs), key => _.keys(errors).includes(key));
const focusInput = this.inputRefs[focusKey];
this.form.scrollTo({y: this.childPosition[focusKey], animated: false});
if (focusInput.focus && typeof focusInput.focus === 'function') {
focusInput.focus();
}

// We substract 10 to scroll slightly above the input
if (focusInput.measureLayout && typeof focusInput.measureLayout === 'function') {
focusInput.measureLayout(this.form, (x, y) => this.form.scrollTo({y: y - 10, animated: false}));
}
}}
containerStyles={[styles.mh0, styles.mt5]}
containerStyles={[styles.mh0, styles.mt5, styles.flex1]}
enabledWhenOffline={this.props.enabledWhenOffline}
isDangerousAction={this.props.isDangerousAction}
/>
Expand Down
5 changes: 3 additions & 2 deletions src/components/Modal/BaseModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import themeColors from '../../styles/themes/default';
import {propTypes as modalPropTypes, defaultProps as modalDefaultProps} from './modalPropTypes';
import * as Modal from '../../libs/actions/Modal';
import getModalStyles from '../../styles/getModalStyles';
import variables from '../../styles/variables';

const propTypes = {
...modalPropTypes,
Expand Down Expand Up @@ -100,8 +101,8 @@ class BaseModal extends PureComponent {
onSwipeComplete={this.props.onClose}
swipeDirection={swipeDirection}
isVisible={this.props.isVisible}
backdropColor={themeColors.modalBackdrop}
backdropOpacity={hideBackdrop ? 0 : 0.5}
backdropColor={themeColors.overlay}
backdropOpacity={hideBackdrop ? 0 : variables.overlayOpacity}
backdropTransitionOutTiming={0}
hasBackdrop={this.props.fullscreen}
coverScreen={this.props.fullscreen}
Expand Down
Loading

0 comments on commit 5662cd6

Please sign in to comment.