From 41d02463e9453698fb9f9e19a226e3598acc48a8 Mon Sep 17 00:00:00 2001 From: Pujan Date: Tue, 23 May 2023 21:58:41 +0530 Subject: [PATCH 001/273] dynamic translate for unlink sent link --- src/libs/actions/Session/index.js | 42 +---------------------------- src/pages/signin/UnlinkLoginForm.js | 2 +- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index 348cafc13d8f..02230dff87df 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -165,45 +165,6 @@ function resendValidateCode(login = credentials.login) { API.write('RequestNewValidateCode', {email: login}, {optimisticData, successData, failureData}); } -/** - * Request a new validate / magic code for user to sign in automatically with the link - * - * @param {String} [login] - */ -function resendLinkWithValidateCode(login = credentials.login) { - const optimisticData = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.ACCOUNT, - value: { - isLoading: true, - message: null, - }, - }, - ]; - const successData = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.ACCOUNT, - value: { - isLoading: false, - message: Localize.translateLocal('validateCodeModal.successfulNewCodeRequest'), - }, - }, - ]; - const failureData = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.ACCOUNT, - value: { - isLoading: false, - message: null, - }, - }, - ]; - API.write('RequestNewValidateCode', {email: login}, {optimisticData, successData, failureData}); -} - /** * Checks the API to see if an account exists for the given login * @@ -717,7 +678,7 @@ function requestUnlinkValidationLink() { key: ONYXKEYS.ACCOUNT, value: { isLoading: false, - message: Localize.translateLocal('unlinkLoginForm.linkSent'), + message: 'unlinkLoginForm.linkSent', }, }, ]; @@ -872,7 +833,6 @@ export { signOutAndRedirectToSignIn, resendValidationLink, resendValidateCode, - resendLinkWithValidateCode, resetPassword, resendResetPassword, requestUnlinkValidationLink, diff --git a/src/pages/signin/UnlinkLoginForm.js b/src/pages/signin/UnlinkLoginForm.js index 31daae92be13..2ff662da4d74 100644 --- a/src/pages/signin/UnlinkLoginForm.js +++ b/src/pages/signin/UnlinkLoginForm.js @@ -65,7 +65,7 @@ const UnlinkLoginForm = (props) => { )} {!_.isEmpty(props.account.errors) && ( From 22223372ace8e1dafd433ea16428902222677d58 Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Thu, 25 May 2023 12:26:33 +0200 Subject: [PATCH 002/273] migrate ReportActionCompose to PressableWithFeedback --- src/pages/home/report/ReportActionCompose.js | 33 +++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index c789b03ab0b9..0c25659d1776 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {View, TouchableOpacity, InteractionManager, LayoutAnimation, NativeModules, findNodeHandle} from 'react-native'; +import {View, InteractionManager, LayoutAnimation, NativeModules, findNodeHandle} from 'react-native'; import _ from 'underscore'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; @@ -54,6 +54,7 @@ import * as Welcome from '../../../libs/actions/Welcome'; import Permissions from '../../../libs/Permissions'; import * as TaskUtils from '../../../libs/actions/Task'; import * as Browser from '../../../libs/Browser'; +import PressableWithFeedback from '../../../components/Pressable/PressableWithFeedback'; const propTypes = { /** Beta features list */ @@ -962,7 +963,7 @@ class ReportActionCompose extends React.Component { > {this.props.isComposerFullSize && ( - { e.preventDefault(); this.setShouldShowSuggestionMenuToFalse(); @@ -972,14 +973,16 @@ class ReportActionCompose extends React.Component { onMouseDown={(e) => e.preventDefault()} style={styles.composerSizeButton} disabled={isBlockedFromConcierge || this.props.disabled} + accessibilityRole="button" + accessibilityLabel={this.props.translate('reportActionCompose.collapse')} > - + )} {!this.props.isComposerFullSize && isFullComposerAvailable && ( - { e.preventDefault(); this.setShouldShowSuggestionMenuToFalse(); @@ -989,13 +992,15 @@ class ReportActionCompose extends React.Component { onMouseDown={(e) => e.preventDefault()} style={styles.composerSizeButton} disabled={isBlockedFromConcierge || this.props.disabled} + accessibilityRole="button" + accessibilityLabel={this.props.translate('reportActionCompose.expand')} > - + )} - (this.actionButton = el)} onPress={(e) => { e.preventDefault(); @@ -1006,9 +1011,11 @@ class ReportActionCompose extends React.Component { }} style={styles.composerSizeButton} disabled={isBlockedFromConcierge || this.props.disabled} + accessibilityRole="button" + accessibilityLabel={this.props.translate('reportActionCompose.addAction')} > - + e.preventDefault()} > - - + From 9829c2564c71ab3081ee21c1b69bc2ffcf2361c1 Mon Sep 17 00:00:00 2001 From: burczu Date: Tue, 16 May 2023 12:41:12 +0200 Subject: [PATCH 003/273] draft solution added --- src/CONST.js | 6 +++--- src/components/UnreadActionIndicator.js | 2 +- src/libs/SelectionScraper/index.js | 8 +++++--- .../ContextMenu/MiniReportActionContextMenu/index.js | 6 +++++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 182548b4d99e..fce6ca2cb870 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -2426,9 +2426,9 @@ const CONST = { }, SPACE_CHARACTER_WIDTH: 4, - // This ID is used in SelectionScraper.js to query the DOM for UnreadActionIndicator's - // div and then remove it from copied contents in the getHTMLOfSelection() method. - UNREAD_ACTION_INDICATOR_ID: 'no-copy-area-unread-action-indicator', + // This attribute is used in SelectionScraper.js to query the DOM elements + // and then remove them from copied contents in the getHTMLOfSelection() method. + SELECTION_SCRAPER_HIDDEN_ELEMENT: 'selection-scrapper-hidden-element', MODERATION: { MODERATOR_DECISION_PENDING: 'pending', MODERATOR_DECISION_PENDING_HIDE: 'pendingHide', diff --git a/src/components/UnreadActionIndicator.js b/src/components/UnreadActionIndicator.js index 81cf266bef28..0d45c90aa441 100755 --- a/src/components/UnreadActionIndicator.js +++ b/src/components/UnreadActionIndicator.js @@ -10,7 +10,7 @@ const UnreadActionIndicator = (props) => ( accessibilityLabel={props.translate('accessibilityHints.newMessageLineIndicator')} data-action-id={props.reportActionID} style={[styles.unreadIndicatorContainer, styles.userSelectNone]} - nativeID={CONST.UNREAD_ACTION_INDICATOR_ID} + dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}} > {props.translate('common.new')} diff --git a/src/libs/SelectionScraper/index.js b/src/libs/SelectionScraper/index.js index aab5ca78e4ed..44b87deba796 100644 --- a/src/libs/SelectionScraper/index.js +++ b/src/libs/SelectionScraper/index.js @@ -83,10 +83,12 @@ const getHTMLOfSelection = () => { // Find and remove the div housing the UnreadActionIndicator because we don't want // the 'New/Nuevo' text inside it being copied. - const newMessageLineIndicatorDiv = div.querySelector(`#${CONST.UNREAD_ACTION_INDICATOR_ID}`); + const divsToRemove = div.querySelectorAll(`[data-${CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT}=true]`); - if (newMessageLineIndicatorDiv) { - newMessageLineIndicatorDiv.remove(); + if (divsToRemove && divsToRemove.length > 0) { + divsToRemove.forEach((element) => { + element.remove(); + }); } return div.innerHTML; diff --git a/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js b/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js index f2883acc3b95..2c0f2ff65561 100644 --- a/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js +++ b/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import {propTypes as genericReportActionContextMenuPropTypes, defaultProps as GenericReportActionContextMenuDefaultProps} from '../genericReportActionContextMenuPropTypes'; import * as StyleUtils from '../../../../../styles/StyleUtils'; import BaseReportActionContextMenu from '../BaseReportActionContextMenu'; +import CONST from '../../../../../CONST'; const propTypes = { ..._.omit(genericReportActionContextMenuPropTypes, ['isMini']), @@ -20,7 +21,10 @@ const defaultProps = { }; const MiniReportActionContextMenu = (props) => ( - + Date: Thu, 25 May 2023 13:17:05 +0200 Subject: [PATCH 004/273] const comment amended --- src/CONST.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index fce6ca2cb870..0b8ddda47d86 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -2426,8 +2426,8 @@ const CONST = { }, SPACE_CHARACTER_WIDTH: 4, - // This attribute is used in SelectionScraper.js to query the DOM elements - // and then remove them from copied contents in the getHTMLOfSelection() method. + // The attribute used in the SelectionScraper.js helper to query all the DOM elements + // that should be removed from the copied contents in the getHTMLOfSelection() method SELECTION_SCRAPER_HIDDEN_ELEMENT: 'selection-scrapper-hidden-element', MODERATION: { MODERATOR_DECISION_PENDING: 'pending', From 940cf8b7d971f0317fe9b2b7a846a62f2f040fc3 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Fri, 26 May 2023 15:36:51 +0200 Subject: [PATCH 005/273] Add Link Previews --- src/libs/ReportActionsUtils.js | 11 +++ src/libs/actions/Report.js | 14 ++++ src/pages/home/report/LinkPreviewer.js | 98 +++++++++++++++++++++++ src/pages/home/report/ReportActionItem.js | 14 ++++ src/styles/colors.js | 1 + src/styles/styles.js | 25 ++++++ 6 files changed, 163 insertions(+) create mode 100644 src/pages/home/report/LinkPreviewer.js diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index d5551e06ba4a..a1e7c7aaf020 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -162,6 +162,16 @@ function getMostRecentIOURequestActionID(reportActions) { return _.last(sortedReportActions).reportActionID; } +/** + * Returns true when the report action contains a link + * + * @param {reportAction} reportAction + * @returns {Boolean} + */ +function containsLink(reportAction) { + return !_.isEmpty(lodashGet(reportAction, ['message', 0, 'html'])); +} + /** * Returns true when the report action immediately before the specified index is a comment made by the same actor who who is leaving a comment in the action at the specified index. * Also checks to ensure that the comment is not too old to be shown as a grouped comment. @@ -387,6 +397,7 @@ export { getLastVisibleAction, getLastVisibleMessageText, getMostRecentIOURequestActionID, + containsLink, isDeletedAction, shouldReportActionBeVisible, isReportActionDeprecated, diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index e7d37ecea837..b0ffb88ec703 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -608,6 +608,19 @@ function openPaymentDetailsPage(chatReportID, iouReportID) { ); } +/** + * Gets metadata info about links in the provided report + * + * @param {String} reportID + * @param {String} reportActionID + */ +function expandURLPreview(reportID, reportActionID) { + API.read('ExpandURLPreview', { + reportID, + reportActionID, + }); +} + /** * Gets transactions and data associated with the linked report (expense or IOU report) * @@ -1776,6 +1789,7 @@ export { deleteReport, navigateToConciergeChatAndDeleteReport, setIsComposerFullSize, + expandURLPreview, markCommentAsUnread, readNewestAction, readOldestAction, diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js new file mode 100644 index 000000000000..f9e0b7ebe5e5 --- /dev/null +++ b/src/pages/home/report/LinkPreviewer.js @@ -0,0 +1,98 @@ +import React from 'react'; +import {View, Image} from 'react-native'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {uniqBy} from 'lodash'; +import Text from '../../../components/Text'; +import styles from '../../../styles/styles'; +import variables from '../../../styles/variables'; +import colors from '../../../styles/colors'; + +const IMAGE_TYPES = ['jpg', 'jpeg', 'png']; + +const propTypes = { + /** Data about links provided in message. */ + linkMetadata: PropTypes.arrayOf( + PropTypes.shape({ + /** The URL of the link. */ + url: PropTypes.string, + + /** A description of the link. */ + description: PropTypes.string, + + /** The title of the link. */ + title: PropTypes.string, + + /** The publisher of the link. */ + publisher: PropTypes.string, + + /** The image associated with the link. */ + image: PropTypes.shape({ + /** The height of the image. */ + height: PropTypes.number, + + /** The width of the image. */ + width: PropTypes.number, + + /** The URL of the image. */ + url: PropTypes.string, + }), + + /** The provider logo associated with the link. */ + logo: PropTypes.shape({ + /** The height of the logo. */ + height: PropTypes.number, + + /** The width of the logo. */ + width: PropTypes.number, + + /** The URL of the logo. */ + url: PropTypes.string, + }), + }), + ), + + /** Maximum amount of visible link previews. */ + maxAmountOfPreviews: PropTypes.number, +}; + +const defaultProps = { + linkMetadata: [], + maxAmountOfPreviews: undefined +}; + +const LinkPreviewer = props => ( + _.map(_.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews > 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { + const { + description, image, title, logo, publisher, url, + } = linkData; + + return linkData && ( + + + {logo && } + {publisher && {publisher}} + + {title && {title}} + {description && {description}} + + {image && IMAGE_TYPES.includes(image.type) && ( + + )} + + + ); + }) +); + +LinkPreviewer.propTypes = propTypes; +LinkPreviewer.defaultProps = defaultProps; +LinkPreviewer.displayName = 'ReportLinkPreview'; + +export default LinkPreviewer; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 5b44f3fa0ed6..1c74c7dbcae7 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -18,6 +18,7 @@ import UnreadActionIndicator from '../../../components/UnreadActionIndicator'; import ReportActionItemMessageEdit from './ReportActionItemMessageEdit'; import ReportActionItemCreated from './ReportActionItemCreated'; import ReportActionItemThread from './ReportActionItemThread'; +import LinkPreviewer from './LinkPreviewer'; import compose from '../../../libs/compose'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import ControlSelection from '../../../libs/ControlSelection'; @@ -117,6 +118,14 @@ function ReportActionItem(props) { focusTextInputAfterAnimation(textInputRef.current, 100); }, [isDraftEmpty]); + useEffect(() => { + if (!ReportActionsUtils.containsLink(props.action)) { + return; + } + + Report.expandURLPreview(props.report.reportID, props.action.reportActionID); + }, [props.action, props.report.reportID]); + const toggleContextMenuFromActiveReportAction = useCallback(() => { setIsContextMenuActive(ReportActionContextMenu.isActiveReportAction(props.action.reportActionID)); }, [props.action.reportActionID]); @@ -276,6 +285,11 @@ function ReportActionItem(props) { return ( <> {children} + {!_.isEmpty(props.action.linkMetadata) && ( + + )} {hasReactions && ( Date: Fri, 26 May 2023 15:49:23 +0200 Subject: [PATCH 006/273] Create disable links and unlimited using maxAmountOfPreviews prop --- src/pages/home/report/LinkPreviewer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index f9e0b7ebe5e5..a2ebed911d1e 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -52,17 +52,17 @@ const propTypes = { }), ), - /** Maximum amount of visible link previews. */ + /** Maximum amount of visible link previews. -1 means unlimited amount of previews */ maxAmountOfPreviews: PropTypes.number, }; const defaultProps = { linkMetadata: [], - maxAmountOfPreviews: undefined + maxAmountOfPreviews: -1 }; const LinkPreviewer = props => ( - _.map(_.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews > 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { + _.map(_.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { const { description, image, title, logo, publisher, url, } = linkData; From 3b5b70fc1ee512069fe2318f11789a1d6b9cb300 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Fri, 26 May 2023 16:51:58 +0200 Subject: [PATCH 007/273] Replace simple check with isEmpty --- src/pages/home/report/LinkPreviewer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index a2ebed911d1e..d8187d313cfd 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -70,13 +70,13 @@ const LinkPreviewer = props => ( return linkData && ( - {logo && } - {publisher && {publisher}} + {!_.isEmpty(logo) && } + {!_.isEmpty(publisher) && {publisher}} - {title && {title}} - {description && {description}} + {!_.isEmpty(title) && {title}} + {!_.isEmpty(description) && {description}} - {image && IMAGE_TYPES.includes(image.type) && ( + {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( Date: Mon, 29 May 2023 12:04:28 +0200 Subject: [PATCH 008/273] Run prettier and add array length check --- src/libs/ReportActionsUtils.js | 10 +-- src/libs/actions/Report.js | 10 +-- src/pages/home/report/LinkPreviewer.js | 88 +++++++++++++++-------- src/pages/home/report/ReportActionItem.js | 6 +- 4 files changed, 69 insertions(+), 45 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index a1e7c7aaf020..9e2a24f6c5a4 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -163,11 +163,11 @@ function getMostRecentIOURequestActionID(reportActions) { } /** - * Returns true when the report action contains a link - * - * @param {reportAction} reportAction - * @returns {Boolean} - */ + * Returns true when the report action contains a link + * + * @param {reportAction} reportAction + * @returns {Boolean} + */ function containsLink(reportAction) { return !_.isEmpty(lodashGet(reportAction, ['message', 0, 'html'])); } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index b0ffb88ec703..3cca63dcfa1f 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -609,11 +609,11 @@ function openPaymentDetailsPage(chatReportID, iouReportID) { } /** - * Gets metadata info about links in the provided report - * - * @param {String} reportID - * @param {String} reportActionID - */ + * Gets metadata info about links in the provided report + * + * @param {String} reportID + * @param {String} reportActionID + */ function expandURLPreview(reportID, reportActionID) { API.read('ExpandURLPreview', { reportID, diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index d8187d313cfd..0454e236cf9f 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -58,38 +58,66 @@ const propTypes = { const defaultProps = { linkMetadata: [], - maxAmountOfPreviews: -1 + maxAmountOfPreviews: -1, }; -const LinkPreviewer = props => ( - _.map(_.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { - const { - description, image, title, logo, publisher, url, - } = linkData; - - return linkData && ( - - - {!_.isEmpty(logo) && } - {!_.isEmpty(publisher) && {publisher}} - - {!_.isEmpty(title) && {title}} - {!_.isEmpty(description) && {description}} - - {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( - - )} - - - ); - }) -); +const LinkPreviewer = (props) => + _.map( + _.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), + (linkData) => { + const {description, image, title, logo, publisher, url} = linkData; + + return ( + linkData && ( + + + {!_.isEmpty(logo) && ( + + )} + {!_.isEmpty(publisher) && ( + + {publisher} + + )} + + {!_.isEmpty(title) && ( + + {title} + + )} + {!_.isEmpty(description) && {description}} + + {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( + + )} + + + ) + ); + }, + ); LinkPreviewer.propTypes = propTypes; LinkPreviewer.defaultProps = defaultProps; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 1c74c7dbcae7..61b32e2fde3e 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -285,11 +285,7 @@ function ReportActionItem(props) { return ( <> {children} - {!_.isEmpty(props.action.linkMetadata) && ( - - )} + {!_.isEmpty(props.action.linkMetadata) && props.action.linkMetadata.length > 0 && } {hasReactions && ( Date: Mon, 29 May 2023 12:06:45 +0200 Subject: [PATCH 009/273] Use size instead of length --- src/pages/home/report/ReportActionItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 61b32e2fde3e..1fe97901bdf3 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -285,7 +285,7 @@ function ReportActionItem(props) { return ( <> {children} - {!_.isEmpty(props.action.linkMetadata) && props.action.linkMetadata.length > 0 && } + {!_.isEmpty(props.action.linkMetadata) && _.size(props.action.linkMetadata) > 0 && } {hasReactions && ( Date: Mon, 29 May 2023 12:19:44 +0200 Subject: [PATCH 010/273] Add check for isArray --- src/pages/home/report/LinkPreviewer.js | 3 +++ src/pages/home/report/ReportActionItem.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index 0454e236cf9f..cf6418017b47 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -65,6 +65,9 @@ const LinkPreviewer = (props) => _.map( _.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { + if (_.isArray( linkData )) { + return; + } const {description, image, title, logo, publisher, url} = linkData; return ( diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 1fe97901bdf3..1b70291dfd36 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -285,7 +285,7 @@ function ReportActionItem(props) { return ( <> {children} - {!_.isEmpty(props.action.linkMetadata) && _.size(props.action.linkMetadata) > 0 && } + {!_.isEmpty(props.action.linkMetadata) && } {hasReactions && ( Date: Mon, 29 May 2023 12:20:21 +0200 Subject: [PATCH 011/273] Run prettier --- src/pages/home/report/LinkPreviewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index cf6418017b47..7e5f06f704ef 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -65,7 +65,7 @@ const LinkPreviewer = (props) => _.map( _.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { - if (_.isArray( linkData )) { + if (_.isArray(linkData)) { return; } const {description, image, title, logo, publisher, url} = linkData; From a9ee8ca6f9334dd967f7d32e16387964f068e322 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 29 May 2023 13:45:27 +0200 Subject: [PATCH 012/273] Show smaller preview image if image would take more than half the screen --- src/pages/home/report/LinkPreviewer.js | 8 ++++++-- src/styles/styles.js | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index 7e5f06f704ef..786a930acd25 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -1,5 +1,5 @@ import React from 'react'; -import {View, Image} from 'react-native'; +import {View, Image, Dimensions} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {uniqBy} from 'lodash'; @@ -9,6 +9,9 @@ import variables from '../../../styles/variables'; import colors from '../../../styles/colors'; const IMAGE_TYPES = ['jpg', 'jpeg', 'png']; +const SCREEN_HEIGHT = Dimensions.get('window').height; +const MAX_IMAGE_SIZE = 350; +const SMALL_SCREEN_MAX_IMAGE_SIZE = 180; const propTypes = { /** Data about links provided in message. */ @@ -102,13 +105,14 @@ const LinkPreviewer = (props) => )} {!_.isEmpty(description) && {description}} - + {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( Date: Mon, 29 May 2023 13:55:38 +0200 Subject: [PATCH 013/273] Replace Dimensions with useWindowDimensions hook --- src/pages/home/report/LinkPreviewer.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index 786a930acd25..f55499bb4c82 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -1,15 +1,15 @@ import React from 'react'; -import {View, Image, Dimensions} from 'react-native'; +import {View, Image} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {uniqBy} from 'lodash'; +import useWindowDimensions from '../../../hooks/useWindowDimensions'; import Text from '../../../components/Text'; import styles from '../../../styles/styles'; import variables from '../../../styles/variables'; import colors from '../../../styles/colors'; const IMAGE_TYPES = ['jpg', 'jpeg', 'png']; -const SCREEN_HEIGHT = Dimensions.get('window').height; const MAX_IMAGE_SIZE = 350; const SMALL_SCREEN_MAX_IMAGE_SIZE = 180; @@ -64,8 +64,10 @@ const defaultProps = { maxAmountOfPreviews: -1, }; -const LinkPreviewer = (props) => - _.map( +const LinkPreviewer = (props) => { + const {windowHeight} = useWindowDimensions(); + + return _.map( _.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), (linkData) => { if (_.isArray(linkData)) { @@ -112,7 +114,7 @@ const LinkPreviewer = (props) => styles.linkPreviewImage, { aspectRatio: image.width / image.height, - maxHeight: SCREEN_HEIGHT / 2 < MAX_IMAGE_SIZE ? SMALL_SCREEN_MAX_IMAGE_SIZE : MAX_IMAGE_SIZE, + maxHeight: windowHeight / 2 < MAX_IMAGE_SIZE ? SMALL_SCREEN_MAX_IMAGE_SIZE : MAX_IMAGE_SIZE, }, ]} resizeMode="contain" @@ -125,6 +127,7 @@ const LinkPreviewer = (props) => ); }, ); +}; LinkPreviewer.propTypes = propTypes; LinkPreviewer.defaultProps = defaultProps; From 37a0afb2685b2d04c1f5abdd450761c97428986d Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 29 May 2023 15:44:52 +0200 Subject: [PATCH 014/273] Add logic to scale image width based on ratio so it doesn't move away from left side of component --- src/pages/home/report/LinkPreviewer.js | 38 +++++++++++++++----------- src/styles/styles.js | 1 - 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index f55499bb4c82..e214189d7e2e 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState, useEffect} from 'react'; import {View, Image} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; @@ -66,6 +66,11 @@ const defaultProps = { const LinkPreviewer = (props) => { const {windowHeight} = useWindowDimensions(); + const [maxImageSize, setMaxImageSize] = useState(MAX_IMAGE_SIZE); + + useEffect(() => { + setMaxImageSize(windowHeight / 2 < MAX_IMAGE_SIZE ? SMALL_SCREEN_MAX_IMAGE_SIZE : MAX_IMAGE_SIZE); + }, [windowHeight]); return _.map( _.take(uniqBy(props.linkMetadata, 'url'), props.maxAmountOfPreviews >= 0 ? Math.min(props.maxAmountOfPreviews, props.linkMetadata.length) : props.linkMetadata.length), @@ -107,21 +112,22 @@ const LinkPreviewer = (props) => { )} {!_.isEmpty(description) && {description}} - - {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( - - )} - + {!_.isEmpty(image) && IMAGE_TYPES.includes(image.type) && ( + + )} ) ); diff --git a/src/styles/styles.js b/src/styles/styles.js index 7ca7af42e210..9926879e8a08 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3271,7 +3271,6 @@ const styles = { linkPreviewImage: { flex: 1, resizeMode: 'contain', - maxWidth: 350, borderRadius: 8, marginTop: 8, }, From 76a7f715cadd06863a7dfb8fb2ce932f3c6bc847 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 30 May 2023 11:44:36 +0200 Subject: [PATCH 015/273] simplify maxLines logic --- src/components/Composer/index.android.js | 6 ++++-- src/components/Composer/index.ios.js | 5 ++--- src/pages/home/report/ReportActionCompose.js | 21 +++----------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index c043ab86381f..232e9bdc240c 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -56,8 +56,8 @@ const defaultProps = { start: 0, end: 0, }, + maxLines: undefined, isFullComposerAvailable: false, - maxLines: -1, setIsFullComposerAvailable: () => {}, isComposerFullSize: false, style: null, @@ -94,6 +94,8 @@ class Composer extends React.Component { } render() { + console.log(this.props.isComposerFullSize); + return ( ComposerUtils.updateNumberOfLines(this.props, e)} rejectResponderTermination={false} textAlignVertical="center" - maximumNumberOfLines={!this.props.isComposerFullSize ? this.props.maxLines : undefined} + maximumNumberOfLines={this.props.isComposerFullSize ? undefined : this.props.maxLines} style={this.state.propStyles} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...this.props} diff --git a/src/components/Composer/index.ios.js b/src/components/Composer/index.ios.js index 3ca2d7edf58a..357a4b187417 100644 --- a/src/components/Composer/index.ios.js +++ b/src/components/Composer/index.ios.js @@ -56,7 +56,7 @@ const defaultProps = { start: 0, end: 0, }, - maxLines: -1, + maxLines: undefined, isFullComposerAvailable: false, setIsFullComposerAvailable: () => {}, isComposerFullSize: false, @@ -103,14 +103,13 @@ class Composer extends React.Component { (this.textInput = el)} onContentSizeChange={(e) => ComposerUtils.updateNumberOfLines(this.props, e)} rejectResponderTermination={false} textAlignVertical="center" smartInsertDelete={false} + maximumNumberOfLines={this.props.isComposerFullSize ? undefined : this.props.maxLines} style={this.state.propStyles} - maximumNumberOfLines={!this.props.isComposerFullSize ? this.props.maxLines : undefined} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...propsToPass} editable={!this.props.isDisabled} diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index c789b03ab0b9..2ddf213eb816 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -195,6 +195,8 @@ class ReportActionCompose extends React.Component { this.shouldAutoFocus = !props.modal.isVisible && (this.shouldFocusInputOnScreenFocus || this.isEmptyChat()) && props.shouldShowComposeInput; + this.maxComposerLines = this.props.isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES; + // For mobile Safari, updating the selection prop on an unfocused input will cause it to automatically gain focus // and subsequent programmatic focus shifts (e.g., modal focus trap) to show the blue frame (:focus-visible style), // so we need to ensure that it is only updated after focus. @@ -211,7 +213,6 @@ class ReportActionCompose extends React.Component { start: isMobileSafari && !this.shouldAutoFocus ? 0 : props.comment.length, end: isMobileSafari && !this.shouldAutoFocus ? 0 : props.comment.length, }, - maxLines: props.isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES, value: props.comment, // If we are on a small width device then don't show last 3 items from conciergePlaceholderOptions @@ -234,7 +235,6 @@ class ReportActionCompose extends React.Component { this.focus(false); }); - this.setMaxLines(); this.updateComment(this.comment); // Shows Popover Menu on Workspace Chat at first sign-in @@ -259,10 +259,6 @@ class ReportActionCompose extends React.Component { this.focus(); } - if (this.props.isComposerFullSize !== prevProps.isComposerFullSize) { - this.setMaxLines(); - } - // Value state does not have the same value as comment props when the comment gets changed from another tab. // In this case, we should synchronize the value between tabs. const shouldSyncComment = prevProps.comment !== this.props.comment && this.state.value !== this.props.comment; @@ -402,17 +398,6 @@ class ReportActionCompose extends React.Component { this.setState({hasExceededMaxCommentLength}); } - /** - * Set the maximum number of lines for the composer - */ - setMaxLines() { - let maxLines = this.props.isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES; - if (this.props.isComposerFullSize) { - maxLines = CONST.COMPOSER.MAX_LINES_FULL; - } - this.setState({maxLines}); - } - // eslint-disable-next-line rulesdir/prefer-early-return setShouldShowSuggestionMenuToFalse() { if (this.state && this.state.shouldShowEmojiSuggestionMenu) { @@ -1076,7 +1061,7 @@ class ReportActionCompose extends React.Component { onChangeText={(comment) => this.updateComment(comment, true)} onKeyPress={this.triggerHotkeyActions} style={[styles.textInputCompose, this.props.isComposerFullSize ? styles.textInputFullCompose : styles.flex4]} - maxLines={this.state.maxLines} + maxLines={this.maxComposerLines} onFocus={() => this.setIsFocused(true)} onBlur={() => { this.setIsFocused(false); From 763302eb8e7f17e3988d423b3781082b59101045 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 30 May 2023 11:51:53 +0200 Subject: [PATCH 016/273] Add fix and comment for textinput maxNumberOfLines bug --- src/components/Composer/index.android.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index 232e9bdc240c..56428235d928 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -104,7 +104,10 @@ class Composer extends React.Component { onContentSizeChange={(e) => ComposerUtils.updateNumberOfLines(this.props, e)} rejectResponderTermination={false} textAlignVertical="center" - maximumNumberOfLines={this.props.isComposerFullSize ? undefined : this.props.maxLines} + // Setting a really high number here fixes an issue with the react-native fork, where on Android the text input would collapse to only one line, + // when it should actually expand to the container (https://github.com/Expensify/App/issues/11694#issuecomment-1560520670) + // TODO: @Szymon20000 is working on fixing this (android-only) issue in the react-native fork, remove this commend once done + maximumNumberOfLines={this.props.isComposerFullSize ? 1000000 : this.props.maxLines} style={this.state.propStyles} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...this.props} From 23d9fd832c65c3adc48805d18d9597eb0d1df343 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 30 May 2023 11:57:22 +0200 Subject: [PATCH 017/273] remove console.log --- src/components/Composer/index.android.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index 56428235d928..ae0146097c35 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -94,8 +94,6 @@ class Composer extends React.Component { } render() { - console.log(this.props.isComposerFullSize); - return ( Date: Wed, 31 May 2023 00:49:57 +0500 Subject: [PATCH 018/273] Fix avatar dropdown in profile and workspace setting --- src/components/PopoverMenu/index.js | 2 +- src/pages/settings/Profile/ProfilePage.js | 2 +- src/pages/workspace/WorkspaceSettingsPage.js | 2 +- src/styles/styles.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PopoverMenu/index.js b/src/components/PopoverMenu/index.js index 17982c0d5684..330a6a8b61f5 100644 --- a/src/components/PopoverMenu/index.js +++ b/src/components/PopoverMenu/index.js @@ -64,7 +64,7 @@ const PopoverMenu = (props) => { return ( { diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js index d58cb4ceec3d..022b77e1a421 100755 --- a/src/pages/settings/Profile/ProfilePage.js +++ b/src/pages/settings/Profile/ProfilePage.js @@ -102,7 +102,7 @@ const ProfilePage = (props) => { onImageSelected={PersonalDetails.updateAvatar} onImageRemoved={PersonalDetails.deleteAvatar} anchorPosition={styles.createMenuPositionProfile(props.windowWidth)} - anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} + anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} size={CONST.AVATAR_SIZE.LARGE} /> diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.js index 20bccddd9448..59e216496e12 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.js +++ b/src/pages/workspace/WorkspaceSettingsPage.js @@ -128,7 +128,7 @@ function WorkspaceSettingsPage(props) { 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}} + anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, 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', ''))} diff --git a/src/styles/styles.js b/src/styles/styles.js index 8195eeb75b11..b17bde1db67f 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1226,7 +1226,7 @@ const styles = { createMenuPositionProfile: (windowWidth) => ({ horizontal: windowWidth - 355, - vertical: 250, + vertical: 162, }), createMenuPositionReportActionCompose: (windowHeight) => ({ From ad455dc1cc59ca8e80f34af2dcd872a80afab5fd Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 31 May 2023 01:08:53 +0500 Subject: [PATCH 019/273] Fix dropdown position for workspace list 3-dots menu --- src/components/HeaderWithCloseButton.js | 12 ++++++++++++ src/components/ThreeDotsMenu/index.js | 8 ++++++++ src/styles/styles.js | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index f6e979cbde7c..1a8894b3ec2b 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -18,6 +18,7 @@ import withKeyboardState, {keyboardStatePropTypes} from './withKeyboardState'; import AvatarWithDisplayName from './AvatarWithDisplayName'; import iouReportPropTypes from '../pages/iouReportPropTypes'; import participantPropTypes from './participantPropTypes'; +import CONST from "../CONST" const propTypes = { /** Title of the Header */ @@ -64,6 +65,12 @@ const propTypes = { left: PropTypes.number, }), + /** The anchor alignment of the menu */ + threeDotsAnchorAlignment: PropTypes.shape({ + horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)), + vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)), + }), + /** Whether we should show a close button */ shouldShowCloseButton: PropTypes.bool, @@ -125,6 +132,10 @@ const defaultProps = { vertical: 0, horizontal: 0, }, + threeDotsAnchorAlignment: { + horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, + vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, + } }; class HeaderWithCloseButton extends Component { @@ -217,6 +228,7 @@ class HeaderWithCloseButton extends Component { menuItems={this.props.threeDotsMenuItems} onIconPress={this.props.onThreeDotsButtonPress} anchorPosition={this.props.threeDotsAnchorPosition} + anchorAlignment={this.props.threeDotsAnchorAlignment} /> )} diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js index 0b4594f9be19..86299ceb48f0 100644 --- a/src/components/ThreeDotsMenu/index.js +++ b/src/components/ThreeDotsMenu/index.js @@ -8,6 +8,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import Tooltip from '../Tooltip'; import * as Expensicons from '../Icon/Expensicons'; import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes'; +import CONST from "../../CONST" const propTypes = { ...withLocalizePropTypes, @@ -38,6 +39,12 @@ const propTypes = { bottom: PropTypes.number, left: PropTypes.number, }).isRequired, + + /** The anchor alignment of the menu */ + anchorAlignment: PropTypes.shape({ + horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)), + vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)), + }), }; const defaultProps = { @@ -94,6 +101,7 @@ class ThreeDotsMenu extends Component { onClose={this.hidePopoverMenu} isVisible={this.state.isPopupMenuVisible} anchorPosition={this.props.anchorPosition} + anchorAlignment={this.props.anchorAlignment} onItemSelected={this.hidePopoverMenu} menuItems={this.props.menuItems} /> diff --git a/src/styles/styles.js b/src/styles/styles.js index b17bde1db67f..c549a5d291cc 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2918,12 +2918,12 @@ const styles = { }, threeDotsPopoverOffset: (windowWidth) => ({ - vertical: 50, + vertical: 60, horizontal: windowWidth - 60, }), threeDotsPopoverOffsetNoCloseButton: (windowWidth) => ({ - vertical: 50, + vertical: 60, horizontal: windowWidth - 10, }), From 300841268cc92018e851b2947ac143847f2355b2 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 31 May 2023 01:44:22 +0500 Subject: [PATCH 020/273] Fix lint issues --- src/components/HeaderWithCloseButton.js | 1 + src/components/ThreeDotsMenu/index.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index 1a8894b3ec2b..385efb446cf0 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -19,6 +19,7 @@ import AvatarWithDisplayName from './AvatarWithDisplayName'; import iouReportPropTypes from '../pages/iouReportPropTypes'; import participantPropTypes from './participantPropTypes'; import CONST from "../CONST" +import _ from 'underscore'; const propTypes = { /** Title of the Header */ diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js index 86299ceb48f0..b1de30276c7a 100644 --- a/src/components/ThreeDotsMenu/index.js +++ b/src/components/ThreeDotsMenu/index.js @@ -9,6 +9,7 @@ import Tooltip from '../Tooltip'; import * as Expensicons from '../Icon/Expensicons'; import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes'; import CONST from "../../CONST" +import _ from 'underscore'; const propTypes = { ...withLocalizePropTypes, @@ -53,6 +54,10 @@ const defaultProps = { iconStyles: [], icon: Expensicons.ThreeDots, onIconPress: () => {}, + anchorAlignment: { + horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, + vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, + }, }; class ThreeDotsMenu extends Component { From 4a3db13770837cf019bd6e31c98365c314cdf260 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 31 May 2023 01:56:08 +0500 Subject: [PATCH 021/273] Fix lint issues --- src/components/HeaderWithCloseButton.js | 2 +- src/components/ThreeDotsMenu/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index 385efb446cf0..2ca8a3c0af33 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {View, Keyboard, Pressable} from 'react-native'; +import _ from 'underscore'; import styles from '../styles/styles'; import Header from './Header'; import Navigation from '../libs/Navigation/Navigation'; @@ -19,7 +20,6 @@ import AvatarWithDisplayName from './AvatarWithDisplayName'; import iouReportPropTypes from '../pages/iouReportPropTypes'; import participantPropTypes from './participantPropTypes'; import CONST from "../CONST" -import _ from 'underscore'; const propTypes = { /** Title of the Header */ diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js index b1de30276c7a..98d1de5ba977 100644 --- a/src/components/ThreeDotsMenu/index.js +++ b/src/components/ThreeDotsMenu/index.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import {View, Pressable} from 'react-native'; import PropTypes from 'prop-types'; +import _ from 'underscore'; import Icon from '../Icon'; import PopoverMenu from '../PopoverMenu'; import styles from '../../styles/styles'; @@ -9,7 +10,6 @@ import Tooltip from '../Tooltip'; import * as Expensicons from '../Icon/Expensicons'; import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes'; import CONST from "../../CONST" -import _ from 'underscore'; const propTypes = { ...withLocalizePropTypes, From 51f869189da72b1cc36a27b7580b5c378d408414 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 31 May 2023 02:05:22 +0500 Subject: [PATCH 022/273] Fix lint issues --- src/components/HeaderWithCloseButton.js | 4 ++-- src/components/ThreeDotsMenu/index.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index 2ca8a3c0af33..535f64640297 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -19,7 +19,7 @@ import withKeyboardState, {keyboardStatePropTypes} from './withKeyboardState'; import AvatarWithDisplayName from './AvatarWithDisplayName'; import iouReportPropTypes from '../pages/iouReportPropTypes'; import participantPropTypes from './participantPropTypes'; -import CONST from "../CONST" +import CONST from '../CONST' const propTypes = { /** Title of the Header */ @@ -136,7 +136,7 @@ const defaultProps = { threeDotsAnchorAlignment: { horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, - } + }, }; class HeaderWithCloseButton extends Component { diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js index 98d1de5ba977..32fcbcab07ed 100644 --- a/src/components/ThreeDotsMenu/index.js +++ b/src/components/ThreeDotsMenu/index.js @@ -9,7 +9,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import Tooltip from '../Tooltip'; import * as Expensicons from '../Icon/Expensicons'; import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes'; -import CONST from "../../CONST" +import CONST from '../../CONST' const propTypes = { ...withLocalizePropTypes, From 0554e58927c55fdc21c78e4aecdcdfd0788ec50e Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 31 May 2023 02:16:06 +0500 Subject: [PATCH 023/273] Fix lint issues --- src/components/HeaderWithCloseButton.js | 2 +- src/components/ThreeDotsMenu/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index 535f64640297..0fe1fb45dc59 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -19,7 +19,7 @@ import withKeyboardState, {keyboardStatePropTypes} from './withKeyboardState'; import AvatarWithDisplayName from './AvatarWithDisplayName'; import iouReportPropTypes from '../pages/iouReportPropTypes'; import participantPropTypes from './participantPropTypes'; -import CONST from '../CONST' +import CONST from '../CONST'; const propTypes = { /** Title of the Header */ diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js index 32fcbcab07ed..b76ac93499e2 100644 --- a/src/components/ThreeDotsMenu/index.js +++ b/src/components/ThreeDotsMenu/index.js @@ -9,7 +9,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import Tooltip from '../Tooltip'; import * as Expensicons from '../Icon/Expensicons'; import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes'; -import CONST from '../../CONST' +import CONST from '../../CONST'; const propTypes = { ...withLocalizePropTypes, From 9c9075de0cedaf1fcfbeed836b5e0352241bb8f3 Mon Sep 17 00:00:00 2001 From: Sujit Kumar <60378235+therealsujitk@users.noreply.github.com> Date: Wed, 31 May 2023 12:44:51 +0530 Subject: [PATCH 024/273] Apply system emoji fonts to all font families --- .../BaseHTMLEngineProvider.js | 2 +- .../home/report/ReportActionItemFragment.js | 1 - src/styles/bold/index.js | 3 --- .../{ => fontFamily}/bold/index.android.js | 0 src/styles/fontFamily/bold/index.js | 3 +++ src/styles/fontFamily/emoji/index.js | 5 ----- src/styles/fontFamily/emoji/index.native.js | 3 --- src/styles/fontFamily/index.js | 22 +++++++++---------- src/styles/fontFamily/index.native.js | 16 ++++++++++++++ src/styles/styles.js | 5 +---- 10 files changed, 32 insertions(+), 28 deletions(-) delete mode 100644 src/styles/bold/index.js rename src/styles/{ => fontFamily}/bold/index.android.js (100%) create mode 100644 src/styles/fontFamily/bold/index.js delete mode 100644 src/styles/fontFamily/emoji/index.js delete mode 100644 src/styles/fontFamily/emoji/index.native.js create mode 100644 src/styles/fontFamily/index.native.js diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js index 576544c60273..cd05bcf057b3 100755 --- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js +++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js @@ -60,7 +60,7 @@ const BaseHTMLEngineProvider = (props) => { // We need to pass multiple system-specific fonts for emojis but // we can't apply multiple fonts at once so we need to pass fallback fonts. - const fallbackFonts = {'ExpensifyNeue-Regular': fontFamily.EMOJI_TEXT_FONT}; + const fallbackFonts = {'ExpensifyNeue-Regular': fontFamily.EXP_NEUE}; return ( { } return ( diff --git a/src/styles/bold/index.js b/src/styles/bold/index.js deleted file mode 100644 index 3ba35f200d3d..000000000000 --- a/src/styles/bold/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const bold = 'ExpensifyNeue-Regular'; - -export default bold; diff --git a/src/styles/bold/index.android.js b/src/styles/fontFamily/bold/index.android.js similarity index 100% rename from src/styles/bold/index.android.js rename to src/styles/fontFamily/bold/index.android.js diff --git a/src/styles/fontFamily/bold/index.js b/src/styles/fontFamily/bold/index.js new file mode 100644 index 000000000000..66d3c64f3565 --- /dev/null +++ b/src/styles/fontFamily/bold/index.js @@ -0,0 +1,3 @@ +const bold = 'ExpensifyNeue-Regular, Segoe UI Emoji, Noto Color Emoji'; + +export default bold; diff --git a/src/styles/fontFamily/emoji/index.js b/src/styles/fontFamily/emoji/index.js deleted file mode 100644 index 67630edf2b2d..000000000000 --- a/src/styles/fontFamily/emoji/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// In windows and ubuntu, we need these system fonts for emojis to work properly -// otherwise few of them will appear as black and white -const emojiFont = 'ExpensifyNeue-Regular, Segoe UI Emoji, Noto Color Emoji'; - -export default emojiFont; diff --git a/src/styles/fontFamily/emoji/index.native.js b/src/styles/fontFamily/emoji/index.native.js deleted file mode 100644 index 33273367b5f4..000000000000 --- a/src/styles/fontFamily/emoji/index.native.js +++ /dev/null @@ -1,3 +0,0 @@ -const emojiFont = 'ExpensifyNeue-Regular'; - -export default emojiFont; diff --git a/src/styles/fontFamily/index.js b/src/styles/fontFamily/index.js index 3e258bbef7b1..899ef20772de 100644 --- a/src/styles/fontFamily/index.js +++ b/src/styles/fontFamily/index.js @@ -1,18 +1,18 @@ -import bold from '../bold'; -import emojiFont from './emoji'; +import bold from './bold'; +// In windows and ubuntu, we need some extra system fonts for emojis to work properly +// otherwise few of them will appear as black and white const fontFamily = { - EXP_NEUE_ITALIC: 'ExpensifyNeue-Italic', + EXP_NEUE_ITALIC: 'ExpensifyNeue-Italic, Segoe UI Emoji, Noto Color Emoji', EXP_NEUE_BOLD: bold, - EXP_NEUE: 'ExpensifyNeue-Regular', - EXP_NEW_KANSAS_MEDIUM: 'ExpensifyNewKansas-Medium', - EXP_NEW_KANSAS_MEDIUM_ITALIC: 'ExpensifyNewKansas-MediumItalic', + EXP_NEUE: 'ExpensifyNeue-Regular, Segoe UI Emoji, Noto Color Emoji', + EXP_NEW_KANSAS_MEDIUM: 'ExpensifyNewKansas-Medium, Segoe UI Emoji, Noto Color Emoji', + EXP_NEW_KANSAS_MEDIUM_ITALIC: 'ExpensifyNewKansas-MediumItalic, Segoe UI Emoji, Noto Color Emoji', SYSTEM: 'System', - MONOSPACE: 'ExpensifyMono-Regular', - MONOSPACE_ITALIC: 'ExpensifyMono-Regular', - MONOSPACE_BOLD: 'ExpensifyMono-Bold', - MONOSPACE_BOLD_ITALIC: 'ExpensifyMono-Bold', - EMOJI_TEXT_FONT: emojiFont, + MONOSPACE: 'ExpensifyMono-Regular, Segoe UI Emoji, Noto Color Emoji', + MONOSPACE_ITALIC: 'ExpensifyMono-Regular, Segoe UI Emoji, Noto Color Emoji', + MONOSPACE_BOLD: 'ExpensifyMono-Bold, Segoe UI Emoji, Noto Color Emoji', + MONOSPACE_BOLD_ITALIC: 'ExpensifyMono-Bold, Segoe UI Emoji, Noto Color Emoji', }; export default fontFamily; diff --git a/src/styles/fontFamily/index.native.js b/src/styles/fontFamily/index.native.js new file mode 100644 index 000000000000..369d1f66f8f1 --- /dev/null +++ b/src/styles/fontFamily/index.native.js @@ -0,0 +1,16 @@ +import bold from './bold'; + +const fontFamily = { + EXP_NEUE_ITALIC: 'ExpensifyNeue-Italic', + EXP_NEUE_BOLD: bold, + EXP_NEUE: 'ExpensifyNeue-Regular', + EXP_NEW_KANSAS_MEDIUM: 'ExpensifyNewKansas-Medium', + EXP_NEW_KANSAS_MEDIUM_ITALIC: 'ExpensifyNewKansas-MediumItalic', + SYSTEM: 'System', + MONOSPACE: 'ExpensifyMono-Regular', + MONOSPACE_ITALIC: 'ExpensifyMono-Regular', + MONOSPACE_BOLD: 'ExpensifyMono-Bold', + MONOSPACE_BOLD_ITALIC: 'ExpensifyMono-Bold', +}; + +export default fontFamily; diff --git a/src/styles/styles.js b/src/styles/styles.js index 8195eeb75b11..a1afbee704aa 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -187,13 +187,11 @@ const styles = { }, emojiSuggestionsEmoji: { - fontFamily: fontFamily.EMOJI_TEXT_FONT, fontSize: variables.fontSizeMedium, width: 51, textAlign: 'center', }, emojiSuggestionsText: { - fontFamily: fontFamily.EMOJI_TEXT_FONT, fontSize: variables.fontSizeMedium, }, @@ -1546,7 +1544,7 @@ const styles = { backgroundColor: themeColors.componentBG, borderColor: themeColors.border, color: themeColors.text, - fontFamily: fontFamily.EMOJI_TEXT_FONT, + fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeNormal, borderWidth: 0, height: 'auto', @@ -1631,7 +1629,6 @@ const styles = { // Emoji Picker Styles emojiText: { - fontFamily: fontFamily.EMOJI_TEXT_FONT, textAlign: 'center', fontSize: variables.emojiSize, ...spacing.pv0, From 2c372801b1b3e38cfd372c4e9f8c3fe8eab7504d Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Wed, 31 May 2023 12:54:37 +0200 Subject: [PATCH 025/273] migrate InitialSettingsPage to PressableWithFeedback --- src/pages/settings/InitialSettingsPage.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 4e775bcd2cd2..dfa01c4898da 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -1,6 +1,6 @@ import lodashGet from 'lodash/get'; import React from 'react'; -import {View, ScrollView, Pressable} from 'react-native'; +import {View, ScrollView} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -39,6 +39,7 @@ import policyMemberPropType from '../policyMemberPropType'; import * as ReportActionContextMenu from '../home/report/ContextMenu/ReportActionContextMenu'; import {CONTEXT_MENU_TYPES} from '../home/report/ContextMenu/ContextMenuActions'; import * as CurrencyUtils from '../../libs/CurrencyUtils'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; const propTypes = { /* Onyx Props */ @@ -325,9 +326,12 @@ class InitialSettingsPage extends React.Component { - - + - - + {Boolean(this.props.currentUserPersonalDetails.displayName) && ( Date: Wed, 31 May 2023 16:56:41 +0200 Subject: [PATCH 026/273] Limit amount of ExpandURL calls, and fix styles while in draft --- src/libs/ReportActionsUtils.js | 20 ++++++++++++++++---- src/pages/home/report/ReportActionItem.js | 11 +++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 9e2a24f6c5a4..5b887d213eaf 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -163,13 +163,25 @@ function getMostRecentIOURequestActionID(reportActions) { } /** - * Returns true when the report action contains a link + * Returns array of links inside given report * * @param {reportAction} reportAction * @returns {Boolean} */ -function containsLink(reportAction) { - return !_.isEmpty(lodashGet(reportAction, ['message', 0, 'html'])); +function getLinksInsideReport(reportAction) { + const htmlContent = lodashGet(reportAction, ['message', 0, 'html']); + + const regex = /]*?\s+)?href="([^"]*)"/gi; + + const urls = []; + let match = regex.exec(htmlContent); + + while (match !== null) { + urls.push(match[1]); + match = regex.exec(htmlContent); + } + + return urls; } /** @@ -397,7 +409,7 @@ export { getLastVisibleAction, getLastVisibleMessageText, getMostRecentIOURequestActionID, - containsLink, + getLinksInsideReport, isDeletedAction, shouldReportActionBeVisible, isReportActionDeprecated, diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 88595018e05f..dea72ff1e2be 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -113,6 +113,7 @@ function ReportActionItem(props) { const [moderationDecision, setModerationDecision] = useState(CONST.MODERATION.MODERATOR_DECISION_APPROVED); const textInputRef = useRef(); const popoverAnchorRef = useRef(); + const downloadedPreviews = useRef([]); const isDraftEmpty = !props.draftMessage; useEffect(() => { @@ -124,10 +125,12 @@ function ReportActionItem(props) { }, [isDraftEmpty]); useEffect(() => { - if (!ReportActionsUtils.containsLink(props.action)) { + const urls = ReportActionsUtils.getLinksInsideReport(props.action); + if (_.isEqual(downloadedPreviews.current, urls)) { return; } + downloadedPreviews.current = urls; Report.expandURLPreview(props.report.reportID, props.action.reportActionID); }, [props.action, props.report.reportID]); @@ -339,7 +342,11 @@ function ReportActionItem(props) { return ( <> {children} - {!_.isEmpty(props.action.linkMetadata) && } + {!_.isEmpty(props.action.linkMetadata) && ( + + + + )} {hasReactions && ( Date: Wed, 31 May 2023 17:15:37 +0200 Subject: [PATCH 027/273] Fix resize link preview logic --- src/pages/home/report/LinkPreviewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index e214189d7e2e..f58d720d9c47 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -121,7 +121,7 @@ const LinkPreviewer = (props) => { maxHeight: Math.min(image.height, maxImageSize), // Calculate maximum width when image is too tall, so it doesn't move away from left - maxWidth: Math.min(image.width, maxImageSize) * (image.width < image.height ? image.width / image.height : 1), + maxWidth: (Math.min(image.height, maxImageSize) / image.height) * image.width, }, ]} resizeMode="contain" From 2c8100bc62fca644fd1be7d818382ee659d754b2 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Wed, 31 May 2023 17:20:05 +0200 Subject: [PATCH 028/273] Add max width --- src/pages/home/report/LinkPreviewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js index f58d720d9c47..87840b64c498 100644 --- a/src/pages/home/report/LinkPreviewer.js +++ b/src/pages/home/report/LinkPreviewer.js @@ -121,7 +121,7 @@ const LinkPreviewer = (props) => { maxHeight: Math.min(image.height, maxImageSize), // Calculate maximum width when image is too tall, so it doesn't move away from left - maxWidth: (Math.min(image.height, maxImageSize) / image.height) * image.width, + maxWidth: Math.min((Math.min(image.height, maxImageSize) / image.height) * image.width, maxImageSize), }, ]} resizeMode="contain" From a4bc5da64b80d3a5ce10c404662c2a0715af61c1 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Wed, 31 May 2023 17:30:41 +0200 Subject: [PATCH 029/273] Prettier --- src/libs/ReportActionsUtils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 5b887d213eaf..47a309bd796e 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -175,12 +175,12 @@ function getLinksInsideReport(reportAction) { const urls = []; let match = regex.exec(htmlContent); - + while (match !== null) { - urls.push(match[1]); - match = regex.exec(htmlContent); + urls.push(match[1]); + match = regex.exec(htmlContent); } - + return urls; } From 455fab0dea90c1748210e8375c6cccff685ce223 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 31 May 2023 18:58:18 +0200 Subject: [PATCH 030/273] change high number to "Infinity" --- src/components/Composer/index.android.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index ae0146097c35..de500931417f 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -105,7 +105,7 @@ class Composer extends React.Component { // Setting a really high number here fixes an issue with the react-native fork, where on Android the text input would collapse to only one line, // when it should actually expand to the container (https://github.com/Expensify/App/issues/11694#issuecomment-1560520670) // TODO: @Szymon20000 is working on fixing this (android-only) issue in the react-native fork, remove this commend once done - maximumNumberOfLines={this.props.isComposerFullSize ? 1000000 : this.props.maxLines} + maximumNumberOfLines={this.props.isComposerFullSize ? Infinity : this.props.maxLines} style={this.state.propStyles} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...this.props} From 37fe914d7f2e6f5132ad4527840d5cbc5493657b Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 31 May 2023 19:12:44 +0200 Subject: [PATCH 031/273] change maxNumberOfLines back to 1000000 --- src/components/Composer/index.android.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index de500931417f..ae0146097c35 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -105,7 +105,7 @@ class Composer extends React.Component { // Setting a really high number here fixes an issue with the react-native fork, where on Android the text input would collapse to only one line, // when it should actually expand to the container (https://github.com/Expensify/App/issues/11694#issuecomment-1560520670) // TODO: @Szymon20000 is working on fixing this (android-only) issue in the react-native fork, remove this commend once done - maximumNumberOfLines={this.props.isComposerFullSize ? Infinity : this.props.maxLines} + maximumNumberOfLines={this.props.isComposerFullSize ? 1000000 : this.props.maxLines} style={this.state.propStyles} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...this.props} From 04e0a8a81ac8703f0d2f578bb68d8e4c74e3949e Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Thu, 1 Jun 2023 12:57:44 +0200 Subject: [PATCH 032/273] Filter empty objects and arrays in linkMetadata --- src/pages/home/report/ReportActionItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index dea72ff1e2be..04fc4f61997c 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -344,7 +344,7 @@ function ReportActionItem(props) { {children} {!_.isEmpty(props.action.linkMetadata) && ( - + !_.isEmpty(item))} /> )} {hasReactions && ( From 681b3f1594eea264c92e33e04ace4cd1fe0b7c8d Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Thu, 1 Jun 2023 15:03:18 +0200 Subject: [PATCH 033/273] Fix styles --- src/pages/home/report/ReportActionItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 39bdd9cc0f3c..abb8df25866a 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -348,7 +348,7 @@ function ReportActionItem(props) { {children} {!_.isEmpty(props.action.linkMetadata) && ( - !_.isEmpty(item))} /> + !_.isEmpty(item))} /> )} {hasReactions && ( From cbb01464bd076cd62b7dfd919eb49c337be624ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Thu, 1 Jun 2023 16:28:49 +0200 Subject: [PATCH 034/273] migrated HeaderView to PressableWithoutFeedback --- src/pages/home/HeaderView.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 2d9d4cd4f265..c011928e2b35 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -1,6 +1,6 @@ import _ from 'underscore'; import React from 'react'; -import {View, Pressable} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; @@ -29,6 +29,7 @@ import ThreeDotsMenu from '../../components/ThreeDotsMenu'; import * as Task from '../../libs/actions/Task'; import reportActionPropTypes from './report/reportActionPropTypes'; import * as Session from '../../libs/actions/Session'; +import PressableWithoutFeedback from '../../components/Pressable/PressableWithoutFeedback'; const propTypes = { /** Toggles the navigationMenu open and closed */ @@ -127,10 +128,12 @@ const HeaderView = (props) => { > {props.isSmallScreenWidth && ( - { - + )} {Boolean(props.report && title) && ( - ReportUtils.navigateToDetailsPage(props.report)} style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} disabled={isTaskReport} + accessibilityLabel={title} + accessibilityRole="button" > {shouldShowSubscript ? ( { /> )} - + {shouldShowCallButton && ( { /> )} - Report.togglePinnedState(props.report))} style={[styles.touchableButtonImage]} + accessibilityLabel={props.translate('common.pin')} + accessibilityState={{ + checked: props.report.isPinned, + }} + accessibilityRole="togglebutton" > - + {shouldShowThreeDotsButton && ( Date: Thu, 1 Jun 2023 20:54:07 +0200 Subject: [PATCH 035/273] migrate BaseAutoCompleteSuggestions to PressableWithFeedback --- .../BaseAutoCompleteSuggestions.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js index b5758680619a..30e0ccfd036d 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js @@ -1,5 +1,5 @@ import React from 'react'; -import {View, Pressable} from 'react-native'; +import {View} from 'react-native'; // We take FlatList from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another import {FlatList} from 'react-native-gesture-handler'; @@ -7,6 +7,7 @@ import styles from '../../styles/styles'; import * as StyleUtils from '../../styles/StyleUtils'; import CONST from '../../CONST'; import {propTypes} from './autoCompleteSuggestionsPropTypes'; +import PressableWithFeedback from '../Pressable/PressableWithFeedback'; /** * @param {Number} numRows @@ -33,14 +34,15 @@ const BaseAutoCompleteSuggestions = (props) => { * @returns {JSX.Element} */ const renderSuggestionMenuItem = ({item, index}) => ( - StyleUtils.getAutoCompleteSuggestionItemStyle(props.highlightedSuggestionIndex, CONST.AUTO_COMPLETE_SUGGESTER.ITEM_HEIGHT, hovered, index)} + hoverDimmingValue={1} onMouseDown={(e) => e.preventDefault()} onPress={() => props.onSelect(index)} onLongPress={() => {}} > {props.renderSuggestionMenuItem(item, index)} - + ); const rowHeight = measureHeightOfSuggestionRows(props.suggestions.length, props.isSuggestionPickerLarge); From 536240ddbfb2b499259b7f37750be307c5ae1a81 Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Fri, 2 Jun 2023 11:55:46 +0200 Subject: [PATCH 036/273] extract accessibility label for every suggestions item --- .../AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js | 1 + .../autoCompleteSuggestionsPropTypes.js | 3 +++ src/components/EmojiSuggestions.js | 1 + src/components/MentionSuggestions.js | 1 + 4 files changed, 6 insertions(+) diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js index 30e0ccfd036d..12a50368b008 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js @@ -40,6 +40,7 @@ const BaseAutoCompleteSuggestions = (props) => { onMouseDown={(e) => e.preventDefault()} onPress={() => props.onSelect(index)} onLongPress={() => {}} + accessibilityLabel={props.accessibilityLabelExtractor(item, index)} > {props.renderSuggestionMenuItem(item, index)} diff --git a/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js b/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js index eed9368e534d..6ff330d839c6 100644 --- a/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js +++ b/src/components/AutoCompleteSuggestions/autoCompleteSuggestionsPropTypes.js @@ -24,6 +24,9 @@ const propTypes = { /** Show that we should include ReportRecipientLocalTime view height */ shouldIncludeReportRecipientLocalTimeHeight: PropTypes.bool.isRequired, + + /** create accessibility label for each item */ + accessibilityLabelExtractor: PropTypes.func.isRequired, }; const defaultProps = {}; diff --git a/src/components/EmojiSuggestions.js b/src/components/EmojiSuggestions.js index c098cc988b81..2af9dfc99368 100644 --- a/src/components/EmojiSuggestions.js +++ b/src/components/EmojiSuggestions.js @@ -94,6 +94,7 @@ const EmojiSuggestions = (props) => { onSelect={props.onSelect} isSuggestionPickerLarge={props.isEmojiPickerLarge} shouldIncludeReportRecipientLocalTimeHeight={props.shouldIncludeReportRecipientLocalTimeHeight} + accessibilityLabelExtractor={keyExtractor} /> ); }; diff --git a/src/components/MentionSuggestions.js b/src/components/MentionSuggestions.js index d1a6441e1d33..14dbeff04a32 100644 --- a/src/components/MentionSuggestions.js +++ b/src/components/MentionSuggestions.js @@ -100,6 +100,7 @@ const MentionSuggestions = (props) => { onSelect={props.onSelect} isSuggestionPickerLarge={props.isMentionPickerLarge} shouldIncludeReportRecipientLocalTimeHeight={props.shouldIncludeReportRecipientLocalTimeHeight} + accessibilityLabelExtractor={keyExtractor} /> ); }; From a73893d94a379e05b226200474e870fe2d1a26f9 Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Fri, 2 Jun 2023 12:23:30 +0200 Subject: [PATCH 037/273] migrate AddPayPalMePage to PressableWithoutFeedback --- src/pages/settings/Payments/AddPayPalMePage.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Payments/AddPayPalMePage.js b/src/pages/settings/Payments/AddPayPalMePage.js index f4b2bd81bb8d..9c28a5c3f2c9 100644 --- a/src/pages/settings/Payments/AddPayPalMePage.js +++ b/src/pages/settings/Payments/AddPayPalMePage.js @@ -1,5 +1,5 @@ import React, {useRef, useState, useCallback} from 'react'; -import {View, TouchableWithoutFeedback, Linking} from 'react-native'; +import {View, Linking} from 'react-native'; import _ from 'underscore'; import CONST from '../../../CONST'; import ROUTES from '../../../ROUTES'; @@ -19,6 +19,7 @@ import * as User from '../../../libs/actions/User'; import Icon from '../../../components/Icon'; import * as Expensicons from '../../../components/Icon/Expensicons'; import variables from '../../../styles/variables'; +import PressableWithoutFeedback from '../../../components/Pressable/PressableWithoutFeedback'; const AddPayPalMePage = (props) => { const [payPalMeUsername, setPayPalMeUsername] = useState(''); @@ -70,8 +71,10 @@ const AddPayPalMePage = (props) => { /> {props.translate('addPayPalMePage.checkListOf')} - Linking.openURL('https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies')} > @@ -90,7 +93,7 @@ const AddPayPalMePage = (props) => { /> - + From b703379bb9da1015cf35a795b5320b3fe2340fea Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Fri, 2 Jun 2023 12:51:14 +0200 Subject: [PATCH 038/273] fix problem with genericPressable autoHitSlop when its false --- .../Pressable/GenericPressable/BaseGenericPressable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.js b/src/components/Pressable/GenericPressable/BaseGenericPressable.js index 6cdb83bbb81a..0b15378de8bc 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.js +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.js @@ -135,7 +135,7 @@ const GenericPressable = forwardRef((props, ref) => { return ( Date: Fri, 2 Jun 2023 19:26:55 +0200 Subject: [PATCH 039/273] migrated ReportActionItemMessageEdit to PressableWithFeedback --- .../report/ReportActionItemMessageEdit.js | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js index 56ccfbe81ca2..0e4c602e674f 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.js +++ b/src/pages/home/report/ReportActionItemMessageEdit.js @@ -1,7 +1,7 @@ /* eslint-disable rulesdir/onyx-props-must-have-default */ import lodashGet from 'lodash/get'; import React from 'react'; -import {InteractionManager, Keyboard, Pressable, TouchableOpacity, View} from 'react-native'; +import {InteractionManager, Keyboard, View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; @@ -23,7 +23,6 @@ import Tooltip from '../../../components/Tooltip'; import * as ReportActionContextMenu from './ContextMenu/ReportActionContextMenu'; import * as ReportUtils from '../../../libs/ReportUtils'; import * as EmojiUtils from '../../../libs/EmojiUtils'; -import getButtonState from '../../../libs/getButtonState'; import reportPropTypes from '../../reportPropTypes'; import ExceededCommentLength from '../../../components/ExceededCommentLength'; import CONST from '../../../CONST'; @@ -34,6 +33,8 @@ import refPropTypes from '../../../components/refPropTypes'; import * as ComposerUtils from '../../../libs/ComposerUtils'; import * as ComposerActions from '../../../libs/actions/Composer'; import * as User from '../../../libs/actions/User'; +import PressableWithFeedback from '../../../components/Pressable/PressableWithFeedback'; +import Hoverable from '../../../components/Hoverable'; const propTypes = { /** All the data of the action */ @@ -278,24 +279,26 @@ class ReportActionItemMessageEdit extends React.Component { - [styles.chatItemSubmitButton, StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed))]} - nativeID={this.cancelButtonID} - onPress={this.deleteDraft} - hitSlop={{ - top: 3, - right: 3, - bottom: 3, - left: 3, - }} - > - {({hovered, pressed}) => ( - + + {(hovered) => ( + + + )} - + - - + From abb38610c8d86ef63b776c81f8c6f02f71bfa7cd Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Mon, 5 Jun 2023 01:41:43 +0500 Subject: [PATCH 040/273] feat: use MenuItem instead of TaskSelectorLink on Task page --- src/components/MenuItem.js | 246 +++++++++++++++------------- src/components/TaskSelectorLink.js | 114 ------------- src/components/menuItemPropTypes.js | 9 +- src/pages/tasks/NewTaskPage.js | 72 ++++---- src/styles/styles.js | 7 - 5 files changed, 173 insertions(+), 275 deletions(-) delete mode 100644 src/components/TaskSelectorLink.js diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index 21195a9f4ca2..8e1a23445db4 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -75,7 +75,7 @@ const MenuItem = (props) => { [ styles.flexShrink1, styles.popoverMenuText, - props.icon ? styles.ml3 : undefined, + props.icon && !_.isArray(props.icon) ? styles.ml3 : undefined, props.shouldShowBasicTitle ? undefined : styles.textStrong, props.interactive && props.disabled ? {...styles.disabledText, ...styles.userSelectNone} : undefined, styles.pre, @@ -87,7 +87,7 @@ const MenuItem = (props) => { ); const descriptionTextStyle = StyleUtils.combineStyles([ styles.textLabelSupporting, - props.icon ? styles.ml3 : undefined, + props.icon && !_.isArray(props.icon) ? styles.ml3 : undefined, styles.lineHeightNormal, props.title ? descriptionVerticalMargin : undefined, props.descriptionTextStyle, @@ -95,6 +95,8 @@ const MenuItem = (props) => { ]); const fallbackAvatarSize = props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT; + const stylesWithoutPadding = _.isArray(props.style) ? _.map(props.style, style => _.omit(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) : _.omit(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); + const paddingStyles = _.isArray(props.style) ? _.map(props.style, style => _.pick(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) : _.pick(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); return ( { onPressOut={ControlSelection.unblock} onSecondaryInteraction={props.onSecondaryInteraction} style={({hovered, pressed}) => [ - props.style, + paddingStyles, !props.interactive && styles.cursorDefault, StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || hovered, pressed, props.success, props.disabled, props.interactive), true), (hovered || pressed) && props.hoverAndPressStyle, @@ -124,135 +126,149 @@ const MenuItem = (props) => { > {({hovered, pressed}) => ( <> - - {Boolean(props.icon) && ( - - {props.iconType === CONST.ICON_TYPE_ICON && ( - - )} - {props.iconType === CONST.ICON_TYPE_WORKSPACE && ( - - )} - {props.iconType === CONST.ICON_TYPE_AVATAR && ( - - )} - - )} - - {Boolean(props.description) && props.shouldShowDescriptionOnTop && ( - - {props.description} - + {props.label && + + {props.label} + + } + + + {Boolean(props.icon) && _.isArray(props.icon) && ( + + )} + {Boolean(props.icon) && !_.isArray(props.icon) && ( + + {props.iconType === CONST.ICON_TYPE_ICON && ( + + )} + {props.iconType === CONST.ICON_TYPE_WORKSPACE && ( + + )} + {props.iconType === CONST.ICON_TYPE_AVATAR && ( + + )} + )} - - {Boolean(props.title) && ( + + {Boolean(props.description) && props.shouldShowDescriptionOnTop && ( + + {props.description} + + )} + + {Boolean(props.title) && ( + + {convertToLTR(props.title)} + + )} + {Boolean(props.shouldShowTitleIcon) && ( + + + + )} + + {Boolean(props.description) && !props.shouldShowDescriptionOnTop && ( - {convertToLTR(props.title)} + {props.description} )} - {Boolean(props.shouldShowTitleIcon) && ( - + {Boolean(props.furtherDetails) && ( + + + {props.furtherDetails} + )} - {Boolean(props.description) && !props.shouldShowDescriptionOnTop && ( - - {props.description} - + + + {Boolean(props.badgeText) && ( + + )} + {/* Since subtitle can be of type number, we should allow 0 to be shown */} + {(props.subtitle || props.subtitle === 0) && ( + + {props.subtitle} + + )} + {!_.isEmpty(props.floatRightAvatars) && ( + + + )} - {Boolean(props.furtherDetails) && ( - + {Boolean(props.brickRoadIndicator) && ( + + + )} + {Boolean(props.shouldShowRightIcon) && ( + + - - {props.furtherDetails} - )} + {props.shouldShowSelectedState && } - - {Boolean(props.badgeText) && ( - - )} - {/* Since subtitle can be of type number, we should allow 0 to be shown */} - {(props.subtitle || props.subtitle === 0) && ( - - {props.subtitle} - - )} - {!_.isEmpty(props.floatRightAvatars) && ( - - - - )} - {Boolean(props.brickRoadIndicator) && ( - - - - )} - {Boolean(props.shouldShowRightIcon) && ( - - - - )} - {props.shouldShowSelectedState && } - )} diff --git a/src/components/TaskSelectorLink.js b/src/components/TaskSelectorLink.js deleted file mode 100644 index a288fc22acb3..000000000000 --- a/src/components/TaskSelectorLink.js +++ /dev/null @@ -1,114 +0,0 @@ -import React from 'react'; -import {View, TouchableOpacity} from 'react-native'; -import PropTypes from 'prop-types'; -import styles from '../styles/styles'; -import Icon from './Icon'; -import * as Expensicons from './Icon/Expensicons'; -import themeColors from '../styles/themes/default'; -import variables from '../styles/variables'; -import Text from './Text'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import * as StyleUtils from '../styles/StyleUtils'; -import DisplayNames from './DisplayNames'; -import MultipleAvatars from './MultipleAvatars'; -import CONST from '../CONST'; -import avatarPropTypes from './avatarPropTypes'; - -const propTypes = { - /** Array of avatar URLs or icons */ - icons: PropTypes.arrayOf(avatarPropTypes), - - /** The title to display */ - text: PropTypes.string, - - /** The description to display */ - alternateText: PropTypes.string, - - /** The function to call when the link is pressed */ - onPress: PropTypes.func.isRequired, - - /** Label for the Link */ - label: PropTypes.string.isRequired, - - /** Whether it is a share location */ - isShareDestination: PropTypes.bool, - - /** Whether the Touchable should be disabled */ - disabled: PropTypes.bool, - - /** Whether we're creating a new task or editing */ - isNewTask: PropTypes.bool, - - ...withLocalizePropTypes, -}; - -const defaultProps = { - icons: [], - text: '', - alternateText: '', - isShareDestination: false, - disabled: false, - isNewTask: true, -}; - -const TaskSelectorLink = (props) => { - const displayNameStyle = StyleUtils.combineStyles(styles.optionDisplayName, styles.pre); - const alternateTextStyle = StyleUtils.combineStyles(styles.sidebarLinkText, styles.optionAlternateText, styles.textLabelSupporting, styles.pre); - return ( - - - {props.icons.length !== 0 || props.text !== '' ? ( - - {props.translate(props.label)} - - - - - {props.alternateText ? ( - - {props.alternateText} - - ) : null} - - - - ) : ( - {props.translate(props.label)} - )} - {props.disabled || !props.isNewTask ? null : ( - - )} - - - ); -}; - -TaskSelectorLink.defaultProps = defaultProps; -TaskSelectorLink.propTypes = propTypes; -TaskSelectorLink.displayName = 'TaskSelectorLink'; - -export default withLocalize(TaskSelectorLink); diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js index 57266831377f..4291a3acbb41 100644 --- a/src/components/menuItemPropTypes.js +++ b/src/components/menuItemPropTypes.js @@ -22,7 +22,11 @@ const propTypes = { onPress: PropTypes.func, /** Icon to display on the left side of component */ - icon: PropTypes.oneOfType([PropTypes.elementType, PropTypes.string]), + icon: PropTypes.oneOfType([ + PropTypes.elementType, + PropTypes.string, + PropTypes.arrayOf(avatarPropTypes) + ]), /** Icon Width */ iconWidth: PropTypes.number, @@ -33,6 +37,9 @@ const propTypes = { /** Text to display for the item */ title: PropTypes.string.isRequired, + /** Text that appears above the title */ + label: PropTypes.string, + /** Boolean whether to display the title right icon */ shouldShowTitleIcon: PropTypes.bool, diff --git a/src/pages/tasks/NewTaskPage.js b/src/pages/tasks/NewTaskPage.js index efeca6b790c8..77e97c084184 100644 --- a/src/pages/tasks/NewTaskPage.js +++ b/src/pages/tasks/NewTaskPage.js @@ -12,7 +12,7 @@ import styles from '../../styles/styles'; import ONYXKEYS from '../../ONYXKEYS'; import Permissions from '../../libs/Permissions'; import ROUTES from '../../ROUTES'; -import TaskSelectorLink from '../../components/TaskSelectorLink'; +import MenuItemWithTopDescription from '../../components/MenuItemWithTopDescription'; import reportPropTypes from '../reportPropTypes'; import * as TaskUtils from '../../libs/actions/Task'; import * as OptionsListUtils from '../../libs/OptionsListUtils'; @@ -126,42 +126,38 @@ const NewTaskPage = (props) => { shouldShowBackButton onBackButtonPress={() => Navigation.goBack()} /> - - - - Navigation.navigate(ROUTES.NEW_TASK_TITLE)} - label="newTaskPage.title" - /> - - - Navigation.navigate(ROUTES.NEW_TASK_DESCRIPTION)} - label="newTaskPage.description" - /> - - - Navigation.navigate(ROUTES.NEW_TASK_ASSIGNEE)} - label="newTaskPage.assignee" - /> - - - Navigation.navigate(ROUTES.NEW_TASK_SHARE_DESTINATION)} - label="newTaskPage.shareSomewhere" - isShareDestination - disabled={Boolean(props.task.parentReportID)} - /> - + + + Navigation.navigate(ROUTES.NEW_TASK_TITLE)} + shouldShowRightIcon + /> + Navigation.navigate(ROUTES.NEW_TASK_DESCRIPTION)} + shouldShowRightIcon + /> + Navigation.navigate(ROUTES.NEW_TASK_ASSIGNEE)} + shouldShowRightIcon + /> + + + Navigation.navigate(ROUTES.NEW_TASK_SHARE_DESTINATION)} + shouldShowRightIcon + /> { onSubmit={() => onSubmit()} enabledWhenOffline buttonText={props.translate('newTaskPage.confirmTask')} - containerStyles={[styles.mh0, styles.mt5, styles.flex1]} + containerStyles={[styles.mh0, styles.mt5, styles.flex1, styles.ph5]} /> diff --git a/src/styles/styles.js b/src/styles/styles.js index 6968016b1503..2474f6859259 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1710,13 +1710,6 @@ const styles = { backgroundColor: themeColors.transparent, }, - taskSelectorLink: { - alignSelf: 'center', - width: '100%', - padding: 6, - backgroundColor: themeColors.transparent, - }, - chatItemAttachmentPlaceholder: { backgroundColor: themeColors.sidebar, borderColor: themeColors.border, From 9f60aeb91ebfbce43a77e7c0a8f91a5a0bd64b28 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 5 Jun 2023 11:51:16 +0530 Subject: [PATCH 041/273] feat: migrated ReportTypingIndicator to Functional Component --- .../home/report/ReportTypingIndicator.js | 86 ++++++++----------- 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/src/pages/home/report/ReportTypingIndicator.js b/src/pages/home/report/ReportTypingIndicator.js index 2bd8c6a913e9..5b58bce3a78f 100755 --- a/src/pages/home/report/ReportTypingIndicator.js +++ b/src/pages/home/report/ReportTypingIndicator.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState, useEffect} from 'react'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -26,66 +26,52 @@ const defaultProps = { userTypingStatuses: {}, }; -class ReportTypingIndicator extends React.Component { - constructor(props) { - super(props); +const ReportTypingIndicator = (props) => { + const [usersTyping, setUsersTyping] = useState(props.userTypingStatuses ? _.filter(_.keys(props.userTypingStatuses), (login) => props.userTypingStatuses[login]) : []); - const usersTyping = props.userTypingStatuses ? _.filter(_.keys(props.userTypingStatuses), (login) => props.userTypingStatuses[login]) : []; - this.state = {usersTyping}; - } - - componentDidUpdate(prevProps) { - // Make sure we only update the state if there's been a change in who's typing. - if (_.isEqual(prevProps.userTypingStatuses, this.props.userTypingStatuses)) { - return; - } - - const usersTyping = _.filter(_.keys(this.props.userTypingStatuses), (login) => this.props.userTypingStatuses[login]); + useEffect(() => { + setUsersTyping(_.filter(_.keys(props.userTypingStatuses), (login) => props.userTypingStatuses[login])); + }, [props.userTypingStatuses]); - // eslint-disable-next-line react/no-did-update-set-state - this.setState({usersTyping}); + // If we are offline, the user typing statuses are not up-to-date so do not show them + if (props.network.isOffline) { + return null; } - render() { - const numUsersTyping = _.size(this.state.usersTyping); + const numUsersTyping = _.size(usersTyping); - // If we are offline, the user typing statuses are not up-to-date so do not show them - if (this.props.network.isOffline) { + // Decide on the Text element that will hold the display based on the number of users that are typing. + switch (numUsersTyping) { + case 0: return null; - } - // Decide on the Text element that will hold the display based on the number of users that are typing. - switch (numUsersTyping) { - case 0: - return null; - - case 1: - return ( - - ); - - default: - return ( - - {this.props.translate('reportTypingIndicator.multipleUsers')} - {` ${this.props.translate('reportTypingIndicator.areTyping')}`} - - ); - } + case 1: + return ( + + ); + + default: + return ( + + {props.translate('reportTypingIndicator.multipleUsers')} + {` ${props.translate('reportTypingIndicator.areTyping')}`} + + ); } -} +}; ReportTypingIndicator.propTypes = propTypes; ReportTypingIndicator.defaultProps = defaultProps; +ReportTypingIndicator.displayName = 'ReportTypingIndicator'; export default compose( withLocalize, From 48d9f5939a46edd4a34c35b793ede6fad307b1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Mon, 5 Jun 2023 09:42:31 +0200 Subject: [PATCH 042/273] removed Podfile.lock changes --- ios/Podfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ae913bda8338..6cb4235c58c8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1019,7 +1019,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Airship: c70eed50e429f97f5adb285423c7291fb7a032ae AirshipFrameworkProxy: 7bc4130c668c6c98e2d4c60fe4c9eb61a999be99 - boost: 57d2868c099736d80fcd648bf211b4431e51a558 + boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: ff54429f0110d3c722630a98096ba689c39f6d5f @@ -1062,7 +1062,7 @@ SPEC CHECKSUMS: Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4 Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2 PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 + RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCTRequired: e9e7b8b45aa9bedb2fdad71740adf07a7265b9be RCTTypeSafety: 9ae0e9206625e995f0df4d5b9ddc94411929fb30 React: a71c8e1380f07e01de721ccd52bcf9c03e81867d @@ -1135,4 +1135,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 4ed1c7b099741c82e2b0411b95f6468e72be6c76 -COCOAPODS: 1.12.1 +COCOAPODS: 1.12.0 From 576b356879000c7fec2207791e907e9a89c683e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Mon, 5 Jun 2023 10:59:37 +0200 Subject: [PATCH 043/273] migrated WorkspaceInitialPage to PressableWithoutFeedback --- src/pages/workspace/WorkspaceInitialPage.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 9cebeb235259..8178812382e7 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -1,7 +1,7 @@ import _ from 'underscore'; import lodashGet from 'lodash/get'; import React, {useCallback, useState} from 'react'; -import {View, ScrollView, Pressable} from 'react-native'; +import {View, ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import Navigation from '../../libs/Navigation/Navigation'; @@ -30,6 +30,7 @@ import OfflineWithFeedback from '../../components/OfflineWithFeedback'; import * as ReimbursementAccountProps from '../ReimbursementAccount/reimbursementAccountPropTypes'; import * as ReportUtils from '../../libs/ReportUtils'; import withWindowDimensions from '../../components/withWindowDimensions'; +import PressableWithoutFeedback from '../../components/Pressable/PressableWithoutFeedback'; const propTypes = { ...policyPropTypes, @@ -188,10 +189,12 @@ const WorkspaceInitialPage = (props) => { - openEditor(policy.id)} + accessibilityLabel={props.translate('workspace.common.settings')} + accessibilityRole="button" > { name={policyName} type={CONST.ICON_TYPE_WORKSPACE} /> - + {!_.isEmpty(policy.name) && ( - openEditor(policy.id)} + accessibilityLabel={props.translate('workspace.common.settings')} + accessibilityRole="button" > { > {policy.name} - + )} From fe9ba8d687a2a5e4e74e4c1cb42d0e75c30623b8 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Mon, 5 Jun 2023 16:44:22 +0500 Subject: [PATCH 044/273] fix: prettier errors --- src/components/MenuItem.js | 12 ++++++++---- src/components/menuItemPropTypes.js | 6 +----- src/pages/tasks/NewTaskPage.js | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index 8e1a23445db4..bbbb0eda3f98 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -95,8 +95,12 @@ const MenuItem = (props) => { ]); const fallbackAvatarSize = props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT; - const stylesWithoutPadding = _.isArray(props.style) ? _.map(props.style, style => _.omit(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) : _.omit(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); - const paddingStyles = _.isArray(props.style) ? _.map(props.style, style => _.pick(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) : _.pick(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); + const stylesWithoutPadding = _.isArray(props.style) + ? _.map(props.style, (style) => _.omit(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) + : _.omit(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); + const paddingStyles = _.isArray(props.style) + ? _.map(props.style, (style) => _.pick(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) + : _.pick(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); return ( { > {({hovered, pressed}) => ( <> - {props.label && + {props.label && ( {props.label} - } + )} {Boolean(props.icon) && _.isArray(props.icon) && ( diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js index 4291a3acbb41..3909f446c907 100644 --- a/src/components/menuItemPropTypes.js +++ b/src/components/menuItemPropTypes.js @@ -22,11 +22,7 @@ const propTypes = { onPress: PropTypes.func, /** Icon to display on the left side of component */ - icon: PropTypes.oneOfType([ - PropTypes.elementType, - PropTypes.string, - PropTypes.arrayOf(avatarPropTypes) - ]), + icon: PropTypes.oneOfType([PropTypes.elementType, PropTypes.string, PropTypes.arrayOf(avatarPropTypes)]), /** Icon Width */ iconWidth: PropTypes.number, diff --git a/src/pages/tasks/NewTaskPage.js b/src/pages/tasks/NewTaskPage.js index 77e97c084184..33e35f7008c0 100644 --- a/src/pages/tasks/NewTaskPage.js +++ b/src/pages/tasks/NewTaskPage.js @@ -143,7 +143,7 @@ const NewTaskPage = (props) => { Navigation.navigate(ROUTES.NEW_TASK_ASSIGNEE)} shouldShowRightIcon @@ -153,7 +153,7 @@ const NewTaskPage = (props) => { Navigation.navigate(ROUTES.NEW_TASK_SHARE_DESTINATION)} shouldShowRightIcon From 5e4bde0796ea35ef2462648ec28438e45ac276ed Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 5 Jun 2023 14:03:13 +0200 Subject: [PATCH 045/273] Improve extractLinksFromMessageHtml func --- src/libs/ReportActionsUtils.js | 16 ++++++---------- src/pages/home/report/ReportActionItem.js | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index d9e4fd58b496..6afb5a0d38c0 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -173,23 +173,19 @@ function getMostRecentIOURequestActionID(reportActions) { /** * Returns array of links inside given report * - * @param {reportAction} reportAction + * @param {object} reportAction * @returns {Boolean} */ -function getLinksInsideReport(reportAction) { +function extractLinksFromMessageHtml(reportAction) { const htmlContent = lodashGet(reportAction, ['message', 0, 'html']); const regex = /]*?\s+)?href="([^"]*)"/gi; - const urls = []; - let match = regex.exec(htmlContent); - - while (match !== null) { - urls.push(match[1]); - match = regex.exec(htmlContent); + if (!htmlContent) { + return; } - return urls; + return _.map([...htmlContent.matchAll(regex)], (match) => match[1]); } /** @@ -421,7 +417,7 @@ export { getLastVisibleAction, getLastVisibleMessageText, getMostRecentIOURequestActionID, - getLinksInsideReport, + extractLinksFromMessageHtml, isDeletedAction, shouldReportActionBeVisible, isReportActionDeprecated, diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 0912673a55e9..c74281baa63c 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -120,7 +120,7 @@ function ReportActionItem(props) { }, [isDraftEmpty]); useEffect(() => { - const urls = ReportActionsUtils.getLinksInsideReport(props.action); + const urls = ReportActionsUtils.extractLinksFromMessageHtml(props.action); if (_.isEqual(downloadedPreviews.current, urls)) { return; } From 6d7b343ab7f6dd56e5151acc8a5396bb137eb997 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 5 Jun 2023 16:21:38 +0200 Subject: [PATCH 046/273] Regex comment and add default transparency --- src/libs/ReportActionsUtils.js | 3 ++- src/styles/styles.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 6afb5a0d38c0..b5856c2cd5d1 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -173,12 +173,13 @@ function getMostRecentIOURequestActionID(reportActions) { /** * Returns array of links inside given report * - * @param {object} reportAction + * @param {Object} reportAction * @returns {Boolean} */ function extractLinksFromMessageHtml(reportAction) { const htmlContent = lodashGet(reportAction, ['message', 0, 'html']); + // Regex to get link in href prop inside of component const regex = /]*?\s+)?href="([^"]*)"/gi; if (!htmlContent) { diff --git a/src/styles/styles.js b/src/styles/styles.js index 69278b300842..1429e62ae599 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -23,7 +23,7 @@ import CONST from '../CONST'; import cursor from './utilities/cursor'; import userSelect from './utilities/userSelect'; -function getTransparentColor(color, transparency) { +function getTransparentColor(color, transparency = 'ff') { return `${color}${transparency}`; } From 92c1f34301b1e1405835d3fa617f1aeea81d14b2 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 5 Jun 2023 10:25:20 -0400 Subject: [PATCH 047/273] Get rid of SetPasswordPage --- src/ROUTES.js | 1 - .../Navigation/AppNavigator/PublicScreens.js | 6 - src/libs/Navigation/linkingConfig.js | 1 - src/pages/SetPasswordPage.js | 137 ------------------ 4 files changed, 145 deletions(-) delete mode 100755 src/pages/SetPasswordPage.js diff --git a/src/ROUTES.js b/src/ROUTES.js index c9075c42d8e1..a5ad4c9b8fc0 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -111,7 +111,6 @@ export default { FLAG_COMMENT: `flag/:reportID/:reportActionID`, getFlagCommentRoute: (reportID, reportActionID) => `flag/${reportID}/${reportActionID}`, SEARCH: 'search', - SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', getDetailsRoute: (login) => `details?login=${encodeURIComponent(login)}`, REPORT_PARTICIPANTS: 'r/:reportID/participants', diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.js b/src/libs/Navigation/AppNavigator/PublicScreens.js index 2bcee425cfbc..0e84de5c4dd5 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.js +++ b/src/libs/Navigation/AppNavigator/PublicScreens.js @@ -1,7 +1,6 @@ import React from 'react'; import {createStackNavigator} from '@react-navigation/stack'; import SignInPage from '../../../pages/signin/SignInPage'; -import SetPasswordPage from '../../../pages/SetPasswordPage'; import ValidateLoginPage from '../../../pages/ValidateLoginPage'; import LogInWithShortLivedAuthTokenPage from '../../../pages/LogInWithShortLivedAuthTokenPage'; import SCREENS from '../../../SCREENS'; @@ -32,11 +31,6 @@ const PublicScreens = () => ( options={defaultScreenOptions} component={UnlinkLoginPage} /> - ); diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 7a45266b0355..788cb560217b 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -18,7 +18,6 @@ export default { }, // Main Routes - SetPassword: ROUTES.SET_PASSWORD_WITH_VALIDATE_CODE, ValidateLogin: ROUTES.VALIDATE_LOGIN, UnlinkLogin: ROUTES.UNLINK_LOGIN, [SCREENS.TRANSITION_FROM_OLD_DOT]: ROUTES.TRANSITION_FROM_OLD_DOT, diff --git a/src/pages/SetPasswordPage.js b/src/pages/SetPasswordPage.js deleted file mode 100755 index f00a7095e463..000000000000 --- a/src/pages/SetPasswordPage.js +++ /dev/null @@ -1,137 +0,0 @@ -import React, {Component} from 'react'; -import {View} from 'react-native'; -import {SafeAreaView} from 'react-native-safe-area-context'; -import PropTypes from 'prop-types'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; -import {propTypes as validateLinkPropTypes, defaultProps as validateLinkDefaultProps} from './ValidateLoginPage/validateLinkPropTypes'; -import styles from '../styles/styles'; -import * as Session from '../libs/actions/Session'; -import ONYXKEYS from '../ONYXKEYS'; -import SignInPageLayout from './signin/SignInPageLayout'; -import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; -import compose from '../libs/compose'; -import NewPasswordForm from './settings/NewPasswordForm'; -import FormAlertWithSubmitButton from '../components/FormAlertWithSubmitButton'; -import FormSubmit from '../components/FormSubmit'; -import * as ErrorUtils from '../libs/ErrorUtils'; - -const propTypes = { - /* Onyx Props */ - - /** The details about the account that the user is signing in with */ - account: PropTypes.shape({ - /** An error message to display to the user */ - errors: PropTypes.objectOf(PropTypes.string), - - /** Whether a sign on form is loading (being submitted) */ - isLoading: PropTypes.bool, - }), - - /** The credentials of the logged in person */ - credentials: PropTypes.shape({ - /** The email the user logged in with */ - login: PropTypes.string, - - /** The password used to log in the user */ - password: PropTypes.string, - }), - - /** Session object */ - session: PropTypes.shape({ - /** An error message to display to the user */ - errors: PropTypes.objectOf(PropTypes.string), - }), - - /** The accountID and validateCode are passed via the URL */ - route: validateLinkPropTypes, - - ...withLocalizePropTypes, -}; - -const defaultProps = { - account: {}, - credentials: {}, - route: validateLinkDefaultProps, - session: { - errors: null, - authToken: '', - }, -}; - -class SetPasswordPage extends Component { - constructor(props) { - super(props); - - this.validateAndSubmitForm = this.validateAndSubmitForm.bind(this); - - this.state = { - password: '', - isFormValid: false, - }; - } - - componentWillUnmount() { - Session.clearAccountMessages(); - } - - validateAndSubmitForm() { - if (!this.state.isFormValid) { - return; - } - const accountID = lodashGet(this.props.route.params, 'accountID', ''); - const validateCode = lodashGet(this.props.route.params, 'validateCode', ''); - Session.updatePasswordAndSignin(accountID, validateCode, this.state.password); - } - - render() { - const buttonText = this.props.translate('setPasswordPage.setPassword'); - const error = ErrorUtils.getLatestErrorMessage(this.props.account) || ErrorUtils.getLatestErrorMessage(this.props.session); - return ( - - - - - this.setState({password})} - updateIsFormValid={(isValid) => this.setState({isFormValid: isValid})} - /> - - - - - - - - ); - } -} - -SetPasswordPage.propTypes = propTypes; -SetPasswordPage.defaultProps = defaultProps; - -export default compose( - withLocalize, - withOnyx({ - credentials: {key: ONYXKEYS.CREDENTIALS}, - account: {key: ONYXKEYS.ACCOUNT}, - session: { - key: ONYXKEYS.SESSION, - initWithStoredValues: false, - }, - }), -)(SetPasswordPage); From dfc71ff729aed6d201f5b1673da7349f971f3cbe Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Fri, 2 Jun 2023 19:07:37 +0200 Subject: [PATCH 048/273] fix styling on long display name in RHN --- src/pages/settings/InitialSettingsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index dfa01c4898da..20dc65a68ab7 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -343,7 +343,7 @@ class InitialSettingsPage extends React.Component { Date: Mon, 5 Jun 2023 12:35:18 +0200 Subject: [PATCH 049/273] set default hover dimming value to 1 --- src/pages/settings/InitialSettingsPage.js | 2 -- src/styles/variables.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 20dc65a68ab7..0e03fc025a98 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -328,7 +328,6 @@ class InitialSettingsPage extends React.Component { Date: Tue, 6 Jun 2023 12:32:08 +0200 Subject: [PATCH 050/273] migrated RadioButton to PressableWithFeedback --- src/components/RadioButton.js | 14 +++++++++++--- src/components/RadioButtonWithLabel.js | 2 +- src/components/RadioButtons.js | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/components/RadioButton.js b/src/components/RadioButton.js index 01d12138d998..1111acc591be 100644 --- a/src/components/RadioButton.js +++ b/src/components/RadioButton.js @@ -1,9 +1,10 @@ import React from 'react'; -import {View, Pressable} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import styles from '../styles/styles'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; +import PressableWithFeedback from './Pressable/PressableWithFeedback'; const propTypes = { /** Whether radioButton is checked */ @@ -12,6 +13,9 @@ const propTypes = { /** A function that is called when the box/label is pressed */ onPress: PropTypes.func.isRequired, + /** Specifies the accessibility label for the radio button */ + accessibilityLabel: PropTypes.string.isRequired, + /** Should the input be styled for errors */ hasError: PropTypes.bool, @@ -25,9 +29,13 @@ const defaultProps = { }; const RadioButton = (props) => ( - ( width={14} /> - + ); RadioButton.propTypes = propTypes; diff --git a/src/components/RadioButtonWithLabel.js b/src/components/RadioButtonWithLabel.js index 776235f90cfe..7dbcb5676ce9 100644 --- a/src/components/RadioButtonWithLabel.js +++ b/src/components/RadioButtonWithLabel.js @@ -55,7 +55,7 @@ const RadioButtonWithLabel = (props) => { - {_.map(this.props.items, (item) => ( + {_.map(this.props.items, (item, index) => ( { From 8290ff18e87e49360e5d03a60259a0d818af00b0 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Tue, 6 Jun 2023 16:37:52 +0500 Subject: [PATCH 051/273] fix: removed extra space between task menu items --- src/pages/tasks/NewTaskPage.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/tasks/NewTaskPage.js b/src/pages/tasks/NewTaskPage.js index 5362b7471ad4..87e1abbfcfad 100644 --- a/src/pages/tasks/NewTaskPage.js +++ b/src/pages/tasks/NewTaskPage.js @@ -147,9 +147,8 @@ const NewTaskPage = (props) => { icon={assignee.icons} onPress={() => Navigation.navigate(ROUTES.NEW_TASK_ASSIGNEE)} shouldShowRightIcon + style={styles.popoverMenuItem} /> - - Date: Tue, 6 Jun 2023 13:53:47 +0200 Subject: [PATCH 052/273] migrate Banner to PressableWithFeedback --- src/components/Banner.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Banner.js b/src/components/Banner.js index 4dcfb7eb6c8e..d52286bb2e4c 100644 --- a/src/components/Banner.js +++ b/src/components/Banner.js @@ -1,6 +1,6 @@ import React, {memo} from 'react'; import PropTypes from 'prop-types'; -import {View, Pressable} from 'react-native'; +import {View} from 'react-native'; import compose from '../libs/compose'; import Hoverable from './Hoverable'; import Icon from './Icon'; @@ -12,6 +12,7 @@ import * as StyleUtils from '../styles/StyleUtils'; import getButtonState from '../libs/getButtonState'; import Tooltip from './Tooltip'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import PressableWithFeedback from './Pressable/PressableWithFeedback'; const propTypes = { /** Text to display in the banner. */ @@ -92,13 +93,13 @@ const Banner = (props) => ( {props.shouldShowCloseButton && ( - - + )} From c5b6dec7745632050f399e114711eee253c146bf Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:21:51 +0500 Subject: [PATCH 053/273] Added getVerticalOffset no-op to add vertical gap on desktop --- src/styles/getVerticalOffset/index.desktop.js | 6 ++++++ src/styles/getVerticalOffset/index.js | 1 + src/styles/styles.js | 7 ++++--- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/styles/getVerticalOffset/index.desktop.js create mode 100644 src/styles/getVerticalOffset/index.js diff --git a/src/styles/getVerticalOffset/index.desktop.js b/src/styles/getVerticalOffset/index.desktop.js new file mode 100644 index 000000000000..420d0f545af1 --- /dev/null +++ b/src/styles/getVerticalOffset/index.desktop.js @@ -0,0 +1,6 @@ +export default (vertical) => ({ + // On desktop app we are adding a header gap of 12px + // which we need to add to vertical offset when setting + // offset on desktop + vertical: vertical + 12, +}); diff --git a/src/styles/getVerticalOffset/index.js b/src/styles/getVerticalOffset/index.js new file mode 100644 index 000000000000..2e7c4fbc07ff --- /dev/null +++ b/src/styles/getVerticalOffset/index.js @@ -0,0 +1 @@ +export default (vertical) => ({vertical}); diff --git a/src/styles/styles.js b/src/styles/styles.js index 9272e96e968d..541734b270d5 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -18,6 +18,7 @@ import writingDirection from './utilities/writingDirection'; import optionAlternateTextPlatformStyles from './optionAlternateTextPlatformStyles'; import pointerEventsNone from './pointerEventsNone'; import pointerEventsAuto from './pointerEventsAuto'; +import getVerticalOffset from './getVerticalOffset'; import overflowXHidden from './overflowXHidden'; import CONST from '../CONST'; import cursor from './utilities/cursor'; @@ -1240,7 +1241,7 @@ const styles = { createMenuPositionProfile: (windowWidth) => ({ horizontal: windowWidth - 355, - vertical: 162, + ...getVerticalOffset(162), }), createMenuPositionReportActionCompose: (windowHeight) => ({ @@ -2938,12 +2939,12 @@ const styles = { }, threeDotsPopoverOffset: (windowWidth) => ({ - vertical: 60, + ...getVerticalOffset(60), horizontal: windowWidth - 60, }), threeDotsPopoverOffsetNoCloseButton: (windowWidth) => ({ - vertical: 60, + ...getVerticalOffset(60), horizontal: windowWidth - 10, }), From 0158ed74ec17f26ef6de3896545ebeb540668946 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:29:41 +0500 Subject: [PATCH 054/273] Fix newline diff --- src/styles/getVerticalOffset/index.desktop.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/styles/getVerticalOffset/index.desktop.js b/src/styles/getVerticalOffset/index.desktop.js index 420d0f545af1..9e59b0f4fe03 100644 --- a/src/styles/getVerticalOffset/index.desktop.js +++ b/src/styles/getVerticalOffset/index.desktop.js @@ -1,6 +1,6 @@ export default (vertical) => ({ - // On desktop app we are adding a header gap of 12px - // which we need to add to vertical offset when setting + // On desktop app we are adding a header gap of 12px + // which we need to add to vertical offset when setting // offset on desktop vertical: vertical + 12, }); From a6e3d4cd7b11a642a336bc8a138437678e2abda9 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:47:48 +0500 Subject: [PATCH 055/273] Move desktop header gap to const --- src/CONST.js | 1 + src/styles/getVerticalOffset/index.desktop.js | 4 +++- src/styles/styles.js | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 42e27f7ad28f..4820f6a03119 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -827,6 +827,7 @@ const CONST = { WIDTH: 320, HEIGHT: 416, }, + DESKTOP_HEADER_HEIGHT: 12, NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT: 256, EMOJI_PICKER_ITEM_HEIGHT: 32, EMOJI_PICKER_HEADER_HEIGHT: 32, diff --git a/src/styles/getVerticalOffset/index.desktop.js b/src/styles/getVerticalOffset/index.desktop.js index 9e59b0f4fe03..97fa8fe390c7 100644 --- a/src/styles/getVerticalOffset/index.desktop.js +++ b/src/styles/getVerticalOffset/index.desktop.js @@ -1,6 +1,8 @@ +import CONST from '../../CONST'; + export default (vertical) => ({ // On desktop app we are adding a header gap of 12px // which we need to add to vertical offset when setting // offset on desktop - vertical: vertical + 12, + vertical: vertical + CONST.DESKTOP_HEADER_HEIGHT, }); diff --git a/src/styles/styles.js b/src/styles/styles.js index 541734b270d5..62b2af367995 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -745,7 +745,7 @@ const styles = { }, headerGap: { - height: 12, + height: CONST.DESKTOP_HEADER_HEIGHT, }, pushTextRight: { From b7f0c1c87c8a7530c4c6952634dd91e7825cccb0 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 7 Jun 2023 00:25:30 +0500 Subject: [PATCH 056/273] Renamed desktop header gap const --- src/CONST.js | 2 +- src/styles/getVerticalOffset/index.desktop.js | 2 +- src/styles/styles.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 4820f6a03119..8cd9c59732bf 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -827,7 +827,7 @@ const CONST = { WIDTH: 320, HEIGHT: 416, }, - DESKTOP_HEADER_HEIGHT: 12, + DESKTOP_HEADER_PADDING: 12, NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT: 256, EMOJI_PICKER_ITEM_HEIGHT: 32, EMOJI_PICKER_HEADER_HEIGHT: 32, diff --git a/src/styles/getVerticalOffset/index.desktop.js b/src/styles/getVerticalOffset/index.desktop.js index 97fa8fe390c7..a1fe12997431 100644 --- a/src/styles/getVerticalOffset/index.desktop.js +++ b/src/styles/getVerticalOffset/index.desktop.js @@ -4,5 +4,5 @@ export default (vertical) => ({ // On desktop app we are adding a header gap of 12px // which we need to add to vertical offset when setting // offset on desktop - vertical: vertical + CONST.DESKTOP_HEADER_HEIGHT, + vertical: vertical + CONST.DESKTOP_HEADER_PADDING, }); diff --git a/src/styles/styles.js b/src/styles/styles.js index 62b2af367995..30c210cb7b77 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -745,7 +745,7 @@ const styles = { }, headerGap: { - height: CONST.DESKTOP_HEADER_HEIGHT, + height: CONST.DESKTOP_HEADER_PADDING, }, pushTextRight: { From b65dd2a770ceb23bf00475666c82efb7cf35b38e Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Wed, 7 Jun 2023 00:26:51 +0500 Subject: [PATCH 057/273] Added js doc for getVerticalOffset --- src/styles/getVerticalOffset/index.desktop.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/styles/getVerticalOffset/index.desktop.js b/src/styles/getVerticalOffset/index.desktop.js index a1fe12997431..bd58266d0bd0 100644 --- a/src/styles/getVerticalOffset/index.desktop.js +++ b/src/styles/getVerticalOffset/index.desktop.js @@ -1,8 +1,13 @@ import CONST from '../../CONST'; +/** + * Adds the header padding with vertical offset on desktop + * @param {Number} vertical + * @returns {Object} + */ export default (vertical) => ({ - // On desktop app we are adding a header gap of 12px - // which we need to add to vertical offset when setting + // We add CONST.DESKTOP_HEADER_GAP on desktop which we + // need to add to vertical offset to have proper vertical // offset on desktop vertical: vertical + CONST.DESKTOP_HEADER_PADDING, }); From 5f0a6ff99dc1844278d9112c2f33dd18d176cf25 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Wed, 7 Jun 2023 05:08:07 +0500 Subject: [PATCH 058/273] fix: vertically center the menu item right icons --- src/components/MenuItem.js | 104 ++++++++++++++++----------------- src/pages/tasks/NewTaskPage.js | 14 ++--- 2 files changed, 56 insertions(+), 62 deletions(-) diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index 9f744563b210..3f03726d0a7c 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -96,12 +96,6 @@ const MenuItem = (props) => { ]); const fallbackAvatarSize = props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT; - const stylesWithoutPadding = _.isArray(props.style) - ? _.map(props.style, (style) => _.omit(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) - : _.omit(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); - const paddingStyles = _.isArray(props.style) - ? _.map(props.style, (style) => _.pick(style, ['padding', 'paddingVertical', 'paddingHorizontal'])) - : _.pick(props.style, ['padding', 'paddingVertical', 'paddingHorizontal']); return ( { onPressOut={ControlSelection.unblock} onSecondaryInteraction={props.onSecondaryInteraction} style={({hovered, pressed}) => [ - paddingStyles, + props.style, !props.interactive && styles.cursorDefault, StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || hovered, pressed, props.success, props.disabled, props.interactive), true), (hovered || pressed) && props.hoverAndPressStyle, @@ -131,12 +125,12 @@ const MenuItem = (props) => { > {({hovered, pressed}) => ( <> - {props.label && ( - - {props.label} - - )} - + + {props.label && ( + + {props.label} + + )} {Boolean(props.icon) && _.isArray(props.icon) && ( { )} - - {Boolean(props.badgeText) && ( - + + {Boolean(props.badgeText) && ( + + )} + {/* Since subtitle can be of type number, we should allow 0 to be shown */} + {(props.subtitle || props.subtitle === 0) && ( + + {props.subtitle} + + )} + {!_.isEmpty(props.floatRightAvatars) && ( + + - )} - {/* Since subtitle can be of type number, we should allow 0 to be shown */} - {(props.subtitle || props.subtitle === 0) && ( - - {props.subtitle} - - )} - {!_.isEmpty(props.floatRightAvatars) && ( - - - - )} - {Boolean(props.brickRoadIndicator) && ( - - - - )} - {Boolean(props.shouldShowRightIcon) && ( - - - - )} - {props.shouldShowSelectedState && } - + + )} + {Boolean(props.brickRoadIndicator) && ( + + + + )} + {Boolean(props.shouldShowRightIcon) && ( + + + + )} + {props.shouldShowSelectedState && } )} diff --git a/src/pages/tasks/NewTaskPage.js b/src/pages/tasks/NewTaskPage.js index 87e1abbfcfad..5fa993b00746 100644 --- a/src/pages/tasks/NewTaskPage.js +++ b/src/pages/tasks/NewTaskPage.js @@ -13,6 +13,7 @@ import ONYXKEYS from '../../ONYXKEYS'; import Permissions from '../../libs/Permissions'; import ROUTES from '../../ROUTES'; import MenuItemWithTopDescription from '../../components/MenuItemWithTopDescription'; +import MenuItem from '../../components/MenuItem'; import reportPropTypes from '../reportPropTypes'; import * as TaskUtils from '../../libs/actions/Task'; import * as OptionsListUtils from '../../libs/OptionsListUtils'; @@ -140,19 +141,18 @@ const NewTaskPage = (props) => { onPress={() => Navigation.navigate(ROUTES.NEW_TASK_DESCRIPTION)} shouldShowRightIcon /> - Navigation.navigate(ROUTES.NEW_TASK_ASSIGNEE)} shouldShowRightIcon - style={styles.popoverMenuItem} /> - Navigation.navigate(ROUTES.NEW_TASK_SHARE_DESTINATION)} shouldShowRightIcon From 7fd48bcbb2b7e45411284121808ed18c43c03790 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Wed, 7 Jun 2023 05:12:21 +0500 Subject: [PATCH 059/273] fix: make menu item container take up full height --- src/components/MenuItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index 3f03726d0a7c..f3382c2c8cd5 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -125,7 +125,7 @@ const MenuItem = (props) => { > {({hovered, pressed}) => ( <> - + {props.label && ( {props.label} From 91beee24cd566f2bb720a9eedc757e2ff6d03cc7 Mon Sep 17 00:00:00 2001 From: Daniel Gale-Rosen Date: Tue, 6 Jun 2023 20:38:27 -0400 Subject: [PATCH 060/273] first pass --- src/pages/settings/Profile/DisplayNamePage.js | 102 ++++++++---------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/src/pages/settings/Profile/DisplayNamePage.js b/src/pages/settings/Profile/DisplayNamePage.js index 2649db5a1805..1fe93717dd82 100644 --- a/src/pages/settings/Profile/DisplayNamePage.js +++ b/src/pages/settings/Profile/DisplayNamePage.js @@ -27,13 +27,8 @@ const defaultProps = { ...withCurrentUserPersonalDetailsDefaultProps, }; -class DisplayNamePage extends Component { - constructor(props) { - super(props); - - this.validate = this.validate.bind(this); - this.updateDisplayName = this.updateDisplayName.bind(this); - } +function DisplayNamePage(props) { + const currentUserDetails = props.currentUserPersonalDetails || {}; /** * Submit form to update user's first and last name (and display name) @@ -41,80 +36,77 @@ class DisplayNamePage extends Component { * @param {String} values.firstName * @param {String} values.lastName */ - updateDisplayName(values) { + const updateDisplayName = (values) => { PersonalDetails.updateDisplayName(values.firstName.trim(), values.lastName.trim()); } - + /** * @param {Object} values * @param {String} values.firstName * @param {String} values.lastName * @returns {Object} - An object containing the errors for each inputID */ - validate(values) { + const validate = (values) => { const errors = {}; // First we validate the first name field if (!ValidationUtils.isValidDisplayName(values.firstName)) { - ErrorUtils.addErrorMessage(errors, 'firstName', this.props.translate('personalDetails.error.hasInvalidCharacter')); + ErrorUtils.addErrorMessage(errors, 'firstName', props.translate('personalDetails.error.hasInvalidCharacter')); } if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_FIRST_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'firstName', this.props.translate('personalDetails.error.containsReservedWord')); + ErrorUtils.addErrorMessage(errors, 'firstName', props.translate('personalDetails.error.containsReservedWord')); } // Then we validate the last name field if (!ValidationUtils.isValidDisplayName(values.lastName)) { - errors.lastName = this.props.translate('personalDetails.error.hasInvalidCharacter'); + errors.lastName = props.translate('personalDetails.error.hasInvalidCharacter'); } return errors; } - render() { - const currentUserDetails = this.props.currentUserPersonalDetails || {}; - - return ( - - Navigation.goBack(ROUTES.SETTINGS_PROFILE)} - /> -
- {this.props.translate('displayNamePage.isShownOnProfile')} - - - - - - -
-
- ); - } + return ( + + Navigation.goBack(ROUTES.SETTINGS_PROFILE)} + /> +
+ {props.translate('displayNamePage.isShownOnProfile')} + + + + + + +
+
+ ); } DisplayNamePage.propTypes = propTypes; DisplayNamePage.defaultProps = defaultProps; +DisplayNamePage.displayName = 'DisplayNamePage'; export default compose(withLocalize, withCurrentUserPersonalDetails)(DisplayNamePage); From 9f9ab333d69e6e56c915581b8eca59c7ae6a34d6 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 7 Jun 2023 10:59:43 +0700 Subject: [PATCH 061/273] fix thread title shown as ExpensiMark syntax in LHN --- src/libs/actions/Report.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 43b52ea431a8..9eaaf34a96d3 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -935,6 +935,7 @@ function editReportComment(reportID, originalReportAction, textForNewComment) { // https://github.com/Expensify/App/issues/13221 const originalCommentHTML = lodashGet(originalReportAction, 'message[0].html'); const htmlForNewComment = handleUserDeletedLinksInHtml(textForNewComment, originalCommentHTML); + const reportComment = parser.htmlToText(htmlForNewComment); // For comments shorter than 10k chars, convert the comment from MD into HTML because that's how it is stored in the database // For longer comments, skip parsing and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!! @@ -966,7 +967,7 @@ function editReportComment(reportID, originalReportAction, textForNewComment) { ...originalMessage, isEdited: true, html: htmlForNewComment, - text: textForNewComment, + text: reportComment, }, ], }, @@ -982,7 +983,6 @@ function editReportComment(reportID, originalReportAction, textForNewComment) { const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(reportID, optimisticReportActions); if (reportActionID === lastVisibleAction.reportActionID) { - const reportComment = parser.htmlToText(htmlForNewComment); const lastMessageText = ReportUtils.formatReportLastMessageText(reportComment); const optimisticReport = { lastMessageText, From c4eb29c995ab8bc9a3654398d9348c51452737a9 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 7 Jun 2023 12:05:48 +0700 Subject: [PATCH 062/273] fix: 20214crash when opening the thread image --- src/components/AttachmentCarousel/index.js | 9 +++++++-- src/components/AttachmentModal.js | 11 ++++++----- .../HTMLEngineProvider/HTMLRenderers/ImageRenderer.js | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/AttachmentCarousel/index.js b/src/components/AttachmentCarousel/index.js index 778044586172..5d8e66c12986 100644 --- a/src/components/AttachmentCarousel/index.js +++ b/src/components/AttachmentCarousel/index.js @@ -20,6 +20,7 @@ import Tooltip from '../Tooltip'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import compose from '../../libs/compose'; import withWindowDimensions from '../withWindowDimensions'; +import reportPropTypes from '../../pages/reportPropTypes'; const propTypes = { /** source is used to determine the starting index in the array of attachments */ @@ -31,6 +32,9 @@ const propTypes = { /** Object of report actions for this report */ reportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), + /** The report currently being looked at */ + report: reportPropTypes.isRequired, + ...withLocalizePropTypes, }; @@ -148,7 +152,8 @@ class AttachmentCarousel extends React.Component { * @returns {{page: Number, attachments: Array, shouldShowArrow: Boolean, containerWidth: Number, isZoomed: Boolean}} */ createInitialState() { - const actions = ReportActionsUtils.getSortedReportActions(_.values(this.props.reportActions)); + const parentReportAction = ReportActionsUtils.getParentReportAction(this.props.report); + const actions = [parentReportAction, ...ReportActionsUtils.getSortedReportActions(_.values(this.props.reportActions))]; const attachments = []; const htmlParser = new HtmlParser({ @@ -359,7 +364,7 @@ AttachmentCarousel.defaultProps = defaultProps; export default compose( withOnyx({ reportActions: { - key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, canEvict: false, }, }), diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index b29c910e83e4..393a0085176c 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -23,6 +23,7 @@ import ConfirmModal from './ConfirmModal'; import HeaderGap from './HeaderGap'; import SafeAreaConsumer from './SafeAreaConsumer'; import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL'; +import reportPropTypes from '../pages/reportPropTypes'; /** * Modal render prop component that exposes modal launching triggers that can be used @@ -57,8 +58,8 @@ const propTypes = { /** Title shown in the header of the modal */ headerTitle: PropTypes.string, - /** The ID of the report that has this attachment */ - reportID: PropTypes.string, + /** The report that has this attachment */ + report: reportPropTypes, ...withLocalizePropTypes, @@ -72,7 +73,7 @@ const defaultProps = { isAuthTokenRequired: false, allowDownload: false, headerTitle: null, - reportID: '', + report: {}, onModalShow: () => {}, onModalHide: () => {}, }; @@ -287,9 +288,9 @@ class AttachmentModal extends PureComponent { onCloseButtonPress={() => this.setState({isModalOpen: false})} /> - {this.props.reportID ? ( + {!_.isEmpty(this.props.report) ? ( { {({anchor, report, action, checkIfContextMenuActive}) => ( Date: Wed, 7 Jun 2023 12:08:57 +0700 Subject: [PATCH 063/273] fix: add error border --- src/pages/workspace/WorkspaceMembersPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 5206c34c1a49..b62ed9c7983e 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -319,15 +319,15 @@ class WorkspaceMembersPage extends React.Component { * @returns {React.Component} */ renderItem({item}) { + const hasError = !_.isEmpty(item.errors) || this.state.errors[item.login]; return ( this.dismissError(item)} pendingAction={item.pendingAction} errors={item.errors} > this.toggleUser(item.login, item.pendingAction)} activeOpacity={0.7} > From 27bf763739a7e4ad0ad5cd320cd5f4181463b6d8 Mon Sep 17 00:00:00 2001 From: Sujit Kumar <60378235+therealsujitk@users.noreply.github.com> Date: Wed, 7 Jun 2023 10:53:09 +0530 Subject: [PATCH 064/273] Remove emoji fonts for iOS --- src/styles/fontFamily/bold/index.ios.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/styles/fontFamily/bold/index.ios.js diff --git a/src/styles/fontFamily/bold/index.ios.js b/src/styles/fontFamily/bold/index.ios.js new file mode 100644 index 000000000000..3ba35f200d3d --- /dev/null +++ b/src/styles/fontFamily/bold/index.ios.js @@ -0,0 +1,3 @@ +const bold = 'ExpensifyNeue-Regular'; + +export default bold; From 5da5f3d5cc0cb381c312052bc5c4687c4c11d50f Mon Sep 17 00:00:00 2001 From: Oliver Wilks Date: Wed, 7 Jun 2023 09:22:03 +0100 Subject: [PATCH 065/273] Added contentContainerStyles prop --- src/components/OptionsSelector/BaseOptionsSelector.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index df15ad71febc..5609c91aa320 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -24,6 +24,9 @@ const propTypes = { /** padding bottom style of safe area */ safeAreaPaddingBottomStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /** Content container styles for OptionsList */ + contentContainerStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + ...optionsSelectorPropTypes, ...withLocalizePropTypes, ...withNavigationFocusPropTypes, @@ -32,6 +35,7 @@ const propTypes = { const defaultProps = { shouldDelayFocus: false, safeAreaPaddingBottomStyle: {}, + contentContainerStyles: [], ...optionsSelectorDefaultProps, }; @@ -325,7 +329,7 @@ class BaseOptionsSelector extends Component { this.props.onLayout(); } }} - contentContainerStyles={shouldShowFooter ? undefined : [this.props.safeAreaPaddingBottomStyle]} + contentContainerStyles={[!shouldShowFooter && this.props.safeAreaPaddingBottomStyle, ...this.props.contentContainerStyles]} isLoading={!this.props.shouldShowOptions} /> ); From 6dca051004615efcd46047385d4ca55d70a03aa8 Mon Sep 17 00:00:00 2001 From: Oliver Wilks Date: Wed, 7 Jun 2023 09:23:10 +0100 Subject: [PATCH 066/273] Changed styles and passed contentContainerStyles --- src/pages/workspace/WorkspaceInvitePage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js index 60eb0a4c4dcc..681c81b23828 100644 --- a/src/pages/workspace/WorkspaceInvitePage.js +++ b/src/pages/workspace/WorkspaceInvitePage.js @@ -272,8 +272,9 @@ class WorkspaceInvitePage extends React.Component { Navigation.goBack(ROUTES.getWorkspaceMembersRoute(this.props.route.params.policyID)); }} /> - + Date: Wed, 7 Jun 2023 09:23:29 +0100 Subject: [PATCH 067/273] Added flexBasis0 style --- src/styles/utilities/flex.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/styles/utilities/flex.js b/src/styles/utilities/flex.js index a8455a265d51..6cdd0a5b1d6a 100644 --- a/src/styles/utilities/flex.js +++ b/src/styles/utilities/flex.js @@ -126,4 +126,8 @@ export default { flexBasisAuto: { flexBasis: 'auto', }, + + flexBasis0: { + flexBasis: 0, + }, }; From 72b8a5e6c06cbf7aed9d846189858d723bfde751 Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Wed, 7 Jun 2023 10:29:22 +0200 Subject: [PATCH 068/273] migrate ReportHeaderSkeletonView to PressableWithFeedback --- src/components/ReportHeaderSkeletonView.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/ReportHeaderSkeletonView.js b/src/components/ReportHeaderSkeletonView.js index d972c9a93dea..a2f9aee5c8e4 100644 --- a/src/components/ReportHeaderSkeletonView.js +++ b/src/components/ReportHeaderSkeletonView.js @@ -1,5 +1,5 @@ import React from 'react'; -import {Pressable, View} from 'react-native'; +import {View} from 'react-native'; import {Rect, Circle} from 'react-native-svg'; import SkeletonViewContentLoader from 'react-content-loader/native'; import PropTypes from 'prop-types'; @@ -9,9 +9,13 @@ import * as Expensicons from './Icon/Expensicons'; import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; import variables from '../styles/variables'; import themeColors from '../styles/themes/default'; +import PressableWithFeedback from './Pressable/PressableWithFeedback'; +import compose from '../libs/compose'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { ...windowDimensionsPropTypes, + ...withLocalizePropTypes, shouldAnimate: PropTypes.bool, }; @@ -23,12 +27,14 @@ const ReportHeaderSkeletonView = (props) => ( {props.isSmallScreenWidth && ( - {}} style={[styles.LHNToggle]} + accessibilityRole="button" + accessibilityLabel={props.translate('common.back')} > - + )} ( ReportHeaderSkeletonView.propTypes = propTypes; ReportHeaderSkeletonView.defaultProps = defaultProps; ReportHeaderSkeletonView.displayName = 'ReportHeaderSkeletonView'; -export default withWindowDimensions(ReportHeaderSkeletonView); +export default compose(withWindowDimensions, withLocalize)(ReportHeaderSkeletonView); From 58a13b38c4bd786501f303c895c428d014b0225d Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Wed, 7 Jun 2023 15:51:03 +0500 Subject: [PATCH 069/273] fix: add storybook item for the updated menuitem --- src/components/MenuItem.js | 2 +- src/stories/MenuItem.stories.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index f3382c2c8cd5..17f84f77cd6b 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -131,7 +131,7 @@ const MenuItem = (props) => { {props.label} )} - + {Boolean(props.icon) && _.isArray(props.icon) && ( Date: Wed, 7 Jun 2023 12:10:19 +0100 Subject: [PATCH 070/273] Use ternary for safeAreaPaddingBottom --- src/components/OptionsSelector/BaseOptionsSelector.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 5609c91aa320..f30830d66747 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -286,6 +286,7 @@ class BaseOptionsSelector extends Component { !this.props.isReadOnly && (this.props.shouldShowConfirmButton || this.props.footerContent) && !(this.props.canSelectMultipleOptions && _.isEmpty(this.props.selectedOptions)); const defaultConfirmButtonText = _.isUndefined(this.props.confirmButtonText) ? this.props.translate('common.confirm') : this.props.confirmButtonText; const shouldShowDefaultConfirmButton = !this.props.footerContent && defaultConfirmButtonText; + const safeAreaPaddingBottom = shouldShowFooter ? undefined : this.props.safeAreaPaddingBottomStyle; const textInput = ( (this.textInput = el)} @@ -329,7 +330,7 @@ class BaseOptionsSelector extends Component { this.props.onLayout(); } }} - contentContainerStyles={[!shouldShowFooter && this.props.safeAreaPaddingBottomStyle, ...this.props.contentContainerStyles]} + contentContainerStyles={[safeAreaPaddingBottom, ...this.props.contentContainerStyles]} isLoading={!this.props.shouldShowOptions} /> ); From 6d287d04a112328b37b4a9e3643dd48d1fe2425e Mon Sep 17 00:00:00 2001 From: Aman Sheikh Date: Wed, 7 Jun 2023 20:45:28 +0530 Subject: [PATCH 071/273] fix positioning of styles.textHeadlineH1 --- src/components/MenuItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index e672c68b6133..dfb8491a2923 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -78,10 +78,10 @@ const MenuItem = (props) => { styles.popoverMenuText, props.icon ? styles.ml3 : undefined, props.shouldShowBasicTitle ? undefined : styles.textStrong, + props.shouldShowHeaderTitle ? styles.textHeadlineH1 : undefined, props.interactive && props.disabled ? {...styles.disabledText, ...styles.userSelectNone} : undefined, styles.pre, styles.ltr, - props.shouldShowHeaderTitle ? styles.textHeadlineH1 : undefined, isDeleted ? styles.offlineFeedback.deleted : undefined, ], props.titleStyle, From 3978d71e59a6ef96309149b7506043341695c77b Mon Sep 17 00:00:00 2001 From: Aman Sheikh Date: Wed, 7 Jun 2023 20:45:57 +0530 Subject: [PATCH 072/273] use interactive prop to avoid reduced opacity --- src/components/TaskHeader.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/TaskHeader.js b/src/components/TaskHeader.js index 2a6d62183954..4c07e673a1c5 100644 --- a/src/components/TaskHeader.js +++ b/src/components/TaskHeader.js @@ -110,12 +110,14 @@ function TaskHeader(props) { description={props.translate('newTaskPage.task')} onPress={() => Navigation.navigate(ROUTES.getTaskReportTitleRoute(props.report.reportID))} disabled={!isOpen} + interactive={isOpen} /> Navigation.navigate(ROUTES.getTaskReportDescriptionRoute(props.report.reportID))} disabled={!isOpen} + interactive={isOpen} /> ); From 09cf7dc362d78781d2efd734018780caa634a126 Mon Sep 17 00:00:00 2001 From: Andrew Li Date: Wed, 7 Jun 2023 11:39:51 -0400 Subject: [PATCH 073/273] Initial coarse refactor, added usePrevious hook, removed lodash dependency --- src/hooks/usePrevious.js | 15 + .../ValidateCodeForm/BaseValidateCodeForm.js | 284 +++++++++--------- 2 files changed, 154 insertions(+), 145 deletions(-) create mode 100644 src/hooks/usePrevious.js diff --git a/src/hooks/usePrevious.js b/src/hooks/usePrevious.js new file mode 100644 index 000000000000..1059df00c8de --- /dev/null +++ b/src/hooks/usePrevious.js @@ -0,0 +1,15 @@ +import {useEffect, useRef} from 'react'; + +/** + * A hook that returns the previous value of a variable + * + * @param {*} value + * @returns {*} + */ +export default function usePrevious(value) { + const ref = useRef(); + useEffect(() => { + ref.current = value; + }, [value]); + return ref.current; +} \ No newline at end of file diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js index 7069d2602430..3a509d9618d3 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js @@ -1,9 +1,7 @@ -import React from 'react'; +import React, { useState } from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; import styles from '../../../styles/styles'; import Button from '../../../components/Button'; import Text from '../../../components/Text'; @@ -25,6 +23,7 @@ import FormHelpMessage from '../../../components/FormHelpMessage'; import MagicCodeInput from '../../../components/MagicCodeInput'; import Terms from '../Terms'; import PressableWithFeedback from '../../../components/Pressable/PressableWithFeedback'; +import usePrevious from '../../../hooks/usePrevious'; const propTypes = { /* Onyx Props */ @@ -63,47 +62,47 @@ const defaultProps = { preferredLocale: CONST.LOCALES.DEFAULT, }; -class BaseValidateCodeForm extends React.Component { - constructor(props) { - super(props); - this.validateAndSubmitForm = this.validateAndSubmitForm.bind(this); - this.resendValidateCode = this.resendValidateCode.bind(this); - this.clearSignInData = this.clearSignInData.bind(this); +function BaseValidateCodeForm(props) { + const [formError, setFormError] = useState({}); + const [validateCode, setValidateCode] = useState(props.credentials.validateCode || ''); + const [twoFactorAuthCode, setTwoFactorAuthCode] = useState(''); + const [linkSent, setLinkSent] = useState(false); - this.state = { - formError: {}, - validateCode: props.credentials.validateCode || '', - twoFactorAuthCode: '', - linkSent: false, - }; - } + const wasVisible = usePrevious(props.isVisible); + const required2FA = usePrevious(props.account.requiresTwoFactorAuth); + const hadValidateCode = usePrevious(props.credentials.validateAndSubmitForm); + + const refValidateCode = useRef(null); + const inputValidateCode = refValidateCode.current; + const ref2FA = useRef(null); + const input2FA = ref2FA.current; - componentDidMount() { - if (!canFocusInputOnScreenFocus() || !this.inputValidateCode || !this.props.isVisible) { + useEffect(() => { + if (!canFocusInputOnScreenFocus() || !inputValidateCode || !props.isVisible) { return; } - this.inputValidateCode.focus(); - } + inputValidateCode.focus(); + }, []); - componentDidUpdate(prevProps) { - if (!prevProps.isVisible && this.props.isVisible) { - this.inputValidateCode.focus(); + useEffect(() => { + if (!wasVisible && props.isVisible) { + inputValidateCode.focus(); } - if (prevProps.isVisible && !this.props.isVisible && this.state.validateCode) { - this.clearValidateCode(); + if (wasVisible && !props.isVisible && validateCode) { + clearValidateCode(); } // Clear the code input if a new magic code was requested - if (this.props.isVisible && this.state.linkSent && this.props.account.message && this.state.validateCode) { - this.clearValidateCode(); + if (props.isVisible && linkSent && props.account.message && validateCode) { + clearValidateCode(); } - if (!prevProps.credentials.validateCode && this.props.credentials.validateCode) { - this.setState({validateCode: this.props.credentials.validateCode}); + if (!hadValidateCode && props.credentials.validateCode) { + setValidateCode(props.credentials.validateCode); } - if (!prevProps.account.requiresTwoFactorAuth && this.props.account.requiresTwoFactorAuth) { - this.input2FA.focus(); + if (!required2FA && props.account.requiresTwoFactorAuth) { + input2FA.focus(); } - } + }, [props.isVisible, wasVisible, props.account, props.credentials, hadValidateCode, required2FA, validateCode, linkSent]); /** * Handle text input and clear formError upon text change @@ -111,14 +110,13 @@ class BaseValidateCodeForm extends React.Component { * @param {String} text * @param {String} key */ - onTextInput(text, key) { - this.setState({ - [key]: text, - formError: {[key]: ''}, - linkSent: false, - }); + const onTextInput = (text, key) => { + const setInput = key === 'validateCode' ? setValidateCode : setTwoFactorAuthCode; + setInput(text); + setFormError((prevError) => ({...prevError, [key]: ''})); + setLinkSent(false); - if (this.props.account.errors) { + if (props.account.errors) { Session.clearAccountMessages(); } } @@ -126,155 +124,151 @@ class BaseValidateCodeForm extends React.Component { /** * Clear Validate Code from the state */ - clearValidateCode() { - this.setState({validateCode: ''}, () => this.inputValidateCode.clear()); + const clearValidateCode = () => { + setValidateCode(''); + inputValidateCode.clear(); } - + /** * Trigger the reset validate code flow and ensure the 2FA input field is reset to avoid it being permanently hidden */ - resendValidateCode() { - if (this.input2FA) { - this.setState({twoFactorAuthCode: ''}, this.input2FA.clear); + const resendValidateCode = () => { + if (input2FA) { + setTwoFactorAuthCode(''); + input2FA.clear(); } - this.setState({formError: {}}); - User.resendValidateCode(this.props.credentials.login, true); + setFormError({}); + User.resendValidateCode(props.credentials.login, true); // Give feedback to the user to let them know the email was sent so they don't spam the button. - this.setState({linkSent: true}); + setLinkSent(true); } /** * Clears local and Onyx sign in states */ - clearSignInData() { - this.setState({twoFactorAuthCode: '', formError: {}}); + const clearSignInData = () => { + setTwoFactorAuthCode(''); + setFormError({}); Session.clearSignInData(); } /** * Check that all the form fields are valid, then trigger the submit callback */ - validateAndSubmitForm() { - const requiresTwoFactorAuth = this.props.account.requiresTwoFactorAuth; - + const validateAndSubmitForm = () => { + const requiresTwoFactorAuth = props.account.requiresTwoFactorAuth; if (requiresTwoFactorAuth) { - if (this.input2FA) { - this.input2FA.blur(); + if (input2FA) { + input2FA.blur(); } - if (!this.state.twoFactorAuthCode.trim()) { - this.setState({formError: {twoFactorAuthCode: 'validateCodeForm.error.pleaseFillTwoFactorAuth'}}); + if (!twoFactorAuthCode.trim()) { + setFormError({twoFactorAuthCode: 'validateCodeForm.error.pleaseFillTwoFactorAuth'}); return; } if (!ValidationUtils.isValidTwoFactorCode(this.state.twoFactorAuthCode)) { - this.setState({formError: {twoFactorAuthCode: 'passwordForm.error.incorrect2fa'}}); + setFormError({twoFactorAuthCode: 'passwordForm.error.incorrect2fa'}); return; } } else { - if (this.inputValidateCode) { - this.inputValidateCode.blur(); + if (inputValidateCode) { + inputValidateCode.blur(); } - - if (!this.state.validateCode.trim()) { - this.setState({formError: {validateCode: 'validateCodeForm.error.pleaseFillMagicCode'}}); + if (!validateCode.trim()) { + setFormError({validateCode: 'validateCodeForm.error.pleaseFillMagicCode'}); return; } - if (!ValidationUtils.isValidValidateCode(this.state.validateCode)) { - this.setState({formError: {validateCode: 'validateCodeForm.error.incorrectMagicCode'}}); + if (!ValidationUtils.isValidValidateCode(validateCode)) { + setFormError({validateCode: 'validateCodeForm.error.incorrectMagicCode'}); return; } } + setFormError({}); - this.setState({ - formError: {}, - }); - - const accountID = lodashGet(this.props, 'credentials.accountID'); + const accountID = props.credentials.accountID; if (accountID) { - Session.signInWithValidateCode(accountID, this.state.validateCode, this.props.preferredLocale, this.state.twoFactorAuthCode); + Session.signInWithValidateCode(accountID, validateCode, props.preferredLocale, twoFactorAuthCode); } else { - Session.signIn('', this.state.validateCode, this.state.twoFactorAuthCode, this.props.preferredLocale); + Session.signIn('', validateCode, twoFactorAuthCode, props.preferredLocale); } } - render() { - const hasError = Boolean(this.props.account) && !_.isEmpty(this.props.account.errors); - return ( - <> - {/* At this point, if we know the account requires 2FA we already successfully authenticated */} - {this.props.account.requiresTwoFactorAuth ? ( - - (this.input2FA = el)} - label={this.props.translate('common.twoFactorCode')} - name="twoFactorAuthCode" - value={this.state.twoFactorAuthCode} - onChangeText={(text) => this.onTextInput(text, 'twoFactorAuthCode')} - onFulfill={this.validateAndSubmitForm} - maxLength={CONST.TFA_CODE_LENGTH} - errorText={this.state.formError.twoFactorAuthCode ? this.props.translate(this.state.formError.twoFactorAuthCode) : ''} - hasError={hasError} - autoFocus - /> - - ) : ( - - (this.inputValidateCode = el)} - label={this.props.translate('common.magicCode')} - name="validateCode" - value={this.state.validateCode} - onChangeText={(text) => this.onTextInput(text, 'validateCode')} - onFulfill={this.validateAndSubmitForm} - errorText={this.state.formError.validateCode ? this.props.translate(this.state.formError.validateCode) : ''} - hasError={hasError} - autoFocus - /> - - {this.state.linkSent ? ( - {this.props.account.message ? this.props.translate(this.props.account.message) : ''} - ) : ( - - {this.props.translate('validateCodeForm.magicCodeNotReceived')} - - )} - - - )} - - {hasError && } - - - )} ); } From 0825c4b6638ee8cb418f548f16d803c88292ce69 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 14 Jun 2023 10:58:38 +0700 Subject: [PATCH 272/273] fix lint --- src/pages/home/report/ReportActionItem.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 48997584f478..153c12a13d80 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -119,6 +119,7 @@ function ReportActionItem(props) { // Hide the message if it is being moderated for a higher offense, or is hidden by a moderator // Removed messages should not be shown anyway and should not need this flow + useEffect(() => { if (!props.action.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT || _.isEmpty(props.action.message[0].moderationDecisions)) { return; @@ -134,6 +135,9 @@ function ReportActionItem(props) { setIsHidden(true); } setModerationDecision(latestDecision.decision); + + // props.action.message doesn't need to be a dependency, we only to check the change of props.action.message[0].moderationDecisions + // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.action.message[0].moderationDecisions, props.action.actionName]); const toggleContextMenuFromActiveReportAction = useCallback(() => { From 3b46dd7ab4d4fc835290181d3975139c9ffd65f5 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 14 Jun 2023 10:59:10 +0700 Subject: [PATCH 273/273] edit comment --- src/pages/home/report/ReportActionItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 153c12a13d80..7139350ca0f6 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -136,7 +136,7 @@ function ReportActionItem(props) { } setModerationDecision(latestDecision.decision); - // props.action.message doesn't need to be a dependency, we only to check the change of props.action.message[0].moderationDecisions + // props.action.message doesn't need to be a dependency, we only need to check the change of props.action.message[0].moderationDecisions // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.action.message[0].moderationDecisions, props.action.actionName]);