From 67c6ca0fd106f8c2f869ebfd2c08204b9472654d Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 3 May 2023 08:39:58 -0700 Subject: [PATCH 01/85] Create a convenience script to quickly lint changed files locally --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index cfd39cfe59f7..abe4ec6df51d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "android-build-e2e": "bundle exec fastlane android build_e2e", "test": "TZ=utc jest", "lint": "eslint . --max-warnings=0", + "lint-changed": "eslint --fix \"$(git diff --name-only main -- \"**/*.js\")\"", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", "print-version": "echo $npm_package_version", From 08229afe1d5b74b7e53139250a2ee891223c9868 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 3 May 2023 08:46:03 -0700 Subject: [PATCH 02/85] Remove directory wildcard --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index abe4ec6df51d..1098193699ea 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "android-build-e2e": "bundle exec fastlane android build_e2e", "test": "TZ=utc jest", "lint": "eslint . --max-warnings=0", - "lint-changed": "eslint --fix \"$(git diff --name-only main -- \"**/*.js\")\"", + "lint-changed": "eslint --fix \"$(git diff --name-only main -- \"*.js\")\"", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", "print-version": "echo $npm_package_version", From 11640e8b63133860e845d94f8c9090f5c2575a66 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 3 May 2023 08:48:38 -0700 Subject: [PATCH 03/85] Remove double-quoting around git diff --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1098193699ea..4e037e0bc851 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "android-build-e2e": "bundle exec fastlane android build_e2e", "test": "TZ=utc jest", "lint": "eslint . --max-warnings=0", - "lint-changed": "eslint --fix \"$(git diff --name-only main -- \"*.js\")\"", + "lint-changed": "eslint --fix $(git diff --name-only main -- \"*.js\")", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", "print-version": "echo $npm_package_version", From 4268a25d937dd6e3abd903eb50c055c3c2c17e1f Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 3 May 2023 10:41:16 -0700 Subject: [PATCH 04/85] Add diff-filter to exclude files that no longer exist in this branch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e037e0bc851..2cccbcbda5fa 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "android-build-e2e": "bundle exec fastlane android build_e2e", "test": "TZ=utc jest", "lint": "eslint . --max-warnings=0", - "lint-changed": "eslint --fix $(git diff --name-only main -- \"*.js\")", + "lint-changed": "eslint --fix $(git diff --diff-filter=AM --name-only main -- \"*.js\")", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", "print-version": "echo $npm_package_version", From 9b59d586a5c08ddf3eddf91252f7c9e01567d516 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 18 May 2023 11:57:04 +0100 Subject: [PATCH 05/85] =?UTF-8?q?if=20no=20roomName,=20dont=20add=20the=20?= =?UTF-8?q?=E2=80=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/ReportUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d17d83c185bf..0b13ad770c66 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -504,7 +504,7 @@ function getChatRoomSubtitle(report) { } } - return [workspaceName, roomName].join(' • '); + return !roomName ? workspaceName : [workspaceName, roomName].join(' • '); } if (!isDefaultRoom(report) && !isUserCreatedPolicyRoom(report) && !isPolicyExpenseChat(report)) { return ''; From 15a90b1021fc073220c5090f066ec0ffe782111f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Fri, 26 May 2023 12:55:59 +0200 Subject: [PATCH 06/85] migrate WorkspaceMembersPage to PressableWithFeedback --- src/pages/workspace/WorkspaceMembersPage.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index c9d6deab2b0e..0d87033ed7f5 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -1,7 +1,7 @@ import React from 'react'; import _ from 'underscore'; import lodashGet from 'lodash/get'; -import {View, TouchableOpacity} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import styles from '../../styles/styles'; @@ -34,6 +34,7 @@ import TextInput from '../../components/TextInput'; import KeyboardDismissingFlatList from '../../components/KeyboardDismissingFlatList'; import withCurrentUserPersonalDetails from '../../components/withCurrentUserPersonalDetails'; import * as PolicyUtils from '../../libs/PolicyUtils'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; const propTypes = { /** The personal details of the person who is logged in */ @@ -318,6 +319,7 @@ class WorkspaceMembersPage extends React.Component { * @returns {React.Component} */ renderItem({item}) { + const isChecked = _.contains(this.state.selectedEmployees, item.login); return ( - this.toggleUser(item.login, item.pendingAction)} - activeOpacity={0.7} + accessibilityRole="checkbox" + accessibilityState={{ + checked: isChecked, + }} + accessibilityLabel={this.props.formatPhoneNumber(item.displayName)} + // disable hover style when disabled + hoverDimmingValue={1} + pressDimmingValue={0.7} > this.toggleUser(item.login, item.pendingAction)} /> this.toggleUser(item.login, item.pendingAction)} + isDisabled boldStyle option={{ text: this.props.formatPhoneNumber(item.displayName), @@ -358,7 +367,7 @@ class WorkspaceMembersPage extends React.Component { {this.props.translate('common.admin')} )} - + {!_.isEmpty(this.state.errors[item.login]) && ( Date: Mon, 29 May 2023 11:52:04 +0200 Subject: [PATCH 07/85] fixed comment --- src/pages/workspace/WorkspaceMembersPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 0d87033ed7f5..cd86874f56e9 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -335,7 +335,7 @@ class WorkspaceMembersPage extends React.Component { checked: isChecked, }} accessibilityLabel={this.props.formatPhoneNumber(item.displayName)} - // disable hover style when disabled + // disable hover dimming hoverDimmingValue={1} pressDimmingValue={0.7} > From eb4ca64184ca8ec2cc2568559a2283952c50d1fd Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 31 May 2023 22:46:02 +0700 Subject: [PATCH 08/85] fix: autofill is not a valid selector --- src/libs/isInputAutoFilled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/isInputAutoFilled.js b/src/libs/isInputAutoFilled.js index 3a64ffd441ee..dfcf50c37460 100644 --- a/src/libs/isInputAutoFilled.js +++ b/src/libs/isInputAutoFilled.js @@ -5,5 +5,5 @@ */ export default function isInputAutoFilled(input) { if (!input.matches) return false; - return input.matches(':-webkit-autofill') || input.matches(':autofill'); + return input.matches(':-webkit-autofill') } From 13805c9946da370f3e1a8f002c2a8c1f8215113e Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 31 May 2023 23:00:48 +0700 Subject: [PATCH 09/85] format code --- src/libs/isInputAutoFilled.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/isInputAutoFilled.js b/src/libs/isInputAutoFilled.js index dfcf50c37460..e873da9ff92f 100644 --- a/src/libs/isInputAutoFilled.js +++ b/src/libs/isInputAutoFilled.js @@ -5,5 +5,5 @@ */ export default function isInputAutoFilled(input) { if (!input.matches) return false; - return input.matches(':-webkit-autofill') + return input.matches(':-webkit-autofill'); } From fb50906b70f76196c050f734b547949c4a5fb1b5 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 2 Jun 2023 12:31:48 +0700 Subject: [PATCH 10/85] fix: duplicate task in DM after reassignment --- src/libs/actions/Task.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index da751e4209a8..5545f2273181 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -311,7 +311,9 @@ function editTaskAndNavigate(report, ownerEmail, title, description, assignee) { let assigneeChatReportID; if (assignee && assignee !== report.managerEmail) { assigneeChatReportID = ReportUtils.getChatByParticipants([assignee]).reportID; - optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`); + if (assigneeChatReportID !== report.parentReportID) { + optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`, report.parentReportID); + } } const optimisticData = [ From 49d2acc1c9caa389fc571fde12c37e16982d1f19 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 2 Jun 2023 12:45:08 +0700 Subject: [PATCH 11/85] fix lint --- src/libs/actions/Task.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 5545f2273181..a462bb66308c 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -312,7 +312,7 @@ function editTaskAndNavigate(report, ownerEmail, title, description, assignee) { if (assignee && assignee !== report.managerEmail) { assigneeChatReportID = ReportUtils.getChatByParticipants([assignee]).reportID; if (assigneeChatReportID !== report.parentReportID) { - optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`, report.parentReportID); + optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`); } } From 99bbff837208229dfc932839d86a2bea47b605d7 Mon Sep 17 00:00:00 2001 From: Duc Nguyen Date: Sat, 3 Jun 2023 01:42:56 +0300 Subject: [PATCH 12/85] migrate CopyTextToClipboard to functional component --- src/components/CopyTextToClipboard.js | 77 ++++++++++++--------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index fbf46be3ee08..bfa6c8a0af43 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -1,5 +1,5 @@ -import React from 'react'; -import {Pressable} from 'react-native'; +import React, { useCallback } from 'react'; +import { Pressable } from 'react-native'; import PropTypes from 'prop-types'; import Text from './Text'; import * as Expensicons from './Icon/Expensicons'; @@ -11,15 +11,14 @@ import Tooltip from './Tooltip'; import styles from '../styles/styles'; import * as StyleUtils from '../styles/StyleUtils'; import variables from '../styles/variables'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState'; +import withLocalize, { withLocalizePropTypes } from './withLocalize'; +import withDelayToggleButtonState, { withDelayToggleButtonStatePropTypes } from './withDelayToggleButtonState'; const propTypes = { /** The text to display and copy to the clipboard */ text: PropTypes.string.isRequired, /** Styles to apply to the text */ - // eslint-disable-next-line react/forbid-prop-types textStyles: PropTypes.arrayOf(PropTypes.object), ...withLocalizePropTypes, @@ -31,48 +30,40 @@ const defaultProps = { textStyles: [], }; -class CopyTextToClipboard extends React.Component { - constructor(props) { - super(props); - - this.copyToClipboard = this.copyToClipboard.bind(this); - } +CopyTextToClipboard.propTypes = propTypes; +CopyTextToClipboard.defaultProps = defaultProps; - copyToClipboard() { - if (this.props.isDelayButtonStateComplete) { +const CopyTextToClipboard = ({ text, textStyles, translate, isDelayButtonStateComplete, toggleDelayButtonState }) => { + const copyToClipboard = useCallback(() => { + if (isDelayButtonStateComplete) { return; } - Clipboard.setString(this.props.text); - this.props.toggleDelayButtonState(true); - } + Clipboard.setString(text); + toggleDelayButtonState(true); + }, [isDelayButtonStateComplete, text, toggleDelayButtonState]); - render() { - return ( - - {`${this.props.text} `} - - - {({hovered, pressed}) => ( - - )} - - - - ); - } + return ( + + {`${text} `} + + + {({ hovered, pressed }) => ( + + )} + + + + ); } -CopyTextToClipboard.propTypes = propTypes; -CopyTextToClipboard.defaultProps = defaultProps; - export default compose(withLocalize, withDelayToggleButtonState)(CopyTextToClipboard); From 14ae86dd5f43e5e1950c745a877c3f7d6fbc4a26 Mon Sep 17 00:00:00 2001 From: Duc Nguyen Date: Sat, 3 Jun 2023 02:27:23 +0300 Subject: [PATCH 13/85] Move props to bottom --- src/components/CopyTextToClipboard.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index bfa6c8a0af43..84bc833446ff 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -30,9 +30,6 @@ const defaultProps = { textStyles: [], }; -CopyTextToClipboard.propTypes = propTypes; -CopyTextToClipboard.defaultProps = defaultProps; - const CopyTextToClipboard = ({ text, textStyles, translate, isDelayButtonStateComplete, toggleDelayButtonState }) => { const copyToClipboard = useCallback(() => { if (isDelayButtonStateComplete) { @@ -66,4 +63,7 @@ const CopyTextToClipboard = ({ text, textStyles, translate, isDelayButtonStateCo ); } +CopyTextToClipboard.propTypes = propTypes; +CopyTextToClipboard.defaultProps = defaultProps; + export default compose(withLocalize, withDelayToggleButtonState)(CopyTextToClipboard); From e1ab57eb8ffe01aad2c32b7b2ddf431d93f1b84c Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 2 Jun 2023 22:04:21 -0400 Subject: [PATCH 14/85] Add route and links for new profile page --- src/ROUTES.js | 2 ++ .../Navigation/AppNavigator/ModalStackNavigators.js | 11 +++++++++++ src/libs/Navigation/linkingConfig.js | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/src/ROUTES.js b/src/ROUTES.js index c9075c42d8e1..195c6101e8f7 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -114,6 +114,8 @@ export default { SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', getDetailsRoute: (login) => `details?login=${encodeURIComponent(login)}`, + PROFILE: 'a/:accountID', + getProfileRoute: (accountID) => `a/${accountID}`, REPORT_PARTICIPANTS: 'r/:reportID/participants', getReportParticipantsRoute: (reportID) => `r/${reportID}/participants`, REPORT_PARTICIPANT: 'r/:reportID/participants/details', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 966d40f9f7d0..d8c0bfcf3ef5 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -131,6 +131,16 @@ const DetailsModalStackNavigator = createModalStackNavigator([ }, ]); +const ProfileModalStackNavigator = createModalStackNavigator([ + { + getComponent: () => { + const ProfilePage = require('../../../pages/ProfilePage').default; + return ProfilePage; + }, + name: 'Profile_Root', + }, +]); + const ReportDetailsModalStackNavigator = createModalStackNavigator([ { getComponent: () => { @@ -718,6 +728,7 @@ export { IOUSendModalStackNavigator, SplitDetailsModalStackNavigator, DetailsModalStackNavigator, + ProfileModalStackNavigator, ReportDetailsModalStackNavigator, TaskModalStackNavigator, ReportSettingsModalStackNavigator, diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 7a45266b0355..717c981827f1 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -267,6 +267,11 @@ export default { Details_Root: ROUTES.DETAILS, }, }, + Profile: { + screens: { + Profile_Root: ROUTES.PROFILE, + }, + }, Participants: { screens: { ReportParticipants_Root: ROUTES.REPORT_PARTICIPANTS, From 558b23c11c3607867063e4d4bec7fe93af6188fb Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 2 Jun 2023 22:32:16 -0400 Subject: [PATCH 15/85] Add ProfilePage --- src/ONYXKEYS.js | 3 + .../Navigation/AppNavigator/AuthScreens.js | 6 + src/pages/ProfilePage.js | 216 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100755 src/pages/ProfilePage.js diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 8cbf4a726f95..ca0f7383c969 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -45,6 +45,9 @@ export default { // Contains all the personalDetails the user has access to PERSONAL_DETAILS: 'personalDetails', + // Contains all the personalDetails the user has access to + PERSONAL_DETAILS_LIST: 'personalDetailsList', + // Contains all the private personal details of the user PRIVATE_PERSONAL_DETAILS: 'private_personalDetails', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 397e970ed1f6..450325af7c06 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -289,6 +289,12 @@ class AuthScreens extends React.Component { component={ModalStackNavigators.DetailsModalStackNavigator} listeners={modalScreenListeners} /> + { + // If the user hasn't set a displayName, it is set to their phone number, so use that + const parsedPhoneNumber = parsePhoneNumber(details.displayName); + if (parsedPhoneNumber.possible) { + return parsedPhoneNumber.number.e164; + } + + // If the user has set a displayName, get the phone number from the SMS login + return details.login ? Str.removeSMSDomain(details.login) : ''; +}; + +class ProfilePage extends React.PureComponent { + render() { + const accountID = lodashGet(this.props.route.params, 'accountID', ''); + const reportID = lodashGet(this.props.route.params, 'reportID', ''); + const details = lodashGet(this.props.personalDetails, accountID); + console.log(details); + + const isSMSLogin = details.login ? Str.isSMSLogin(details.login) : false; + + // If we have a reportID param this means that we + // arrived here via the ParticipantsPage and should be allowed to navigate back to it + const shouldShowBackButton = Boolean(reportID); + const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([details.login]) && details.timezone; + let pronouns = details.pronouns; + + if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { + const localeKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); + pronouns = this.props.translate(`pronouns.${localeKey}`); + } + + const phoneNumber = getPhoneNumber(details); + const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : details.login; + + const isCurrentUser = _.keys(this.props.loginList).includes(details.login); + + return ( + + Navigation.goBack()} + onCloseButtonPress={() => Navigation.dismissModal()} + /> + + {details ? ( + + + + {({show}) => ( + + + + + + )} + + {Boolean(details.displayName) && ( + + {details.displayName} + + )} + {details.login ? ( + + + {this.props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} + + + + {isSMSLogin ? this.props.formatPhoneNumber(phoneNumber) : details.login} + + + + ) : null} + {pronouns ? ( + + + {this.props.translate('profilePage.preferredPronouns')} + + {pronouns} + + ) : null} + {shouldShowLocalTime && } + + {!isCurrentUser && ( + Report.navigateToAndOpenReport([details.login])} + wrapperStyle={styles.breakAll} + shouldShowRightIcon + /> + )} + + ) : null} + + + ); + } +} + +ProfilePage.propTypes = propTypes; +ProfilePage.defaultProps = defaultProps; + +export default compose( + withLocalize, + withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + loginList: { + key: ONYXKEYS.LOGIN_LIST, + }, + }), +)(ProfilePage); From 540087d32eaf2e81667f1152b5b8499977d3bbd0 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 3 Jun 2023 09:37:04 -0500 Subject: [PATCH 16/85] Use lodashGet for various details --- src/pages/ProfilePage.js | 44 ++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 6685f596200e..703d20437413 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -76,7 +76,8 @@ const defaultProps = { */ const getPhoneNumber = (details) => { // If the user hasn't set a displayName, it is set to their phone number, so use that - const parsedPhoneNumber = parsePhoneNumber(details.displayName); + const displayName = lodashGet(details, 'displayName', ''); + const parsedPhoneNumber = parsePhoneNumber(displayName); if (parsedPhoneNumber.possible) { return parsedPhoneNumber.number.e164; } @@ -89,16 +90,19 @@ class ProfilePage extends React.PureComponent { render() { const accountID = lodashGet(this.props.route.params, 'accountID', ''); const reportID = lodashGet(this.props.route.params, 'reportID', ''); - const details = lodashGet(this.props.personalDetails, accountID); - console.log(details); - - const isSMSLogin = details.login ? Str.isSMSLogin(details.login) : false; + const details = lodashGet(this.props.personalDetails, accountID, {}); + const displayName = lodashGet(details, 'displayName', ''); + const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar()); + const originalFileName = lodashGet(details, 'originalFileName', ''); + const login = lodashGet(details, 'login', ''); + let pronouns = lodashGet(details, 'pronouns', ''); + const timezone = lodashGet(details, 'timezone', {}); + const isSMSLogin = login ? Str.isSMSLogin(login) : false; // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowBackButton = Boolean(reportID); - const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([details.login]) && details.timezone; - let pronouns = details.pronouns; + const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && timezone; if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { const localeKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); @@ -106,9 +110,9 @@ class ProfilePage extends React.PureComponent { } const phoneNumber = getPhoneNumber(details); - const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : details.login; + const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; - const isCurrentUser = _.keys(this.props.loginList).includes(details.login); + const isCurrentUser = _.keys(this.props.loginList).includes(login); return ( @@ -126,10 +130,10 @@ class ProfilePage extends React.PureComponent { {({show}) => ( )} - {Boolean(details.displayName) && ( + {Boolean(displayName) && ( - {details.displayName} + {displayName} )} - {details.login ? ( + {login ? ( - {isSMSLogin ? this.props.formatPhoneNumber(phoneNumber) : details.login} + {isSMSLogin ? this.props.formatPhoneNumber(phoneNumber) : login} @@ -181,13 +185,13 @@ class ProfilePage extends React.PureComponent { {pronouns} ) : null} - {shouldShowLocalTime && } + {shouldShowLocalTime && } {!isCurrentUser && ( Report.navigateToAndOpenReport([details.login])} + onPress={() => Report.navigateToAndOpenReport([login])} wrapperStyle={styles.breakAll} shouldShowRightIcon /> From 09e6b1fa32c9998d584628b04ffcfe8038a87a47 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 3 Jun 2023 09:52:28 -0500 Subject: [PATCH 17/85] Show loading indicator when details arent available --- src/pages/ProfilePage.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 703d20437413..88825d3a5fcc 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -28,6 +28,7 @@ import * as Report from '../libs/actions/Report'; import OfflineWithFeedback from '../components/OfflineWithFeedback'; import AutoUpdateTime from '../components/AutoUpdateTime'; import * as UserUtils from '../libs/UserUtils'; +import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; const matchType = PropTypes.shape({ params: PropTypes.shape({ @@ -126,7 +127,9 @@ class ProfilePage extends React.PureComponent { pointerEvents="box-none" style={[styles.containerWithSpaceBetween]} > - {details ? ( + {_.isEmpty(details) ? ( + + ) : ( )} - ) : null} + )} ); From e138aee2ac14bfd5946fb4782135960e2ab9a281 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 3 Jun 2023 10:10:32 -0500 Subject: [PATCH 18/85] Use "hidden" as fallback displayName --- src/languages/en.js | 1 + src/languages/es.js | 1 + src/pages/ProfilePage.js | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 8bfb80d1d22d..1db870cd62b0 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -44,6 +44,7 @@ export default { and: 'and', details: 'Details', privacy: 'Privacy', + hidden: 'Hidden', delete: 'Delete', archived: 'archived', contacts: 'Contacts', diff --git a/src/languages/es.js b/src/languages/es.js index 2a0631bf9703..27b57a0bf8bc 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -43,6 +43,7 @@ export default { and: 'y', details: 'Detalles', privacy: 'Privacidad', + hidden: 'Oculto', delete: 'Eliminar', archived: 'archivado', contacts: 'Contactos', diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 88825d3a5fcc..b1a7999371d0 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -92,24 +92,24 @@ class ProfilePage extends React.PureComponent { const accountID = lodashGet(this.props.route.params, 'accountID', ''); const reportID = lodashGet(this.props.route.params, 'reportID', ''); const details = lodashGet(this.props.personalDetails, accountID, {}); - const displayName = lodashGet(details, 'displayName', ''); + const displayName = details.displayName ? details.displayName : this.props.translate('common.hidden'); const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar()); const originalFileName = lodashGet(details, 'originalFileName', ''); const login = lodashGet(details, 'login', ''); - let pronouns = lodashGet(details, 'pronouns', ''); const timezone = lodashGet(details, 'timezone', {}); - const isSMSLogin = login ? Str.isSMSLogin(login) : false; // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowBackButton = Boolean(reportID); const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && timezone; + let pronouns = lodashGet(details, 'pronouns', ''); if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { const localeKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); pronouns = this.props.translate(`pronouns.${localeKey}`); } + const isSMSLogin = Str.isSMSLogin(login); const phoneNumber = getPhoneNumber(details); const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; @@ -118,7 +118,7 @@ class ProfilePage extends React.PureComponent { return ( Navigation.goBack()} onCloseButtonPress={() => Navigation.dismissModal()} From 249369eaa0891f25f2603857cba37ad81047356c Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sun, 4 Jun 2023 11:10:07 -0500 Subject: [PATCH 19/85] Replace getDetailsRoute usage with getProfileRoute --- src/components/ReportWelcomeText.js | 3 ++- src/libs/ReportUtils.js | 6 +++--- src/pages/home/report/ReactionList/BaseReactionList.js | 2 +- src/pages/home/report/ReportActionItemSingle.js | 10 +++++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/components/ReportWelcomeText.js b/src/components/ReportWelcomeText.js index a954fe3d8730..f2a79dd50fe3 100644 --- a/src/components/ReportWelcomeText.js +++ b/src/components/ReportWelcomeText.js @@ -55,6 +55,7 @@ const ReportWelcomeText = (props) => { const isChatRoom = ReportUtils.isChatRoom(props.report); const isDefault = !(isChatRoom || isPolicyExpenseChat); const participants = lodashGet(props.report, 'participants', []); + const participantAccountIDs = lodashGet(props.report, 'participantAccountIDs', []); const isMultipleParticipant = participants.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForLogins(participants, props.personalDetails), isMultipleParticipant); const roomWelcomeMessage = ReportUtils.getRoomWelcomeMessage(props.report); @@ -97,7 +98,7 @@ const ReportWelcomeText = (props) => { Navigation.navigate(ROUTES.getDetailsRoute(participants[index]))} + onPress={() => Navigation.navigate(ROUTES.getProfileRoute(participantAccountIDs[index]))} > {displayName} diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8231886e8632..462a8a5b0f99 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1047,14 +1047,14 @@ function getReportName(report) { * @param {Object} report */ function navigateToDetailsPage(report) { - const participants = lodashGet(report, 'participants', []); + const participantAccountIDs = lodashGet(report, 'participantAccountIDs', []); if (isChatRoom(report) || isPolicyExpenseChat(report) || isThread(report)) { Navigation.navigate(ROUTES.getReportDetailsRoute(report.reportID)); return; } - if (participants.length === 1) { - Navigation.navigate(ROUTES.getDetailsRoute(participants[0])); + if (participantAccountIDs.length === 1) { + Navigation.navigate(ROUTES.getProfileRoute(participantAccountIDs[0])); return; } Navigation.navigate(ROUTES.getReportParticipantsRoute(report.reportID)); diff --git a/src/pages/home/report/ReactionList/BaseReactionList.js b/src/pages/home/report/ReactionList/BaseReactionList.js index eda4f4db0f48..7b3453072994 100755 --- a/src/pages/home/report/ReactionList/BaseReactionList.js +++ b/src/pages/home/report/ReactionList/BaseReactionList.js @@ -79,7 +79,7 @@ const BaseReactionList = (props) => { hoverStyle={styles.hoveredComponentBG} onSelectRow={() => { props.onClose(); - Navigation.navigate(ROUTES.getDetailsRoute(item.login)); + Navigation.navigate(ROUTES.getProfileRoute(item.accountID)); }} option={{ text: Str.removeSMSDomain(item.displayName), diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 96fd6be6ad26..eb5f2fa07434 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -61,13 +61,13 @@ const defaultProps = { report: undefined, }; -const showUserDetails = (email) => { - Navigation.navigate(ROUTES.getDetailsRoute(email)); +const showUserDetails = (accountID) => { + Navigation.navigate(ROUTES.getProfileRoute(accountID)); }; const ReportActionItemSingle = (props) => { const actorEmail = props.action.actorEmail.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); - const {avatar, displayName, pendingFields} = props.personalDetails[actorEmail] || {}; + const {accountID, avatar, displayName, pendingFields} = props.personalDetails[actorEmail] || {}; const avatarSource = UserUtils.getAvatar(avatar, actorEmail); // Since the display name for a report action message is delivered with the report history as an array of fragments @@ -88,7 +88,7 @@ const ReportActionItemSingle = (props) => { style={[styles.alignSelfStart, styles.mr3]} onPressIn={ControlSelection.block} onPressOut={ControlSelection.unblock} - onPress={() => showUserDetails(actorEmail)} + onPress={() => showUserDetails(accountID)} > {props.shouldShowSubscriptAvatar ? ( @@ -118,7 +118,7 @@ const ReportActionItemSingle = (props) => { style={[styles.flexShrink1, styles.mr1]} onPressIn={ControlSelection.block} onPressOut={ControlSelection.unblock} - onPress={() => showUserDetails(actorEmail)} + onPress={() => showUserDetails(accountID)} > {_.map(personArray, (fragment, index) => ( Date: Sun, 4 Jun 2023 12:07:13 -0500 Subject: [PATCH 20/85] Fetch the personal details from the API when opening profile page --- src/libs/actions/PersonalDetails.js | 9 +++++++++ src/pages/ProfilePage.js | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index ebabfb3d58ca..0a2731609041 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -310,6 +310,14 @@ function openPersonalDetailsPage() { API.read('OpenPersonalDetailsPage'); } +/** + * Fetches public profile info about a given user + * @param {Number} accountID + */ +function openPublicProfilePage(accountID) { + API.read('OpenPublicProfilePage', {accountID}); +} + /** * Updates the user's avatar image * @@ -427,6 +435,7 @@ export { deleteAvatar, openMoneyRequestModalPage, openPersonalDetailsPage, + openPublicProfilePage, extractFirstAndLastNameFromAvailableDetails, updateDisplayName, updateLegalName, diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index b1a7999371d0..e92deae41ad8 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -28,6 +28,7 @@ import * as Report from '../libs/actions/Report'; import OfflineWithFeedback from '../components/OfflineWithFeedback'; import AutoUpdateTime from '../components/AutoUpdateTime'; import * as UserUtils from '../libs/UserUtils'; +import * as PersonalDetails from '../libs/actions/PersonalDetails'; import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; const matchType = PropTypes.shape({ @@ -88,8 +89,12 @@ const getPhoneNumber = (details) => { }; class ProfilePage extends React.PureComponent { + componentDidMount() { + PersonalDetails.openPublicProfilePage(this.props.route.params.accountID); + } + render() { - const accountID = lodashGet(this.props.route.params, 'accountID', ''); + const accountID = lodashGet(this.props.route.params, 'accountID', 0); const reportID = lodashGet(this.props.route.params, 'reportID', ''); const details = lodashGet(this.props.personalDetails, accountID, {}); const displayName = details.displayName ? details.displayName : this.props.translate('common.hidden'); From 7f5f1658dc0c7d65c4df103954b0e221f5cf88ae Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sun, 4 Jun 2023 12:14:16 -0500 Subject: [PATCH 21/85] Dont show timezone if we dont have it --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index e92deae41ad8..866d5ee532d5 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -106,7 +106,7 @@ class ProfilePage extends React.PureComponent { // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowBackButton = Boolean(reportID); - const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && timezone; + const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && !_.isEmpty(timezone); let pronouns = lodashGet(details, 'pronouns', ''); if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { From f5832a39e1b2045e7a347ab5faf55b9372685bff Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sun, 4 Jun 2023 12:28:28 -0500 Subject: [PATCH 22/85] Dont show message option if you dont have their login info --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 866d5ee532d5..0264acb2a04f 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -195,7 +195,7 @@ class ProfilePage extends React.PureComponent { ) : null} {shouldShowLocalTime && } - {!isCurrentUser && ( + {!isCurrentUser && Boolean(login) && ( Date: Sun, 4 Jun 2023 14:05:23 -0400 Subject: [PATCH 23/85] Use avatar that we have --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 0264acb2a04f..4588656574a5 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -152,7 +152,7 @@ class ProfilePage extends React.PureComponent { From a95884e721ea18e3e7535e93ba9ee03568ae5f75 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Jun 2023 11:30:10 +0700 Subject: [PATCH 24/85] add isSelectorSupported function --- src/libs/isInputAutoFilled.js | 5 +++++ src/libs/isSelectorSupported/index.js | 13 +++++++++++++ src/libs/isSelectorSupported/index.native.js | 4 ++++ 3 files changed, 22 insertions(+) create mode 100644 src/libs/isSelectorSupported/index.js create mode 100644 src/libs/isSelectorSupported/index.native.js diff --git a/src/libs/isInputAutoFilled.js b/src/libs/isInputAutoFilled.js index e873da9ff92f..bfd967e850ba 100644 --- a/src/libs/isInputAutoFilled.js +++ b/src/libs/isInputAutoFilled.js @@ -1,3 +1,5 @@ +import isSelectorSupported from './isSelectorSupported'; + /** * Check the input is auto filled or not * @param {Object} input @@ -5,5 +7,8 @@ */ export default function isInputAutoFilled(input) { if (!input.matches) return false; + if (isSelectorSupported(':autofill')) { + return input.matches(':-webkit-autofill') || input.matches(':autofill'); + } return input.matches(':-webkit-autofill'); } diff --git a/src/libs/isSelectorSupported/index.js b/src/libs/isSelectorSupported/index.js new file mode 100644 index 000000000000..a574a3f12570 --- /dev/null +++ b/src/libs/isSelectorSupported/index.js @@ -0,0 +1,13 @@ +/** + * Check platform supports the selector or not + * @param {String} selector + * @return {Boolean} + */ +export default function isSelectorSupported(selector) { + try { + document.querySelector(selector); + return true; + } catch (error) { + return false; + } +} diff --git a/src/libs/isSelectorSupported/index.native.js b/src/libs/isSelectorSupported/index.native.js new file mode 100644 index 000000000000..c393079f80b8 --- /dev/null +++ b/src/libs/isSelectorSupported/index.native.js @@ -0,0 +1,4 @@ +// Native platforms do not support the selector +export default function isSelectorSupported() { + return false; +} From 66e5ffa7404a5c7c4a0fb3d8ff2ea667c0bffc8a Mon Sep 17 00:00:00 2001 From: Joel Davies Date: Mon, 5 Jun 2023 16:11:29 +0200 Subject: [PATCH 25/85] Immediately show [Deleted message] --- src/components/OfflineWithFeedback.js | 7 ++++++- src/libs/ReportActionsUtils.js | 9 +++++++++ src/libs/actions/Report.js | 1 + src/pages/home/report/ReportActionItem.js | 1 + src/pages/home/report/ReportActionItemFragment.js | 2 +- src/pages/home/report/ReportActionItemMessage.js | 2 ++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js index 9117492f2991..458b91dc2685 100644 --- a/src/components/OfflineWithFeedback.js +++ b/src/components/OfflineWithFeedback.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import compose from '../libs/compose'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import {withNetwork} from './OnyxProvider'; +import CONST from '../CONST'; import networkPropTypes from './networkPropTypes'; import stylePropTypes from '../styles/stylePropTypes'; import styles from '../styles/styles'; @@ -25,6 +26,9 @@ const propTypes = { /** The type of action that's pending */ pendingAction: PropTypes.oneOf(['add', 'update', 'delete']), + /** Determine whether to hide the component's children if deletion is pending */ + hideOnDelete: PropTypes.bool, + /** The errors to display */ // eslint-disable-next-line react/forbid-prop-types errors: PropTypes.object, @@ -55,6 +59,7 @@ const propTypes = { const defaultProps = { pendingAction: null, + hideOnDelete: true, errors: null, shouldShowErrorMessages: true, onClose: () => {}, @@ -88,7 +93,7 @@ const OfflineWithFeedback = (props) => { const isAddError = hasErrors && props.pendingAction === 'add'; const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError; const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete'; - const hideChildren = !props.network.isOffline && props.pendingAction === 'delete' && !hasErrors; + const hideChildren = props.hideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; let children = props.children; // Apply strikethrough to children if needed, but skip it if we are not going to render them diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 6b6a9d5637c6..c255760f5d87 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -56,6 +56,14 @@ function isMoneyRequestAction(reportAction) { return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.IOU; } +/** + * @param {Object} reportAction + * @returns {Boolean} + */ +function hasCommentThread(reportAction) { + return lodashGet(reportAction, 'childType', '') === CONST.REPORT.TYPE.CHAT; +} + /** * Returns the parentReportAction if the given report is a thread. * @@ -407,6 +415,7 @@ export { getLastClosedReportAction, getLatestReportActionFromOnyxData, isMoneyRequestAction, + hasCommentThread, getLinkedTransactionID, getReportPreviewAction, isCreatedTaskReportAction, diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 7910f0e5e798..0c124722c74c 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -798,6 +798,7 @@ function deleteReportComment(reportID, reportAction) { html: '', text: '', isEdited: true, + isDeletedParentAction: true, }, ]; const optimisticReportActions = { diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 03eb9407b8dc..d18c118fc228 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -447,6 +447,7 @@ function ReportActionItem(props) { ReportActions.clearReportActionErrors(props.report.reportID, props.action)} pendingAction={props.draftMessage ? null : props.action.pendingAction} + hideOnDelete={!ReportActionsUtils.hasCommentThread(props.action)} errors={props.action.errors} errorRowStyles={[styles.ml10, styles.mr2]} needsOffscreenAlphaCompositing={ReportActionsUtils.isMoneyRequestAction(props.action)} diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 05cba64e6236..19dc7717b2a0 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -97,7 +97,7 @@ const ReportActionItemFragment = (props) => { } const {html, text} = props.fragment; - if (props.fragment.isDeletedParentAction) { + if ((!props.network.isOffline && props.isCommentThread && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) || props.fragment.isDeletedParentAction) { return ${props.translate('parentReportAction.deletedMessage')}`} />; } diff --git a/src/pages/home/report/ReportActionItemMessage.js b/src/pages/home/report/ReportActionItemMessage.js index a764eafb84b7..e045a584edb6 100644 --- a/src/pages/home/report/ReportActionItemMessage.js +++ b/src/pages/home/report/ReportActionItemMessage.js @@ -5,6 +5,7 @@ import _ from 'underscore'; import lodashGet from 'lodash/get'; import styles from '../../../styles/styles'; import ReportActionItemFragment from './ReportActionItemFragment'; +import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; import reportActionPropTypes from './reportActionPropTypes'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; @@ -35,6 +36,7 @@ const ReportActionItemMessage = (props) => ( key={`actionFragment-${props.action.reportActionID}-${index}`} fragment={fragment} isAttachment={props.action.isAttachment} + isCommentThread={ReportActionsUtils.hasCommentThread(props.action)} attachmentInfo={props.action.attachmentInfo} pendingAction={props.action.pendingAction} source={lodashGet(props.action, 'originalMessage.source')} From 865e4131a1f9649bddf59aa2f1f05ac0dcce19d2 Mon Sep 17 00:00:00 2001 From: Joel Davies Date: Mon, 5 Jun 2023 16:21:37 +0200 Subject: [PATCH 26/85] Comments and naming tweak --- src/pages/home/report/ReportActionItemFragment.js | 4 +++- src/pages/home/report/ReportActionItemMessage.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 19dc7717b2a0..6703b74a3551 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -97,7 +97,9 @@ const ReportActionItemFragment = (props) => { } const {html, text} = props.fragment; - if ((!props.network.isOffline && props.isCommentThread && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) || props.fragment.isDeletedParentAction) { + // Threaded messages display a [Deleted message] note instead of being hidden altogether. + // When not offline we want to immediately display this message whilst the delete action is pending + if ((!props.network.isOffline && props.hasCommentThread && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) || props.fragment.isDeletedParentAction) { return ${props.translate('parentReportAction.deletedMessage')}`} />; } diff --git a/src/pages/home/report/ReportActionItemMessage.js b/src/pages/home/report/ReportActionItemMessage.js index e045a584edb6..aa8639ea071c 100644 --- a/src/pages/home/report/ReportActionItemMessage.js +++ b/src/pages/home/report/ReportActionItemMessage.js @@ -36,7 +36,7 @@ const ReportActionItemMessage = (props) => ( key={`actionFragment-${props.action.reportActionID}-${index}`} fragment={fragment} isAttachment={props.action.isAttachment} - isCommentThread={ReportActionsUtils.hasCommentThread(props.action)} + hasCommentThread={ReportActionsUtils.hasCommentThread(props.action)} attachmentInfo={props.action.attachmentInfo} pendingAction={props.action.pendingAction} source={lodashGet(props.action, 'originalMessage.source')} From 05d59796cad8884f654f916dff00b376814b555d Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 13:22:27 -0400 Subject: [PATCH 27/85] Use accountID for default avatar if no login --- src/pages/ProfilePage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 4588656574a5..d9a3589139a9 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -139,7 +139,7 @@ class ProfilePage extends React.PureComponent { @@ -152,7 +152,7 @@ class ProfilePage extends React.PureComponent { From 516daeb26f884921f4dc353e7ff608aeb9f6974b Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 15:38:11 -0400 Subject: [PATCH 28/85] Use new profile for report participants --- src/ROUTES.js | 4 ++-- src/libs/Navigation/AppNavigator/ModalStackNavigators.js | 4 ++-- src/pages/ReportParticipantsPage.js | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ROUTES.js b/src/ROUTES.js index 195c6101e8f7..3ca04de8e0f3 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -118,8 +118,8 @@ export default { getProfileRoute: (accountID) => `a/${accountID}`, REPORT_PARTICIPANTS: 'r/:reportID/participants', getReportParticipantsRoute: (reportID) => `r/${reportID}/participants`, - REPORT_PARTICIPANT: 'r/:reportID/participants/details', - getReportParticipantRoute: (reportID, login) => `r/${reportID}/participants/details?login=${encodeURIComponent(login)}`, + REPORT_PARTICIPANT: 'r/:reportID/participants/a/:accountID', + getReportParticipantRoute: (reportID, accountID) => `r/${reportID}/participants/a/${accountID}`, REPORT_WITH_ID_DETAILS: 'r/:reportID/details', getReportDetailsRoute: (reportID) => `r/${reportID}/details`, REPORT_SETTINGS: 'r/:reportID/settings', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index d8c0bfcf3ef5..994c58a5f0d3 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -233,8 +233,8 @@ const ReportParticipantsModalStackNavigator = createModalStackNavigator([ }, { getComponent: () => { - const DetailsPage = require('../../../pages/DetailsPage').default; - return DetailsPage; + const ProfilePage = require('../../../pages/ProfilePage').default; + return ProfilePage; }, name: 'ReportParticipants_Details', }, diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 81b4bb0ec2ab..85dee10c2bef 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -64,6 +64,7 @@ const getAllParticipants = (report, personalDetails) => { return { alternateText: userLogin, displayName: userPersonalDetail.displayName, + accountID: userPersonalDetail.accountID, icons: [ { source: UserUtils.getAvatar(userPersonalDetail.avatar, login), @@ -112,7 +113,7 @@ const ReportParticipantsPage = (props) => { }, ]} onSelectRow={(option) => { - Navigation.navigate(ROUTES.getReportParticipantRoute(props.route.params.reportID, option.login)); + Navigation.navigate(ROUTES.getReportParticipantRoute(props.route.params.reportID, option.accountID)); }} hideSectionHeaders showTitleTooltip From b28bf1c650d3c52fc54479fbba4b402ecf66b8fc Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 15:59:44 -0400 Subject: [PATCH 29/85] Make component functional --- src/libs/actions/PersonalDetails.js | 2 + src/pages/ProfilePage.js | 232 ++++++++++++++-------------- 2 files changed, 118 insertions(+), 116 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 0a2731609041..3e9a2c9d4f9c 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -312,6 +312,8 @@ function openPersonalDetailsPage() { /** * Fetches public profile info about a given user + * The API will only return the accountID, displayName, and avatar for the user + * But the profile page will use other info (e.g. contact methods and pronouns) if they are already available in Onyx * @param {Number} accountID */ function openPublicProfilePage(accountID) { diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index fe41ac84ddb6..049cda0de3e2 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -1,5 +1,5 @@ -import React from 'react'; import {View, ScrollView} from 'react-native'; +import React, {useEffect, useMemo} from 'react'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -88,132 +88,132 @@ const getPhoneNumber = (details) => { return details.login ? Str.removeSMSDomain(details.login) : ''; }; -class ProfilePage extends React.PureComponent { - componentDidMount() { - PersonalDetails.openPublicProfilePage(this.props.route.params.accountID); +function ProfilePage(props) { + const accountID = lodashGet(props.route.params, 'accountID', 0); + + useEffect(() => { + PersonalDetails.openPublicProfilePage(accountID); + }, [accountID]); + + const reportID = lodashGet(props.route.params, 'reportID', ''); + const details = lodashGet(props.personalDetails, accountID, {}); + const displayName = details.displayName ? details.displayName : props.translate('common.hidden'); + const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar()); + const originalFileName = lodashGet(details, 'originalFileName', ''); + const login = lodashGet(details, 'login', ''); + const timezone = lodashGet(details, 'timezone', {}); + + // If we have a reportID param this means that we + // arrived here via the ParticipantsPage and should be allowed to navigate back to it + const shouldShowBackButton = Boolean(reportID); + const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && !_.isEmpty(timezone); + + let pronouns = lodashGet(details, 'pronouns', ''); + if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { + const localeKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); + pronouns = props.translate(`pronouns.${localeKey}`); } - render() { - const accountID = lodashGet(this.props.route.params, 'accountID', 0); - const reportID = lodashGet(this.props.route.params, 'reportID', ''); - const details = lodashGet(this.props.personalDetails, accountID, {}); - const displayName = details.displayName ? details.displayName : this.props.translate('common.hidden'); - const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar()); - const originalFileName = lodashGet(details, 'originalFileName', ''); - const login = lodashGet(details, 'login', ''); - const timezone = lodashGet(details, 'timezone', {}); - - // If we have a reportID param this means that we - // arrived here via the ParticipantsPage and should be allowed to navigate back to it - const shouldShowBackButton = Boolean(reportID); - const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([login]) && !_.isEmpty(timezone); - - let pronouns = lodashGet(details, 'pronouns', ''); - if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { - const localeKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); - pronouns = this.props.translate(`pronouns.${localeKey}`); - } - - const isSMSLogin = Str.isSMSLogin(login); - const phoneNumber = getPhoneNumber(details); - const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; - - const isCurrentUser = _.keys(this.props.loginList).includes(login); - - return ( - - Navigation.goBack()} - onCloseButtonPress={() => Navigation.dismissModal()} - /> - - {_.isEmpty(details) ? ( - - ) : ( - - - + Navigation.goBack()} + onCloseButtonPress={() => Navigation.dismissModal()} + /> + + {_.isEmpty(details) ? ( + + ) : ( + + + + {({show}) => ( + + + + + + )} + + {Boolean(displayName) && ( + - {({show}) => ( - - - - - - )} - - {Boolean(displayName) && ( + {displayName} + + )} + {login ? ( + - {displayName} + {props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} - )} - {login ? ( - - - {this.props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} - - - - {isSMSLogin ? this.props.formatPhoneNumber(phoneNumber) : login} - - - - ) : null} - {pronouns ? ( - - - {this.props.translate('profilePage.preferredPronouns')} - - {pronouns} - - ) : null} - {shouldShowLocalTime && } - - {!isCurrentUser && Boolean(login) && ( - Report.navigateToAndOpenReport([login])} - wrapperStyle={styles.breakAll} - shouldShowRightIcon - /> - )} - - )} - - - ); - } + + + {isSMSLogin ? props.formatPhoneNumber(phoneNumber) : login} + + + + ) : null} + {pronouns ? ( + + + {props.translate('profilePage.preferredPronouns')} + + {pronouns} + + ) : null} + {shouldShowLocalTime && } + + {!isCurrentUser && Boolean(login) && ( + Report.navigateToAndOpenReport([login])} + wrapperStyle={styles.breakAll} + shouldShowRightIcon + /> + )} + + )} + + + ); } ProfilePage.propTypes = propTypes; ProfilePage.defaultProps = defaultProps; +ProfilePage.displayName = 'ProfilePage'; export default compose( withLocalize, From 3ef6eaa52bfc8b62499946db46614b9085d9c0b5 Mon Sep 17 00:00:00 2001 From: Duc Nguyen Date: Mon, 5 Jun 2023 23:17:39 +0300 Subject: [PATCH 30/85] Remove space between before and after curly brackets, use props instead of destruction --- src/components/CopyTextToClipboard.js | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index 84bc833446ff..b489f4dbbb11 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -1,5 +1,5 @@ -import React, { useCallback } from 'react'; -import { Pressable } from 'react-native'; +import React, {useCallback} from 'react'; +import {Pressable} from 'react-native'; import PropTypes from 'prop-types'; import Text from './Text'; import * as Expensicons from './Icon/Expensicons'; @@ -11,14 +11,15 @@ import Tooltip from './Tooltip'; import styles from '../styles/styles'; import * as StyleUtils from '../styles/StyleUtils'; import variables from '../styles/variables'; -import withLocalize, { withLocalizePropTypes } from './withLocalize'; -import withDelayToggleButtonState, { withDelayToggleButtonStatePropTypes } from './withDelayToggleButtonState'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState'; const propTypes = { /** The text to display and copy to the clipboard */ text: PropTypes.string.isRequired, /** Styles to apply to the text */ + // eslint-disable-next-line react/forbid-prop-types textStyles: PropTypes.arrayOf(PropTypes.object), ...withLocalizePropTypes, @@ -30,14 +31,14 @@ const defaultProps = { textStyles: [], }; -const CopyTextToClipboard = ({ text, textStyles, translate, isDelayButtonStateComplete, toggleDelayButtonState }) => { +const CopyTextToClipboard = (props) => { const copyToClipboard = useCallback(() => { - if (isDelayButtonStateComplete) { + if (props.isDelayButtonStateComplete) { return; } - Clipboard.setString(text); - toggleDelayButtonState(true); - }, [isDelayButtonStateComplete, text, toggleDelayButtonState]); + Clipboard.setString(props.text); + props.toggleDelayButtonState(true); + }, [props.isDelayButtonStateComplete, props.text, props.toggleDelayButtonState]); return ( - {`${text} `} - + {`${props.text} `} + - {({ hovered, pressed }) => ( + {({hovered, pressed}) => ( Date: Mon, 5 Jun 2023 23:30:19 +0300 Subject: [PATCH 31/85] Update with main, using PressableWithDelayToggle instead --- src/components/CopyTextToClipboard.js | 51 +++++++-------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index b489f4dbbb11..d880d042a04d 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -1,18 +1,9 @@ -import React, {useCallback} from 'react'; -import {Pressable} from 'react-native'; +import React from 'react'; import PropTypes from 'prop-types'; -import Text from './Text'; import * as Expensicons from './Icon/Expensicons'; -import compose from '../libs/compose'; +import PressableWithDelayToggle from './PressableWithDelayToggle'; import Clipboard from '../libs/Clipboard'; -import getButtonState from '../libs/getButtonState'; -import Icon from './Icon'; -import Tooltip from './Tooltip'; -import styles from '../styles/styles'; -import * as StyleUtils from '../styles/StyleUtils'; -import variables from '../styles/variables'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState'; const propTypes = { /** The text to display and copy to the clipboard */ @@ -23,8 +14,6 @@ const propTypes = { textStyles: PropTypes.arrayOf(PropTypes.object), ...withLocalizePropTypes, - - ...withDelayToggleButtonStatePropTypes, }; const defaultProps = { @@ -32,39 +21,23 @@ const defaultProps = { }; const CopyTextToClipboard = (props) => { - const copyToClipboard = useCallback(() => { - if (props.isDelayButtonStateComplete) { - return; - } + const copyToClipboard = () => { Clipboard.setString(props.text); - props.toggleDelayButtonState(true); - }, [props.isDelayButtonStateComplete, props.text, props.toggleDelayButtonState]); + } return ( - - {`${props.text} `} - - - {({hovered, pressed}) => ( - - )} - - - + /> ); } CopyTextToClipboard.propTypes = propTypes; CopyTextToClipboard.defaultProps = defaultProps; -export default compose(withLocalize, withDelayToggleButtonState)(CopyTextToClipboard); +export default withLocalize(CopyTextToClipboard); From a9631fc27817acfff7ac205a773bd551708ff7f7 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 17:04:25 -0400 Subject: [PATCH 32/85] Fix lint error --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 049cda0de3e2..081e7efc9c55 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -1,5 +1,5 @@ import {View, ScrollView} from 'react-native'; -import React, {useEffect, useMemo} from 'react'; +import React, {useEffect} from 'react'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; From c1d5958fb3fa72e043b65dc08d598aa2b04496d8 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 17:57:10 -0400 Subject: [PATCH 33/85] Add failed to load view --- src/libs/actions/PersonalDetails.js | 40 ++++++++++++++++++++++++++++- src/pages/ProfilePage.js | 18 ++++++++++--- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 3e9a2c9d4f9c..cd487d0021be 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -317,7 +317,45 @@ function openPersonalDetailsPage() { * @param {Number} accountID */ function openPublicProfilePage(accountID) { - API.read('OpenPublicProfilePage', {accountID}); + API.read( + 'OpenPublicProfilePage', + {accountID}, + { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: true, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, + }, + }, + ], + }, + ); } /** diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 081e7efc9c55..cbc77b413297 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -30,6 +30,9 @@ import AutoUpdateTime from '../components/AutoUpdateTime'; import * as UserUtils from '../libs/UserUtils'; import * as PersonalDetails from '../libs/actions/PersonalDetails'; import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; +import BlockingView from '../components/BlockingViews/BlockingView'; +import * as Illustrations from '../components/Icon/Illustrations'; +import variables from '../styles/variables'; const matchType = PropTypes.shape({ params: PropTypes.shape({ @@ -119,6 +122,8 @@ function ProfilePage(props) { const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; const isCurrentUser = _.keys(props.loginList).includes(login); + const hasMinimumDetails = !_.isEmpty(details.displayName) && !_.isEmpty(details.avatar); + const isLoading = lodashGet(details, 'isLoading', false) && !hasMinimumDetails; return ( @@ -132,9 +137,7 @@ function ProfilePage(props) { pointerEvents="box-none" style={[styles.containerWithSpaceBetween]} > - {_.isEmpty(details) ? ( - - ) : ( + {hasMinimumDetails && ( )} + {!hasMinimumDetails && isLoading && } + {!hasMinimumDetails && !isLoading && ( + + )} ); From 35502cea5a3bd38e9319107ad5874330fd8355c8 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Tue, 6 Jun 2023 03:08:30 +0500 Subject: [PATCH 34/85] feat: allow workspace pages access to authorised people only --- src/components/AutoEmailLink.js | 41 +++++++++++++++++++ src/components/BlockingViews/BlockingView.js | 6 ++- src/languages/en.js | 1 + src/languages/es.js | 1 + src/pages/workspace/WorkspaceInitialPage.js | 3 +- .../workspace/WorkspacePageWithSections.js | 4 +- 6 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/components/AutoEmailLink.js diff --git a/src/components/AutoEmailLink.js b/src/components/AutoEmailLink.js new file mode 100644 index 000000000000..859806eabd9a --- /dev/null +++ b/src/components/AutoEmailLink.js @@ -0,0 +1,41 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {CONST} from 'expensify-common/lib/CONST'; +import Text from './Text'; +import TextLink from './TextLink'; +import styles from '../styles/styles'; + +const propTypes = { + text: PropTypes.string.isRequired, + style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), +}; + +const defaultProps = { + style: [], +}; + +const AutoEmailLink = (props) => ( + + {_.map(props.text.split(CONST.REG_EXP.EXTRACT_EMAIL), (str, index) => { + if (CONST.REG_EXP.EMAIL.test(str)) { + return ( + + {str} + + ); + } + + return {str}; + })} + +); + +AutoEmailLink.displayName = 'AutoEmailLink'; +AutoEmailLink.propTypes = propTypes; +AutoEmailLink.defaultProps = defaultProps; +export default AutoEmailLink; diff --git a/src/components/BlockingViews/BlockingView.js b/src/components/BlockingViews/BlockingView.js index 0cee6396c801..3128debff407 100644 --- a/src/components/BlockingViews/BlockingView.js +++ b/src/components/BlockingViews/BlockingView.js @@ -8,6 +8,7 @@ import Text from '../Text'; import themeColors from '../../styles/themes/default'; import TextLink from '../TextLink'; import Navigation from '../../libs/Navigation/Navigation'; +import AutoEmailLink from '../AutoEmailLink'; const propTypes = { /** Expensicon for the page */ @@ -56,7 +57,10 @@ const BlockingView = (props) => ( height={props.iconHeight} /> {props.title} - {props.subtitle} + {props.shouldShowLink ? ( `Go to ${roomName} room`, }, emptyWorkspace: { diff --git a/src/languages/es.js b/src/languages/es.js index 2a0631bf9703..d0c994d58be7 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1076,6 +1076,7 @@ export default { growlMessageOnDeleteError: 'No se puede eliminar el espacio de trabajo porque tiene informes que están siendo procesados', unavailable: 'Espacio de trabajo no disponible', memberNotFound: 'Miembro no encontrado. Para invitar a un nuevo miembro al espacio de trabajo, por favor, utiliza el botón Invitar que está arriba.', + notAuthorized: `You do not have access to this page. Are you trying to join the workspace? Please reach out to the owner of this workspace so they can add you as a member! Something else? Reach out to ${CONST.EMAIL.CONCIERGE}`, goToRoom: ({roomName}) => `Ir a la sala ${roomName}`, }, emptyWorkspace: { diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 9cebeb235259..8747e0fdc495 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -163,8 +163,9 @@ const WorkspaceInitialPage = (props) => { {({safeAreaPaddingBottomStyle}) => ( Navigation.navigate(ROUTES.SETTINGS_WORKSPACES)} + shouldShow={_.isEmpty(props.policy) || !Policy.isPolicyOwner(props.policy)} + subtitleKey={_.isEmpty(props.policy) ? undefined : 'workspace.common.notAuthorized'} > Navigation.navigate(ROUTES.SETTINGS_WORKSPACES)} + shouldShow={_.isEmpty(this.props.policy) || !Policy.isPolicyOwner(this.props.policy)} + subtitleKey={_.isEmpty(this.props.policy) ? undefined : 'workspace.common.notAuthorized'} > Date: Tue, 6 Jun 2023 03:27:55 +0500 Subject: [PATCH 35/85] fix: center text in AutoEmailLink component on iOS --- src/components/AutoEmailLink.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/AutoEmailLink.js b/src/components/AutoEmailLink.js index 859806eabd9a..f25df01c934a 100644 --- a/src/components/AutoEmailLink.js +++ b/src/components/AutoEmailLink.js @@ -23,14 +23,21 @@ const AutoEmailLink = (props) => ( {str} ); } - return {str}; + return ( + + {str} + + ); })} ); From 61976f17be8f408d5644b6c8f5f83b98af9f5cb5 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 5 Jun 2023 20:01:41 -0400 Subject: [PATCH 36/85] Dont make subtitle requied on BlockingView --- src/components/BlockingViews/BlockingView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/BlockingViews/BlockingView.js b/src/components/BlockingViews/BlockingView.js index 0cee6396c801..078b5cb2a337 100644 --- a/src/components/BlockingViews/BlockingView.js +++ b/src/components/BlockingViews/BlockingView.js @@ -20,7 +20,7 @@ const propTypes = { title: PropTypes.string.isRequired, /** Subtitle message below the title */ - subtitle: PropTypes.string.isRequired, + subtitle: PropTypes.string, /** Link message below the subtitle */ link: PropTypes.string, @@ -40,6 +40,7 @@ const propTypes = { const defaultProps = { iconColor: themeColors.offline, + subtitle: '', shouldShowLink: false, link: 'notFound.goBackHome', iconWidth: variables.iconSizeSuperLarge, From 986f4104088f961cc31c652bf4f4c2ffcd704c32 Mon Sep 17 00:00:00 2001 From: VH Date: Tue, 6 Jun 2023 14:45:53 +0700 Subject: [PATCH 37/85] Fix user's name/picture is not dynamically updated if the emoji popup --- .../home/report/ReactionList/PopoverReactionList.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/pages/home/report/ReactionList/PopoverReactionList.js b/src/pages/home/report/ReactionList/PopoverReactionList.js index ba36c1ce09ff..216349d90b62 100644 --- a/src/pages/home/report/ReactionList/PopoverReactionList.js +++ b/src/pages/home/report/ReactionList/PopoverReactionList.js @@ -68,8 +68,8 @@ class PopoverReactionList extends React.Component { } shouldComponentUpdate(nextProps, nextState) { - const prevSelectedReaction = this.getSelectedReaction(this.props.reportActions, this.state.reportActionID, this.state.emojiName); const selectedReaction = this.getSelectedReaction(nextProps.reportActions, nextState.reportActionID, nextState.emojiName); + const {emojiCount, emojiCodes, hasUserReacted, users} = this.getReactionInformation(selectedReaction); const previousLocale = lodashGet(this.props, 'preferredLocale', 'en'); const nextLocale = lodashGet(nextProps, 'preferredLocale', 'en'); @@ -78,13 +78,12 @@ class PopoverReactionList extends React.Component { this.state.popoverAnchorPosition !== nextState.popoverAnchorPosition || previousLocale !== nextLocale || (this.state.isPopoverVisible && - (!_.isEqual(prevSelectedReaction, selectedReaction) || + (this.state.reportActionID !== nextState.reportActionID || this.state.emojiName !== nextState.emojiName || - this.state.emojiCount !== nextState.emojiCount || - this.state.hasUserReacted !== nextState.hasUserReacted || - this.state.reportActionID !== nextState.reportActionID || - !_.isEqual(this.state.emojiCodes, nextState.emojiCodes) || - !_.isEqual(this.state.users, nextState.users))) + this.state.emojiCount !== emojiCount || + this.state.hasUserReacted !== hasUserReacted || + !_.isEqual(this.state.emojiCodes, emojiCodes) || + !_.isEqual(this.state.users, users))) ); } From 11d838df1d12181ea6d7c2dcbd03bd54b1a151b4 Mon Sep 17 00:00:00 2001 From: VH Date: Tue, 6 Jun 2023 14:47:52 +0700 Subject: [PATCH 38/85] Use constants instead of hard coded text --- src/pages/home/report/ReactionList/PopoverReactionList.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReactionList/PopoverReactionList.js b/src/pages/home/report/ReactionList/PopoverReactionList.js index 216349d90b62..bd790af8cf5e 100644 --- a/src/pages/home/report/ReactionList/PopoverReactionList.js +++ b/src/pages/home/report/ReactionList/PopoverReactionList.js @@ -15,6 +15,7 @@ import withCurrentUserPersonalDetails from '../../../../components/withCurrentUs import * as PersonalDetailsUtils from '../../../../libs/PersonalDetailsUtils'; import emojis from '../../../../../assets/emojis'; import * as EmojiUtils from '../../../../libs/EmojiUtils'; +import CONST from '../../../../CONST'; const propTypes = { /** Actions from the ChatReport */ @@ -70,8 +71,8 @@ class PopoverReactionList extends React.Component { shouldComponentUpdate(nextProps, nextState) { const selectedReaction = this.getSelectedReaction(nextProps.reportActions, nextState.reportActionID, nextState.emojiName); const {emojiCount, emojiCodes, hasUserReacted, users} = this.getReactionInformation(selectedReaction); - const previousLocale = lodashGet(this.props, 'preferredLocale', 'en'); - const nextLocale = lodashGet(nextProps, 'preferredLocale', 'en'); + const previousLocale = lodashGet(this.props, 'preferredLocale', CONST.LOCALES.DEFAULT); + const nextLocale = lodashGet(nextProps, 'preferredLocale', CONST.LOCALES.DEFAULT); return ( this.state.isPopoverVisible !== nextState.isPopoverVisible || From 613673a8dc0fe37dacc7a5aa08dd470a2aa87479 Mon Sep 17 00:00:00 2001 From: chychkoi Date: Tue, 6 Jun 2023 01:29:08 -0700 Subject: [PATCH 39/85] Migrate TermsStep.js to function component --- src/pages/EnablePayments/TermsStep.js | 165 ++++++++++++-------------- 1 file changed, 75 insertions(+), 90 deletions(-) diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.js index 7a145b8a70f4..503b4fb79837 100644 --- a/src/pages/EnablePayments/TermsStep.js +++ b/src/pages/EnablePayments/TermsStep.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useEffect, useMemo, useState} from 'react'; import {ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; @@ -28,107 +28,92 @@ const defaultProps = { walletTerms: {}, }; -class TermsStep extends React.Component { - constructor(props) { - super(props); +const TermsStep = ({translate, walletTerms}) => { + const [hasAcceptedDisclosure, setHasAcceptedDisclosure] = useState(false); + const [hasAcceptedPrivacyPolicyAndWalletAgreement, setHasAcceptedPrivacyPolicyAndWalletAgreement] = useState(false); + const [error, setError] = useState(false); - this.toggleDisclosure = this.toggleDisclosure.bind(this); - this.togglePrivacyPolicy = this.togglePrivacyPolicy.bind(this); - this.state = { - hasAcceptedDisclosure: false, - hasAcceptedPrivacyPolicyAndWalletAgreement: false, - error: false, - }; - } + const errorMessage = useMemo(() => error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(walletTerms) || '', [error, walletTerms]); - clearError() { - if (!this.state.hasAcceptedDisclosure || !this.state.hasAcceptedPrivacyPolicyAndWalletAgreement) { - return; - } + const toggleDisclosure = () => { + setHasAcceptedDisclosure(!hasAcceptedDisclosure); + }; - this.setState({error: false}); - } + const togglePrivacyPolicy = () => { + setHasAcceptedPrivacyPolicyAndWalletAgreement(!hasAcceptedPrivacyPolicyAndWalletAgreement); + }; - toggleDisclosure() { - this.setState( - (prevState) => ({hasAcceptedDisclosure: !prevState.hasAcceptedDisclosure}), - () => this.clearError(), - ); - } + /** clear error */ + useEffect(() => { + if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { + return; + } - togglePrivacyPolicy() { - this.setState( - (prevState) => ({ - hasAcceptedPrivacyPolicyAndWalletAgreement: !prevState.hasAcceptedPrivacyPolicyAndWalletAgreement, - }), - () => this.clearError(), - ); - } + setError(false); + }, [hasAcceptedDisclosure, hasAcceptedPrivacyPolicyAndWalletAgreement]); - render() { - const errorMessage = this.state.error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(this.props.walletTerms) || ''; - return ( - <> - Navigation.dismissModal()} + return ( + <> + Navigation.dismissModal()} + /> + + + + ( + + {`${translate('termsStep.haveReadAndAgree')}`} + {`${translate('termsStep.electronicDisclosures')}.`} + + )} /> - - - - ( - - {`${this.props.translate('termsStep.haveReadAndAgree')}`} - {`${this.props.translate('termsStep.electronicDisclosures')}.`} - - )} - /> - ( - - {`${this.props.translate('termsStep.agreeToThe')} `} + ( + + {`${translate('termsStep.agreeToThe')} `} - {`${this.props.translate('common.privacy')} `} + {`${translate('common.privacy')} `} - {`${this.props.translate('common.and')} `} + {`${translate('common.and')} `} - {`${this.props.translate('termsStep.walletAgreement')}.`} - - )} - /> - { - if (!this.state.hasAcceptedDisclosure || !this.state.hasAcceptedPrivacyPolicyAndWalletAgreement) { - this.setState({error: true}); - return; - } + {`${translate('termsStep.walletAgreement')}.`} + + )} + /> + { + if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { + setError(true); + return; + } - this.setState({error: false}); - BankAccounts.acceptWalletTerms({ - hasAcceptedTerms: this.state.hasAcceptedDisclosure && this.state.hasAcceptedPrivacyPolicyAndWalletAgreement, - chatReportID: this.props.walletTerms.chatReportID, - }); - }} - message={errorMessage} - isAlertVisible={this.state.error || Boolean(errorMessage)} - containerStyles={[styles.mh0, styles.mv4]} - /> - - - ); - } -} + setError(false); + BankAccounts.acceptWalletTerms({ + hasAcceptedTerms: hasAcceptedDisclosure && hasAcceptedPrivacyPolicyAndWalletAgreement, + chatReportID: walletTerms.chatReportID, + }); + }} + message={errorMessage} + isAlertVisible={error || Boolean(errorMessage)} + containerStyles={[styles.mh0, styles.mv4]} + /> + + + ); +}; +TermsStep.displayName = "TermsPage"; TermsStep.propTypes = propTypes; TermsStep.defaultProps = defaultProps; export default compose( From 8fd388b3aaa9ce01d0fb19cb628b8f24a64bd6af Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 6 Jun 2023 16:17:20 +0530 Subject: [PATCH 40/85] feat: extracted camera icon from OfflineWithFeedback --- src/components/AvatarWithImagePicker.js | 58 ++++++++++++++------ src/pages/settings/Profile/ProfilePage.js | 24 ++++---- src/pages/workspace/WorkspaceSettingsPage.js | 55 +++++++++---------- 3 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index 1ce12b6033ae..d4ae8efd2277 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -12,6 +12,7 @@ import themeColors from '../styles/themes/default'; import AttachmentPicker from './AttachmentPicker'; import ConfirmModal from './ConfirmModal'; import AvatarCropModal from './AvatarCropModal/AvatarCropModal'; +import OfflineWithFeedback from './OfflineWithFeedback'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import variables from '../styles/variables'; import CONST from '../CONST'; @@ -63,6 +64,19 @@ const propTypes = { /** Image crop vector mask */ editorMaskImage: PropTypes.func, + /** Additional style object for the error row */ + errorRowStyles: stylePropTypes, + + /** A function to run when the X button next to the error is clicked */ + onErrorClose: PropTypes.func, + + /** The type of action that's pending */ + pendingAction: PropTypes.oneOf(['add', 'update', 'delete']), + + /** The errors to display */ + // eslint-disable-next-line react/forbid-prop-types + errors: PropTypes.object, + ...withLocalizePropTypes, }; @@ -78,6 +92,10 @@ const defaultProps = { fallbackIcon: Expensicons.FallbackAvatar, type: CONST.ICON_TYPE_AVATAR, editorMaskImage: undefined, + errorRowStyles: [], + onErrorClose: () => {}, + pendingAction: null, + errors: null, }; class AvatarWithImagePicker extends React.Component { @@ -258,22 +276,30 @@ class AvatarWithImagePicker extends React.Component { this.setState({isMenuVisible: true})}> - - - {this.props.source ? ( - - ) : ( - - )} - - + + + + {this.props.source ? ( + + ) : ( + + )} + + + + {({openPicker}) => ( <> diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js index d58cb4ceec3d..5df2856ee529 100755 --- a/src/pages/settings/Profile/ProfilePage.js +++ b/src/pages/settings/Profile/ProfilePage.js @@ -9,7 +9,6 @@ import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; import MenuItem from '../../../components/MenuItem'; import MenuItemWithTopDescription from '../../../components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '../../../components/OfflineWithFeedback'; import ScreenWrapper from '../../../components/ScreenWrapper'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '../../../components/withCurrentUserPersonalDetails'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; @@ -90,22 +89,19 @@ const ProfilePage = (props) => { onCloseButtonPress={() => Navigation.dismissModal(true)} /> - - - + onErrorClose={PersonalDetails.clearAvatarErrors} + /> {_.map(profileSettingsOptions, (detail, index) => ( - ( + + )} + type={CONST.ICON_TYPE_WORKSPACE} + fallbackIcon={Expensicons.FallbackWorkspaceAvatar} + style={[styles.mb3]} + anchorPosition={styles.createMenuPositionProfile(props.windowWidth)} + anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} + isUsingDefaultAvatar={!lodashGet(props.policy, 'avatar', null)} + onImageSelected={(file) => Policy.updateWorkspaceAvatar(lodashGet(props.policy, 'id', ''), file)} + onImageRemoved={() => Policy.deleteWorkspaceAvatar(lodashGet(props.policy, 'id', ''))} + editorMaskImage={Expensicons.ImageCropSquareMask} pendingAction={lodashGet(props.policy, 'pendingFields.avatar', null)} errors={lodashGet(props.policy, 'errorFields.avatar', null)} - onClose={() => Policy.clearAvatarErrors(props.policy.id)} - > - ( - - )} - type={CONST.ICON_TYPE_WORKSPACE} - fallbackIcon={Expensicons.FallbackWorkspaceAvatar} - style={[styles.mb3]} - anchorPosition={styles.createMenuPositionProfile(props.windowWidth)} - anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} - isUsingDefaultAvatar={!lodashGet(props.policy, 'avatar', null)} - onImageSelected={(file) => Policy.updateWorkspaceAvatar(lodashGet(props.policy, 'id', ''), file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(lodashGet(props.policy, 'id', ''))} - editorMaskImage={Expensicons.ImageCropSquareMask} - /> - + onErrorClose={() => Policy.clearAvatarErrors(props.policy.id)} + /> Date: Tue, 6 Jun 2023 10:08:20 -0400 Subject: [PATCH 41/85] Fix not found page showing after loading --- src/pages/ProfilePage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index cbc77b413297..e6c80c68ebe9 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -122,8 +122,8 @@ function ProfilePage(props) { const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; const isCurrentUser = _.keys(props.loginList).includes(login); - const hasMinimumDetails = !_.isEmpty(details.displayName) && !_.isEmpty(details.avatar); - const isLoading = lodashGet(details, 'isLoading', false) && !hasMinimumDetails; + const hasMinimumDetails = !_.isEmpty(details.avatar); + const isLoading = lodashGet(details, 'isLoading', false); return ( From c10f7317e40d82840143f7b2fe86e7ca3f1c2919 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 6 Jun 2023 22:53:27 +0800 Subject: [PATCH 42/85] allow edit by up key on thread parent message --- src/pages/home/report/ReportActionCompose.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 4a4e6a722225..3f0bd7163ed7 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -833,7 +833,9 @@ class ReportActionCompose extends React.Component { ) { e.preventDefault(); - const lastReportAction = _.find(this.props.reportActions, (action) => ReportUtils.canEditReportAction(action)); + const parentReportActionID = lodashGet(this.props.report, 'parentReportActionID', ''); + const parentReportAction = lodashGet(this.props.parentReportActions, [parentReportActionID], {}); + const lastReportAction = _.find([...this.props.reportActions, parentReportAction], (action) => ReportUtils.canEditReportAction(action)); if (lastReportAction !== -1 && lastReportAction) { Report.saveReportActionDraft(this.props.reportID, lastReportAction.reportActionID, _.last(lastReportAction.message).html); @@ -1263,5 +1265,9 @@ export default compose( shouldShowComposeInput: { key: ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT, }, + parentReportActions: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, + canEvict: false, + }, }), )(ReportActionCompose); From 85b2d11693e3a6cebd761bb1c26edab8334d7228 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 6 Jun 2023 23:09:31 +0800 Subject: [PATCH 43/85] add proptypes --- src/pages/home/report/ReportActionCompose.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 3f0bd7163ed7..8ada1cf73061 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -87,6 +87,9 @@ const propTypes = { /** Array of report actions for this report */ reportActions: PropTypes.arrayOf(PropTypes.shape(reportActionPropTypes)), + /** The actions from the parent report */ + parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), + /** Is the report view covered by the drawer */ isDrawerOpen: PropTypes.bool.isRequired, @@ -130,6 +133,7 @@ const defaultProps = { modal: {}, report: {}, reportActions: [], + parentReportAcions: {}, blockedFromConcierge: {}, personalDetails: {}, preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, From 4554e704a6ad0820af141110fc220c9d2349080e Mon Sep 17 00:00:00 2001 From: s-alves10 Date: Tue, 6 Jun 2023 10:09:57 -0500 Subject: [PATCH 44/85] fix: change word splitting logic in WrappedText to include emojis --- src/CONST.js | 4 ++++ src/components/InlineCodeBlock/WrappedText.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index f4e2847ba7a5..07b10aa3e21a 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1121,6 +1121,10 @@ const CONST = { SPECIAL_CHAR_OR_EMOJI: // eslint-disable-next-line no-misleading-character-class /[\n\s,/?"{}[\]()&^%$#<>!*\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, + + EMOJI_WORD_SPLITTER: + // eslint-disable-next-line no-misleading-character-class + /(\s+|(?:[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3)+)/gu, // Define the regular expression pattern to match a string starting with an at sign and ending with a space or newline character MENTION_REPLACER: diff --git a/src/components/InlineCodeBlock/WrappedText.js b/src/components/InlineCodeBlock/WrappedText.js index 5a39ccf01e2c..6613b1c65851 100644 --- a/src/components/InlineCodeBlock/WrappedText.js +++ b/src/components/InlineCodeBlock/WrappedText.js @@ -4,6 +4,7 @@ import {View} from 'react-native'; import PropTypes from 'prop-types'; import styles from '../../styles/styles'; import Text from '../Text'; +import CONST from '../../CONST'; /** * Breaks the text into matrix @@ -16,7 +17,7 @@ import Text from '../Text'; * @returns {Array} */ function getTextMatrix(text) { - return _.map(text.split('\n'), (row) => _.without(row.split(/(\s)/), '')); + return _.map(text.split('\n'), (row) => _.without(row.split(CONST.REGEX.EMOJI_WORD_SPLITTER), '')); } const propTypes = { From a84f8598732d2fd67b88e13eff6eef697c4ccb1e Mon Sep 17 00:00:00 2001 From: s-alves10 Date: Tue, 6 Jun 2023 10:11:00 -0500 Subject: [PATCH 45/85] fix: increase code word-wrapper, word-style and text-style height and line-height --- src/styles/codeStyles/index.ios.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/styles/codeStyles/index.ios.js b/src/styles/codeStyles/index.ios.js index 65b1eaef718f..2f337ad785e2 100644 --- a/src/styles/codeStyles/index.ios.js +++ b/src/styles/codeStyles/index.ios.js @@ -1,15 +1,15 @@ const codeWordWrapper = { - height: 20, + height: 22, justifyContent: 'center', }; const codeWordStyle = { - height: 16, + height: 18, top: 4, }; const codeTextStyle = { - lineHeight: 15, + lineHeight: 18, }; export default {codeWordWrapper, codeWordStyle, codeTextStyle}; From aa21afb335fceacc94bd971adeb49dccf4481435 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 6 Jun 2023 23:15:54 +0800 Subject: [PATCH 46/85] fix typo --- src/pages/home/report/ReportActionCompose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 8ada1cf73061..67b89e8ee438 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -133,7 +133,7 @@ const defaultProps = { modal: {}, report: {}, reportActions: [], - parentReportAcions: {}, + parentReportActions: {}, blockedFromConcierge: {}, personalDetails: {}, preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, From 6949923f431972508d8446e99ceac120ddeb2812 Mon Sep 17 00:00:00 2001 From: s-alves10 Date: Tue, 6 Jun 2023 12:13:09 -0500 Subject: [PATCH 47/85] fix: run prettier --- src/CONST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index 07b10aa3e21a..19844795ec0a 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1121,7 +1121,7 @@ const CONST = { SPECIAL_CHAR_OR_EMOJI: // eslint-disable-next-line no-misleading-character-class /[\n\s,/?"{}[\]()&^%$#<>!*\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, - + EMOJI_WORD_SPLITTER: // eslint-disable-next-line no-misleading-character-class /(\s+|(?:[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3)+)/gu, From d44469cddc67c55ea3368faa333d0ebfc623678f Mon Sep 17 00:00:00 2001 From: chychkoi Date: Tue, 6 Jun 2023 10:14:07 -0700 Subject: [PATCH 48/85] Update code style --- src/pages/EnablePayments/TermsStep.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.js index 503b4fb79837..63b1002a6974 100644 --- a/src/pages/EnablePayments/TermsStep.js +++ b/src/pages/EnablePayments/TermsStep.js @@ -1,4 +1,4 @@ -import React, {useEffect, useMemo, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import {ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; @@ -28,12 +28,12 @@ const defaultProps = { walletTerms: {}, }; -const TermsStep = ({translate, walletTerms}) => { +function TermsStep(props) { const [hasAcceptedDisclosure, setHasAcceptedDisclosure] = useState(false); const [hasAcceptedPrivacyPolicyAndWalletAgreement, setHasAcceptedPrivacyPolicyAndWalletAgreement] = useState(false); const [error, setError] = useState(false); - const errorMessage = useMemo(() => error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(walletTerms) || '', [error, walletTerms]); + const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms) || ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); @@ -55,7 +55,7 @@ const TermsStep = ({translate, walletTerms}) => { return ( <> Navigation.dismissModal()} /> { onInputChange={toggleDisclosure} LabelComponent={() => ( - {`${translate('termsStep.haveReadAndAgree')}`} - {`${translate('termsStep.electronicDisclosures')}.`} + {`${props.translate('termsStep.haveReadAndAgree')}`} + {`${props.translate('termsStep.electronicDisclosures')}.`} )} /> @@ -80,18 +80,18 @@ const TermsStep = ({translate, walletTerms}) => { onInputChange={togglePrivacyPolicy} LabelComponent={() => ( - {`${translate('termsStep.agreeToThe')} `} + {`${props.translate('termsStep.agreeToThe')} `} - {`${translate('common.privacy')} `} + {`${props.translate('common.privacy')} `} - {`${translate('common.and')} `} + {`${props.translate('common.and')} `} - {`${translate('termsStep.walletAgreement')}.`} + {`${props.translate('termsStep.walletAgreement')}.`} )} /> { if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { setError(true); @@ -101,7 +101,7 @@ const TermsStep = ({translate, walletTerms}) => { setError(false); BankAccounts.acceptWalletTerms({ hasAcceptedTerms: hasAcceptedDisclosure && hasAcceptedPrivacyPolicyAndWalletAgreement, - chatReportID: walletTerms.chatReportID, + chatReportID: props.walletTerms.chatReportID, }); }} message={errorMessage} @@ -111,7 +111,7 @@ const TermsStep = ({translate, walletTerms}) => { ); -}; +} TermsStep.displayName = "TermsPage"; TermsStep.propTypes = propTypes; From 79c6be448fdff627da32a943b720016a1a27956c Mon Sep 17 00:00:00 2001 From: s-alves10 Date: Tue, 6 Jun 2023 14:27:31 -0500 Subject: [PATCH 49/85] fix: rename to SPACE_OR_EMOJI --- src/CONST.js | 2 +- src/components/InlineCodeBlock/WrappedText.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 19844795ec0a..e9fa722ac137 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1122,7 +1122,7 @@ const CONST = { // eslint-disable-next-line no-misleading-character-class /[\n\s,/?"{}[\]()&^%$#<>!*\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, - EMOJI_WORD_SPLITTER: + SPACE_OR_EMOJI: // eslint-disable-next-line no-misleading-character-class /(\s+|(?:[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3)+)/gu, diff --git a/src/components/InlineCodeBlock/WrappedText.js b/src/components/InlineCodeBlock/WrappedText.js index 6613b1c65851..c13b007e0b1b 100644 --- a/src/components/InlineCodeBlock/WrappedText.js +++ b/src/components/InlineCodeBlock/WrappedText.js @@ -17,7 +17,7 @@ import CONST from '../../CONST'; * @returns {Array} */ function getTextMatrix(text) { - return _.map(text.split('\n'), (row) => _.without(row.split(CONST.REGEX.EMOJI_WORD_SPLITTER), '')); + return _.map(text.split('\n'), (row) => _.without(row.split(CONST.REGEX.SPACE_OR_EMOJI), '')); } const propTypes = { From bb18f2274713a619514e21b3059534d61be41027 Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Tue, 6 Jun 2023 22:46:27 +0200 Subject: [PATCH 50/85] fix welcome message value not trimmed --- src/pages/ReportWelcomeMessagePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.js index 0c6ef5f9dc52..3b6375164115 100644 --- a/src/pages/ReportWelcomeMessagePage.js +++ b/src/pages/ReportWelcomeMessagePage.js @@ -44,7 +44,7 @@ function ReportWelcomeMessagePage(props) { }, []); const submitForm = useCallback(() => { - Report.updateWelcomeMessage(props.report.reportID, props.report.welcomeMessage, welcomeMessage); + Report.updateWelcomeMessage(props.report.reportID, props.report.welcomeMessage, welcomeMessage.trim()); }, [props.report.reportID, props.report.welcomeMessage, welcomeMessage]); return ( From f5ff4040e9e01a9025b75b5ac89831f1c5b4a6c7 Mon Sep 17 00:00:00 2001 From: Duc Nguyen Date: Wed, 7 Jun 2023 00:22:50 +0300 Subject: [PATCH 51/85] Fix lint, useCallback for copyToClipboard, add displayName = CopyTextToClipboard --- src/components/CopyTextToClipboard.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index d880d042a04d..bf393e6aa2bc 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import PropTypes from 'prop-types'; import * as Expensicons from './Icon/Expensicons'; import PressableWithDelayToggle from './PressableWithDelayToggle'; @@ -21,9 +21,9 @@ const defaultProps = { }; const CopyTextToClipboard = (props) => { - const copyToClipboard = () => { + const copyToClipboard = useCallback(() => { Clipboard.setString(props.text); - } + }, [props.text]); return ( { CopyTextToClipboard.propTypes = propTypes; CopyTextToClipboard.defaultProps = defaultProps; +CopyTextToClipboard.displayName = 'CopyTextToClipboard'; export default withLocalize(CopyTextToClipboard); From ef4c5ee54ffb15c8664037c052304432ae8a7792 Mon Sep 17 00:00:00 2001 From: Joel Davies Date: Wed, 7 Jun 2023 10:16:24 +0200 Subject: [PATCH 52/85] Tweaks to comments and naming --- src/components/OfflineWithFeedback.js | 6 +++--- src/pages/home/report/ReportActionItem.js | 2 +- src/pages/home/report/ReportActionItemFragment.js | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js index 458b91dc2685..7854126da87d 100644 --- a/src/components/OfflineWithFeedback.js +++ b/src/components/OfflineWithFeedback.js @@ -27,7 +27,7 @@ const propTypes = { pendingAction: PropTypes.oneOf(['add', 'update', 'delete']), /** Determine whether to hide the component's children if deletion is pending */ - hideOnDelete: PropTypes.bool, + shouldHideOnDelete: PropTypes.bool, /** The errors to display */ // eslint-disable-next-line react/forbid-prop-types @@ -59,7 +59,7 @@ const propTypes = { const defaultProps = { pendingAction: null, - hideOnDelete: true, + shouldHideOnDelete: true, errors: null, shouldShowErrorMessages: true, onClose: () => {}, @@ -93,7 +93,7 @@ const OfflineWithFeedback = (props) => { const isAddError = hasErrors && props.pendingAction === 'add'; const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError; const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete'; - const hideChildren = props.hideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; + const hideChildren = props.shouldHideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; let children = props.children; // Apply strikethrough to children if needed, but skip it if we are not going to render them diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index d18c118fc228..e98fc4fdd6f1 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -447,7 +447,7 @@ function ReportActionItem(props) { ReportActions.clearReportActionErrors(props.report.reportID, props.action)} pendingAction={props.draftMessage ? null : props.action.pendingAction} - hideOnDelete={!ReportActionsUtils.hasCommentThread(props.action)} + shouldHideOnDelete={!ReportActionsUtils.hasCommentThread(props.action)} errors={props.action.errors} errorRowStyles={[styles.ml10, styles.mr2]} needsOffscreenAlphaCompositing={ReportActionsUtils.isMoneyRequestAction(props.action)} diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 6703b74a3551..d1aa0cf7ddac 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -97,8 +97,10 @@ const ReportActionItemFragment = (props) => { } const {html, text} = props.fragment; - // Threaded messages display a [Deleted message] note instead of being hidden altogether. - // When not offline we want to immediately display this message whilst the delete action is pending + // Threaded messages display "[Deleted message]" instead of being hidden altogether. + // While offline we display the previous message with a strikethrough style. Once online we want to + // immediately display "[Deleted message]" while the delete action is pending. + if ((!props.network.isOffline && props.hasCommentThread && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) || props.fragment.isDeletedParentAction) { return ${props.translate('parentReportAction.deletedMessage')}`} />; } From 4d185c2ed871f974df78391a7db732121ed0e29a Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 7 Jun 2023 13:18:44 +0100 Subject: [PATCH 53/85] non negative check for clearer reading --- src/libs/ReportUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 1b69de6337ae..f4413b4b4156 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -556,7 +556,7 @@ function getChatRoomSubtitle(report) { } } - return !roomName ? workspaceName : [workspaceName, roomName].join(' • '); + return roomName ? [workspaceName, roomName].join(' • ') : workspaceName; } if (!isDefaultRoom(report) && !isUserCreatedPolicyRoom(report) && !isPolicyExpenseChat(report)) { return ''; From eb7584bfb40b0ad2b3495eb7cfe726c77fbe8e92 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 7 Jun 2023 18:47:31 +0100 Subject: [PATCH 54/85] Update the trigger condition for the reassure workflow --- .github/workflows/reassurePerformanceTests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reassurePerformanceTests.yml b/.github/workflows/reassurePerformanceTests.yml index 9894efeb9001..fe0d8616f3dd 100644 --- a/.github/workflows/reassurePerformanceTests.yml +++ b/.github/workflows/reassurePerformanceTests.yml @@ -1,10 +1,9 @@ name: Reassure Performance Tests on: - push: - branches: [main] pull_request: - branches: ['**'] + types: [opened, synchronize] + branches-ignore: [staging, production] jobs: perf-tests: From 1c95fff10a8e4cec1a57ba2cd7dd605756a8ec18 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 7 Jun 2023 19:09:44 +0100 Subject: [PATCH 55/85] Test commit --- contributingGuides/NAVIGATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributingGuides/NAVIGATION.md b/contributingGuides/NAVIGATION.md index 6a01d6984ed9..53313902730f 100644 --- a/contributingGuides/NAVIGATION.md +++ b/contributingGuides/NAVIGATION.md @@ -1 +1 @@ -This is a placeholder for the documentation of how navigation is implemented in the App. +This is a placeholder for the documentation of how navigation is implemented in the App. Test From 736a620f8dcf86d21e18bba08087b976310cd19d Mon Sep 17 00:00:00 2001 From: Duc Nguyen Date: Wed, 7 Jun 2023 22:06:29 +0300 Subject: [PATCH 56/85] Run prettier --- src/components/CopyTextToClipboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js index bf393e6aa2bc..1f9affab67d4 100644 --- a/src/components/CopyTextToClipboard.js +++ b/src/components/CopyTextToClipboard.js @@ -35,7 +35,7 @@ const CopyTextToClipboard = (props) => { onPress={copyToClipboard} /> ); -} +}; CopyTextToClipboard.propTypes = propTypes; CopyTextToClipboard.defaultProps = defaultProps; From bbbfea6fa20c5d68100ec62b05968ee42b144041 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Thu, 8 Jun 2023 00:15:51 +0500 Subject: [PATCH 57/85] fix: add spanish translations for un-authorized workspace access --- src/components/AutoEmailLink.js | 6 ++++++ src/languages/es.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/AutoEmailLink.js b/src/components/AutoEmailLink.js index f25df01c934a..f99c8ea76f3c 100644 --- a/src/components/AutoEmailLink.js +++ b/src/components/AutoEmailLink.js @@ -15,6 +15,12 @@ const defaultProps = { style: [], }; +/* + * This is a "utility component", that does this: + * - Checks if a text contains any email. If it does, render it as a mailto: link + * - Else just render it inside `Text` component + */ + const AutoEmailLink = (props) => ( {_.map(props.text.split(CONST.REG_EXP.EXTRACT_EMAIL), (str, index) => { diff --git a/src/languages/es.js b/src/languages/es.js index e1265d0b1353..eb710750b0eb 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1078,7 +1078,7 @@ export default { growlMessageOnDeleteError: 'No se puede eliminar el espacio de trabajo porque tiene informes que están siendo procesados', unavailable: 'Espacio de trabajo no disponible', memberNotFound: 'Miembro no encontrado. Para invitar a un nuevo miembro al espacio de trabajo, por favor, utiliza el botón Invitar que está arriba.', - notAuthorized: `You do not have access to this page. Are you trying to join the workspace? Please reach out to the owner of this workspace so they can add you as a member! Something else? Reach out to ${CONST.EMAIL.CONCIERGE}`, + notAuthorized: `No tienes acceso a esta página. ¿Estás tratando de unirte al espacio de trabajo? Comunícate con el propietario de este espacio de trabajo para que pueda agregarte como miembro. ¿Necesitas algo más? Comunícate con ${CONST.EMAIL.CONCIERGE}`, goToRoom: ({roomName}) => `Ir a la sala ${roomName}`, }, emptyWorkspace: { From 29c025af4860455e82d713188a6595480972478d Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Thu, 8 Jun 2023 00:25:58 +0500 Subject: [PATCH 58/85] fix: render error before continue bank account setup button --- .../ReimbursementAccountPage.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js index a7cf6f4d4a1b..7e18a7edbdc2 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js @@ -343,16 +343,6 @@ class ReimbursementAccountPage extends React.Component { ); } - if (this.state.shouldShowContinueSetupButton) { - return ( - - ); - } - let errorComponent; const userHasPhonePrimaryEmail = Str.endsWith(this.props.session.email, CONST.SMS.DOMAIN); @@ -386,6 +376,16 @@ class ReimbursementAccountPage extends React.Component { ); } + if (this.state.shouldShowContinueSetupButton) { + return ( + + ); + } + if (currentStep === CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT) { return ( Date: Wed, 7 Jun 2023 22:41:44 +0000 Subject: [PATCH 59/85] Update version to 1.3.25-5 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 6 +++--- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1b58063e217e..94e6717829b0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032504 - versionName "1.3.25-4" + versionCode 1001032505 + versionName "1.3.25-5" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 3a7b72c3e9ec..5012de71c0af 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion en CFBundleDisplayName @@ -30,7 +32,7 @@ CFBundleVersion - 1.3.25.4 + 1.3.25.5 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes @@ -114,7 +116,5 @@ Dark UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 63839481a570..5aedd70fb3aa 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.3.25.4 + 1.3.25.5 diff --git a/package-lock.json b/package-lock.json index f39a002a5a57..7992f8766475 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.25-4", + "version": "1.3.25-5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.25-4", + "version": "1.3.25-5", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index bacfa85258a7..4c2361aacbcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.25-4", + "version": "1.3.25-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.", From 36e97df3f40bd5bfc1de12d22f20f4eb73a62351 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 7 Jun 2023 15:49:06 -0700 Subject: [PATCH 60/85] Skip reassure tests for OSBotify --- .github/workflows/reassurePerformanceTests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/reassurePerformanceTests.yml b/.github/workflows/reassurePerformanceTests.yml index 9894efeb9001..349ce45c5786 100644 --- a/.github/workflows/reassurePerformanceTests.yml +++ b/.github/workflows/reassurePerformanceTests.yml @@ -8,6 +8,7 @@ on: jobs: perf-tests: + if: ${{ github.actor != 'OSBotify' }} runs-on: ubuntu-latest steps: - name: Checkout From 68176c4504cd9ca0a1f1cbefe58a7bb26a31069e Mon Sep 17 00:00:00 2001 From: Daniel Gale-Rosen Date: Wed, 7 Jun 2023 15:49:33 -0700 Subject: [PATCH 61/85] add back button back --- src/pages/iou/SplitBillDetailsPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/iou/SplitBillDetailsPage.js b/src/pages/iou/SplitBillDetailsPage.js index a2354e6a2502..e0c9129712c0 100644 --- a/src/pages/iou/SplitBillDetailsPage.js +++ b/src/pages/iou/SplitBillDetailsPage.js @@ -77,7 +77,6 @@ const SplitBillDetailsPage = (props) => { Date: Wed, 7 Jun 2023 23:50:24 +0100 Subject: [PATCH 62/85] Update NAVIGATION.md --- contributingGuides/NAVIGATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributingGuides/NAVIGATION.md b/contributingGuides/NAVIGATION.md index 53313902730f..6a01d6984ed9 100644 --- a/contributingGuides/NAVIGATION.md +++ b/contributingGuides/NAVIGATION.md @@ -1 +1 @@ -This is a placeholder for the documentation of how navigation is implemented in the App. Test +This is a placeholder for the documentation of how navigation is implemented in the App. From 922a5051938d3792040dff4d7d4d530829ddc902 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Wed, 7 Jun 2023 19:10:34 -0400 Subject: [PATCH 63/85] Re-add personalDetailsList onyx key --- src/ONYXKEYS.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 2b4e81205590..082a1c7efbd5 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -45,6 +45,9 @@ export default { // Contains all the personalDetails the user has access to PERSONAL_DETAILS: 'personalDetails', + // Contains all the personalDetails the user has access to, keyed by accountID + PERSONAL_DETAILS_LIST: 'personalDetailsList', + // Contains all the private personal details of the user PRIVATE_PERSONAL_DETAILS: 'private_personalDetails', From b40efdff7cb831f5deae1995904ca7c3a5d7a064 Mon Sep 17 00:00:00 2001 From: Daniel Gale-Rosen Date: Wed, 7 Jun 2023 16:22:48 -0700 Subject: [PATCH 64/85] prettier --- src/pages/iou/SplitBillDetailsPage.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/iou/SplitBillDetailsPage.js b/src/pages/iou/SplitBillDetailsPage.js index e0c9129712c0..d4e5cc85d3fb 100644 --- a/src/pages/iou/SplitBillDetailsPage.js +++ b/src/pages/iou/SplitBillDetailsPage.js @@ -75,9 +75,7 @@ const SplitBillDetailsPage = (props) => { return ( - + Date: Thu, 8 Jun 2023 00:28:28 +0100 Subject: [PATCH 65/85] Fix the split view --- src/components/ReportActionItem/IOUPreview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/IOUPreview.js b/src/components/ReportActionItem/IOUPreview.js index fe0b22ed940e..a4e4561bd6db 100644 --- a/src/components/ReportActionItem/IOUPreview.js +++ b/src/components/ReportActionItem/IOUPreview.js @@ -125,7 +125,7 @@ const defaultProps = { }; const IOUPreview = (props) => { - if (_.isEmpty(props.iouReport)) { + if (_.isEmpty(props.iouReport) && !props.isBillSplit) { return null; } const sessionEmail = lodashGet(props.session, 'email', null); From 444018d1c1d63a0c986b760c6d5399b015326c70 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 7 Jun 2023 23:35:42 +0000 Subject: [PATCH 66/85] Update version to 1.3.25-6 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 94e6717829b0..e77d756cbbe8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032505 - versionName "1.3.25-5" + versionCode 1001032506 + versionName "1.3.25-6" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 5012de71c0af..11d265768732 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.3.25.5 + 1.3.25.6 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 5aedd70fb3aa..a593ef9285c7 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.3.25.5 + 1.3.25.6 diff --git a/package-lock.json b/package-lock.json index 7992f8766475..3a5af08c5f17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.25-5", + "version": "1.3.25-6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.25-5", + "version": "1.3.25-6", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4c2361aacbcf..5aa1ea5c96ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.25-5", + "version": "1.3.25-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.", From c27e85cb33173bbeaffd9c9f5195a43435764ea2 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Thu, 8 Jun 2023 01:54:49 +0200 Subject: [PATCH 67/85] Update src/libs/actions/PersonalDetails.js Co-authored-by: Alex Beaman --- src/libs/actions/PersonalDetails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 09f12ff4b9d4..c671011e2289 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -311,7 +311,7 @@ function openPersonalDetailsPage() { } /** - * Fetches public profile info about a given user + * Fetches public profile info about a given user. * The API will only return the accountID, displayName, and avatar for the user * But the profile page will use other info (e.g. contact methods and pronouns) if they are already available in Onyx * @param {Number} accountID From d77d9b5e0453f31c5a62c05990f7137e3c2f7847 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Thu, 8 Jun 2023 01:55:02 +0200 Subject: [PATCH 68/85] Update src/libs/actions/PersonalDetails.js Co-authored-by: Alex Beaman --- src/libs/actions/PersonalDetails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index c671011e2289..83450df021b2 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -313,7 +313,7 @@ function openPersonalDetailsPage() { /** * Fetches public profile info about a given user. * The API will only return the accountID, displayName, and avatar for the user - * But the profile page will use other info (e.g. contact methods and pronouns) if they are already available in Onyx + * but the profile page will use other info (e.g. contact methods and pronouns) if they are already available in Onyx * @param {Number} accountID */ function openPublicProfilePage(accountID) { From 74b5ed27d61981561060685fc61d6f3c51660cdd Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Thu, 8 Jun 2023 01:55:29 +0200 Subject: [PATCH 69/85] Update src/libs/actions/PersonalDetails.js Co-authored-by: Alex Beaman --- src/libs/actions/PersonalDetails.js | 65 ++++++++++++----------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 83450df021b2..1e59fbaa80ce 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -317,45 +317,34 @@ function openPersonalDetailsPage() { * @param {Number} accountID */ function openPublicProfilePage(accountID) { - API.read( - 'OpenPublicProfilePage', - {accountID}, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: true, - }, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: false, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: false, - }, - }, - }, - ], + const optimisticData = [{ + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: true, + }, }, - ); + }]; + const successData = [{ + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, + }, + }]; + const failureData = [{ + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, + }, + }]; + API.read('OpenPublicProfilePage', {accountID}, {optimisticData, successData, failureData}); } /** From f1564d357f012f4b4bf6751fb33e5e05a2da90c0 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 8 Jun 2023 01:02:48 +0000 Subject: [PATCH 70/85] Update version to 1.3.25-7 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e77d756cbbe8..0976b66e69bd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032506 - versionName "1.3.25-6" + versionCode 1001032507 + versionName "1.3.25-7" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 11d265768732..38c7628b753b 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.3.25.6 + 1.3.25.7 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index a593ef9285c7..bf23732dceb4 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.3.25.6 + 1.3.25.7 diff --git a/package-lock.json b/package-lock.json index 3a5af08c5f17..d0405cf47463 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.25-6", + "version": "1.3.25-7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.25-6", + "version": "1.3.25-7", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 5aa1ea5c96ba..9e9b4a53e543 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.25-6", + "version": "1.3.25-7", "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.", From 133cd8e56cbdbd028d15e05646d0bccb4fae1d16 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Wed, 7 Jun 2023 21:40:03 -0400 Subject: [PATCH 71/85] Alex comments --- src/pages/ProfilePage.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 43e9f1ec9b5e..f1a3d84871ee 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -49,18 +49,15 @@ const propTypes = { /* Onyx Props */ /** The personal details of all users */ - personalDetails: personalDetailsPropType, + personalDetails: PropTypes.objectOf(personalDetailsPropType), /** Route params */ route: matchType.isRequired, /** Login list for the user that is signed in */ loginList: PropTypes.shape({ - /** Date login was validated, used to show info indicator status */ - validatedDate: PropTypes.string, - - /** Field-specific server side errors keyed by microtime */ - errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)), + /** Phone/Email associated with user */ + partnerUserID: PropTypes.string, }), ...withLocalizePropTypes, @@ -95,8 +92,11 @@ const getPhoneNumber = (details) => { function ProfilePage(props) { const accountID = lodashGet(props.route.params, 'accountID', 0); + // eslint-disable-next-line rulesdir/prefer-early-return useEffect(() => { - PersonalDetails.openPublicProfilePage(accountID); + if (accountID > 0) { + PersonalDetails.openPublicProfilePage(accountID); + } }, [accountID]); const details = lodashGet(props.personalDetails, accountID, {}); @@ -122,7 +122,10 @@ function ProfilePage(props) { const isCurrentUser = _.keys(props.loginList).includes(login); const hasMinimumDetails = !_.isEmpty(details.avatar); - const isLoading = lodashGet(details, 'isLoading', false); + const isLoading = lodashGet(details, 'isLoading', false) || _.isEmpty(details); + + // If they API returns an error for some reason there won't be any details and isLoading will get set to false, so we want to show a blocking screen + const shouldShowBlockingView = !hasMinimumDetails && !isLoading; return ( @@ -207,7 +210,7 @@ function ProfilePage(props) { )} {!hasMinimumDetails && isLoading && } - {!hasMinimumDetails && !isLoading && ( + {shouldShowBlockingView && ( Date: Thu, 8 Jun 2023 03:48:22 +0200 Subject: [PATCH 72/85] Update src/pages/ProfilePage.js Co-authored-by: Alex Beaman --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index f1a3d84871ee..932f489be5f4 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -124,7 +124,7 @@ function ProfilePage(props) { const hasMinimumDetails = !_.isEmpty(details.avatar); const isLoading = lodashGet(details, 'isLoading', false) || _.isEmpty(details); - // If they API returns an error for some reason there won't be any details and isLoading will get set to false, so we want to show a blocking screen + // If the API returns an error for some reason there won't be any details and isLoading will get set to false, so we want to show a blocking screen const shouldShowBlockingView = !hasMinimumDetails && !isLoading; return ( From 57beb1dcdcef45aeb5dfe596a335b48ff45e755d Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Wed, 7 Jun 2023 21:49:06 -0400 Subject: [PATCH 73/85] Prettier fix --- src/libs/actions/PersonalDetails.js | 48 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 1e59fbaa80ce..b362436def5c 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -317,33 +317,39 @@ function openPersonalDetailsPage() { * @param {Number} accountID */ function openPublicProfilePage(accountID) { - const optimisticData = [{ - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: true, + const optimisticData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: true, + }, }, }, - }]; - const successData = [{ - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: false, + ]; + const successData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, }, }, - }]; - const failureData = [{ - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - value: { - [accountID]: { - isLoading: false, + ]; + const failureData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [accountID]: { + isLoading: false, + }, }, }, - }]; + ]; API.read('OpenPublicProfilePage', {accountID}, {optimisticData, successData, failureData}); } From 77e55c3d756b98100bd1939ff26685fe2a21bb05 Mon Sep 17 00:00:00 2001 From: chychkoi Date: Wed, 7 Jun 2023 19:35:52 -0700 Subject: [PATCH 74/85] Fix prettier issue --- src/pages/EnablePayments/TermsStep.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.js index d5aeb9482563..2e4fc367db13 100644 --- a/src/pages/EnablePayments/TermsStep.js +++ b/src/pages/EnablePayments/TermsStep.js @@ -54,7 +54,7 @@ function TermsStep(props) { return ( <> - + Date: Thu, 8 Jun 2023 12:26:13 +0800 Subject: [PATCH 75/85] fix link is shown in a separate line --- .../BaseAnchorForCommentsOnly.js | 68 +++++++++---------- src/components/AnchorForCommentsOnly/index.js | 20 +++--- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js index 21c1ea618841..5588e173aeae 100644 --- a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js @@ -51,41 +51,39 @@ const BaseAnchorForCommentsOnly = (props) => { const isEmail = Str.isValidEmailMarkdown(props.href.replace(/mailto:/i, '')); return ( - - { - ReportActionContextMenu.showContextMenu( - isEmail ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, - event, - props.href, - lodashGet(linkRef, 'current'), - ); - }} - onPress={linkProps.onPress} - onPressIn={props.onPressIn} - onPressOut={props.onPressOut} - > - - (linkRef = el)} - style={StyleSheet.flatten([props.style, defaultTextStyle])} - accessibilityRole="link" - hrefAttrs={{ - rel: props.rel, - target: isEmail ? '_self' : props.target, - }} - href={linkProps.href} - // Add testID so it gets selected as an anchor tag by SelectionScraper - testID="a" - // eslint-disable-next-line react/jsx-props-no-spreading - {...rest} - > - {props.children} - - - - + { + ReportActionContextMenu.showContextMenu( + isEmail ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, + event, + props.href, + lodashGet(linkRef, 'current'), + ); + }} + onPress={linkProps.onPress} + onPressIn={props.onPressIn} + onPressOut={props.onPressOut} + > + + (linkRef = el)} + style={StyleSheet.flatten([props.style, defaultTextStyle])} + accessibilityRole="link" + hrefAttrs={{ + rel: props.rel, + target: isEmail ? '_self' : props.target, + }} + href={linkProps.href} + // Add testID so it gets selected as an anchor tag by SelectionScraper + testID="a" + // eslint-disable-next-line react/jsx-props-no-spreading + {...rest} + > + {props.children} + + + ); }; diff --git a/src/components/AnchorForCommentsOnly/index.js b/src/components/AnchorForCommentsOnly/index.js index fd670809e2cf..1de4ea56b3aa 100644 --- a/src/components/AnchorForCommentsOnly/index.js +++ b/src/components/AnchorForCommentsOnly/index.js @@ -1,4 +1,5 @@ import React from 'react'; +import {View} from 'react-native'; import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes'; import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; @@ -6,17 +7,14 @@ import ControlSelection from '../../libs/ControlSelection'; import styles from '../../styles/styles'; const AnchorForCommentsOnly = (props) => ( - DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} - onPressOut={() => ControlSelection.unblock()} - // HTML renderer root view display is flex. Using flex will force all child elements - // to be block elements even when they have display inline added to them. - // This will affect elements like which are inline by default. - // Setting display block to the container view will solve that. - containerStyles={[styles.dBlock]} - /> + + DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} + onPressOut={() => ControlSelection.unblock()} + /> + ); AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes; From f2f4e9f6738eed6edcfa3ef686fc6c751f8f82c0 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 7 Jun 2023 21:41:28 -0700 Subject: [PATCH 76/85] Dont hide the context menu from the LHN if Sidebar not in focus --- src/components/LHNOptionsList/OptionRowLHN.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index ddac84028404..b1fee50b8ddc 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; import {View, StyleSheet} from 'react-native'; +import {useIsFocused} from '@react-navigation/native'; import * as optionRowStyles from '../../styles/optionRowStyles'; import styles from '../../styles/styles'; import * as StyleUtils from '../../styles/StyleUtils'; @@ -57,7 +58,13 @@ const OptionRowLHN = (props) => { const optionItem = SidebarUtils.getOptionData(props.reportID); const isPinned = _.get(optionItem, 'isPinned', false); + const isScreenFocused = useIsFocused(); React.useEffect(() => { + // Don't perform this side-effect if the SidebarScreen is not focused + if (!isScreenFocused) { + return; + } + ReportActionContextMenu.hideContextMenu(false); }, [isPinned]); From e37a362c3112fc5bb49a31edafedac71ed779e03 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 8 Jun 2023 12:43:36 +0800 Subject: [PATCH 77/85] remove unused import --- .../AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js index 5588e173aeae..4a002ef49cf1 100644 --- a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js @@ -1,6 +1,6 @@ import _ from 'underscore'; import React from 'react'; -import {View, StyleSheet} from 'react-native'; +import {StyleSheet} from 'react-native'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import Str from 'expensify-common/lib/str'; From 567430a3b6b4e8c24d9610d45e27a0dc8b022500 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 7 Jun 2023 22:58:58 -0700 Subject: [PATCH 78/85] Remove unnecessary effect from OptionRowLHN --- src/components/LHNOptionsList/OptionRowLHN.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index b1fee50b8ddc..ed209750f49e 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -2,7 +2,6 @@ import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; import {View, StyleSheet} from 'react-native'; -import {useIsFocused} from '@react-navigation/native'; import * as optionRowStyles from '../../styles/optionRowStyles'; import styles from '../../styles/styles'; import * as StyleUtils from '../../styles/StyleUtils'; @@ -56,17 +55,6 @@ const defaultProps = { const OptionRowLHN = (props) => { const optionItem = SidebarUtils.getOptionData(props.reportID); - const isPinned = _.get(optionItem, 'isPinned', false); - - const isScreenFocused = useIsFocused(); - React.useEffect(() => { - // Don't perform this side-effect if the SidebarScreen is not focused - if (!isScreenFocused) { - return; - } - - ReportActionContextMenu.hideContextMenu(false); - }, [isPinned]); if (!optionItem) { return null; From 1f65d08ef7c1cf7d9bf225ded564dcaf493f0b80 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 8 Jun 2023 13:21:27 +0700 Subject: [PATCH 79/85] fix type error --- src/libs/actions/Task.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 101f04340fb6..958ed2dcf20c 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -297,7 +297,8 @@ function editTaskAndNavigate(report, ownerEmail, title, description, assignee) { let assigneeChatReportID; if (assignee && assignee !== report.managerEmail) { assigneeChatReportID = ReportUtils.getChatByParticipants([assignee]).reportID; - if (assigneeChatReportID !== report.parentReportID) { + console.log(assigneeChatReportID, report.parentReportID) + if (assigneeChatReportID !== report.parentReportID.toString()) { optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`); } } From 4866a9d2465dea0263b14b7122c4d674bd18f155 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 8 Jun 2023 13:22:13 +0700 Subject: [PATCH 80/85] remove log --- src/libs/actions/Task.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 958ed2dcf20c..59ea33e0d722 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -297,7 +297,6 @@ function editTaskAndNavigate(report, ownerEmail, title, description, assignee) { let assigneeChatReportID; if (assignee && assignee !== report.managerEmail) { assigneeChatReportID = ReportUtils.getChatByParticipants([assignee]).reportID; - console.log(assigneeChatReportID, report.parentReportID) if (assigneeChatReportID !== report.parentReportID.toString()) { optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`); } From ba8f77a3e307207ff09adaab8989f41a86250943 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 8 Jun 2023 12:49:48 +0000 Subject: [PATCH 81/85] Update version to 1.3.25-8 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0976b66e69bd..374f500fa0a5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032507 - versionName "1.3.25-7" + versionCode 1001032508 + versionName "1.3.25-8" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 38c7628b753b..cd1da5b74a23 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.3.25.7 + 1.3.25.8 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index bf23732dceb4..437fc846fc70 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.3.25.7 + 1.3.25.8 diff --git a/package-lock.json b/package-lock.json index d0405cf47463..cef9739b8b71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.25-7", + "version": "1.3.25-8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.25-7", + "version": "1.3.25-8", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c58561daea9e..9e4e39bffbb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.25-7", + "version": "1.3.25-8", "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.", From 5bfb05a1c92bfcf1fba89a95027e036eb50579f8 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 8 Jun 2023 13:53:39 +0100 Subject: [PATCH 82/85] refactor MoneyRequestParticipantsPage const to function --- .../MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js index 632906cc408e..142687997a6b 100644 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js @@ -43,7 +43,7 @@ const defaultProps = { safeAreaPaddingBottomStyle: {}, }; -const MoneyRequestParticipantsPage = (props) => { +function MoneyRequestParticipantsPage(props) { if (props.iou.loading) { return ( From 70cf5438afdae778ea27482c01526f0d33fb074a Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 8 Jun 2023 15:36:34 +0100 Subject: [PATCH 83/85] apply prettier --- .../MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js index 142687997a6b..54e98729a8e8 100644 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js @@ -67,7 +67,7 @@ function MoneyRequestParticipantsPage(props) { iouType={props.iouType} /> ); -}; +} MoneyRequestParticipantsPage.displayName = 'IOUParticipantsPage'; MoneyRequestParticipantsPage.propTypes = propTypes; From 183b3d1088d101db5ddd4933fe9eed2860514681 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 8 Jun 2023 16:24:44 +0000 Subject: [PATCH 84/85] Update version to 1.3.26-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 374f500fa0a5..e053b9ed7fbc 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032508 - versionName "1.3.25-8" + versionCode 1001032600 + versionName "1.3.26-0" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index cd1da5b74a23..03498d7292eb 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.25 + 1.3.26 CFBundleSignature ???? CFBundleURLTypes @@ -32,7 +32,7 @@ CFBundleVersion - 1.3.25.8 + 1.3.26.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 437fc846fc70..ec82796b7242 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.3.25 + 1.3.26 CFBundleSignature ???? CFBundleVersion - 1.3.25.8 + 1.3.26.0 diff --git a/package-lock.json b/package-lock.json index cef9739b8b71..dbf2d553d417 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.25-8", + "version": "1.3.26-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.25-8", + "version": "1.3.26-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 9e4e39bffbb2..154aa21d38fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.25-8", + "version": "1.3.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.", From 87b58217017b441857b4cd3b200c203fdd2fe598 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 8 Jun 2023 16:29:28 +0000 Subject: [PATCH 85/85] Update version to 1.3.26-1 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e053b9ed7fbc..c29f64297d23 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032600 - versionName "1.3.26-0" + versionCode 1001032601 + versionName "1.3.26-1" } splits { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 03498d7292eb..4a2406aaa1b8 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.3.26.0 + 1.3.26.1 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index ec82796b7242..591c2f2b999a 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.3.26.0 + 1.3.26.1 diff --git a/package-lock.json b/package-lock.json index dbf2d553d417..61bb8d860991 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.26-0", + "version": "1.3.26-1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.26-0", + "version": "1.3.26-1", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 154aa21d38fd..393e3be8e186 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.26-0", + "version": "1.3.26-1", "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.",