diff --git a/README.md b/README.md index d63b6b064532..d456c5e52af4 100644 --- a/README.md +++ b/README.md @@ -311,7 +311,7 @@ This application is built with the following principles. - The UI should never call any Onyx methods except for `Onyx.connect()`. That is the job of Actions (see next section). - The UI always triggers an Action when something needs to happen (eg. a person inputs data, the UI triggers an Action with this data). - The UI should be as flexible as possible when it comes to: - - Incomplete or missing data. Always assume data is incomplete or not there. For example, when a comment is pushed to the client from a pusher event, it's possible that Onyx does not have data for that report yet. That's OK. A partial report object is added to Onyx for the report key `report_1234 = {reportID: 1234, isUnread: true}`. Then there is code that monitors Onyx for reports with incomplete data, and calls `fetchChatReportsByIDs(1234)` to get the full data for that report. The UI should be able to gracefully handle the report object not being complete. In this example, the sidebar wouldn't display any report that does not have a report name. + - Incomplete or missing data. Always assume data is incomplete or not there. For example, when a comment is pushed to the client from a pusher event, it's possible that Onyx does not have data for that report yet. That's OK. A partial report object is added to Onyx for the report key `report_1234 = {reportID: 1234, isUnread: true}`. Then there is code that monitors Onyx for reports with incomplete data, and calls `openReport(1234)` to get the full data for that report. The UI should be able to gracefully handle the report object not being complete. In this example, the sidebar wouldn't display any report that does not have a report name. - The order that actions are done in. All actions should be done in parallel instead of sequence. - Parallel actions are asynchronous methods that don't return promises. Any number of these actions can be called at one time and it doesn't matter what order they happen in or when they complete. - In-Sequence actions are asynchronous methods that return promises. This is necessary when one asynchronous method depends on the results from a previous asynchronous method. Example: Making an XHR to `command=CreateChatReport` which returns a reportID which is used to call `command=Get&rvl=reportStuff`. diff --git a/android/app/build.gradle b/android/app/build.gradle index c6001ca26cb2..64ba323e74fd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001022404 - versionName "1.2.24-4" + versionCode 1001022600 + versionName "1.2.26-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md index 8e10fa3002e9..4743f8c418a4 100644 --- a/contributingGuides/CONTRIBUTING.md +++ b/contributingGuides/CONTRIBUTING.md @@ -39,6 +39,14 @@ New contributors are limited to working on one job at a time, however experience 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.** +**Important:** Payment amounts are variable, dependent on when your PR is merged. Your PR will be reviewed by a Contributor+ (C+) team member and an internal engineer. All tests must pass and all code must pass lint checks before a merge. + +**Payment timeline** all based on the day the contributor has an accepted proposal and is assigned to the Github issue +- Merged PR within 3 business days - 50% **bonus** +- Merged PR within 6 business days - 0% bonus +- Merged PR within 9 business days - 50% **penalty** +- No PR within 12 business days - **Contract terminated** + ## Finding Jobs There are two ways you can find a job that you can contribute to: diff --git a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md new file mode 100644 index 000000000000..1e950bbf1a63 --- /dev/null +++ b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md @@ -0,0 +1,27 @@ +## What is a Contributor+ (C+)? +C+ are contributors who are experienced at working with Expensify and have gained the confidence of the internal Expensify team. Accordingly, they are allocated additional opportunities and responsibilities: + - They review proposed solutions in external GitHub issues, validate them, and make recommendations to an internal Contributor Manager Engineer (CME). + - Once a proposal has been accepted by a CME, the C+ will be the first person to review the pull request associated with that proposal. + +## Why would someone want to be a C+ +- C+ are compensated the same price as the contributor for reviewing proposals and the associated PR. (ie. if a job is listed at $1000, that’s how much the C+ will make if they review both the proposals and PR). If regressions are found that should have* been caught after the PR has been approved, C+ payment is reduced by 50% for each regression found. + - * Should have = C+ should have caught the bug by fully following the PR checklist. If C+ skips a step or completed the checklist incompletely, payment will be cut in half. +- C+ can also work on jobs as a contributor +- Earning potential is variable, it depends on how much a C+ wants to work and other jobs they’re hired for. We’ve seen C+ make ~$100k/year. +- There isn’t a set number of hours a C+ needs to work in a week. Proposals and PRs reviews are expected to be addressed within 24 hours on weekdays. +- Dedicated #contributor-plus Slack room to discuss issues, processes and proposals. +- If C+ ever applies to work at Expensify, they’ve got a leg up on the competition because they're familiar with the company and processes. View job openings at https://we.are.expensify.com. + +## Requirements to join C+ +- Have had 10 PRs deployed to production without regressions. +- Follow our Code of Conduct, Contributing.md and README.md docs and processes. +- Comment and fix bugs in a timely manner. +- Clear communicator +- Bonus points: + - Help other contributors by commenting on their issues. + - Actively involved in the #expensify-open-source slack channel + - Adheres to the PR review guidelines + +## How to join? + +Email contributors@expensify.com and include "C+ Team Application" in the subject line if you’re interested in joining. diff --git a/docs/README.md b/docs/README.md index f7a7df509de7..c134b516238a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,7 +34,7 @@ bundle install The [docs](https://github.com/Expensify/App/tree/main/docs) folder will contain the following main folders: -- *_layouts*: Contains HTML templates used by Jekyll to create pages in the static site. For now it has only one file ([default.html](https://github.com/Expensify/App/blob/main/docs/_layouts/default.html)) which will render the common HTML elements and the assets on every page. +- *_layouts*: Contains HTML templates used by Jekyll to create pages in the static site. For now, it has only one file ([default.html](https://github.com/Expensify/App/blob/main/docs/_layouts/default.html)) which will render the common HTML elements and the assets on every page. - *_includes*: Contains HTML content that can be reused on different pages. [Includes](https://jekyllrb.com/docs/includes/) can accept parameters and be nested, so they are quite powerful. - *assets*: Contains the three sub-folders css, images, and js. The css folder can contain either .css or .sass files (where SASS files will be processed by Jekyll and it will generate a CSS file in an output folder also generated by Jekyll). - *hubs*: Contains hubs that display various related articles, optionally grouped by sub-topic within the hub. diff --git a/docs/_data/routes.yml b/docs/_data/routes.yml index 8e613030f3cb..6cebdefee5b1 100644 --- a/docs/_data/routes.yml +++ b/docs/_data/routes.yml @@ -1,13 +1,13 @@ home: href: home - title: Welcome to the New Expensify! + title: Welcome to ExpensifyHelp! description: Find the answers to all of your questions about receipts, expenses, corporate cards, or anything else in the spend management universe. # Hubs are comprised of sections and articles. Sections contain multiple related articles, but there can be standalone articles as well hubs: - href: send-money title: Send money - description: With only a couple of clicks, send money to your friends or coworkers using NewExpensify. + description: With only a couple of clicks, send money to your friends or coworkers. icon: /assets/images/send.svg articles: - href: Request-and-Send-Money @@ -27,7 +27,7 @@ hubs: - href: request-money title: Request money icon: /assets/images/money-circle.svg - description: Request money for work expenses, bills, or a night out with friends using NewExpensify. + description: Request money for work expenses, bills, or a night out with friends. articles: - href: Request-and-Send-Money title: Request and Send Money diff --git a/docs/_includes/hub-card.html b/docs/_includes/hub-card.html index 379a42a26340..36bf3bc36e6a 100644 --- a/docs/_includes/hub-card.html +++ b/docs/_includes/hub-card.html @@ -6,8 +6,8 @@ {{ hub.href }}
-

{{ hub.title }}

-

{{ hub.description }}

+

{{ hub.title }}

+

{{ hub.description }}

diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index b2614aeef4a4..ad40909a805d 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -66,7 +66,7 @@

-

Didn't find what you were looking for?

+

Didn't find what you were looking for?

Concierge is here to answer all your questions.

diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index 44ab37ffbca8..809463dd79b8 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -390,12 +390,12 @@ button { .cards-group { display: grid; grid-template-columns: auto; - row-gap: 12px; - column-gap: 4%; + row-gap: 20px; + column-gap: 20px; padding-bottom: 20px; @include breakpoint($breakpoint-desktop) { - grid-template-columns: 48% 48%; + grid-template-columns: auto auto; } } @@ -456,12 +456,26 @@ button { h3.title { padding: 0; margin: 0; + + &.with-margin { + margin: 0 0 4px 0; + } } + + p.description { padding: 0; - margin: 16px 0 0 0; + margin: 0; font-weight: normal; + + &.with-min-height { + min-height: 68px; + + @include breakpoint($breakpoint-tablet) { + min-height: 48px; + } + } } } diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 1937c0102918..dcc764f10ffa 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.24 + 1.2.26 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.24.4 + 1.2.26.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index f4241782e2fc..0affc6c431d0 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.24 + 1.2.26 CFBundleSignature ???? CFBundleVersion - 1.2.24.4 + 1.2.26.0 diff --git a/package-lock.json b/package-lock.json index 0a44a3029502..53241fceaad0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.24-4", + "version": "1.2.26-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.24-4", + "version": "1.2.26-0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -38,7 +38,7 @@ "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", "dotenv": "^8.2.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#6010b3c49a16f63ee9cecc0c720f6d10395775ef", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#805a4c34debc7e27b14e33847ac4df4d59b6d878", "fbjs": "^3.0.2", "file-loader": "^6.0.0", "html-entities": "^1.3.1", @@ -68,7 +68,7 @@ "react-native-image-picker": "^4.8.5", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.27", + "react-native-onyx": "1.0.29", "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", @@ -23860,8 +23860,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#6010b3c49a16f63ee9cecc0c720f6d10395775ef", - "integrity": "sha512-QRKmQUEVzdEwOJEsh1XFhcGdSl+taPdHYTUZt0Bdbb9SyQvBHX4g6/NqMIfQRYiBq6q3eKpAd4nTKmkaHAfKsA==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#805a4c34debc7e27b14e33847ac4df4d59b6d878", + "integrity": "sha512-46gx59CkEPWEH4Y0VDIZreZg7fvaPdi8TEitTu7kiejKmKJWnPxNt/2RDZK3QFHLUiMy0RzTxAozLqR7N2MsYw==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -35432,9 +35432,9 @@ } }, "node_modules/react-native-onyx": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.27.tgz", - "integrity": "sha512-+kC4SQhgl+kI2PEnj6RAGSteMV2Amy9+1BvUV4gxpKEseMzcTHlpozxNeYiXYfgIo7lIsk0DicZbtwBuB3sgaw==", + "version": "1.0.29", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.29.tgz", + "integrity": "sha512-Zg7v6bimkRPqaAM5C/CqMswSObPGX+2BK2Gr7r4P1htSMjNlvn+fZ9gD4mwJBPgnoEUqMdFGLUshksHbE+GSMg==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -60809,9 +60809,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#6010b3c49a16f63ee9cecc0c720f6d10395775ef", - "integrity": "sha512-QRKmQUEVzdEwOJEsh1XFhcGdSl+taPdHYTUZt0Bdbb9SyQvBHX4g6/NqMIfQRYiBq6q3eKpAd4nTKmkaHAfKsA==", - "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#6010b3c49a16f63ee9cecc0c720f6d10395775ef", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#805a4c34debc7e27b14e33847ac4df4d59b6d878", + "integrity": "sha512-46gx59CkEPWEH4Y0VDIZreZg7fvaPdi8TEitTu7kiejKmKJWnPxNt/2RDZK3QFHLUiMy0RzTxAozLqR7N2MsYw==", + "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#805a4c34debc7e27b14e33847ac4df4d59b6d878", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", @@ -69778,9 +69778,9 @@ } }, "react-native-onyx": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.27.tgz", - "integrity": "sha512-+kC4SQhgl+kI2PEnj6RAGSteMV2Amy9+1BvUV4gxpKEseMzcTHlpozxNeYiXYfgIo7lIsk0DicZbtwBuB3sgaw==", + "version": "1.0.29", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.29.tgz", + "integrity": "sha512-Zg7v6bimkRPqaAM5C/CqMswSObPGX+2BK2Gr7r4P1htSMjNlvn+fZ9gD4mwJBPgnoEUqMdFGLUshksHbE+GSMg==", "requires": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", diff --git a/package.json b/package.json index cc2599d0d705..7e3fe98b3a2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.24-4", + "version": "1.2.26-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.", @@ -67,7 +67,7 @@ "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", "dotenv": "^8.2.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#6010b3c49a16f63ee9cecc0c720f6d10395775ef", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#805a4c34debc7e27b14e33847ac4df4d59b6d878", "fbjs": "^3.0.2", "file-loader": "^6.0.0", "html-entities": "^1.3.1", @@ -97,7 +97,7 @@ "react-native-image-picker": "^4.8.5", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.27", + "react-native-onyx": "1.0.29", "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", diff --git a/src/CONST.js b/src/CONST.js index 02656fb2682e..88b4e789a3ad 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -265,9 +265,6 @@ const CONST = { REMOVED_FROM_POLICY: 'removedFromPolicy', POLICY_DELETED: 'policyDeleted', }, - ERROR: { - INACCESSIBLE_REPORT: 'Report not found', - }, MESSAGE: { TYPE: { COMMENT: 'COMMENT', @@ -318,6 +315,7 @@ const CONST = { MAX_ROOM_NAME_LENGTH: 80, LAST_MESSAGE_TEXT_MAX_LENGTH: 200, OWNER_EMAIL_FAKE: '__FAKE__', + DEFAULT_REPORT_NAME: 'Chat Report', }, COMPOSER: { MAX_LINES: 16, @@ -351,7 +349,6 @@ const CONST = { SEARCH_RENDER: 'search_render', HOMEPAGE_INITIAL_RENDER: 'homepage_initial_render', REPORT_INITIAL_RENDER: 'report_initial_render', - HOMEPAGE_REPORTS_LOADED: 'homepage_reports_loaded', SWITCH_REPORT: 'switch_report', SIDEBAR_LOADED: 'sidebar_loaded', COLD: 'cold', @@ -576,6 +573,7 @@ const CONST = { STEP: { // In the order they appear in the Wallet flow ADDITIONAL_DETAILS: 'AdditionalDetailsStep', + ADDITIONAL_DETAILS_KBA: 'AdditionalDetailsKBAStep', ONFIDO: 'OnfidoStep', TERMS: 'TermsStep', ACTIVATE: 'ActivateStep', diff --git a/src/ROUTES.js b/src/ROUTES.js index 6872398c20f1..3ae1dcc48022 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -107,7 +107,6 @@ export default { WORKSPACE_INVOICES: 'workspace/:policyID/invoices', WORKSPACE_TRAVEL: 'workspace/:policyID/travel', WORKSPACE_MEMBERS: 'workspace/:policyID/members', - WORKSPACE_BANK_ACCOUNT: 'workspace/:policyID/bank-account', WORKSPACE_NEW_ROOM: 'workspace/new-room', getWorkspaceInitialRoute: policyID => `workspace/${policyID}`, getWorkspaceInviteRoute: policyID => `workspace/${policyID}/invite`, @@ -118,7 +117,6 @@ export default { getWorkspaceInvoicesRoute: policyID => `workspace/${policyID}/invoices`, getWorkspaceTravelRoute: policyID => `workspace/${policyID}/travel`, getWorkspaceMembersRoute: policyID => `workspace/${policyID}/members`, - getWorkspaceBankAccountRoute: policyID => `workspace/${policyID}/bank-account`, getRequestCallRoute: taskID => `request-call/${taskID}`, REQUEST_CALL: 'request-call/:taskID', diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index 83bf0e5754aa..36e70e075733 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -245,15 +245,6 @@ class AttachmentModal extends PureComponent { } render() { - // When the confirm button is visible we don't need bottom padding on the attachment view. - const attachmentViewPaddingStyles = this.props.onConfirm - ? [styles.pl5, styles.pr5, styles.pt5] - : styles.p5; - - const attachmentViewStyles = this.props.isSmallScreenWidth || this.props.isMediumScreenWidth - ? [styles.imageModalImageCenterContainer] - : [styles.imageModalImageCenterContainer, attachmentViewPaddingStyles]; - const originalFileName = lodashGet(this.state, 'file.name') || this.props.originalFileName; const {fileName, fileExtension} = FileUtils.splitExtensionFromFileName(originalFileName); @@ -285,7 +276,7 @@ class AttachmentModal extends PureComponent { /> ) : ''} /> - + {this.state.reportId ? ( ( successIcon={Expensicons.Checkmark} successText={props.translate('reportActionContextMenu.copied')} isMini - autoReset onPress={() => Clipboard.setString(props.value)} /> diff --git a/src/components/ContextMenuItem.js b/src/components/ContextMenuItem.js index 639742efa00d..96f28164e166 100644 --- a/src/components/ContextMenuItem.js +++ b/src/components/ContextMenuItem.js @@ -41,7 +41,7 @@ const defaultProps = { isMini: false, successIcon: null, successText: '', - autoReset: false, + autoReset: true, description: '', }; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js index 36adfe30f6b5..3597aa641192 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js @@ -14,6 +14,7 @@ import styles from '../../../styles/styles'; import Navigation from '../../../libs/Navigation/Navigation'; import AnchorForCommentsOnly from '../../AnchorForCommentsOnly'; import AnchorForAttachmentsOnly from '../../AnchorForAttachmentsOnly'; +import ROUTES from '../../../ROUTES'; const AnchorRenderer = (props) => { const htmlAttribs = props.tnode.attributes; @@ -30,6 +31,18 @@ const AnchorRenderer = (props) => { && attrHref.replace(CONFIG.EXPENSIFY.EXPENSIFY_URL, ''); const navigateToLink = () => { + // There can be messages from Concierge with links to specific NewDot reports. Those URLs look like this: + // https://www.expensify.com.dev/newdotreport?reportID=3429600449838908 and they have a target="_blank" attribute. This is so that when a user is on OldDot, + // clicking on the link will open the chat in NewDot. However, when a user is in NewDot and clicks on the concierge link, the link needs to be handled differently. + // Normally, the link would be sent to Link.openOldDotLink() and opened in a new tab, and that's jarring to the user. Since the intention is to link to a specific NewDot chat, + // the reportID is extracted from the URL and then opened as an internal link, taking the user straight to the chat in the same tab. + if (attrHref.startsWith(CONFIG.EXPENSIFY.EXPENSIFY_URL) && attrHref.indexOf('newdotreport?reportID=') > -1) { + const reportID = attrHref.split('newdotreport?reportID=').pop(); + const reportRoute = ROUTES.getReportRoute(reportID); + Navigation.navigate(reportRoute); + return; + } + // If we are handling a New Expensify link then we will assume this should be opened by the app internally. This ensures that the links are opened internally via react-navigation // instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag) if (internalNewExpensifyPath) { diff --git a/src/components/Modal/BaseModal.js b/src/components/Modal/BaseModal.js index 14662bc370fa..91b1867a6f91 100644 --- a/src/components/Modal/BaseModal.js +++ b/src/components/Modal/BaseModal.js @@ -62,6 +62,8 @@ class BaseModal extends PureComponent { swipeDirection, animationIn, animationOut, + shouldAddTopSafeAreaMargin, + shouldAddBottomSafeAreaMargin, shouldAddTopSafeAreaPadding, shouldAddBottomSafeAreaPadding, hideBackdrop, @@ -128,8 +130,12 @@ class BaseModal extends PureComponent { safeAreaPaddingBottom, safeAreaPaddingLeft, safeAreaPaddingRight, + shouldAddBottomSafeAreaMargin, + shouldAddTopSafeAreaMargin, shouldAddBottomSafeAreaPadding, shouldAddTopSafeAreaPadding, + modalContainerStyleMarginTop: modalContainerStyle.marginTop, + modalContainerStyleMarginBottom: modalContainerStyle.marginBottom, modalContainerStylePaddingTop: modalContainerStyle.paddingTop, modalContainerStylePaddingBottom: modalContainerStyle.paddingBottom, }); diff --git a/src/components/PDFView/PDFPasswordForm.js b/src/components/PDFView/PDFPasswordForm.js index 144de7de6497..482e31405ef0 100644 --- a/src/components/PDFView/PDFPasswordForm.js +++ b/src/components/PDFView/PDFPasswordForm.js @@ -5,10 +5,7 @@ import {View, ScrollView} from 'react-native'; import Button from '../Button'; import Text from '../Text'; import TextInput from '../TextInput'; -import Icon from '../Icon'; -import * as Expensicons from '../Icon/Expensicons'; import styles from '../../styles/styles'; -import colors from '../../styles/colors'; import PDFInfoMessage from './PDFInfoMessage'; import compose from '../../libs/compose'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; @@ -120,26 +117,16 @@ class PDFPasswordForm extends Component { onChangeText={this.updatePassword} returnKeyType="done" onSubmitEditing={this.submitPassword} - errorText={this.state.validationErrorText} + errorText={this.props.isPasswordInvalid ? this.props.translate('attachmentView.passwordIncorrect') : this.state.validationErrorText} onFocus={() => this.props.onPasswordFieldFocused(true)} onBlur={this.validateAndNotifyPasswordBlur} autoFocus={this.props.shouldAutofocusPasswordField} secureTextEntry /> - {this.props.isPasswordInvalid && ( - - - - - {this.props.translate('attachmentView.passwordIncorrect')} - - - - )}