From 26378c9eff52946b81600593763e65a841e7fbe4 Mon Sep 17 00:00:00 2001 From: sourcecodedeveloper Date: Tue, 7 Nov 2023 08:49:53 -0800 Subject: [PATCH 1/5] exclude rooms having undefined reportID --- src/pages/workspace/WorkspaceInitialPage.js | 29 ++++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 207db2620f9f..5153a30a2829 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -179,24 +179,33 @@ function WorkspaceInitialPage(props) { }, ]; + const availableRooms = _.filter( + props.reports, + (report) => + report && + report.reportID !== undefined && + report.policyID === policy.id && + (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS || report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE), + ); + const threeDotsMenuItems = [ { icon: Expensicons.Trashcan, text: props.translate('workspace.common.delete'), onSelected: () => setIsDeleteModalOpen(true), }, - { - icon: Expensicons.Hashtag, - text: props.translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}), - onSelected: () => goToRoom(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS), - }, - { - icon: Expensicons.Hashtag, - text: props.translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE}), - onSelected: () => goToRoom(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE), - }, ]; + availableRooms.forEach((room) => { + threeDotsMenuItems.push({ + icon: Expensicons.Hashtag, + text: props.translate('workspace.common.goToRoom', { + roomName: room.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS ? CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS : CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE, + }), + onSelected: () => goToRoom(room.chatType), + }); + }); + return ( Date: Thu, 9 Nov 2023 10:37:26 -0800 Subject: [PATCH 2/5] handle scroll index --- src/components/SelectionList/BaseSelectionList.js | 15 ++++++++++++++- src/libs/Permissions.ts | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 2a7947733a9e..9120b88693f4 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -347,7 +347,20 @@ function BaseSelectionList({ // set the focus on the first item when the sections list is changed if (sections.length > 0) { - updateAndScrollToFocusedIndex(0); + const selectedOptions = _.filter(flattenedSections.selectedOptions, (selectedOption) => selectedOption.isSelected === true); + if (!canSelectMultiple) { + if (_.isEmpty(selectedOptions)) { + updateAndScrollToFocusedIndex(0); + } + else { + const selectedOption = _.first(selectedOptions); + const index = _.findIndex(flattenedSections.allOptions, (option) => option.text === selectedOption.text); + updateAndScrollToFocusedIndex(index); + } + } + else { + // For Multiple options selectRow is handling focus. + } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [sections]); diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 5200e5803ee3..8ddefed97c96 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -2,7 +2,7 @@ import CONST from '@src/CONST'; import Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: Beta[]): boolean { - return betas?.includes(CONST.BETAS.ALL); + return true; //betas?.includes(CONST.BETAS.ALL); } function canUseChronos(betas: Beta[]): boolean { From ce259c1ea99cdded3ed9c7ea8cf2754d0f3630ae Mon Sep 17 00:00:00 2001 From: sourcecodedeveloper Date: Thu, 9 Nov 2023 10:45:02 -0800 Subject: [PATCH 3/5] Revert "handle scroll index" This reverts commit 448cbc2bd611cd99753470b418957ffc70a06f5e. --- src/components/SelectionList/BaseSelectionList.js | 15 +-------------- src/libs/Permissions.ts | 2 +- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 9120b88693f4..2a7947733a9e 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -347,20 +347,7 @@ function BaseSelectionList({ // set the focus on the first item when the sections list is changed if (sections.length > 0) { - const selectedOptions = _.filter(flattenedSections.selectedOptions, (selectedOption) => selectedOption.isSelected === true); - if (!canSelectMultiple) { - if (_.isEmpty(selectedOptions)) { - updateAndScrollToFocusedIndex(0); - } - else { - const selectedOption = _.first(selectedOptions); - const index = _.findIndex(flattenedSections.allOptions, (option) => option.text === selectedOption.text); - updateAndScrollToFocusedIndex(index); - } - } - else { - // For Multiple options selectRow is handling focus. - } + updateAndScrollToFocusedIndex(0); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [sections]); diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 8ddefed97c96..5200e5803ee3 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -2,7 +2,7 @@ import CONST from '@src/CONST'; import Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: Beta[]): boolean { - return true; //betas?.includes(CONST.BETAS.ALL); + return betas?.includes(CONST.BETAS.ALL); } function canUseChronos(betas: Beta[]): boolean { From f596a7d9f10840aa485bc86f8e65a26e53073b1e Mon Sep 17 00:00:00 2001 From: sourcecodedeveloper Date: Sat, 11 Nov 2023 02:18:53 -0800 Subject: [PATCH 4/5] add memoization --- src/pages/workspace/WorkspaceInitialPage.js | 133 +++++++++++--------- 1 file changed, 71 insertions(+), 62 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 5153a30a2829..1c4442dac502 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -1,6 +1,6 @@ import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -15,10 +15,10 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import withWindowDimensions from '@components/withWindowDimensions'; +import useLocalize from '@hooks/useLocalize'; import useSingleExecution from '@hooks/useSingleExecution'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; +import useWindowDimensions from '@hooks/useWindowDimensions'; import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; @@ -37,7 +37,6 @@ import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; const propTypes = { ...policyPropTypes, - ...withLocalizePropTypes, /** All reports shared with the user (coming from Onyx) */ reports: PropTypes.objectOf(reportPropTypes), @@ -75,16 +74,42 @@ function WorkspaceInitialPage(props) { const waitForNavigate = useWaitForNavigation(); const {singleExecution, isExecuting} = useSingleExecution(); + const {translate} = useLocalize(); + const {windowWidth} = useWindowDimensions(); + + const policyID = useMemo(() => policy.id, [policy]); + const [policyReports, adminsRoom, announceRoom] = useMemo(() => { + const reports = []; + let admins; + let announce; + _.each(props.reports, (report) => { + if (!report || report.policyID !== policyID) { + return; + } + + reports.push(report); + + if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS && !ReportUtils.isThread(report) && report.reportID) { + admins = report; + return; + } + + if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE && !ReportUtils.isThread(report) && report.reportID) { + announce = report; + } + }); + return [reports, admins, announce]; + }, [policyID, props.reports]); + /** * Call the delete policy and hide the modal */ const confirmDeleteAndHideModal = useCallback(() => { - const policyReports = _.filter(props.reports, (report) => report && report.policyID === policy.id); Policy.deleteWorkspace(policy.id, policyReports, policy.name); setIsDeleteModalOpen(false); // Pop the deleted workspace page before opening workspace settings. Navigation.goBack(ROUTES.SETTINGS_WORKSPACES); - }, [props.reports, policy]); + }, [policy.id, policy.name, policyReports]); useEffect(() => { const policyDraftId = lodashGet(props.policyDraft, 'id', null); @@ -111,19 +136,7 @@ function WorkspaceInitialPage(props) { Policy.updateGeneralSettings(policy.id, policy.name, CONST.CURRENCY.USD); setIsCurrencyModalOpen(false); ReimbursementAccount.navigateToBankAccountRoute(policy.id); - }, [policy]); - - /** - * Navigates to workspace rooms - * @param {String} chatType - */ - const goToRoom = useCallback( - (type) => { - const room = _.find(props.reports, (report) => report && report.policyID === policy.id && report.chatType === type && !ReportUtils.isThread(report)); - Navigation.dismissModal(room.reportID); - }, - [props.reports, policy], - ); + }, [policy.id, policy.name]); const policyName = lodashGet(policy, 'name', ''); const hasMembersError = PolicyUtils.hasPolicyMemberError(props.policyMembers); @@ -179,32 +192,30 @@ function WorkspaceInitialPage(props) { }, ]; - const availableRooms = _.filter( - props.reports, - (report) => - report && - report.reportID !== undefined && - report.policyID === policy.id && - (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS || report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE), - ); - - const threeDotsMenuItems = [ - { - icon: Expensicons.Trashcan, - text: props.translate('workspace.common.delete'), - onSelected: () => setIsDeleteModalOpen(true), - }, - ]; - - availableRooms.forEach((room) => { - threeDotsMenuItems.push({ - icon: Expensicons.Hashtag, - text: props.translate('workspace.common.goToRoom', { - roomName: room.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS ? CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS : CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE, - }), - onSelected: () => goToRoom(room.chatType), - }); - }); + const threeDotsMenuItems = useMemo(() => { + const items = [ + { + icon: Expensicons.Trashcan, + text: translate('workspace.common.delete'), + onSelected: () => setIsDeleteModalOpen(true), + }, + ]; + if (adminsRoom) { + items.push({ + icon: Expensicons.Hashtag, + text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}), + onSelected: () => Navigation.dismissModal(adminsRoom.reportID), + }); + } + if (announceRoom) { + items.push({ + icon: Expensicons.Hashtag, + text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE}), + onSelected: () => Navigation.dismissModal(announceRoom.reportID), + }); + } + return items; + }, [adminsRoom, announceRoom, translate]); return ( Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} /> @@ -239,12 +250,12 @@ function WorkspaceInitialPage(props) { - + openEditor(policy.id)))} - accessibilityLabel={props.translate('workspace.common.settings')} + accessibilityLabel={translate('workspace.common.settings')} accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} > {!_.isEmpty(policy.name) && ( - + openEditor(policy.id)))} - accessibilityLabel={props.translate('workspace.common.settings')} + accessibilityLabel={translate('workspace.common.settings')} accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} > setIsCurrencyModalOpen(false)} - prompt={props.translate('workspace.bankAccount.updateCurrencyPrompt')} - confirmText={props.translate('workspace.bankAccount.updateToUSD')} - cancelText={props.translate('common.cancel')} + prompt={translate('workspace.bankAccount.updateCurrencyPrompt')} + confirmText={translate('workspace.bankAccount.updateToUSD')} + cancelText={translate('common.cancel')} danger /> setIsDeleteModalOpen(false)} - prompt={props.translate('workspace.common.deleteConfirmation')} - confirmText={props.translate('common.delete')} - cancelText={props.translate('common.cancel')} + prompt={translate('workspace.common.deleteConfirmation')} + confirmText={translate('common.delete')} + cancelText={translate('common.cancel')} danger /> @@ -329,9 +340,7 @@ WorkspaceInitialPage.defaultProps = defaultProps; WorkspaceInitialPage.displayName = 'WorkspaceInitialPage'; export default compose( - withLocalize, withPolicyAndFullscreenLoading, - withWindowDimensions, withOnyx({ reports: { key: ONYXKEYS.COLLECTION.REPORT, From 7f654b551429649ea2756dcd7e053de1327ecf0d Mon Sep 17 00:00:00 2001 From: sourcecodedeveloper Date: Sat, 11 Nov 2023 10:12:03 -0800 Subject: [PATCH 5/5] add early return --- src/pages/workspace/WorkspaceInitialPage.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 105d7ac02890..bedf7f6ba945 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -89,12 +89,16 @@ function WorkspaceInitialPage(props) { reports.push(report); - if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS && !ReportUtils.isThread(report) && report.reportID) { + if (!report.reportID || ReportUtils.isThread(report)) { + return; + } + + if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS) { admins = report; return; } - if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE && !ReportUtils.isThread(report) && report.reportID) { + if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE) { announce = report; } }); @@ -105,11 +109,11 @@ function WorkspaceInitialPage(props) { * Call the delete policy and hide the modal */ const confirmDeleteAndHideModal = useCallback(() => { - Policy.deleteWorkspace(policy.id, policyReports, policy.name); + Policy.deleteWorkspace(policyID, policyReports, policy.name); setIsDeleteModalOpen(false); // Pop the deleted workspace page before opening workspace settings. Navigation.goBack(ROUTES.SETTINGS_WORKSPACES); - }, [policy.id, policy.name, policyReports]); + }, [policyID, policy.name, policyReports]); useEffect(() => { const policyDraftId = lodashGet(props.policyDraft, 'id', null); @@ -133,10 +137,10 @@ function WorkspaceInitialPage(props) { * Call update workspace currency and hide the modal */ const confirmCurrencyChangeAndHideModal = useCallback(() => { - Policy.updateGeneralSettings(policy.id, policy.name, CONST.CURRENCY.USD); + Policy.updateGeneralSettings(policyID, policy.name, CONST.CURRENCY.USD); setIsCurrencyModalOpen(false); - ReimbursementAccount.navigateToBankAccountRoute(policy.id); - }, [policy.id, policy.name]); + ReimbursementAccount.navigateToBankAccountRoute(policyID); + }, [policyID, policy.name]); const policyName = lodashGet(policy, 'name', ''); const hasMembersError = PolicyUtils.hasPolicyMemberError(props.policyMembers);