Skip to content

Commit

Permalink
Merge branch 'main' of github.com:mananjadhav/App into feat/ghost-screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mananjadhav committed Jul 28, 2022
2 parents 80671e6 + 84c2435 commit 719a477
Show file tree
Hide file tree
Showing 61 changed files with 1,422 additions and 1,190 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001018601
versionName "1.1.86-1"
versionCode 1001018605
versionName "1.1.86-5"
}
splits {
abi {
Expand Down
2 changes: 2 additions & 0 deletions contributingGuides/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Payment for your contributions will be made no less than 7 days after the pull r

New contributors are limited to working on one job at a time, however experienced contributors may work on numerous jobs simultaneously.

Please be aware that compensation for any support in solving an issue is provided **entirely at Expensify’s discretion**. Personal time or resources applied towards investigating a proposal **will not guarantee compensation**. Compensation is only guaranteed to those who **[propose a solution and get hired for that job](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job)**. We understand there may be cases where a selected proposal may take inspiration from a previous proposal. Unfortunately, it’s not possible for us to evaluate every individual case and we have no process that can efficiently do so. Issues with higher rewards come with higher risk factors so try to keep things civil and make the best proposal you can. Once again, **any information provided may not necessarily lead to you getting hired for that issue or compensated in any way.**

## Finding Jobs
There are two ways you can find a job that you can contribute to:

Expand Down
8 changes: 8 additions & 0 deletions desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Testing the auto-update process can be a little involved. The most effective way

**Note:** In order to test with a notarized build you'll need to have a paid Apple developer account.

You can inspect auto update related logs in the log file at `~/Library/Logs/new.expensify.desktop/main.log`

## Setting up Min.IO
Rather than pushing new builds to the production S3 bucket, the best way to test locally is to use [Min.IO](https://min.io). Min.IO is an S3-compatible service that you can set up and deploy locally. In order to set up a local Min.IO instance to emulate an S3 bucket, follow these steps:

Expand Down Expand Up @@ -139,3 +141,9 @@ To see the actual `app.asar` content run the following script
npx asar extract desktop-build/mac/New\ Expensify.app/Contents/Resources/app.asar ./unpacked-asar
```
The expected size of `app.asar` = `desktop/dist/www/` + `desktop/node_modules/`;


# Logging

- `main` process logs are written to `~/Library/Logs/new.expensify.desktop/main.log`
- `renderer` logs can be observed live in the developer console (⌘ Cmd + ⌥ Option + I)
4 changes: 2 additions & 2 deletions desktop/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ app.commandLine.appendSwitch('enable-network-information-downlink-max');
// See https://github.com/sindresorhus/electron-context-menu
contextMenu();

// Send all autoUpdater logs to a log file: ~/Library/Logs/new.expensify/main.log
// Send all autoUpdater logs to a log file: ~/Library/Logs/new.expensify.desktop/main.log
// See https://www.npmjs.com/package/electron-log
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';

// Send all Console logs to a log file: ~/Library/Logs/new.expensify/main.log
// Send all Console logs to a log file: ~/Library/Logs/new.expensify.desktop/main.log
// See https://www.npmjs.com/package/electron-log
_.assign(console, log.functions);

Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.1.86.1</string>
<string>1.1.86.5</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.1.86.1</string>
<string>1.1.86.5</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion 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.1.86-1",
"version": "1.1.86-5",
"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
16 changes: 14 additions & 2 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,17 @@ const CONST = {
ANDROID_PACKAGE_NAME,
ANIMATED_TRANSITION: 300,

// 50 megabytes in bytes
API_MAX_ATTACHMENT_SIZE: 52428800,
API_ATTACHMENT_VALIDATIONS: {
// Same as the PHP layer allows
ALLOWED_EXTENSIONS: ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'html', 'txt', 'rtf', 'doc', 'docx', 'htm', 'tiff', 'tif', 'xml'],

// 50 megabytes in bytes
MAX_SIZE: 52428800,

// An arbitrary size, but the same minimum as in the PHP layer
MIN_SIZE: 240,
},

AVATAR_MAX_ATTACHMENT_SIZE: 6291456,
NEW_EXPENSIFY_URL: ACTIVE_EXPENSIFY_URL,
APP_DOWNLOAD_LINKS: {
Expand Down Expand Up @@ -106,6 +115,7 @@ const CONST = {
FREE_PLAN: 'freePlan',
DEFAULT_ROOMS: 'defaultRooms',
BETA_EXPENSIFY_WALLET: 'expensifyWallet',
BETA_COMMENT_LINKING: 'commentLinking',
INTERNATIONALIZATION: 'internationalization',
IOU_SEND: 'sendMoney',
POLICY_ROOMS: 'policyRooms',
Expand Down Expand Up @@ -686,6 +696,7 @@ const CONST = {
CARD_SECURITY_CODE: /^[0-9]{3,4}$/,
CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/,
PAYPAL_ME_USERNAME: /^[a-zA-Z0-9]+$/,
RATE_VALUE: /^\d{1,8}(\.\d*)?$/,

// Adapted from: https://gist.github.com/dperini/729294
// eslint-disable-next-line max-len
Expand Down Expand Up @@ -742,6 +753,7 @@ const CONST = {
SET: 'set',
},
},
MICROSECONDS_PER_MS: 1000,
};

export default CONST;
5 changes: 3 additions & 2 deletions src/components/AddPlaidBankAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ class AddPlaidBankAccount extends React.Component {
<ActivityIndicator color={themeColors.spinner} size="large" />
</View>
)}
{this.props.plaidData.error && (
{Boolean(this.props.plaidData.error) && (
<Text style={[styles.formError, styles.mh5]}>
{this.props.plaidData.error}
</Text>
)}
{token && (
{Boolean(token) && (
<PlaidLink
token={token}
onSuccess={({publicToken, metadata}) => {
Expand Down Expand Up @@ -217,6 +217,7 @@ export default compose(
},
plaidLinkToken: {
key: ONYXKEYS.PLAID_LINK_TOKEN,
initWithStoredValues: false,
},
}),
)(AddPlaidBankAccount);
126 changes: 88 additions & 38 deletions src/components/AttachmentModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {View} from 'react-native';
import Str from 'expensify-common/lib/str';
import lodashGet from 'lodash/get';
import _ from 'lodash';
import lodashExtend from 'lodash/extend';
import _ from 'underscore';
import CONST from '../CONST';
import Modal from './Modal';
import AttachmentView from './AttachmentView';
Expand Down Expand Up @@ -71,15 +72,17 @@ class AttachmentModal extends PureComponent {

this.state = {
isModalOpen: false,
isConfirmModalOpen: false,
isAttachmentInvalid: false,
attachmentInvalidReasonTitle: null,
attachmentInvalidReason: null,
file: null,
sourceURL: props.sourceURL,
modalType: CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE,
};

this.submitAndClose = this.submitAndClose.bind(this);
this.closeConfirmModal = this.closeConfirmModal.bind(this);
this.isValidSize = this.isValidSize.bind(this);
this.validateAndDisplayFileToUpload = this.validateAndDisplayFileToUpload.bind(this);
}

/**
Expand All @@ -89,22 +92,30 @@ class AttachmentModal extends PureComponent {
* @returns {String}
*/
getModalType(sourceUrl, file) {
const modalType = (sourceUrl
&& (Str.isPDF(sourceUrl) || (file && Str.isPDF(file.name || this.props.translate('attachmentView.unknownFilename')))))
return (
sourceUrl
&& (
Str.isPDF(sourceUrl)
|| (
file
&& Str.isPDF(file.name || this.props.translate('attachmentView.unknownFilename'))
)
)
)
? CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE
: CONST.MODAL.MODAL_TYPE.CENTERED;
return modalType;
}

/**
* Returns the filename split into fileName and fileExtension
*
* @param {String} fullFileName
* @returns {Object}
*/
splitExtensionFromFileName() {
const fullFileName = this.props.originalFileName ? this.props.originalFileName.trim() : lodashGet(this.state, 'file.name', '').trim();
const splittedFileName = fullFileName.split('.');
const fileExtension = splittedFileName.pop();
const fileName = splittedFileName.join('.');
splitExtensionFromFileName(fullFileName) {
const fileName = fullFileName.trim();
const splitFileName = fileName.split('.');
const fileExtension = splitFileName.pop();
return {fileName, fileExtension};
}

Expand All @@ -118,7 +129,7 @@ class AttachmentModal extends PureComponent {
}

if (this.props.onConfirm) {
this.props.onConfirm(_.extend(this.state.file, {source: this.state.sourceURL}));
this.props.onConfirm(lodashExtend(this.state.file, {source: this.state.sourceURL}));
}

this.setState({isModalOpen: false});
Expand All @@ -128,16 +139,70 @@ class AttachmentModal extends PureComponent {
* Close the confirm modal.
*/
closeConfirmModal() {
this.setState({isConfirmModalOpen: false});
this.setState({isAttachmentInvalid: false});
}

/**
* Check if the attachment size is less than the API size limit.
* @param {Object} file
* @returns {Boolean}
*/
isValidSize(file) {
return !file || lodashGet(file, 'size', 0) < CONST.API_MAX_ATTACHMENT_SIZE;
isValidFile(file) {
if (lodashGet(file, 'size', 0) > CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE) {
this.setState({
isAttachmentInvalid: true,
attachmentInvalidReasonTitle: this.props.translate('attachmentPicker.attachmentTooLarge'),
attachmentInvalidReason: this.props.translate('attachmentPicker.sizeExceeded'),
});
return false;
}

if (lodashGet(file, 'size', 0) < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) {
this.setState({
isAttachmentInvalid: true,
attachmentInvalidReasonTitle: this.props.translate('attachmentPicker.attachmentTooSmall'),
attachmentInvalidReason: this.props.translate('attachmentPicker.sizeNotMet'),
});
return false;
}

const {fileExtension} = this.splitExtensionFromFileName(lodashGet(file, 'name', ''));
if (!_.contains(CONST.API_ATTACHMENT_VALIDATIONS.ALLOWED_EXTENSIONS, fileExtension)) {
const invalidReason = `${this.props.translate('attachmentPicker.notAllowedExtension')} ${CONST.API_ATTACHMENT_VALIDATIONS.ALLOWED_EXTENSIONS.join(', ')}`;
this.setState({
isAttachmentInvalid: true,
attachmentInvalidReasonTitle: this.props.translate('attachmentPicker.wrongFileType'),
attachmentInvalidReason: invalidReason,
});
return false;
}

return true;
}

/**
* @param {Object} file
*/
validateAndDisplayFileToUpload(file) {
if (!file) {
return;
}

if (!this.isValidFile(file)) {
return;
}

if (file instanceof File) {
const source = URL.createObjectURL(file);
const modalType = this.getModalType(source, file);
this.setState({
isModalOpen: true, sourceURL: source, file, modalType,
});
} else {
const modalType = this.getModalType(file.uri, file);
this.setState({
isModalOpen: true, sourceURL: file.uri, file, modalType,
});
}
}

render() {
Expand All @@ -149,7 +214,7 @@ class AttachmentModal extends PureComponent {
? [styles.imageModalImageCenterContainer]
: [styles.imageModalImageCenterContainer, styles.p5];

const {fileName, fileExtension} = this.splitExtensionFromFileName();
const {fileName, fileExtension} = this.splitExtensionFromFileName(this.props.originalFileName || lodashGet(this.state, 'file.name', ''));

return (
<>
Expand Down Expand Up @@ -197,34 +262,19 @@ class AttachmentModal extends PureComponent {
/>
)}
</Modal>

<ConfirmModal
title={this.props.translate('attachmentPicker.attachmentTooLarge')}
title={this.state.attachmentInvalidReasonTitle}
onConfirm={this.closeConfirmModal}
onCancel={this.closeConfirmModal}
isVisible={this.state.isConfirmModalOpen}
prompt={this.props.translate('attachmentPicker.sizeExceeded')}
isVisible={this.state.isAttachmentInvalid}
prompt={this.state.attachmentInvalidReason}
confirmText={this.props.translate('common.close')}
shouldShowCancelButton={false}
/>

{this.props.children({
displayFileInModal: ({file}) => {
if (!this.isValidSize(file)) {
this.setState({isConfirmModalOpen: true});
return;
}
if (file instanceof File) {
const source = URL.createObjectURL(file);
const modalType = this.getModalType(source, file);
this.setState({
isModalOpen: true, sourceURL: source, file, modalType,
});
} else {
const modalType = this.getModalType(file.uri, file);
this.setState({
isModalOpen: true, sourceURL: file.uri, file, modalType,
});
}
},
displayFileInModal: this.validateAndDisplayFileToUpload,
show: () => {
this.setState({isModalOpen: true});
},
Expand Down
8 changes: 7 additions & 1 deletion src/components/Avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import themeColors from '../styles/themes/default';
import CONST from '../CONST';
import * as StyleUtils from '../styles/StyleUtils';
import * as Expensicons from './Icon/Expensicons';
import getAvatarDefaultSource from '../libs/getAvatarDefaultSource';

const propTypes = {
/** Source for the avatar. Can be a URL or an icon. */
Expand Down Expand Up @@ -70,7 +71,12 @@ class Avatar extends PureComponent {
/>
)
: (
<Image source={{uri: this.props.source}} style={imageStyle} onError={() => this.setState({imageError: true})} />
<Image
source={{uri: this.props.source}}
defaultSource={getAvatarDefaultSource(this.props.source)}
style={imageStyle}
onError={() => this.setState({imageError: true})}
/>
)}
</View>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/BigNumberPad.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class BigNumberPad extends React.Component {
style={[styles.flex1, marginLeft]}
text={column === '<' ? column : this.props.toLocaleDigit(column)}
onLongPress={() => this.handleLongPress(column)}
onPress={() => this.props.numberPressed(column === '<' ? column : this.props.toLocaleDigit(column))}
onPress={() => this.props.numberPressed(column)}
onPressIn={ControlSelection.block}
onPressOut={() => {
clearInterval(this.state.timer);
Expand Down
Loading

0 comments on commit 719a477

Please sign in to comment.