From 750ac4886592330f7eef581fc96c15a4f53a47a9 Mon Sep 17 00:00:00 2001 From: Sam Hariri <137707942+samh-nl@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:14:57 +0200 Subject: [PATCH 01/17] feat: support accountid attribute in user mentions --- .../HTMLRenderers/MentionUserRenderer.js | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js index 7f7753dfea44..992f8494dc1f 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js @@ -1,6 +1,8 @@ import React from 'react'; import _ from 'underscore'; import {TNodeChildrenRenderer} from 'react-native-render-html'; +import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import Navigation from '../../../libs/Navigation/Navigation'; import ROUTES from '../../../ROUTES'; import Text from '../../Text'; @@ -10,52 +12,63 @@ import withCurrentUserPersonalDetails from '../../withCurrentUserPersonalDetails import personalDetailsPropType from '../../../pages/personalDetailsPropType'; import * as StyleUtils from '../../../styles/StyleUtils'; import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils'; +import compose from '../../../libs/compose'; import TextLink from '../../TextLink'; +import ONYXKEYS from '../../../ONYXKEYS'; +import useLocalize from '../../../hooks/useLocalize'; const propTypes = { ...htmlRendererPropTypes, - /** - * Current user personal details - */ + /** Current user personal details */ currentUserPersonalDetails: personalDetailsPropType.isRequired, -}; -/** - * Navigates to user details screen based on email - * @param {String} email - * @returns {void} - * */ -const showUserDetails = (email) => Navigation.navigate(ROUTES.getDetailsRoute(email)); + /** Personal details of all users */ + personalDetails: personalDetailsPropType.isRequired, +}; function MentionUserRenderer(props) { + const {translate} = useLocalize(); const defaultRendererProps = _.omit(props, ['TDefaultRenderer', 'style']); + const htmlAttribAccountID = lodashGet(props.tnode.attributes, 'accountid'); + + let accountID; + let displayNameOrLogin; + let navigationRoute; - // We need to remove the leading @ from data as it is not part of the login - const loginWithoutLeadingAt = props.tnode.data ? props.tnode.data.slice(1) : ''; + if (!_.isEmpty(htmlAttribAccountID)) { + const user = lodashGet(props.personalDetails, htmlAttribAccountID); + accountID = parseInt(htmlAttribAccountID, 10); + displayNameOrLogin = lodashGet(user, 'login', '') || lodashGet(user, 'displayName', '') || translate('common.hidden'); + navigationRoute = ROUTES.getProfileRoute(htmlAttribAccountID); + } else { + // We need to remove the leading @ from data as it is not part of the login + displayNameOrLogin = props.tnode.data ? props.tnode.data.slice(1) : ''; - const accountID = _.first(PersonalDetailsUtils.getAccountIDsByLogins([loginWithoutLeadingAt])); + accountID = _.first(PersonalDetailsUtils.getAccountIDsByLogins([displayNameOrLogin])); + navigationRoute = ROUTES.getDetailsRoute(displayNameOrLogin); + } - const isOurMention = loginWithoutLeadingAt === props.currentUserPersonalDetails.login; + const isOurMention = accountID === props.currentUserPersonalDetails.accountID; return ( showUserDetails(loginWithoutLeadingAt)} + onPress={() => Navigation.navigate(navigationRoute)} // Add testID so it is NOT selected as an anchor tag by SelectionScraper testID="span" > - + {!_.isEmpty(htmlAttribAccountID) ? `@${displayNameOrLogin}` : } @@ -65,4 +78,11 @@ function MentionUserRenderer(props) { MentionUserRenderer.propTypes = propTypes; MentionUserRenderer.displayName = 'MentionUserRenderer'; -export default withCurrentUserPersonalDetails(MentionUserRenderer); +export default compose( + withCurrentUserPersonalDetails, + withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + }), +)(MentionUserRenderer); From 19faf7deb3ed7043108a3ad7162fcbd90bb45901 Mon Sep 17 00:00:00 2001 From: Sam Hariri <137707942+samh-nl@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:52:57 +0200 Subject: [PATCH 02/17] feat: remove navigation and tooltip when hidden --- .../HTMLRenderers/MentionUserRenderer.js | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js index 992f8494dc1f..087334061fa2 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js @@ -10,6 +10,7 @@ import UserDetailsTooltip from '../../UserDetailsTooltip'; import htmlRendererPropTypes from './htmlRendererPropTypes'; import withCurrentUserPersonalDetails from '../../withCurrentUserPersonalDetails'; import personalDetailsPropType from '../../../pages/personalDetailsPropType'; +import styles from '../../../styles/styles'; import * as StyleUtils from '../../../styles/StyleUtils'; import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils'; import compose from '../../../libs/compose'; @@ -39,8 +40,13 @@ function MentionUserRenderer(props) { if (!_.isEmpty(htmlAttribAccountID)) { const user = lodashGet(props.personalDetails, htmlAttribAccountID); accountID = parseInt(htmlAttribAccountID, 10); - displayNameOrLogin = lodashGet(user, 'login', '') || lodashGet(user, 'displayName', '') || translate('common.hidden'); - navigationRoute = ROUTES.getProfileRoute(htmlAttribAccountID); + displayNameOrLogin = lodashGet(user, 'login', '') || lodashGet(user, 'displayName', ''); + + if (_.isEmpty(displayNameOrLogin)) { + displayNameOrLogin = translate('common.hidden'); + } else { + navigationRoute = ROUTES.getProfileRoute(htmlAttribAccountID); + } } else { // We need to remove the leading @ from data as it is not part of the login displayNameOrLogin = props.tnode.data ? props.tnode.data.slice(1) : ''; @@ -50,26 +56,33 @@ function MentionUserRenderer(props) { } const isOurMention = accountID === props.currentUserPersonalDetails.accountID; + const TextLinkComponent = _.isEmpty(navigationRoute) ? Text : TextLink; return ( - Navigation.navigate(navigationRoute)} + style={[ + _.omit(props.style, 'color'), + StyleUtils.getMentionStyle(isOurMention), + {color: StyleUtils.getMentionTextColor(isOurMention)}, + _.isEmpty(navigationRoute) && styles.cursorDefault, + ]} + href={_.isEmpty(navigationRoute) ? undefined : `/${navigationRoute}`} + onPress={_.isEmpty(navigationRoute) ? undefined : () => Navigation.navigate(navigationRoute)} // Add testID so it is NOT selected as an anchor tag by SelectionScraper testID="span" > {!_.isEmpty(htmlAttribAccountID) ? `@${displayNameOrLogin}` : } - + ); From 2af817dfd68a3d0b34b50a52de8c34edb58ba515 Mon Sep 17 00:00:00 2001 From: Sam Hariri <137707942+samh-nl@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:28:07 +0200 Subject: [PATCH 03/17] fix: ensure proptype is adhered to --- .../HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js index 087334061fa2..155596fb23b0 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.js @@ -74,7 +74,7 @@ function MentionUserRenderer(props) { _.omit(props.style, 'color'), StyleUtils.getMentionStyle(isOurMention), {color: StyleUtils.getMentionTextColor(isOurMention)}, - _.isEmpty(navigationRoute) && styles.cursorDefault, + _.isEmpty(navigationRoute) ? styles.cursorDefault : {}, ]} href={_.isEmpty(navigationRoute) ? undefined : `/${navigationRoute}`} onPress={_.isEmpty(navigationRoute) ? undefined : () => Navigation.navigate(navigationRoute)} From 3bc8d30190fa818e16c4c8c6a2e57cbf507470b2 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 15 Sep 2023 14:00:02 +0200 Subject: [PATCH 04/17] fix focus on different scenarios --- src/components/CategoryPicker/index.js | 26 ++++++++++--------- .../OptionsSelector/BaseOptionsSelector.js | 4 +-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index 91c7e82e7887..4ee429a2e389 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -34,21 +34,23 @@ function CategoryPicker({policyCategories, reportID, iouType, iou, policyRecentl ]; }, [iou.category]); + const sections = useMemo(() => { + const {categoryOptions} = OptionsListUtils.getNewChatOptions({}, {}, [], searchValue, selectedOptions, [], false, false, true, policyCategories, policyRecentlyUsedCategories, false); + + return categoryOptions; + }, [policyCategories, policyRecentlyUsedCategories, searchValue, selectedOptions]); + const initialFocusedIndex = useMemo(() => { - if (isCategoriesCountBelowThreshold && selectedOptions.length > 0) { - return _.chain(policyCategories) - .values() - .findIndex((category) => category.name === selectedOptions[0].name, true) - .value(); - } + let categoryInitialFocusedIndex = 0; - return 0; - }, [policyCategories, selectedOptions, isCategoriesCountBelowThreshold]); + if (!_.isEmpty(searchValue) || isCategoriesCountBelowThreshold) { + const index = _.findIndex(lodashGet(sections, '[0].data', []), (category) => category.searchText === iou.category); - const sections = useMemo( - () => OptionsListUtils.getNewChatOptions({}, {}, [], searchValue, selectedOptions, [], false, false, true, policyCategories, policyRecentlyUsedCategories, false).categoryOptions, - [policyCategories, policyRecentlyUsedCategories, searchValue, selectedOptions], - ); + categoryInitialFocusedIndex = index === -1 ? 0 : index; + } + + return categoryInitialFocusedIndex; + }, [iou.category, searchValue, isCategoriesCountBelowThreshold, sections]); const headerMessage = OptionsListUtils.getHeaderMessage(lodashGet(sections, '[0].data.length', 0) > 0, false, searchValue); const shouldShowTextInput = !isCategoriesCountBelowThreshold; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index bff9f8b6d7d0..aa02701b1c98 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -107,13 +107,13 @@ class BaseOptionsSelector extends Component { }); return; } - const newFocusedIndex = this.props.selectedOptions.length; + const newFocusedIndex = this.props.selectedOptions.length; // eslint-disable-next-line react/no-did-update-set-state this.setState( { allOptions: newOptions, - focusedIndex: newFocusedIndex, + focusedIndex: _.isNumber(this.props.initialFocusedIndex) ? this.props.initialFocusedIndex : newFocusedIndex, }, () => { // If we just toggled an option on a multi-selection page or cleared the search input, scroll to top From 5671e36517609466dc91a30a34b0d984b69e3faf Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Mon, 18 Sep 2023 05:17:49 +0530 Subject: [PATCH 05/17] Make the footer button part of the ScrollView in 2FA Verify Step This makes the Footer button a child of the ScrollView container. The footer button will now be scrollable below the content. --- .../TwoFactorAuth/Steps/VerifyStep.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js index 8c3d9689cfcd..01258f8dff3b 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js @@ -110,20 +110,20 @@ function VerifyStep({account = defaultAccount}) { + +