From 887d7001d6405dcbf2e2f8cbffa0f963ae197827 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 22 Sep 2023 16:43:48 +0700 Subject: [PATCH 001/764] fix: 22383 Whole thread disappears if the thread header is flagged as an Assault or Harassment --- src/libs/ReportActionsUtils.js | 3 ++- src/libs/ReportUtils.js | 15 +++++---------- src/libs/SidebarUtils.js | 2 +- src/pages/home/report/ReportActionItem.js | 14 ++++++++++---- src/pages/home/report/ReportActionItemFragment.js | 8 ++++++++ src/pages/home/report/ReportActionItemMessage.js | 1 + src/pages/home/report/ReportActionItemSingle.js | 1 + 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index cda1f39d3087..822b75944c87 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -341,7 +341,8 @@ function shouldReportActionBeVisible(reportAction, key) { return false; } - if (isPendingRemove(reportAction)) { + const isThreadParent = reportAction && reportAction.childReportID && reportAction.childReportID !== 0; + if (isPendingRemove(reportAction) && !isThreadParent) { return false; } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index eee9d6549f6c..ee4fbe767380 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1694,7 +1694,8 @@ function getReportName(report, policy = undefined) { } if ( lodashGet(parentReportAction, 'message[0].moderationDecision.decision') === CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE || - lodashGet(parentReportAction, 'message[0].moderationDecision.decision') === CONST.MODERATION.MODERATOR_DECISION_HIDDEN + lodashGet(parentReportAction, 'message[0].moderationDecision.decision') === CONST.MODERATION.MODERATOR_DECISION_HIDDEN || + lodashGet(parentReportAction, 'message[0].moderationDecision.decision') === CONST.MODERATION.MODERATOR_DECISION_PENDING_REMOVE ) { return Localize.translateLocal('parentReportAction.hiddenMessage'); } @@ -2843,14 +2844,9 @@ function canSeeDefaultRoom(report, policies, betas) { * @param {Object} report * @param {Array} policies * @param {Array} betas - * @param {Object} allReportActions * @returns {Boolean} */ -function canAccessReport(report, policies, betas, allReportActions) { - if (isThread(report) && ReportActionsUtils.isPendingRemove(ReportActionsUtils.getParentReportAction(report, allReportActions))) { - return false; - } - +function canAccessReport(report, policies, betas) { // We hide default rooms (it's basically just domain rooms now) from people who aren't on the defaultRooms beta. if (isDefaultRoom(report) && !canSeeDefaultRoom(report, policies, betas)) { return false; @@ -2883,11 +2879,10 @@ function shouldHideReport(report, currentReportId) { * @param {Boolean} isInGSDMode * @param {String[]} betas * @param {Object} policies - * @param {Object} allReportActions * @param {Boolean} excludeEmptyChats * @returns {boolean} */ -function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies, allReportActions, excludeEmptyChats = false) { +function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies, excludeEmptyChats = false) { const isInDefaultMode = !isInGSDMode; // Exclude reports that have no data because there wouldn't be anything to show in the option item. @@ -2908,7 +2903,7 @@ function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, return false; } - if (!canAccessReport(report, policies, betas, allReportActions)) { + if (!canAccessReport(report, policies, betas)) { return false; } diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index f645697690e6..06d0f2935168 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -129,7 +129,7 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p const isInDefaultMode = !isInGSDMode; const allReportsDictValues = Object.values(allReportsDict); // Filter out all the reports that shouldn't be displayed - const reportsToDisplay = allReportsDictValues.filter((report) => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies, allReportActions, true)); + const reportsToDisplay = allReportsDictValues.filter((report) => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies, true)); if (reportsToDisplay.length === 0) { // Display Concierge chat report when there is no report to be displayed diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 8cf8fd78371d..896bcb6ae758 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -213,12 +213,13 @@ function ReportActionItem(props) { } setModerationDecision(latestDecision); - if (!_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], latestDecision)) { + if (!_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], latestDecision) && !ReportActionsUtils.isPendingRemove(props.action)) { setIsHidden(true); return; } setIsHidden(false); - }, [latestDecision, props.action.actionName]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [latestDecision, props.action.actionName, latestDecision]); const toggleContextMenuFromActiveReportAction = useCallback(() => { setIsContextMenuActive(ReportActionContextMenu.isActiveReportAction(props.action.reportActionID)); @@ -353,7 +354,9 @@ function ReportActionItem(props) { } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE) { children = ; } else { - const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision); + const hasBeenFlagged = + !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision) && + !ReportActionsUtils.isPendingRemove(props.action); children = ( {content} diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 1f61b44841bc..3c41f91d2bcf 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -69,6 +69,9 @@ const propTypes = { /** Whether the comment is a thread parent message/the first message in a thread */ isThreadParentMessage: PropTypes.bool, + /** Moderation decision of the report action */ + moderationDecision: PropTypes.string, + ...windowDimensionsPropTypes, /** localization props */ @@ -91,6 +94,7 @@ const defaultProps = { delegateAccountID: 0, actorIcon: {}, isThreadParentMessage: false, + moderationDecision: '', }; function ReportActionItemFragment(props) { @@ -121,6 +125,10 @@ function ReportActionItemFragment(props) { return ${props.translate('parentReportAction.deletedMessage')}`} />; } + if (props.isThreadParentMessage && props.moderationDecision === CONST.MODERATION.MODERATOR_DECISION_PENDING_REMOVE) { + return ${props.translate('parentReportAction.hiddenMessage')}`} />; + } + // If the only difference between fragment.text and fragment.html is
tags // we render it as text, not as html. // This is done to render emojis with line breaks between them as text. diff --git a/src/pages/home/report/ReportActionItemMessage.js b/src/pages/home/report/ReportActionItemMessage.js index bc92889158d0..b18599621c34 100644 --- a/src/pages/home/report/ReportActionItemMessage.js +++ b/src/pages/home/report/ReportActionItemMessage.js @@ -63,6 +63,7 @@ function ReportActionItemMessage(props) { accountID={props.action.actorAccountID} loading={props.action.isLoading} style={props.style} + moderationDecision={lodashGet(props.action, 'message[0].moderationDecision.decision')} /> )) ) : ( diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index bfbce8aed336..c0614ddcde53 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -243,6 +243,7 @@ function ReportActionItemSingle(props) { delegateAccountID={props.action.delegateAccountID} isSingleLine actorIcon={icon} + moderationDecision={lodashGet(props.action, 'message[0].moderationDecision.decision')} /> ))} From fe3ed22888aef75ffa04b65d6c86b0458ae86392 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 26 Sep 2023 13:19:13 +0700 Subject: [PATCH 002/764] fix: LHN message --- src/CONST.ts | 1 + src/libs/OptionsListUtils.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index c6ae9cc5928d..883f4325ff6a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2586,6 +2586,7 @@ const CONST = { }, TRANSLATION_KEYS: { ATTACHMENT: 'common.attachment', + HIDDEN_MESSSAGE: 'parentReportAction.hiddenMessage', }, TEACHERS_UNITE: { PUBLIC_ROOM_ID: '207591744844000', diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 7c36fa095029..2bd70705103f 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -403,6 +403,9 @@ function getLastMessageTextForReport(report) { // then set the last message text to the text of the latest visible action that is not a whisper or the report creation message. const lastNonWhisper = _.find(allSortedReportActions[report.reportID], (action) => !ReportActionUtils.isWhisperAction(action)) || {}; if (ReportActionUtils.isPendingRemove(lastNonWhisper)) { + if (ReportActionUtils.isThreadParentMessage(lastNonWhisper)) { + return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); + } const latestVisibleAction = _.find( allSortedReportActions[report.reportID], From 8910bb99ea6f517f4cf1808876974aba05da5b5c Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 26 Sep 2023 23:28:55 +0700 Subject: [PATCH 003/764] fix deleted message --- src/libs/OptionsListUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 2bd70705103f..5cef616bd4f4 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -381,10 +381,11 @@ function getAllReportErrors(report, reportActions) { * @returns {String} */ function getLastMessageTextForReport(report) { - const lastReportAction = _.find( + const visibleActions = _.filter( allSortedReportActions[report.reportID], (reportAction, key) => ReportActionUtils.shouldReportActionBeVisible(reportAction, key) && reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); + const lastReportAction = _.last(visibleActions); let lastMessageTextFromReport = ''; if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml, translationKey: report.lastMessageTranslationKey})) { @@ -401,7 +402,7 @@ function getLastMessageTextForReport(report) { // Yeah this is a bit ugly. If the latest report action that is not a whisper has been moderated as pending remove // then set the last message text to the text of the latest visible action that is not a whisper or the report creation message. - const lastNonWhisper = _.find(allSortedReportActions[report.reportID], (action) => !ReportActionUtils.isWhisperAction(action)) || {}; + const lastNonWhisper = _.find(visibleActions, (action) => !ReportActionUtils.isWhisperAction(action)) || {}; if (ReportActionUtils.isPendingRemove(lastNonWhisper)) { if (ReportActionUtils.isThreadParentMessage(lastNonWhisper)) { return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); From 787d2e30e7566615d709b697a3f4be403c3ead09 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 26 Sep 2023 23:46:32 +0700 Subject: [PATCH 004/764] fix change to first --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5cef616bd4f4..5aadf33028b9 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -385,7 +385,7 @@ function getLastMessageTextForReport(report) { allSortedReportActions[report.reportID], (reportAction, key) => ReportActionUtils.shouldReportActionBeVisible(reportAction, key) && reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); - const lastReportAction = _.last(visibleActions); + const lastReportAction = _.first(visibleActions); let lastMessageTextFromReport = ''; if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml, translationKey: report.lastMessageTranslationKey})) { From aa741899a75e9d81bccd39787e85fcdcdbc8a6d2 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 27 Sep 2023 13:28:10 +0700 Subject: [PATCH 005/764] fix: isThreadParent --- src/libs/ReportActionsUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 5ac542f9e926..858b71ec0fe3 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -356,7 +356,7 @@ function shouldReportActionBeVisible(reportAction, key) { return false; } - const isThreadParent = reportAction && reportAction.childReportID && reportAction.childReportID !== 0; + const isThreadParent = isThreadParentMessage(reportAction, ''); if (isPendingRemove(reportAction) && !isThreadParent) { return false; } From 0487fc89584e948fc44ff977d1f0eb8337ced9eb Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 27 Sep 2023 14:06:53 +0700 Subject: [PATCH 006/764] fix lastNonWhisper --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5aadf33028b9..a84f1b3e5286 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -381,11 +381,10 @@ function getAllReportErrors(report, reportActions) { * @returns {String} */ function getLastMessageTextForReport(report) { - const visibleActions = _.filter( + const lastReportAction = _.find( allSortedReportActions[report.reportID], (reportAction, key) => ReportActionUtils.shouldReportActionBeVisible(reportAction, key) && reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); - const lastReportAction = _.first(visibleActions); let lastMessageTextFromReport = ''; if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml, translationKey: report.lastMessageTranslationKey})) { @@ -402,7 +401,8 @@ function getLastMessageTextForReport(report) { // Yeah this is a bit ugly. If the latest report action that is not a whisper has been moderated as pending remove // then set the last message text to the text of the latest visible action that is not a whisper or the report creation message. - const lastNonWhisper = _.find(visibleActions, (action) => !ReportActionUtils.isWhisperAction(action)) || {}; + const lastNonWhisper = + _.find(allSortedReportActions[report.reportID], (action) => !ReportActionUtils.isWhisperAction(action) && !ReportActionUtils.isDeletedParentAction(action)) || {}; if (ReportActionUtils.isPendingRemove(lastNonWhisper)) { if (ReportActionUtils.isThreadParentMessage(lastNonWhisper)) { return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); From de6bb44632f5e13d39701baaee5fa358018b91e4 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 20 Oct 2023 15:31:04 +0700 Subject: [PATCH 007/764] merge main --- src/libs/OptionsListUtils.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 1653339d81b1..24b49f80c32d 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -418,14 +418,16 @@ function getLastMessageTextForReport(report) { const lastNonWhisper = _.find(allSortedReportActions[report.reportID], (action) => !ReportActionUtils.isWhisperAction(action) && !ReportActionUtils.isDeletedParentAction(action)) || {}; if (ReportActionUtils.isPendingRemove(lastNonWhisper)) { - if (ReportActionUtils.isThreadParentMessage(lastNonWhisper)) { - return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); - } const latestVisibleAction = _.find( allSortedReportActions[report.reportID], (action) => ReportActionUtils.shouldReportActionBeVisibleAsLastAction(action) && !ReportActionUtils.isCreatedAction(action), ) || {}; + + if (ReportActionUtils.isThreadParentMessage(latestVisibleAction) && ReportActionUtils.isPendingRemove(latestVisibleAction)) { + return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); + } + lastMessageTextFromReport = lodashGet(latestVisibleAction, 'message[0].text', ''); } } From 53bc74cf8a2cb666731b348b8e75c675104fb816 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 20 Oct 2023 15:39:18 +0700 Subject: [PATCH 008/764] fix remove js file --- src/libs/ReportActionsUtils.js | 690 --------------------------------- 1 file changed, 690 deletions(-) delete mode 100644 src/libs/ReportActionsUtils.js diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js deleted file mode 100644 index 6d6fe0fb44c8..000000000000 --- a/src/libs/ReportActionsUtils.js +++ /dev/null @@ -1,690 +0,0 @@ -/* eslint-disable rulesdir/prefer-underscore-method */ -import lodashGet from 'lodash/get'; -import _ from 'underscore'; -import {max, parseISO, isEqual} from 'date-fns'; -import lodashFindLast from 'lodash/findLast'; -import Onyx from 'react-native-onyx'; -import * as CollectionUtils from './CollectionUtils'; -import CONST from '../CONST'; -import ONYXKEYS from '../ONYXKEYS'; -import Log from './Log'; -import isReportMessageAttachment from './isReportMessageAttachment'; - -const allReports = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - callback: (report, key) => { - if (!key || !report) { - return; - } - - const reportID = CollectionUtils.extractCollectionItemID(key); - allReports[reportID] = report; - }, -}); - -const allReportActions = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - callback: (actions, key) => { - if (!key || !actions) { - return; - } - - const reportID = CollectionUtils.extractCollectionItemID(key); - allReportActions[reportID] = actions; - }, -}); - -let isNetworkOffline = false; -Onyx.connect({ - key: ONYXKEYS.NETWORK, - callback: (val) => (isNetworkOffline = lodashGet(val, 'isOffline', false)), -}); - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isCreatedAction(reportAction) { - return lodashGet(reportAction, 'actionName') === CONST.REPORT.ACTIONS.TYPE.CREATED; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isDeletedAction(reportAction) { - // A deleted comment has either an empty array or an object with html field with empty string as value - const message = lodashGet(reportAction, 'message', []); - return message.length === 0 || lodashGet(message, [0, 'html']) === ''; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isDeletedParentAction(reportAction) { - return lodashGet(reportAction, ['message', 0, 'isDeletedParentAction'], false) && lodashGet(reportAction, 'childVisibleActionCount', 0) > 0; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isPendingRemove(reportAction) { - return lodashGet(reportAction, 'message[0].moderationDecision.decision') === CONST.MODERATION.MODERATOR_DECISION_PENDING_REMOVE; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isMoneyRequestAction(reportAction) { - return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.IOU; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isReportPreviewAction(reportAction) { - return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW; -} - -/** - * @param {Object} reportAction - * @returns {Boolean} - */ -function isModifiedExpenseAction(reportAction) { - return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE; -} - -function isWhisperAction(action) { - return (action.whisperedToAccountIDs || []).length > 0; -} - -/** - * Returns whether the comment is a thread parent message/the first message in a thread - * - * @param {Object} reportAction - * @param {String} reportID - * @returns {Boolean} - */ -function isThreadParentMessage(reportAction = {}, reportID) { - const {childType, childVisibleActionCount = 0, childReportID} = reportAction; - return childType === CONST.REPORT.TYPE.CHAT && (childVisibleActionCount > 0 || String(childReportID) === reportID); -} - -/** - * Returns the parentReportAction if the given report is a thread/task. - * - * @param {Object} report - * @param {Object} [allReportActionsParam] - * @returns {Object} - * @deprecated Use Onyx.connect() or withOnyx() instead - */ -function getParentReportAction(report, allReportActionsParam = undefined) { - if (!report || !report.parentReportID || !report.parentReportActionID) { - return {}; - } - return lodashGet(allReportActionsParam || allReportActions, [report.parentReportID, report.parentReportActionID], {}); -} - -/** - * Determines if the given report action is sent money report action by checking for 'pay' type and presence of IOUDetails object. - * - * @param {Object} reportAction - * @returns {Boolean} - */ -function isSentMoneyReportAction(reportAction) { - return ( - reportAction && - reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && - lodashGet(reportAction, 'originalMessage.type') === CONST.IOU.REPORT_ACTION_TYPE.PAY && - _.has(reportAction.originalMessage, 'IOUDetails') - ); -} - -/** - * Returns whether the thread is a transaction thread, which is any thread with IOU parent - * report action from requesting money (type - create) or from sending money (type - pay with IOUDetails field) - * - * @param {Object} parentReportAction - * @returns {Boolean} - */ -function isTransactionThread(parentReportAction) { - const originalMessage = lodashGet(parentReportAction, 'originalMessage', {}); - return ( - parentReportAction && - parentReportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && - (originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE || (originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && _.has(originalMessage, 'IOUDetails'))) - ); -} - -/** - * Sort an array of reportActions by their created timestamp first, and reportActionID second - * This gives us a stable order even in the case of multiple reportActions created on the same millisecond - * - * @param {Array} reportActions - * @param {Boolean} shouldSortInDescendingOrder - * @returns {Array} - */ -function getSortedReportActions(reportActions, shouldSortInDescendingOrder = false) { - if (!_.isArray(reportActions)) { - throw new Error(`ReportActionsUtils.getSortedReportActions requires an array, received ${typeof reportActions}`); - } - - const invertedMultiplier = shouldSortInDescendingOrder ? -1 : 1; - return _.chain(reportActions) - .compact() - .sort((first, second) => { - // First sort by timestamp - if (first.created !== second.created) { - return (first.created < second.created ? -1 : 1) * invertedMultiplier; - } - - // Then by action type, ensuring that `CREATED` actions always come first if they have the same timestamp as another action type - if ((first.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED || second.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) && first.actionName !== second.actionName) { - return (first.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED ? -1 : 1) * invertedMultiplier; - } - // Ensure that `REPORTPREVIEW` actions always come after if they have the same timestamp as another action type - if ((first.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW || second.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW) && first.actionName !== second.actionName) { - return (first.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW ? 1 : -1) * invertedMultiplier; - } - - // Then fallback on reportActionID as the final sorting criteria. It is a random number, - // but using this will ensure that the order of reportActions with the same created time and action type - // will be consistent across all users and devices - return (first.reportActionID < second.reportActionID ? -1 : 1) * invertedMultiplier; - }) - .value(); -} - -/** - * Finds most recent IOU request action ID. - * - * @param {Array} reportActions - * @returns {String} - */ -function getMostRecentIOURequestActionID(reportActions) { - const iouRequestTypes = [CONST.IOU.REPORT_ACTION_TYPE.CREATE, CONST.IOU.REPORT_ACTION_TYPE.SPLIT]; - const iouRequestActions = _.filter(reportActions, (action) => iouRequestTypes.includes(lodashGet(action, 'originalMessage.type'))); - - if (_.isEmpty(iouRequestActions)) { - return null; - } - - const sortedReportActions = getSortedReportActions(iouRequestActions); - return _.last(sortedReportActions).reportActionID; -} - -/** - * Returns array of links inside a given report action - * - * @param {Object} reportAction - * @returns {Array} - */ -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) { - return []; - } - - return _.map([...htmlContent.matchAll(regex)], (match) => match[1]); -} - -/** - * Returns the report action immediately before the specified index. - * @param {Array} reportActions - all actions - * @param {Number} actionIndex - index of the action - * @returns {Object|null} - */ -function findPreviousAction(reportActions, actionIndex) { - for (let i = actionIndex + 1; i < reportActions.length; i++) { - // Find the next non-pending deletion report action, as the pending delete action means that it is not displayed in the UI, but still is in the report actions list. - // If we are offline, all actions are pending but shown in the UI, so we take the previous action, even if it is a delete. - if (isNetworkOffline || reportActions[i].pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { - return reportActions[i]; - } - } - return null; -} - -/** - * 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. - * - * @param {Array} reportActions - * @param {Number} actionIndex - index of the comment item in state to check - * @returns {Boolean} - */ -function isConsecutiveActionMadeByPreviousActor(reportActions, actionIndex) { - const previousAction = findPreviousAction(reportActions, actionIndex); - const currentAction = reportActions[actionIndex]; - - // It's OK for there to be no previous action, and in that case, false will be returned - // so that the comment isn't grouped - if (!currentAction || !previousAction) { - return false; - } - - // Comments are only grouped if they happen within 5 minutes of each other - if (new Date(currentAction.created).getTime() - new Date(previousAction.created).getTime() > 300000) { - return false; - } - - // Do not group if previous action was a created action - if (previousAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) { - return false; - } - - // Do not group if previous or current action was a renamed action - if (previousAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED || currentAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) { - return false; - } - - // Do not group if the delegate account ID is different - if (previousAction.delegateAccountID !== currentAction.delegateAccountID) { - return false; - } - - return currentAction.actorAccountID === previousAction.actorAccountID; -} - -/** - * Checks if a reportAction is deprecated. - * - * @param {Object} reportAction - * @param {String} key - * @returns {Boolean} - */ -function isReportActionDeprecated(reportAction, key) { - if (!reportAction) { - return true; - } - - // HACK ALERT: We're temporarily filtering out any reportActions keyed by sequenceNumber - // to prevent bugs during the migration from sequenceNumber -> reportActionID - if (String(reportAction.sequenceNumber) === key) { - Log.info('Front-end filtered out reportAction keyed by sequenceNumber!', false, reportAction); - return true; - } - - return false; -} - -/** - * Checks if a reportAction is fit for display, meaning that it's not deprecated, is of a valid - * and supported type, it's not deleted and also not closed. - * - * @param {Object} reportAction - * @param {String} key - * @returns {Boolean} - */ -function shouldReportActionBeVisible(reportAction, key) { - if (isReportActionDeprecated(reportAction, key)) { - return false; - } - - if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.TASKEDITED) { - return false; - } - - // Filter out any unsupported reportAction types - if (!Object.values(CONST.REPORT.ACTIONS.TYPE).includes(reportAction.actionName) && !Object.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG).includes(reportAction.actionName)) { - return false; - } - - // Ignore closed action here since we're already displaying a footer that explains why the report was closed - if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED) { - return false; - } - - const isThreadParent = isThreadParentMessage(reportAction, ''); - if (isPendingRemove(reportAction) && !isThreadParent) { - return false; - } - - // All other actions are displayed except thread parents, deleted, or non-pending actions - const isDeleted = isDeletedAction(reportAction); - const isPending = !!reportAction.pendingAction; - return !isDeleted || isPending || isDeletedParentAction(reportAction); -} - -/** - * Checks if a reportAction is fit for display as report last action, meaning that - * it satisfies shouldReportActionBeVisible, it's not whisper action and not deleted. - * - * @param {Object} reportAction - * @returns {Boolean} - */ -function shouldReportActionBeVisibleAsLastAction(reportAction) { - if (!reportAction) { - return false; - } - - if (!_.isEmpty(reportAction.errors)) { - return false; - } - - // If a whisper action is the REPORTPREVIEW action, we are displaying it. - return ( - shouldReportActionBeVisible(reportAction, reportAction.reportActionID) && - !(isWhisperAction(reportAction) && !isReportPreviewAction(reportAction) && !isMoneyRequestAction(reportAction)) && - !isDeletedAction(reportAction) - ); -} - -/** - * @param {String} reportID - * @param {Object} [actionsToMerge] - * @return {Object} - */ -function getLastVisibleAction(reportID, actionsToMerge = {}) { - const updatedActionsToMerge = {}; - if (actionsToMerge && Object.keys(actionsToMerge).length !== 0) { - Object.keys(actionsToMerge).forEach( - (actionToMergeID) => (updatedActionsToMerge[actionToMergeID] = {...allReportActions[reportID][actionToMergeID], ...actionsToMerge[actionToMergeID]}), - ); - } - const actions = Object.values({ - ...allReportActions[reportID], - ...updatedActionsToMerge, - }); - const visibleActions = actions.filter((action) => shouldReportActionBeVisibleAsLastAction(action)); - - if (visibleActions.length === 0) { - return {}; - } - const maxDate = max(visibleActions.map((action) => parseISO(action.created))); - const maxAction = visibleActions.find((action) => isEqual(parseISO(action.created), maxDate)); - return maxAction; -} - -/** - * @param {String} reportID - * @param {Object} [actionsToMerge] - * @return {Object} - */ -function getLastVisibleMessage(reportID, actionsToMerge = {}) { - const lastVisibleAction = getLastVisibleAction(reportID, actionsToMerge); - const message = lodashGet(lastVisibleAction, ['message', 0], {}); - - if (isReportMessageAttachment(message)) { - return { - lastMessageTranslationKey: CONST.TRANSLATION_KEYS.ATTACHMENT, - lastMessageText: CONST.ATTACHMENT_MESSAGE_TEXT, - lastMessageHtml: CONST.TRANSLATION_KEYS.ATTACHMENT, - }; - } - - if (isCreatedAction(lastVisibleAction)) { - return { - lastMessageText: '', - }; - } - - const messageText = lodashGet(message, 'text', ''); - return { - lastMessageText: String(messageText).replace(CONST.REGEX.AFTER_FIRST_LINE_BREAK, '').substring(0, CONST.REPORT.LAST_MESSAGE_TEXT_MAX_LENGTH).trim(), - }; -} - -/** - * A helper method to filter out report actions keyed by sequenceNumbers. - * - * @param {Object} reportActions - * @returns {Array} - */ -function filterOutDeprecatedReportActions(reportActions) { - return _.filter(reportActions, (reportAction, key) => !isReportActionDeprecated(reportAction, key)); -} - -/** - * This method returns the report actions that are ready for display in the ReportActionsView. - * The report actions need to be sorted by created timestamp first, and reportActionID second - * to ensure they will always be displayed in the same order (in case multiple actions have the same timestamp). - * This is all handled with getSortedReportActions() which is used by several other methods to keep the code DRY. - * - * @param {Object} reportActions - * @returns {Array} - */ -function getSortedReportActionsForDisplay(reportActions) { - const filteredReportActions = _.filter(reportActions, (reportAction, key) => shouldReportActionBeVisible(reportAction, key)); - return getSortedReportActions(filteredReportActions, true); -} - -/** - * In some cases, there can be multiple closed report actions in a chat report. - * This method returns the last closed report action so we can always show the correct archived report reason. - * Additionally, archived #admins and #announce do not have the closed report action so we will return null if none is found. - * - * @param {Object} reportActions - * @returns {Object|null} - */ -function getLastClosedReportAction(reportActions) { - // If closed report action is not present, return early - if (!_.some(reportActions, (action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED)) { - return null; - } - const filteredReportActions = filterOutDeprecatedReportActions(reportActions); - const sortedReportActions = getSortedReportActions(filteredReportActions); - return lodashFindLast(sortedReportActions, (action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED); -} - -/** - * @param {Array} onyxData - * @returns {Object} The latest report action in the `onyxData` or `null` if one couldn't be found - */ -function getLatestReportActionFromOnyxData(onyxData) { - const reportActionUpdate = _.find(onyxData, (onyxUpdate) => onyxUpdate.key.startsWith(ONYXKEYS.COLLECTION.REPORT_ACTIONS)); - - if (!reportActionUpdate) { - return null; - } - - const reportActions = _.values(reportActionUpdate.value); - const sortedReportActions = getSortedReportActions(reportActions); - return _.last(sortedReportActions); -} - -/** - * Find the transaction associated with this reportAction, if one exists. - * - * @param {String} reportID - * @param {String} reportActionID - * @returns {String|null} - */ -function getLinkedTransactionID(reportID, reportActionID) { - const reportAction = lodashGet(allReportActions, [reportID, reportActionID]); - if (!reportAction || reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU) { - return null; - } - return reportAction.originalMessage.IOUTransactionID; -} - -/** - * - * @param {String} reportID - * @param {String} reportActionID - * @returns {Object} - */ -function getReportAction(reportID, reportActionID) { - return lodashGet(allReportActions, [reportID, reportActionID], {}); -} - -/** - * @returns {string} - */ -function getMostRecentReportActionLastModified() { - // Start with the oldest date possible - let mostRecentReportActionLastModified = new Date(0).toISOString(); - - // Flatten all the actions - // Loop over them all to find the one that is the most recent - const flatReportActions = _.flatten(_.map(allReportActions, (actions) => _.values(actions))); - _.each(flatReportActions, (action) => { - // Pending actions should not be counted here as a user could create a comment or some other action while offline and the server might know about - // messages they have not seen yet. - if (!_.isEmpty(action.pendingAction)) { - return; - } - - const lastModified = action.lastModified || action.created; - if (lastModified < mostRecentReportActionLastModified) { - return; - } - - mostRecentReportActionLastModified = lastModified; - }); - - // We might not have actions so we also look at the report objects to see if any have a lastVisibleActionLastModified that is more recent. We don't need to get - // any reports that have been updated before either a recently updated report or reportAction as we should be up to date on these - _.each(allReports, (report) => { - const reportLastVisibleActionLastModified = report.lastVisibleActionLastModified || report.lastVisibleActionCreated; - if (!reportLastVisibleActionLastModified || reportLastVisibleActionLastModified < mostRecentReportActionLastModified) { - return; - } - - mostRecentReportActionLastModified = reportLastVisibleActionLastModified; - }); - - return mostRecentReportActionLastModified; -} - -/** - * @param {*} chatReportID - * @param {*} iouReportID - * @returns {Object} The report preview action or `null` if one couldn't be found - */ -function getReportPreviewAction(chatReportID, iouReportID) { - return _.find( - allReportActions[chatReportID], - (reportAction) => reportAction && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && lodashGet(reportAction, 'originalMessage.linkedReportID') === iouReportID, - ); -} - -/** - * Get the iouReportID for a given report action. - * - * @param {Object} reportAction - * @returns {String} - */ -function getIOUReportIDFromReportActionPreview(reportAction) { - return lodashGet(reportAction, 'originalMessage.linkedReportID', ''); -} - -function isCreatedTaskReportAction(reportAction) { - return reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT && _.has(reportAction.originalMessage, 'taskReportID'); -} - -/** - * A helper method to identify if the message is deleted or not. - * - * @param {Object} reportAction - * @returns {Boolean} - */ -function isMessageDeleted(reportAction) { - return lodashGet(reportAction, ['message', 0, 'isDeletedParentAction'], false); -} - -/** - * Returns the number of money requests associated with a report preview - * - * @param {Object|null} reportPreviewAction - * @returns {Number} - */ -function getNumberOfMoneyRequests(reportPreviewAction) { - return lodashGet(reportPreviewAction, 'childMoneyRequestCount', 0); -} - -/** - * @param {*} reportAction - * @returns {Boolean} - */ -function isSplitBillAction(reportAction) { - return lodashGet(reportAction, 'originalMessage.type', '') === CONST.IOU.REPORT_ACTION_TYPE.SPLIT; -} - -/** - * - * @param {*} reportAction - * @returns {Boolean} - */ -function isTaskAction(reportAction) { - const reportActionName = lodashGet(reportAction, 'actionName', ''); - return ( - reportActionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED || - reportActionName === CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED || - reportActionName === CONST.REPORT.ACTIONS.TYPE.TASKREOPENED - ); -} - -/** - * @param {*} reportID - * @returns {[Object]} - */ -function getAllReportActions(reportID) { - return lodashGet(allReportActions, reportID, []); -} - -/** - * Check whether a report action is an attachment (a file, such as an image or a zip). - * - * @param {Object} reportAction report action - * @returns {Boolean} - */ -function isReportActionAttachment(reportAction) { - const message = _.first(lodashGet(reportAction, 'message', [{}])); - return _.has(reportAction, 'isAttachment') ? reportAction.isAttachment : isReportMessageAttachment(message); -} - -// eslint-disable-next-line rulesdir/no-negated-variables -function isNotifiableReportAction(reportAction) { - return reportAction && _.contains([CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE], reportAction.actionName); -} - -export { - getSortedReportActions, - getLastVisibleAction, - getLastVisibleMessage, - getMostRecentIOURequestActionID, - extractLinksFromMessageHtml, - isCreatedAction, - isDeletedAction, - shouldReportActionBeVisible, - shouldReportActionBeVisibleAsLastAction, - isReportActionDeprecated, - isConsecutiveActionMadeByPreviousActor, - getSortedReportActionsForDisplay, - getLastClosedReportAction, - getLatestReportActionFromOnyxData, - isMoneyRequestAction, - isThreadParentMessage, - getLinkedTransactionID, - getMostRecentReportActionLastModified, - getReportPreviewAction, - isCreatedTaskReportAction, - getParentReportAction, - isTransactionThread, - isSentMoneyReportAction, - isDeletedParentAction, - isReportPreviewAction, - isModifiedExpenseAction, - getIOUReportIDFromReportActionPreview, - isMessageDeleted, - isWhisperAction, - isPendingRemove, - getReportAction, - getNumberOfMoneyRequests, - isSplitBillAction, - isTaskAction, - getAllReportActions, - isReportActionAttachment, - isNotifiableReportAction, -}; From d3921d9523b759c4275ea47757bc522a40c38b50 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 27 Oct 2023 18:39:52 +0700 Subject: [PATCH 009/764] fix ts --- src/pages/home/report/withReportOrNotFound.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/withReportOrNotFound.tsx b/src/pages/home/report/withReportOrNotFound.tsx index 28d6707b085f..fe20a8a25d12 100644 --- a/src/pages/home/report/withReportOrNotFound.tsx +++ b/src/pages/home/report/withReportOrNotFound.tsx @@ -39,7 +39,7 @@ export default function ( const shouldShowFullScreenLoadingIndicator = props.isLoadingReportData && (!Object.entries(props.report ?? {}).length || !props.report?.reportID); const shouldShowNotFoundPage = - !Object.entries(props.report ?? {}).length || !props.report?.reportID || !ReportUtils.canAccessReport(props.report, props.policies, props.betas, {}); + !Object.entries(props.report ?? {}).length || !props.report?.reportID || !ReportUtils.canAccessReport(props.report, props.policies, props.betas); // If the content was shown but it's not anymore that means the report was deleted and we are probably navigating out of this screen. // Return null for this case to avoid rendering FullScreenLoadingIndicator or NotFoundPage when animating transition. From 34d4a7e6ba5e46b6afdaf8cf501882a3c4aced6e Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 3 Nov 2023 11:03:08 +0700 Subject: [PATCH 010/764] merge main --- src/libs/OptionsListUtils.js | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 08fddb0a8416..2e54b434293d 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -378,10 +378,7 @@ function getAllReportErrors(report, reportActions) { * @returns {String} */ function getLastMessageTextForReport(report) { - const lastReportAction = _.find( - allSortedReportActions[report.reportID], - (reportAction, key) => ReportActionUtils.shouldReportActionBeVisible(reportAction, key) && reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - ); + const lastReportAction = _.find(allSortedReportActions[report.reportID], (reportAction) => ReportActionUtils.shouldReportActionBeVisibleAsLastAction(reportAction)); let lastMessageTextFromReport = ''; const lastActionName = lodashGet(lastReportAction, 'actionName', ''); @@ -404,6 +401,8 @@ function getLastMessageTextForReport(report) { lastMessageTextFromReport = ReportUtils.getReimbursementQueuedActionMessage(lastReportAction, report); } else if (ReportActionUtils.isDeletedParentAction(lastReportAction) && ReportUtils.isChatReport(report)) { lastMessageTextFromReport = ReportUtils.getDeletedParentActionMessageForChatReport(lastReportAction); + } else if (ReportActionUtils.isPendingRemove(lastReportAction) && ReportActionUtils.isThreadParentMessage(lastReportAction, report.reportID)) { + return Localize.translateLocal('parentReportAction.hiddenMessage'); } else if (ReportActionUtils.isModifiedExpenseAction(lastReportAction)) { const properSchemaForModifiedExpenseMessage = ReportUtils.getModifiedExpenseMessage(lastReportAction); lastMessageTextFromReport = ReportUtils.formatReportLastMessageText(properSchemaForModifiedExpenseMessage, true); @@ -415,24 +414,6 @@ function getLastMessageTextForReport(report) { lastMessageTextFromReport = lodashGet(lastReportAction, 'message[0].text', ''); } else { lastMessageTextFromReport = report ? report.lastMessageText || '' : ''; - - // Yeah this is a bit ugly. If the latest report action that is not a whisper has been moderated as pending remove - // then set the last message text to the text of the latest visible action that is not a whisper or the report creation message. - const lastNonWhisper = - _.find(allSortedReportActions[report.reportID], (action) => !ReportActionUtils.isWhisperAction(action) && !ReportActionUtils.isDeletedParentAction(action)) || {}; - if (ReportActionUtils.isPendingRemove(lastNonWhisper)) { - const latestVisibleAction = - _.find( - allSortedReportActions[report.reportID], - (action) => ReportActionUtils.shouldReportActionBeVisibleAsLastAction(action) && !ReportActionUtils.isCreatedAction(action), - ) || {}; - - if (ReportActionUtils.isThreadParentMessage(latestVisibleAction) && ReportActionUtils.isPendingRemove(latestVisibleAction)) { - return Localize.translateLocal(CONST.TRANSLATION_KEYS.HIDDEN_MESSSAGE); - } - - lastMessageTextFromReport = lodashGet(latestVisibleAction, 'message[0].text', ''); - } } return lastMessageTextFromReport; } From 68a40f865bb0d47e1689eb6b4c11d671fb551e4d Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:34:45 +0100 Subject: [PATCH 011/764] add test navigator --- src/NAVIGATORS.ts | 1 + src/ROUTES.ts | 1 + src/SCREENS.ts | 1 + .../Navigation/AppNavigator/AuthScreens.js | 6 ++++ .../Navigators/SettingsNavigator.js | 36 +++++++++++++++++++ src/libs/Navigation/linkingConfig.js | 6 ++++ .../FloatingActionButtonAndPopover.js | 8 ++--- 7 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js diff --git a/src/NAVIGATORS.ts b/src/NAVIGATORS.ts index a3a041e65684..52480d874d7b 100644 --- a/src/NAVIGATORS.ts +++ b/src/NAVIGATORS.ts @@ -5,5 +5,6 @@ export default { CENTRAL_PANE_NAVIGATOR: 'CentralPaneNavigator', RIGHT_MODAL_NAVIGATOR: 'RightModalNavigator', + SETTINGS_NAVIGATOR: 'Settings_Navigator', FULL_SCREEN_NAVIGATOR: 'FullScreenNavigator', } as const; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 57d4eb8187ec..bd5f6cc422b3 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -58,6 +58,7 @@ export default { }, SETTINGS: 'settings', + SETTINGS_NEW: 'settings_new', SETTINGS_PROFILE: 'settings/profile', SETTINGS_SHARE_CODE: 'settings/shareCode', SETTINGS_DISPLAY_NAME: 'settings/profile/display-name', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index afc368858f55..f18fb49dff80 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -16,6 +16,7 @@ export default { NOT_FOUND: 'not-found', TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', VALIDATE_LOGIN: 'ValidateLogin', + SETTINGS_NEW: 'SettingsNew', SETTINGS: { ROOT: 'Settings_Root', PREFERENCES: 'Settings_Preferences', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index aedb2fa8d741..52a7f0c41afe 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -35,6 +35,7 @@ import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; import CentralPaneNavigator from './Navigators/CentralPaneNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; +import SettingsNavigator from './Navigators/SettingsNavigator'; const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default; const loadSidebarScreen = () => require('../../../pages/home/sidebar/SidebarScreen').default; @@ -335,6 +336,11 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio component={RightModalNavigator} listeners={modalScreenListeners} /> + + + + + + ); +} + +SettingsNavigator.propTypes = propTypes; +SettingsNavigator.displayName = 'SettingsNavigator'; + +export default SettingsNavigator; diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 44473998ac62..4137260e2390 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -429,6 +429,12 @@ export default { }, }, }, + + [NAVIGATORS.SETTINGS_NAVIGATOR]: { + screens: { + [SCREENS.SETTINGS_NEW]: ROUTES.SETTINGS_NEW, + } + } }, }, }; diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index 739f7e3e0295..1eebf43d8a0a 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -243,11 +243,9 @@ function FloatingActionButtonAndPopover(props) { isActive={isCreateMenuActive} ref={anchorRef} onPress={() => { - if (isCreateMenuActive) { - hideCreateMenu(); - } else { - showCreateMenu(); - } + console.log('FloatingActionButtonAndPopover.js: showCreateMenu()'); + // navigate to new screen + Navigation.navigate(ROUTES.SETTINGS_NEW); }} /> From bddaa69fad1bfc22d4cd5afe66e38c7ebba4003e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:43:00 +0100 Subject: [PATCH 012/764] draft --- src/ROUTES.ts | 1 + .../Navigators/SettingsNavigator.js | 41 +++++++++++++------ .../createCustomStackNavigator/index.js | 15 +++++-- src/libs/Navigation/linkingConfig.js | 4 +- .../FloatingActionButtonAndPopover.js | 2 +- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index bd5f6cc422b3..95d6f13a8921 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -59,6 +59,7 @@ export default { SETTINGS: 'settings', SETTINGS_NEW: 'settings_new', + SETTINGS_NEW_PROFILE: 'settings_new/profile', SETTINGS_PROFILE: 'settings/profile', SETTINGS_SHARE_CODE: 'settings/shareCode', SETTINGS_DISPLAY_NAME: 'settings/profile/display-name', diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index 46d80cb0fb55..ef4d0b30a05f 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -1,12 +1,13 @@ -import {createStackNavigator} from '@react-navigation/stack'; import PropTypes from 'prop-types'; import React from 'react'; -import {View} from 'react-native'; -import RHPScreenOptions from '@libs/Navigation/AppNavigator/RHPScreenOptions'; +import { View } from 'react-native'; import useThemeStyles from '@styles/useThemeStyles'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; - -const Stack = createStackNavigator(); +import useWindowDimensions from '@hooks/useWindowDimensions'; +import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRootNavigatorScreenOptions'; +import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator'; +import NAVIGATORS from '@src/NAVIGATORS'; +import ROUTES from '@src/ROUTES'; const propTypes = { /* Navigation functions provided by React Navigation */ @@ -15,18 +16,32 @@ const propTypes = { }).isRequired, }; +const RootStack = createCustomStackNavigator(); + function SettingsNavigator() { const styles = useThemeStyles(); + const {isSmallScreenWidth} = useWindowDimensions(); + const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth); return ( - - - - - + + + + + + ); } diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index 8924b01e2acb..bb2edb3aa2bb 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -19,20 +19,23 @@ const propTypes = { /* Screen options defined for this navigator */ // eslint-disable-next-line react/forbid-prop-types screenOptions: PropTypes.object, + + centralRoute: PropTypes.string, }; const defaultProps = { initialRouteName: undefined, screenOptions: undefined, + centralRoute: NAVIGATORS.CENTRAL_PANE_NAVIGATOR, }; -function reduceReportRoutes(routes) { +function reduceReportRoutes(routes, centralRoute=NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { const result = []; let count = 0; const reverseRoutes = [...routes].reverse(); reverseRoutes.forEach((route) => { - if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { + if (route.name === centralRoute) { // Remove all report routes except the last 3. This will improve performance. if (count < 3) { result.push(route); @@ -43,6 +46,8 @@ function reduceReportRoutes(routes) { } }); + console.log('reduceReportRoutes', centralRoute, routes, result); + return result.reverse(); } @@ -62,14 +67,16 @@ function ResponsiveStackNavigator(props) { }); const stateToRender = useMemo(() => { - const result = reduceReportRoutes(state.routes); + const result = reduceReportRoutes(state.routes, props.centralRoute); return { ...state, index: result.length - 1, routes: [...result], }; - }, [state]); + }, [props.centralRoute, state]); + + console.log('ResponsiveStackNavigator', props.centralRoute); return ( diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 4137260e2390..05f6e3c4e344 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -432,8 +432,8 @@ export default { [NAVIGATORS.SETTINGS_NAVIGATOR]: { screens: { - [SCREENS.SETTINGS_NEW]: ROUTES.SETTINGS_NEW, - } + [SCREENS.SETTINGS_NEW_PROFILE]: {path: ROUTES.SETTINGS_NEW_PROFILE}, + }, } }, }, diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index 1eebf43d8a0a..c798121b1d2a 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -245,7 +245,7 @@ function FloatingActionButtonAndPopover(props) { onPress={() => { console.log('FloatingActionButtonAndPopover.js: showCreateMenu()'); // navigate to new screen - Navigation.navigate(ROUTES.SETTINGS_NEW); + Navigation.navigate(ROUTES.SETTINGS_NEW_PROFILE); }} /> From d8910f7d0d038a80b7b1e490008bf4b26a2f7527 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:53:09 +0100 Subject: [PATCH 013/764] add patch --- .../@react-navigation+stack+6.3.16+002+dontDetachScreen.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/@react-navigation+stack+6.3.16+002+dontDetachScreen.patch b/patches/@react-navigation+stack+6.3.16+002+dontDetachScreen.patch index d64fc4fecf74..ac4e8bafa8ab 100644 --- a/patches/@react-navigation+stack+6.3.16+002+dontDetachScreen.patch +++ b/patches/@react-navigation+stack+6.3.16+002+dontDetachScreen.patch @@ -43,7 +43,7 @@ index 7558eb3..b7bb75e 100644 }) : STATE_TRANSITIONING_OR_BELOW_TOP; } + -+ const isHomeScreenAndNotOnTop = route.name === 'Home' && isScreenActive !== STATE_ON_TOP; ++ const isHomeScreenAndNotOnTop = (route.name === 'Home' || route.name === 'SettingsHome') && isScreenActive !== STATE_ON_TOP; + const { headerShown = true, From 52388b93907b5aeef07c91e5c03244494124e1bf Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:32:14 +0100 Subject: [PATCH 014/764] draft --- src/NAVIGATORS.ts | 1 - src/ROUTES.ts | 2 +- src/SCREENS.ts | 2 +- .../Navigation/AppNavigator/AuthScreens.js | 2 +- .../Navigators/SettingsNavigator.js | 27 ++++++++++++------- src/libs/Navigation/linkTo.js | 1 + src/libs/Navigation/linkingConfig.js | 15 +++++++++-- 7 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/NAVIGATORS.ts b/src/NAVIGATORS.ts index 52480d874d7b..a3a041e65684 100644 --- a/src/NAVIGATORS.ts +++ b/src/NAVIGATORS.ts @@ -5,6 +5,5 @@ export default { CENTRAL_PANE_NAVIGATOR: 'CentralPaneNavigator', RIGHT_MODAL_NAVIGATOR: 'RightModalNavigator', - SETTINGS_NAVIGATOR: 'Settings_Navigator', FULL_SCREEN_NAVIGATOR: 'FullScreenNavigator', } as const; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 95d6f13a8921..3d1a52230f3e 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -58,7 +58,7 @@ export default { }, SETTINGS: 'settings', - SETTINGS_NEW: 'settings_new', + SETTINGS_HOME: 'settings_new', SETTINGS_NEW_PROFILE: 'settings_new/profile', SETTINGS_PROFILE: 'settings/profile', SETTINGS_SHARE_CODE: 'settings/shareCode', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f18fb49dff80..b721d7f32c4b 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -16,7 +16,7 @@ export default { NOT_FOUND: 'not-found', TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', VALIDATE_LOGIN: 'ValidateLogin', - SETTINGS_NEW: 'SettingsNew', + SETTINGS_HOME: 'SettingsHome', SETTINGS: { ROOT: 'Settings_Root', PREFERENCES: 'Settings_Preferences', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 52a7f0c41afe..1d8ce5c69164 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -337,7 +337,7 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio listeners={modalScreenListeners} /> diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index ef4d0b30a05f..da46b8a4a761 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -8,38 +8,47 @@ import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRoot import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator'; import NAVIGATORS from '@src/NAVIGATORS'; import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; const propTypes = { /* Navigation functions provided by React Navigation */ navigation: PropTypes.shape({ goBack: PropTypes.func.isRequired, + getState: PropTypes.func.isRequired, }).isRequired, }; const RootStack = createCustomStackNavigator(); -function SettingsNavigator() { +function SettingsNavigator({navigation}) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth); + console.log('navigation state', navigation.getState()); + return ( - + + {/* */} ); diff --git a/src/libs/Navigation/linkTo.js b/src/libs/Navigation/linkTo.js index 286074914cf7..72ff8f795a95 100644 --- a/src/libs/Navigation/linkTo.js +++ b/src/libs/Navigation/linkTo.js @@ -58,6 +58,7 @@ export default function linkTo(navigation, path, type) { const state = getStateFromPath(path); const action = getActionFromState(state, linkingConfig.config); + console.log('linkTo', state, action); // If action type is different than NAVIGATE we can't change it to the PUSH safely if (action.type === CONST.NAVIGATION.ACTION_TYPE.NAVIGATE) { diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 05f6e3c4e344..1a63a8e47569 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -430,9 +430,20 @@ export default { }, }, - [NAVIGATORS.SETTINGS_NAVIGATOR]: { + [NAVIGATORS.FULL_SCREEN_NAVIGATOR]: { screens: { - [SCREENS.SETTINGS_NEW_PROFILE]: {path: ROUTES.SETTINGS_NEW_PROFILE}, + Settings: { + screens: { + [SCREENS.SETTINGS_HOME]: { + path: ROUTES.SETTINGS_HOME, + exact: true, + }, + [SCREENS.SETTINGS_NEW_PROFILE]: { + path: ROUTES.SETTINGS_NEW_PROFILE, + exact: true, + }, + } + } }, } }, From 0d665ef8c9270972710606527d09671c1648de77 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:02:19 +0100 Subject: [PATCH 015/764] another step --- .../Navigators/SettingsNavigator.js | 10 +++---- src/libs/Navigation/linkingConfig.js | 27 ++++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index da46b8a4a761..fa0bc62cc9c0 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -2,15 +2,14 @@ import PropTypes from 'prop-types'; import React from 'react'; import { View } from 'react-native'; import useThemeStyles from '@styles/useThemeStyles'; -import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import useWindowDimensions from '@hooks/useWindowDimensions'; import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRootNavigatorScreenOptions'; import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator'; -import NAVIGATORS from '@src/NAVIGATORS'; -import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; +const loadSidebarScreen = () => require('../../../../pages/home/sidebar/SidebarScreen').default; + const propTypes = { /* Navigation functions provided by React Navigation */ navigation: PropTypes.shape({ @@ -33,15 +32,14 @@ function SettingsNavigator({navigation}) { diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 1a63a8e47569..71f7f6916355 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -432,18 +432,21 @@ export default { [NAVIGATORS.FULL_SCREEN_NAVIGATOR]: { screens: { - Settings: { - screens: { - [SCREENS.SETTINGS_HOME]: { - path: ROUTES.SETTINGS_HOME, - exact: true, - }, - [SCREENS.SETTINGS_NEW_PROFILE]: { - path: ROUTES.SETTINGS_NEW_PROFILE, - exact: true, - }, - } - } + [SCREENS.SETTINGS_HOME]: { + path: ROUTES.SETTINGS_HOME, + }, + SettingsCentralPane: { + path: ROUTES.SETTINGS_NEW_PROFILE, + exact: true, + }, + // Settings: { + // screens: { + // [SCREENS.SETTINGS_NEW_PROFILE]: { + // path: ROUTES.SETTINGS_NEW_PROFILE, + // exact: true, + // }, + // } + // } }, } }, From dba92bfb1fe64b727baf8d56665953c36b7c1846 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:05:44 +0100 Subject: [PATCH 016/764] another step forward --- src/SCREENS.ts | 1 + .../Navigation/AppNavigator/Navigators/SettingsNavigator.js | 2 +- src/libs/Navigation/linkingConfig.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index b721d7f32c4b..b7def3ce8e23 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -17,6 +17,7 @@ export default { TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', VALIDATE_LOGIN: 'ValidateLogin', SETTINGS_HOME: 'SettingsHome', + SETTINGS_NEW_PROFILE: 'SettingsNewProfile', SETTINGS: { ROOT: 'Settings_Root', PREFERENCES: 'Settings_Preferences', diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index fa0bc62cc9c0..705eaf35eb7b 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -39,7 +39,7 @@ function SettingsNavigator({navigation}) { getComponent={loadSidebarScreen} /> diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 71f7f6916355..0d09a984ae61 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -435,7 +435,7 @@ export default { [SCREENS.SETTINGS_HOME]: { path: ROUTES.SETTINGS_HOME, }, - SettingsCentralPane: { + [SCREENS.SETTINGS_NEW_PROFILE]: { path: ROUTES.SETTINGS_NEW_PROFILE, exact: true, }, From 14e07418e95a4e342b33f278e8690d6525ae60a4 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:19:38 +0100 Subject: [PATCH 017/764] another step forward --- .../Navigators/SettingsNavigator.js | 7 +-- .../CustomRouter.js | 53 +++++++++++++------ .../createCustomStackNavigator/index.js | 1 + src/libs/Navigation/linkingConfig.js | 2 +- .../FloatingActionButtonAndPopover.js | 2 +- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index 705eaf35eb7b..3d82337c6ad7 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -32,6 +32,7 @@ function SettingsNavigator({navigation}) { - {/* */} ); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js index 5d3eb38d49dc..2a05a90796bb 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js @@ -3,12 +3,14 @@ import lodashFindLast from 'lodash/findLast'; import _ from 'underscore'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; +import CentralPaneNavigator from '../Navigators/CentralPaneNavigator'; /** * @param {Object} state - react-navigation state + * @param {String} centralRoute - name of the central route * @returns {Boolean} */ -const isAtLeastOneCentralPaneNavigatorInState = (state) => _.find(state.routes, (r) => r.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); +const isAtLeastOneCentralPaneNavigatorInState = (state, centralRoute) => _.find(state.routes, (r) => r.name === centralRoute); /** * @param {Object} state - react-navigation state @@ -41,22 +43,37 @@ const getTopMostReportIDFromRHP = (state) => { * The report screen will self set proper reportID param based on the helper function findLastAccessedReport (look at ReportScreenWrapper for more info) * * @param {Object} state - react-navigation state + * @param {String} centralRoute - name of the central route */ -const addCentralPaneNavigatorRoute = (state) => { +const addCentralPaneNavigatorRoute = (state, centralRoute) => { const reportID = getTopMostReportIDFromRHP(state); - const centralPaneNavigatorRoute = { - name: NAVIGATORS.CENTRAL_PANE_NAVIGATOR, - state: { - routes: [ - { - name: SCREENS.REPORT, - params: { - reportID, + let centralPaneNavigatorRoute; + if (centralRoute === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { + centralPaneNavigatorRoute = { + name: NAVIGATORS.CENTRAL_PANE_NAVIGATOR, + state: { + routes: [ + { + name: SCREENS.REPORT, + params: { + reportID, + }, }, - }, - ], - }, - }; + ], + }, + }; + } else { + centralPaneNavigatorRoute = { + name: centralRoute, + state: { + routes: [ + { + name: 'SettingsCentralPane', + }, + ], + }, + }; + } state.routes.splice(1, 0, centralPaneNavigatorRoute); // eslint-disable-next-line no-param-reassign state.index = state.routes.length - 1; @@ -64,16 +81,20 @@ const addCentralPaneNavigatorRoute = (state) => { function CustomRouter(options) { const stackRouter = StackRouter(options); + const centralRoute = options.centralRoute || NAVIGATORS.CENTRAL_PANE_NAVIGATOR; + console.log('CustomRouter', centralRoute); return { ...stackRouter, getRehydratedState(partialState, {routeNames, routeParamList}) { + console.log('getRehydratedState', centralRoute); // Make sure that there is at least one CentralPaneNavigator (ReportScreen by default) in the state if this is a wide layout - if (!isAtLeastOneCentralPaneNavigatorInState(partialState) && !options.getIsSmallScreenWidth()) { + if (!isAtLeastOneCentralPaneNavigatorInState(partialState, centralRoute) && !options.getIsSmallScreenWidth()) { + console.log('getRehydratedState', centralRoute, 'adding CentralPaneNavigator'); // If we added a route we need to make sure that the state.stale is true to generate new key for this route // eslint-disable-next-line no-param-reassign partialState.stale = true; - addCentralPaneNavigatorRoute(partialState); + addCentralPaneNavigatorRoute(partialState, centralRoute); } const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList}); return state; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index bb2edb3aa2bb..120e6e99dd61 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -64,6 +64,7 @@ function ResponsiveStackNavigator(props) { initialRouteName: props.initialRouteName, // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, + centralRoute: props.centralRoute, }); const stateToRender = useMemo(() => { diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 0d09a984ae61..71f7f6916355 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -435,7 +435,7 @@ export default { [SCREENS.SETTINGS_HOME]: { path: ROUTES.SETTINGS_HOME, }, - [SCREENS.SETTINGS_NEW_PROFILE]: { + SettingsCentralPane: { path: ROUTES.SETTINGS_NEW_PROFILE, exact: true, }, diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index c798121b1d2a..5ad3e4431b32 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -245,7 +245,7 @@ function FloatingActionButtonAndPopover(props) { onPress={() => { console.log('FloatingActionButtonAndPopover.js: showCreateMenu()'); // navigate to new screen - Navigation.navigate(ROUTES.SETTINGS_NEW_PROFILE); + Navigation.navigate(ROUTES.SETTINGS_HOME); }} /> From 18ed44a367f7cdc2e423bf3d1cdb16d2fa90a584 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:39:52 +0100 Subject: [PATCH 018/764] another step forward 123 --- .../AppNavigator/Navigators/SettingsNavigator.js | 6 +++++- .../createCustomStackNavigator/CustomRouter.js | 11 ++++++----- .../AppNavigator/createCustomStackNavigator/index.js | 6 +++++- src/libs/Navigation/NavigationRoot.js | 1 + src/libs/Navigation/linkingConfig.js | 8 ++++++-- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index 3d82337c6ad7..13cd7ebfd27c 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -9,6 +9,7 @@ import SCREENS from '@src/SCREENS'; import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; const loadSidebarScreen = () => require('../../../../pages/home/sidebar/SidebarScreen').default; +const loadPage = () => require('../../../../pages/ErrorPage/NotFoundPage').default; const propTypes = { /* Navigation functions provided by React Navigation */ @@ -27,17 +28,20 @@ function SettingsNavigator({navigation}) { console.log('navigation state', navigation.getState()); + console.log('loadSidebarScreen', loadSidebarScreen, 'not found page', loadPage) + return ( _.find(state.routes, (r) => r.name === centralRoute); +const isAtLeastOneCentralPaneNavigatorInState = (state, centralRoute) => { + console.log('isAtLeastOneCentralPaneNavigatorInState', centralRoute); + return _.find(state.routes, (r) => r.name === centralRoute) +}; /** * @param {Object} state - react-navigation state @@ -81,16 +83,15 @@ const addCentralPaneNavigatorRoute = (state, centralRoute) => { function CustomRouter(options) { const stackRouter = StackRouter(options); - const centralRoute = options.centralRoute || NAVIGATORS.CENTRAL_PANE_NAVIGATOR; - console.log('CustomRouter', centralRoute); return { ...stackRouter, getRehydratedState(partialState, {routeNames, routeParamList}) { + const centralRoute = options.centralRoute(); console.log('getRehydratedState', centralRoute); // Make sure that there is at least one CentralPaneNavigator (ReportScreen by default) in the state if this is a wide layout if (!isAtLeastOneCentralPaneNavigatorInState(partialState, centralRoute) && !options.getIsSmallScreenWidth()) { - console.log('getRehydratedState', centralRoute, 'adding CentralPaneNavigator'); + console.log('getRehydratedState', centralRoute, 'adding central pane'); // If we added a route we need to make sure that the state.stale is true to generate new key for this route // eslint-disable-next-line no-param-reassign partialState.stale = true; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index 120e6e99dd61..25fee9a02c77 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -52,19 +52,23 @@ function reduceReportRoutes(routes, centralRoute=NAVIGATORS.CENTRAL_PANE_NAVIGAT } function ResponsiveStackNavigator(props) { + console.log('ResponsiveStackNavigator', props.centralRoute) const {isSmallScreenWidth} = useWindowDimensions(); const isSmallScreenWidthRef = useRef(isSmallScreenWidth); isSmallScreenWidthRef.current = isSmallScreenWidth; + const centralRouteRef = useRef(props.centralRoute); + centralRouteRef.current = props.centralRoute; + const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, { children: props.children, screenOptions: props.screenOptions, initialRouteName: props.initialRouteName, // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, - centralRoute: props.centralRoute, + centralRoute: () => centralRouteRef.current, }); const stateToRender = useMemo(() => { diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js index 2373066cf4bd..314a324dc0fe 100644 --- a/src/libs/Navigation/NavigationRoot.js +++ b/src/libs/Navigation/NavigationRoot.js @@ -75,6 +75,7 @@ function NavigationRoot(props) { if (!navigationRef.isReady() || !props.authenticated) { return; } + // TODO: Add force rehydration! // We need to force state rehydration so the CustomRouter can add the CentralPaneNavigator route if necessary. navigationRef.resetRoot(navigationRef.getRootState()); }, [isSmallScreenWidth, props.authenticated]); diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 71f7f6916355..2fd0db3cd48f 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -436,8 +436,12 @@ export default { path: ROUTES.SETTINGS_HOME, }, SettingsCentralPane: { - path: ROUTES.SETTINGS_NEW_PROFILE, - exact: true, + screens: { + [SCREENS.SETTINGS_NEW_PROFILE]: { + path: ROUTES.SETTINGS_NEW_PROFILE, + exact: true, + } + } }, // Settings: { // screens: { From 7fa40aedb098807d85aa709f9527e26080b58ab2 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:49:31 +0100 Subject: [PATCH 019/764] mini step forward --- .../Navigators/SettingsNavigator.js | 7 +- src/libs/Navigation/linkingConfig.js | 402 +++++++++--------- 2 files changed, 199 insertions(+), 210 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index 13cd7ebfd27c..4cfb5a9ae82b 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -7,9 +7,9 @@ import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRoot import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator'; import SCREENS from '@src/SCREENS'; import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; +import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; -const loadSidebarScreen = () => require('../../../../pages/home/sidebar/SidebarScreen').default; -const loadPage = () => require('../../../../pages/ErrorPage/NotFoundPage').default; +const loadPage = () => require('../../../../pages/settings/InitialSettingsPage').default; const propTypes = { /* Navigation functions provided by React Navigation */ @@ -28,14 +28,11 @@ function SettingsNavigator({navigation}) { console.log('navigation state', navigation.getState()); - console.log('loadSidebarScreen', loadSidebarScreen, 'not found page', loadPage) - return ( Date: Tue, 21 Nov 2023 16:14:00 +0100 Subject: [PATCH 020/764] add initial state --- .../AppNavigator/Navigators/SettingsNavigator.js | 1 - .../createCustomStackNavigator/CustomRouter.js | 11 ++++++++++- src/libs/Navigation/Navigation.js | 8 +++++++- src/pages/settings/InitialSettingsPage.js | 1 + src/pages/settings/Preferences/PreferencesPage.js | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js index 4cfb5a9ae82b..e1d68e58e973 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/SettingsNavigator.js @@ -7,7 +7,6 @@ import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRoot import createCustomStackNavigator from '@libs/Navigation/AppNavigator/createCustomStackNavigator'; import SCREENS from '@src/SCREENS'; import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; -import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; const loadPage = () => require('../../../../pages/settings/InitialSettingsPage').default; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js index 31bf4a7bb1b5..3a53a54e60ad 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js @@ -70,7 +70,7 @@ const addCentralPaneNavigatorRoute = (state, centralRoute) => { state: { routes: [ { - name: 'SettingsCentralPane', + name: SCREENS.SETTINGS.PREFERENCES, }, ], }, @@ -86,6 +86,15 @@ function CustomRouter(options) { return { ...stackRouter, + getInitialState({routeNames, routeParamList, routeGetIdList}) { + console.log('getInitialState', routeNames, routeParamList, routeGetIdList); + const centralRoute = options.centralRoute(); + const initialState = stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList}); + if (!isAtLeastOneCentralPaneNavigatorInState(initialState, centralRoute) && !options.getIsSmallScreenWidth()) { + addCentralPaneNavigatorRoute(initialState, centralRoute); + } + return initialState; + }, getRehydratedState(partialState, {routeNames, routeParamList}) { const centralRoute = options.centralRoute(); console.log('getRehydratedState', centralRoute); diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index 7a2c61ea7b53..bcf0effa37a4 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -66,7 +66,7 @@ const getActiveRouteIndex = function (route, index) { return getActiveRouteIndex(childActiveRoute, route.state.index || 0); } - if (route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR) { + if (route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR || route.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) { return 0; } @@ -147,6 +147,12 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f navigationRef.current.goBack(); return; } + + if(lastRoute.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) { + console.log('lastRoute', lastRoute); + navigationRef.current.goBack(); + return; + } } if (shouldEnforceFallback || (isFirstRouteInNavigator && fallbackRoute)) { diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index d88105b31360..628ca489fc70 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -388,6 +388,7 @@ function InitialSettingsPage(props) { headerContent={headerContent} headerContainerStyles={[styles.staticHeaderImage, styles.justifyContentCenter]} backgroundColor={theme.PAGE_BACKGROUND_COLORS[SCREENS.SETTINGS.ROOT]} + onBackButtonPress={() => Navigation.goBack()} > {getMenuItems} diff --git a/src/pages/settings/Preferences/PreferencesPage.js b/src/pages/settings/Preferences/PreferencesPage.js index 4dbc5fda9198..5c056385dd2d 100755 --- a/src/pages/settings/Preferences/PreferencesPage.js +++ b/src/pages/settings/Preferences/PreferencesPage.js @@ -45,7 +45,7 @@ function PreferencesPage(props) { return ( Navigation.goBack(ROUTES.SETTINGS)} + shouldShowBackButton={false} backgroundColor={theme.PAGE_BACKGROUND_COLORS[SCREENS.SETTINGS.PREFERENCES]} illustration={LottieAnimations.PreferencesDJ} > From 6b1dee1cfb3ce68b8bb9c3a4283d3dee3f9db837 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 21 Nov 2023 16:44:04 +0100 Subject: [PATCH 021/764] few fixes --- src/SCREENS.ts | 1 + .../AppNavigator/ModalStackNavigators.js | 6 +++--- .../CustomRouter.js | 2 +- src/libs/Navigation/Navigation.js | 21 ++++++++++++++----- src/libs/Navigation/linkingConfig.js | 5 +---- .../sidebar/PressableAvatarWithIndicator.js | 2 +- src/pages/settings/InitialSettingsPage.js | 7 ++++++- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index b7def3ce8e23..6ef776ef4507 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -21,6 +21,7 @@ export default { SETTINGS: { ROOT: 'Settings_Root', PREFERENCES: 'Settings_Preferences', + PROFILE: 'Settings_Profile', WORKSPACES: 'Settings_Workspaces', SECURITY: 'Settings_Security', STATUS: 'Settings_Status', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index a2f9bdd7a903..1368f12a0213 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -1,4 +1,4 @@ -import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; +import {createStackNavigator} from '@react-navigation/stack'; import React from 'react'; import _ from 'underscore'; import styles from '@styles/styles'; @@ -7,7 +7,8 @@ import SCREENS from '@src/SCREENS'; const defaultSubRouteOptions = { cardStyle: styles.navigationScreenCardStyle, headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, + // TODO: Can remove it + // cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, }; /** @@ -131,7 +132,6 @@ const NewTeachersUniteNavigator = createModalStackNavigator({ }); const SettingsModalStackNavigator = createModalStackNavigator({ - [SCREENS.SETTINGS.ROOT]: () => require('../../../pages/settings/InitialSettingsPage').default, Settings_Share_Code: () => require('../../../pages/ShareCodePage').default, [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../pages/workspace/WorkspacesListPage').default, Settings_Profile: () => require('../../../pages/settings/Profile/ProfilePage').default, diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js index 3a53a54e60ad..5ac04ab884a4 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js @@ -70,7 +70,7 @@ const addCentralPaneNavigatorRoute = (state, centralRoute) => { state: { routes: [ { - name: SCREENS.SETTINGS.PREFERENCES, + name: SCREENS.SETTINGS.PROFILE, }, ], }, diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index bcf0effa37a4..da5e8fbaecf0 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -121,6 +121,7 @@ function navigate(route = ROUTES.HOME, type) { * @param {Boolean} shouldPopToTop - Should we navigate to LHN on back press */ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = false) { + console.log('goBack', 1, navigationRef.current.state); if (!canNavigate('goBack')) { return; } @@ -132,14 +133,17 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f return; } } + console.log('goBack', 2); if (!navigationRef.current.canGoBack()) { Log.hmmm('[Navigation] Unable to go back'); return; } + console.log('goBack', 3); const isFirstRouteInNavigator = !getActiveRouteIndex(navigationRef.current.getState()); if (isFirstRouteInNavigator) { + console.log('goBack', 4); const rootState = navigationRef.getRootState(); const lastRoute = _.last(rootState.routes); // If the user comes from a different flow (there is more than one route in RHP) we should go back to the previous flow on UP button press instead of using the fallbackRoute. @@ -148,18 +152,21 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f return; } - if(lastRoute.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) { - console.log('lastRoute', lastRoute); - navigationRef.current.goBack(); - return; - } + // if(lastRoute.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) { + // console.log('lastRoute', lastRoute); + // navigationRef.current.goBack(); + // return; + // } } + console.log('goBack', 5); if (shouldEnforceFallback || (isFirstRouteInNavigator && fallbackRoute)) { navigate(fallbackRoute, CONST.NAVIGATION.TYPE.UP); return; } + console.log('goBack', 6); + const isCentralPaneFocused = findFocusedRoute(navigationRef.current.getState()).name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR; const distanceFromPathInRootNavigator = getDistanceFromPathInRootNavigator(fallbackRoute); @@ -169,6 +176,8 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f return; } + console.log('goBack', 7); + // Add posibility to go back more than one screen in root navigator if that screen is on the stack. if (isCentralPaneFocused && fallbackRoute && distanceFromPathInRootNavigator > 0) { navigationRef.current.dispatch(StackActions.pop(distanceFromPathInRootNavigator)); @@ -176,6 +185,8 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f } navigationRef.current.goBack(); + + console.log('goBack', 8); } /** diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 63f97f0fe6f8..8b745639147e 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -234,9 +234,6 @@ export default { }, SettingsCentralPane: { screens: { - [SCREENS.SETTINGS.ROOT]: { - path: ROUTES.SETTINGS, - }, [SCREENS.SETTINGS.WORKSPACES]: { path: ROUTES.SETTINGS_WORKSPACES, exact: true, @@ -309,7 +306,7 @@ export default { path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT, exact: true, }, - Settings_Profile: { + [SCREENS.SETTINGS.PROFILE]: { path: ROUTES.SETTINGS_PROFILE, exact: true, }, diff --git a/src/pages/home/sidebar/PressableAvatarWithIndicator.js b/src/pages/home/sidebar/PressableAvatarWithIndicator.js index ddf89321b680..ec2f48cc6a91 100644 --- a/src/pages/home/sidebar/PressableAvatarWithIndicator.js +++ b/src/pages/home/sidebar/PressableAvatarWithIndicator.js @@ -46,7 +46,7 @@ function PressableAvatarWithIndicator({isCreateMenuOpen, currentUserPersonalDeta return; } - Navigation.navigate(ROUTES.SETTINGS); + Navigation.navigate(ROUTES.SETTINGS_HOME); }, [isCreateMenuOpen]); return ( diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 628ca489fc70..caccb1438293 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -382,13 +382,18 @@ function InitialSettingsPage(props) { ); + const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.HOME); + return ( Navigation.goBack()} + onBackButtonPress={() => { + console.log('navigateBackTo', navigateBackTo); + Navigation.goBack(navigateBackTo) + }} > {getMenuItems} From 8703e12c99f6c7bb3dba18e242c65ad2bf9b49ec Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 23 Nov 2023 09:38:07 +0100 Subject: [PATCH 022/764] fix closing settings --- src/pages/settings/InitialSettingsPage.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index caccb1438293..1ca111d205a0 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -390,10 +390,7 @@ function InitialSettingsPage(props) { headerContent={headerContent} headerContainerStyles={[styles.staticHeaderImage, styles.justifyContentCenter]} backgroundColor={theme.PAGE_BACKGROUND_COLORS[SCREENS.SETTINGS.ROOT]} - onBackButtonPress={() => { - console.log('navigateBackTo', navigateBackTo); - Navigation.goBack(navigateBackTo) - }} + onBackButtonPress={() => Navigation.navigate(navigateBackTo)} > {getMenuItems} From 248d664e47bd8c6234b7c63d868d2b9054903c27 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 23 Nov 2023 09:41:10 +0100 Subject: [PATCH 023/764] revert --- src/pages/settings/Preferences/PreferencesPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/settings/Preferences/PreferencesPage.js b/src/pages/settings/Preferences/PreferencesPage.js index 5c056385dd2d..0c02fe9772fb 100755 --- a/src/pages/settings/Preferences/PreferencesPage.js +++ b/src/pages/settings/Preferences/PreferencesPage.js @@ -45,7 +45,6 @@ function PreferencesPage(props) { return ( From a5ce5bfac7db7f8aca2c0d721f96b5cd8c13db74 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 23 Nov 2023 09:57:55 +0100 Subject: [PATCH 024/764] fix deeplink --- .../CustomRouter.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js index 5ac04ab884a4..36faa6816c86 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js @@ -9,10 +9,7 @@ import SCREENS from '@src/SCREENS'; * @param {String} centralRoute - name of the central route * @returns {Boolean} */ -const isAtLeastOneCentralPaneNavigatorInState = (state, centralRoute) => { - console.log('isAtLeastOneCentralPaneNavigatorInState', centralRoute); - return _.find(state.routes, (r) => r.name === centralRoute) -}; +const isAtLeastOneCentralPaneNavigatorInState = (state, centralRoute) => _.find(state.routes, (r) => r.name === centralRoute); /** * @param {Object} state - react-navigation state @@ -48,9 +45,9 @@ const getTopMostReportIDFromRHP = (state) => { * @param {String} centralRoute - name of the central route */ const addCentralPaneNavigatorRoute = (state, centralRoute) => { - const reportID = getTopMostReportIDFromRHP(state); let centralPaneNavigatorRoute; if (centralRoute === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { + const reportID = getTopMostReportIDFromRHP(state); centralPaneNavigatorRoute = { name: NAVIGATORS.CENTRAL_PANE_NAVIGATOR, state: { @@ -81,6 +78,17 @@ const addCentralPaneNavigatorRoute = (state, centralRoute) => { state.index = state.routes.length - 1; }; +const addLHPRoute = (state, centralRoute) => { + const settingsHomeRoute = { + name: SCREENS.SETTINGS_HOME, + }; + if (state.routes[0].name !== SCREENS.SETTINGS_HOME && centralRoute === 'SettingsCentralPane') { + state.routes.splice(0, 0, settingsHomeRoute); + // eslint-disable-next-line no-param-reassign + state.index = state.routes.length - 1; + } +} + function CustomRouter(options) { const stackRouter = StackRouter(options); @@ -106,6 +114,7 @@ function CustomRouter(options) { partialState.stale = true; addCentralPaneNavigatorRoute(partialState, centralRoute); } + addLHPRoute(partialState, centralRoute); const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList}); return state; }, From a30391373b3642f9316cc48124231de0952a3a5e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:11:31 +0100 Subject: [PATCH 025/764] add better linking --- src/libs/Navigation/linkingConfig.js | 364 +++++++++++++-------------- 1 file changed, 180 insertions(+), 184 deletions(-) diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 8b745639147e..a3ebd12838be 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -36,6 +36,178 @@ export default { [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: { screens: { + Settings: { + screens: { + Settings_Preferences_PriorityMode: { + path: ROUTES.SETTINGS_PRIORITY_MODE, + exact: true, + }, + Settings_Preferences_Language: { + path: ROUTES.SETTINGS_LANGUAGE, + exact: true, + }, + Settings_Preferences_Theme: { + path: ROUTES.SETTINGS_THEME, + exact: true, + }, + Settings_Close: { + path: ROUTES.SETTINGS_CLOSE, + exact: true, + }, + Settings_Wallet_DomainCards: { + path: ROUTES.SETTINGS_WALLET_DOMAINCARD.route, + exact: true, + }, + Settings_Wallet_ReportVirtualCardFraud: { + path: ROUTES.SETTINGS_REPORT_FRAUD.route, + exact: true, + }, + Settings_Wallet_EnablePayments: { + path: ROUTES.SETTINGS_ENABLE_PAYMENTS, + exact: true, + }, + Settings_Wallet_Transfer_Balance: { + path: ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE, + exact: true, + }, + Settings_Wallet_Choose_Transfer_Account: { + path: ROUTES.SETTINGS_WALLET_CHOOSE_TRANSFER_ACCOUNT, + exact: true, + }, + Settings_ReportCardLostOrDamaged: { + path: ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.route, + exact: true, + }, + Settings_Wallet_Card_Activate: { + path: ROUTES.SETTINGS_WALLET_CARD_ACTIVATE.route, + exact: true, + }, + Settings_Wallet_Cards_Digital_Details_Update_Address: { + path: ROUTES.SETTINGS_WALLET_CARD_DIGITAL_DETAILS_UPDATE_ADDRESS.route, + exact: true, + }, + Settings_Add_Debit_Card: { + path: ROUTES.SETTINGS_ADD_DEBIT_CARD, + exact: true, + }, + Settings_Add_Bank_Account: { + path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT, + exact: true, + }, + Settings_Pronouns: { + path: ROUTES.SETTINGS_PRONOUNS, + exact: true, + }, + Settings_Display_Name: { + path: ROUTES.SETTINGS_DISPLAY_NAME, + exact: true, + }, + Settings_Timezone: { + path: ROUTES.SETTINGS_TIMEZONE, + exact: true, + }, + Settings_Timezone_Select: { + path: ROUTES.SETTINGS_TIMEZONE_SELECT, + exact: true, + }, + Settings_App_Download_Links: { + path: ROUTES.SETTINGS_APP_DOWNLOAD_LINKS, + exact: true, + }, + Settings_ContactMethods: { + path: ROUTES.SETTINGS_CONTACT_METHODS.route, + exact: true, + }, + Settings_ContactMethodDetails: { + path: ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.route, + }, + Settings_Lounge_Access: { + path: ROUTES.SETTINGS_LOUNGE_ACCESS, + }, + Settings_NewContactMethod: { + path: ROUTES.SETTINGS_NEW_CONTACT_METHOD, + exact: true, + }, + Settings_PersonalDetails_Initial: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS, + exact: true, + }, + Settings_PersonalDetails_LegalName: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS_LEGAL_NAME, + exact: true, + }, + Settings_PersonalDetails_DateOfBirth: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH, + exact: true, + }, + Settings_PersonalDetails_Address: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS, + exact: true, + }, + Settings_PersonalDetails_Address_Country: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY.route, + exact: true, + }, + Settings_TwoFactorAuth: { + path: ROUTES.SETTINGS_2FA, + exact: true, + }, + [SCREENS.SETTINGS.STATUS]: { + path: ROUTES.SETTINGS_STATUS, + exact: true, + }, + Settings_Status_Set: { + path: ROUTES.SETTINGS_STATUS_SET, + exact: true, + }, + Workspace_Initial: { + path: ROUTES.WORKSPACE_INITIAL.route, + }, + Workspace_Settings: { + path: ROUTES.WORKSPACE_SETTINGS.route, + }, + Workspace_Settings_Currency: { + path: ROUTES.WORKSPACE_SETTINGS_CURRENCY.route, + }, + Workspace_Card: { + path: ROUTES.WORKSPACE_CARD.route, + }, + Workspace_Reimburse: { + path: ROUTES.WORKSPACE_REIMBURSE.route, + }, + Workspace_RateAndUnit: { + path: ROUTES.WORKSPACE_RATE_AND_UNIT.route, + }, + Workspace_Bills: { + path: ROUTES.WORKSPACE_BILLS.route, + }, + Workspace_Invoices: { + path: ROUTES.WORKSPACE_INVOICES.route, + }, + Workspace_Travel: { + path: ROUTES.WORKSPACE_TRAVEL.route, + }, + Workspace_Members: { + path: ROUTES.WORKSPACE_MEMBERS.route, + }, + Workspace_Invite: { + path: ROUTES.WORKSPACE_INVITE.route, + }, + Workspace_Invite_Message: { + path: ROUTES.WORKSPACE_INVITE_MESSAGE.route, + }, + ReimbursementAccount: { + path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route, + exact: true, + }, + GetAssistance: { + path: ROUTES.GET_ASSISTANCE.route, + }, + KeyboardShortcuts: { + path: ROUTES.KEYBOARD_SHORTCUTS, + }, + } + }, Private_Notes: { screens: { PrivateNotes_View: ROUTES.PRIVATE_NOTES_VIEW.route, @@ -234,28 +406,20 @@ export default { }, SettingsCentralPane: { screens: { - [SCREENS.SETTINGS.WORKSPACES]: { - path: ROUTES.SETTINGS_WORKSPACES, - exact: true, - }, - [SCREENS.SETTINGS.PREFERENCES]: { - path: ROUTES.SETTINGS_PREFERENCES, - exact: true, - }, - Settings_Preferences_PriorityMode: { - path: ROUTES.SETTINGS_PRIORITY_MODE, + Settings_Share_Code: { + path: ROUTES.SETTINGS_SHARE_CODE, exact: true, }, - Settings_Preferences_Language: { - path: ROUTES.SETTINGS_LANGUAGE, + [SCREENS.SETTINGS.WORKSPACES]: { + path: ROUTES.SETTINGS_WORKSPACES, exact: true, }, - Settings_Preferences_Theme: { - path: ROUTES.SETTINGS_THEME, + [SCREENS.SETTINGS.PROFILE]: { + path: ROUTES.SETTINGS_PROFILE, exact: true, }, - Settings_Close: { - path: ROUTES.SETTINGS_CLOSE, + [SCREENS.SETTINGS.PREFERENCES]: { + path: ROUTES.SETTINGS_PREFERENCES, exact: true, }, [SCREENS.SETTINGS.SECURITY]: { @@ -266,180 +430,12 @@ export default { path: ROUTES.SETTINGS_WALLET, exact: true, }, - Settings_Wallet_DomainCards: { - path: ROUTES.SETTINGS_WALLET_DOMAINCARD.route, - exact: true, - }, - Settings_Wallet_ReportVirtualCardFraud: { - path: ROUTES.SETTINGS_REPORT_FRAUD.route, - exact: true, - }, - Settings_Wallet_EnablePayments: { - path: ROUTES.SETTINGS_ENABLE_PAYMENTS, - exact: true, - }, - Settings_Wallet_Transfer_Balance: { - path: ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE, - exact: true, - }, - Settings_Wallet_Choose_Transfer_Account: { - path: ROUTES.SETTINGS_WALLET_CHOOSE_TRANSFER_ACCOUNT, - exact: true, - }, - Settings_ReportCardLostOrDamaged: { - path: ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.route, - exact: true, - }, - Settings_Wallet_Card_Activate: { - path: ROUTES.SETTINGS_WALLET_CARD_ACTIVATE.route, - exact: true, - }, - Settings_Wallet_Cards_Digital_Details_Update_Address: { - path: ROUTES.SETTINGS_WALLET_CARD_DIGITAL_DETAILS_UPDATE_ADDRESS.route, - exact: true, - }, - Settings_Add_Debit_Card: { - path: ROUTES.SETTINGS_ADD_DEBIT_CARD, - exact: true, - }, - Settings_Add_Bank_Account: { - path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE]: { - path: ROUTES.SETTINGS_PROFILE, - exact: true, - }, - Settings_Pronouns: { - path: ROUTES.SETTINGS_PRONOUNS, - exact: true, - }, - Settings_Display_Name: { - path: ROUTES.SETTINGS_DISPLAY_NAME, - exact: true, - }, - Settings_Timezone: { - path: ROUTES.SETTINGS_TIMEZONE, - exact: true, - }, - Settings_Timezone_Select: { - path: ROUTES.SETTINGS_TIMEZONE_SELECT, - exact: true, - }, Settings_About: { path: ROUTES.SETTINGS_ABOUT, exact: true, }, - Settings_App_Download_Links: { - path: ROUTES.SETTINGS_APP_DOWNLOAD_LINKS, - exact: true, - }, - Settings_ContactMethods: { - path: ROUTES.SETTINGS_CONTACT_METHODS.route, - exact: true, - }, - Settings_ContactMethodDetails: { - path: ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.route, - }, - Settings_Lounge_Access: { - path: ROUTES.SETTINGS_LOUNGE_ACCESS, - }, - Settings_NewContactMethod: { - path: ROUTES.SETTINGS_NEW_CONTACT_METHOD, - exact: true, - }, - Settings_PersonalDetails_Initial: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS, - exact: true, - }, - Settings_PersonalDetails_LegalName: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_LEGAL_NAME, - exact: true, - }, - Settings_PersonalDetails_DateOfBirth: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH, - exact: true, - }, - Settings_PersonalDetails_Address: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS, - exact: true, - }, - Settings_PersonalDetails_Address_Country: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY.route, - exact: true, - }, - Settings_TwoFactorAuth: { - path: ROUTES.SETTINGS_2FA, - exact: true, - }, - Settings_Share_Code: { - path: ROUTES.SETTINGS_SHARE_CODE, - exact: true, - }, - [SCREENS.SETTINGS.STATUS]: { - path: ROUTES.SETTINGS_STATUS, - exact: true, - }, - Settings_Status_Set: { - path: ROUTES.SETTINGS_STATUS_SET, - exact: true, - }, - Workspace_Initial: { - path: ROUTES.WORKSPACE_INITIAL.route, - }, - Workspace_Settings: { - path: ROUTES.WORKSPACE_SETTINGS.route, - }, - Workspace_Settings_Currency: { - path: ROUTES.WORKSPACE_SETTINGS_CURRENCY.route, - }, - Workspace_Card: { - path: ROUTES.WORKSPACE_CARD.route, - }, - Workspace_Reimburse: { - path: ROUTES.WORKSPACE_REIMBURSE.route, - }, - Workspace_RateAndUnit: { - path: ROUTES.WORKSPACE_RATE_AND_UNIT.route, - }, - Workspace_Bills: { - path: ROUTES.WORKSPACE_BILLS.route, - }, - Workspace_Invoices: { - path: ROUTES.WORKSPACE_INVOICES.route, - }, - Workspace_Travel: { - path: ROUTES.WORKSPACE_TRAVEL.route, - }, - Workspace_Members: { - path: ROUTES.WORKSPACE_MEMBERS.route, - }, - Workspace_Invite: { - path: ROUTES.WORKSPACE_INVITE.route, - }, - Workspace_Invite_Message: { - path: ROUTES.WORKSPACE_INVITE_MESSAGE.route, - }, - ReimbursementAccount: { - path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route, - exact: true, - }, - GetAssistance: { - path: ROUTES.GET_ASSISTANCE.route, - }, - KeyboardShortcuts: { - path: ROUTES.KEYBOARD_SHORTCUTS, - }, }, }, - // Settings: { - // screens: { - // [SCREENS.SETTINGS_NEW_PROFILE]: { - // path: ROUTES.SETTINGS_NEW_PROFILE, - // exact: true, - // }, - // } - // } }, } }, From f24f917933ccbda3a92e95bd0508932f62684f88 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:30:07 +0100 Subject: [PATCH 026/764] general refactor --- src/components/HeaderWithBackButton/index.js | 7 +++++-- src/pages/ShareCodePage.js | 1 + src/pages/settings/AboutPage/AboutPage.js | 1 + src/pages/settings/Preferences/PreferencesPage.js | 1 + src/pages/settings/Profile/LoungeAccessPage.js | 2 +- src/pages/settings/Profile/ProfilePage.js | 1 + src/pages/settings/Security/SecuritySettingsPage.js | 1 + src/pages/settings/Wallet/WalletPage/WalletPage.js | 1 + src/pages/workspace/WorkspacesListPage.js | 1 + 9 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/HeaderWithBackButton/index.js b/src/components/HeaderWithBackButton/index.js index edb3b8d26831..528ddb3ad310 100755 --- a/src/components/HeaderWithBackButton/index.js +++ b/src/components/HeaderWithBackButton/index.js @@ -1,5 +1,5 @@ import React from 'react'; -import {Keyboard, View} from 'react-native'; +import { Keyboard, View } from 'react-native'; import AvatarWithDisplayName from '@components/AvatarWithDisplayName'; import Header from '@components/Header'; import Icon from '@components/Icon'; @@ -18,6 +18,7 @@ import * as StyleUtils from '@styles/StyleUtils'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +import useWindowDimensions from '@hooks/useWindowDimensions'; import headerWithBackButtonPropTypes from './headerWithBackButtonPropTypes'; function HeaderWithBackButton({ @@ -40,6 +41,7 @@ function HeaderWithBackButton({ shouldShowPinButton = false, shouldShowThreeDotsButton = false, shouldDisableThreeDotsButton = false, + shouldShowBackButtonOnlyOnMobile = false, stepCounter = null, subtitle = '', title = '', @@ -59,6 +61,7 @@ function HeaderWithBackButton({ const {translate} = useLocalize(); const {isKeyboardShown} = useKeyboardState(); const waitForNavigate = useWaitForNavigation(); + const {isSmallScreenWidth} = useWindowDimensions(); return ( - {shouldShowBackButton && ( + {shouldShowBackButton && (!shouldShowBackButtonOnlyOnMobile || isSmallScreenWidth) && ( { diff --git a/src/pages/ShareCodePage.js b/src/pages/ShareCodePage.js index d8322b8c58d5..05a3578557f4 100644 --- a/src/pages/ShareCodePage.js +++ b/src/pages/ShareCodePage.js @@ -82,6 +82,7 @@ class ShareCodePage extends React.Component { Navigation.goBack(isReport ? ROUTES.REPORT_WITH_ID_DETAILS.getRoute(this.props.report.reportID) : ROUTES.SETTINGS)} + shouldShowBackButtonOnlyOnMobile /> diff --git a/src/pages/settings/AboutPage/AboutPage.js b/src/pages/settings/AboutPage/AboutPage.js index a88a07117f08..59adb9a7befc 100644 --- a/src/pages/settings/AboutPage/AboutPage.js +++ b/src/pages/settings/AboutPage/AboutPage.js @@ -104,6 +104,7 @@ function AboutPage(props) { Navigation.goBack(ROUTES.SETTINGS)} + shouldShowBackButtonOnlyOnMobile /> diff --git a/src/pages/settings/Preferences/PreferencesPage.js b/src/pages/settings/Preferences/PreferencesPage.js index 0c02fe9772fb..cf2aee9d930d 100755 --- a/src/pages/settings/Preferences/PreferencesPage.js +++ b/src/pages/settings/Preferences/PreferencesPage.js @@ -47,6 +47,7 @@ function PreferencesPage(props) { title={translate('common.preferences')} backgroundColor={theme.PAGE_BACKGROUND_COLORS[SCREENS.SETTINGS.PREFERENCES]} illustration={LottieAnimations.PreferencesDJ} + shouldShowBackButtonOnlyOnMobile > Navigation.goBack(ROUTES.SETTINGS)} + onBackButtonPress={() => Navigation.goBack(ROUTES)} illustration={LottieAnimations.ExpensifyLounge} > Navigation.goBack(ROUTES.SETTINGS)} + shouldShowBackButtonOnlyOnMobile /> diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js index 23d4112eea21..2a6ae9dc7105 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.js +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js @@ -326,6 +326,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen Navigation.goBack(ROUTES.SETTINGS)} + shouldShowBackButtonOnlyOnMobile /> diff --git a/src/pages/workspace/WorkspacesListPage.js b/src/pages/workspace/WorkspacesListPage.js index dc0c6d8b3043..dbb73d9dd300 100755 --- a/src/pages/workspace/WorkspacesListPage.js +++ b/src/pages/workspace/WorkspacesListPage.js @@ -189,6 +189,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, u illustration={LottieAnimations.WorkspacePlanet} onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS)} title={translate('common.workspaces')} + shouldShowBackButtonOnlyOnMobile footer={ ",showToastMessageOnCopy:!1,toastMessage:"Code copied to clipboard",toastDuration:3e3}},o={...e,...t,copyToClipboardSettings:{...e.copyToClipboardSettings,...t.copyToClipboardSettings}},c=document.querySelectorAll("ul.tab > li > a");if(Array.prototype.forEach.call(c,(t=>{t.addEventListener("click",(e=>{e.preventDefault(),s(t),o.activateTabFromUrl&&n(t),o.syncTabsWithSameLabels&&l(t)}),!1)})),o.addCopyToClipboardButtons){const t=o.copyToClipboardSettings;r(t),t.showToastMessageOnCopy&&i(t.toastMessage)}o.activateTabFromUrl&&a()}}},925:(t,e,o)=>{const{getChildPosition:a,createElementFromHTML:n,findElementsWithTextContent:s,addClass:r}=o(918),l=t=>{const e=t.querySelectorAll("ul > li");Array.prototype.forEach.call(e,(t=>{t.classList.remove("active")}))},i=t=>{const e=t.parentNode,o=e.parentNode,n=a(e);if(e.className.includes("active"))return;const s=o.getAttribute("data-tab");if(!s)return;const r=document.getElementById(s);l(o),l(r),r.querySelectorAll("ul.tab-content > li")[n].classList.add("active"),e.classList.add("active")},c=(t,e)=>{if(navigator.clipboard&&window.isSecureContext)navigator.clipboard.writeText(t);else{const e=document.createElement("textarea");e.value=t,e.style.position="absolute",e.style.left="-999999px",document.body.prepend(e),e.select();try{document.execCommand("copy")}catch(t){console.error(t)}finally{e.remove()}}"function"==typeof e&&e()},d=t=>{r(document.getElementById("jekyll-tabs-copy-to-clipboard-message"),"show",t)};t.exports={removeActiveClasses:l,handleTabClicked:i,copyToClipboard:c,addCopyToClipboardButtons:({buttonHTML:t,showToastMessageOnCopy:e,toastDuration:o})=>{const a=document.querySelectorAll("ul.tab-content > li pre");for(let s=0;s{d(o)}),i.addEventListener("click",(()=>{c(r.innerText,p)}))}},activateTabFromUrl:()=>{const t=window.location.hash?.substring(1);if(!t)return;const e=document.getElementById(t);if(!e)return;const o=new URLSearchParams(window.location.search).get("active_tab");if(!o)return;const a=e.querySelector("li#"+o+" > a");a&&i(a)},updateUrlWithActiveTab:t=>{const e=t.parentNode,o=e.parentNode,a=new URLSearchParams(window.location.search);a.set("active_tab",e.id);const n=window.location.pathname+"?"+a.toString()+"#"+o.id;history.replaceState(null,"",n)},syncTabsWithSameLabels:t=>{const e=s("a",t.textContent);for(let o=0;o{const e=document.createElement("div");e.id="jekyll-tabs-copy-to-clipboard-message",e.textContent=t,document.getElementsByTagName("body")[0].appendChild(e)}}}},e={},function o(a){var n=e[a];if(void 0!==n)return n.exports;var s=e[a]={exports:{}};return t[a](s,s.exports,o),s.exports}(613);var t,e})); - -window.addEventListener('load', function () { - jekyllTabs.init({ - syncTabsWithSameLabels: true, - }); -}); From 1891c00f10b734f45dbbeb0ad652c73a6bd9e9dd Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 01:44:48 +0530 Subject: [PATCH 575/764] rm whitespace --- docs/_config.yml | 1 - .../deposit-accounts/Deposit-Accounts-USD.md | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index b68bcdf8a1f3..888f0b24a91e 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -20,6 +20,5 @@ plugins: - jekyll-seo-tag - jekyll-redirect-from - whitelist: - jekyll-redirect-from diff --git a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/deposit-accounts/Deposit-Accounts-USD.md b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/deposit-accounts/Deposit-Accounts-USD.md index 8880e923ce3b..0bc5cb0ad955 100644 --- a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/deposit-accounts/Deposit-Accounts-USD.md +++ b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/deposit-accounts/Deposit-Accounts-USD.md @@ -2,7 +2,6 @@ title: Deposit Accounts - USD description: How to add a deposit account to receive payments for yourself or your business (US) --- - # Overview There are two types of deposit-only accounts: @@ -75,4 +74,4 @@ There are a few reasons a reimbursement may be unsuccessful. The first step is t If you aren’t sure, please reach out to Concierge and we can assist! -{% include faq-end.md %} \ No newline at end of file +{% include faq-end.md %} From f3e572665d7f48ade61db8f8bfdb59318134241f Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:15:23 +0530 Subject: [PATCH 576/764] fix lint --- docs/assets/js/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index 14f455247dd0..69252be6d33c 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -232,6 +232,7 @@ window.addEventListener('DOMContentLoaded', () => { }); } + // eslint-disable-line es/no-optional-chaining expensifyClassicTab?.addEventListener('click', () => { expensifyClassicTab.classList.add('active'); expensifyClassicContent.classList.remove('hidden'); @@ -244,13 +245,13 @@ window.addEventListener('DOMContentLoaded', () => { }); }); + // eslint-disable-line es/no-optional-chaining newExpensifyTab?.addEventListener('click', () => { newExpensifyTab.classList.add('active'); newExpensifyContent.classList.remove('hidden'); expensifyClassicTab.classList.remove('active'); expensifyClassicContent.classList.add('hidden'); - active = '#new-expensify'; window.tocbot.refresh({ ...tocbotOptions, contentSelector: '#new-expensify' From 8c4c1766d971a9c1a343a7904155c52c68e2d5eb Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:16:29 +0530 Subject: [PATCH 577/764] fix lint --- docs/assets/js/platform-tabs.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/assets/js/platform-tabs.js b/docs/assets/js/platform-tabs.js index d49d898517c4..97e6efc554e2 100644 --- a/docs/assets/js/platform-tabs.js +++ b/docs/assets/js/platform-tabs.js @@ -1,6 +1,3 @@ -const expensifyClassic = document.getElementById('platform-tab-expensify-classic'); -const newExpensify = document.getElementById('platform-tab-new-expensify'); - const expensifyClassicContent = document.getElementById('expensify-classic'); const newExpensifyContent = document.getElementById('new-expensify'); From 889c4bbbd1539c3470ccc50f3608fa1934a8b060 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:22:31 +0530 Subject: [PATCH 578/764] fix lint --- docs/assets/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index 69252be6d33c..caafd0ac1c67 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -232,7 +232,7 @@ window.addEventListener('DOMContentLoaded', () => { }); } - // eslint-disable-line es/no-optional-chaining + // eslint-disable-next-line es/no-optional-chaining expensifyClassicTab?.addEventListener('click', () => { expensifyClassicTab.classList.add('active'); expensifyClassicContent.classList.remove('hidden'); @@ -245,7 +245,7 @@ window.addEventListener('DOMContentLoaded', () => { }); }); - // eslint-disable-line es/no-optional-chaining + // eslint-disable-next-line es/no-optional-chaining newExpensifyTab?.addEventListener('click', () => { newExpensifyTab.classList.add('active'); newExpensifyContent.classList.remove('hidden'); From 5771cf87191d3edfa2c9161210a3cfe56e5e7cb8 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:31:59 +0530 Subject: [PATCH 579/764] add breakpoint for mobile --- docs/_sass/_main.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index 1c0728b152ea..a238b3d0f7f3 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -853,6 +853,11 @@ button { h1 { padding: 0; } + + @include maxBreakpoint($breakpoint-tablet) { + flex-direction: column; + gap: 20px; + } } #platform-tabs { From 97a7a4c01269ccf331ef479dbd4124a2bde93343 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:41:39 +0530 Subject: [PATCH 580/764] fix lint --- docs/assets/js/main.js | 46 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index caafd0ac1c67..31c480bb8aaf 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -232,31 +232,33 @@ window.addEventListener('DOMContentLoaded', () => { }); } - // eslint-disable-next-line es/no-optional-chaining - expensifyClassicTab?.addEventListener('click', () => { - expensifyClassicTab.classList.add('active'); - expensifyClassicContent.classList.remove('hidden'); - - newExpensifyTab.classList.remove('active'); - newExpensifyContent.classList.add('hidden'); - window.tocbot.refresh({ - ...tocbotOptions, - contentSelector: '#expensify-classic' + if (expensifyClassicTab) { + expensifyClassicTab.addEventListener('click', () => { + expensifyClassicTab.classList.add('active'); + expensifyClassicContent.classList.remove('hidden'); + + newExpensifyTab.classList.remove('active'); + newExpensifyContent.classList.add('hidden'); + window.tocbot.refresh({ + ...tocbotOptions, + contentSelector: '#expensify-classic' + }); }); - }); + } - // eslint-disable-next-line es/no-optional-chaining - newExpensifyTab?.addEventListener('click', () => { - newExpensifyTab.classList.add('active'); - newExpensifyContent.classList.remove('hidden'); - - expensifyClassicTab.classList.remove('active'); - expensifyClassicContent.classList.add('hidden'); - window.tocbot.refresh({ - ...tocbotOptions, - contentSelector: '#new-expensify' + if (newExpensifyTab) { + newExpensifyTab.addEventListener('click', () => { + newExpensifyTab.classList.add('active'); + newExpensifyContent.classList.remove('hidden'); + + expensifyClassicTab.classList.remove('active'); + expensifyClassicContent.classList.add('hidden'); + window.tocbot.refresh({ + ...tocbotOptions, + contentSelector: '#new-expensify' + }); }); - }); + } document.getElementById('header-button').addEventListener('click', toggleHeaderMenu); From b914b57684e3c40d67f19656e27c0b46287fa07b Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:43:02 +0530 Subject: [PATCH 581/764] Revert "fix lint" This reverts commit 97a7a4c01269ccf331ef479dbd4124a2bde93343. --- docs/assets/js/main.js | 46 ++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index 31c480bb8aaf..caafd0ac1c67 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -232,33 +232,31 @@ window.addEventListener('DOMContentLoaded', () => { }); } - if (expensifyClassicTab) { - expensifyClassicTab.addEventListener('click', () => { - expensifyClassicTab.classList.add('active'); - expensifyClassicContent.classList.remove('hidden'); - - newExpensifyTab.classList.remove('active'); - newExpensifyContent.classList.add('hidden'); - window.tocbot.refresh({ - ...tocbotOptions, - contentSelector: '#expensify-classic' - }); + // eslint-disable-next-line es/no-optional-chaining + expensifyClassicTab?.addEventListener('click', () => { + expensifyClassicTab.classList.add('active'); + expensifyClassicContent.classList.remove('hidden'); + + newExpensifyTab.classList.remove('active'); + newExpensifyContent.classList.add('hidden'); + window.tocbot.refresh({ + ...tocbotOptions, + contentSelector: '#expensify-classic' }); - } + }); - if (newExpensifyTab) { - newExpensifyTab.addEventListener('click', () => { - newExpensifyTab.classList.add('active'); - newExpensifyContent.classList.remove('hidden'); - - expensifyClassicTab.classList.remove('active'); - expensifyClassicContent.classList.add('hidden'); - window.tocbot.refresh({ - ...tocbotOptions, - contentSelector: '#new-expensify' - }); + // eslint-disable-next-line es/no-optional-chaining + newExpensifyTab?.addEventListener('click', () => { + newExpensifyTab.classList.add('active'); + newExpensifyContent.classList.remove('hidden'); + + expensifyClassicTab.classList.remove('active'); + expensifyClassicContent.classList.add('hidden'); + window.tocbot.refresh({ + ...tocbotOptions, + contentSelector: '#new-expensify' }); - } + }); document.getElementById('header-button').addEventListener('click', toggleHeaderMenu); From bee81409c5f996f08af54285db5b336d2bd18567 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 02:43:42 +0530 Subject: [PATCH 582/764] run prettier --- docs/assets/js/main.js | 14 +++++++------- docs/assets/js/platform-tabs.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index caafd0ac1c67..473bd544c7b8 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -194,7 +194,7 @@ const tocbotOptions = { // If there is a fixed article scroll container, set to calculate titles' offset scrollContainer: 'content-area', -} +}; window.addEventListener('DOMContentLoaded', () => { injectFooterCopywrite(); @@ -212,14 +212,14 @@ window.addEventListener('DOMContentLoaded', () => { const expensifyClassicTab = document.getElementById('platform-tab-expensify-classic'); const newExpensifyTab = document.getElementById('platform-tab-new-expensify'); - + const expensifyClassicContent = document.getElementById('expensify-classic'); const newExpensifyContent = document.getElementById('new-expensify'); let contentSelector; if (expensifyClassicContent) { contentSelector = '#expensify-classic'; - } else if(newExpensifyContent) { + } else if (newExpensifyContent) { contentSelector = '#new-expensify'; } else { contentSelector = '.article-toc-content'; @@ -236,12 +236,12 @@ window.addEventListener('DOMContentLoaded', () => { expensifyClassicTab?.addEventListener('click', () => { expensifyClassicTab.classList.add('active'); expensifyClassicContent.classList.remove('hidden'); - + newExpensifyTab.classList.remove('active'); newExpensifyContent.classList.add('hidden'); window.tocbot.refresh({ ...tocbotOptions, - contentSelector: '#expensify-classic' + contentSelector: '#expensify-classic', }); }); @@ -249,12 +249,12 @@ window.addEventListener('DOMContentLoaded', () => { newExpensifyTab?.addEventListener('click', () => { newExpensifyTab.classList.add('active'); newExpensifyContent.classList.remove('hidden'); - + expensifyClassicTab.classList.remove('active'); expensifyClassicContent.classList.add('hidden'); window.tocbot.refresh({ ...tocbotOptions, - contentSelector: '#new-expensify' + contentSelector: '#new-expensify', }); }); diff --git a/docs/assets/js/platform-tabs.js b/docs/assets/js/platform-tabs.js index 97e6efc554e2..d9890fde9d25 100644 --- a/docs/assets/js/platform-tabs.js +++ b/docs/assets/js/platform-tabs.js @@ -17,7 +17,7 @@ if (newExpensifyContent) { tab.id = 'platform-tab-new-expensify'; if (!expensifyClassicContent) { - tab.classList.add('active'); + tab.classList.add('active'); } platformTabs.appendChild(tab); } From aaeefdcf3f53a53dbe6bcbab100b631a0bfec577 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 05:02:00 +0530 Subject: [PATCH 583/764] add gap b/w buttons --- docs/_sass/_main.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index a238b3d0f7f3..0689c1b39b56 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -867,6 +867,7 @@ button { text-align: center; font-weight: 700; font-size: 13px; + gap: 4px; } #platform-tabs > * { From 687ae7a6813b3053c06a11bcf865ed2f7e3874f5 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 05:03:56 +0530 Subject: [PATCH 584/764] fix case --- docs/assets/js/platform-tabs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/assets/js/platform-tabs.js b/docs/assets/js/platform-tabs.js index d9890fde9d25..18746efc5a84 100644 --- a/docs/assets/js/platform-tabs.js +++ b/docs/assets/js/platform-tabs.js @@ -5,7 +5,7 @@ const platformTabs = document.getElementById('platform-tabs'); if (expensifyClassicContent) { const tab = document.createElement('div'); - tab.innerHTML = 'Expensify classic'; + tab.innerHTML = 'Expensify Classic'; tab.id = 'platform-tab-expensify-classic'; tab.classList.add('active'); platformTabs.appendChild(tab); @@ -13,7 +13,7 @@ if (expensifyClassicContent) { if (newExpensifyContent) { const tab = document.createElement('div'); - tab.innerHTML = 'New expensify'; + tab.innerHTML = 'New Expensify'; tab.id = 'platform-tab-new-expensify'; if (!expensifyClassicContent) { From 72ead7ba41d8a2c74d9a3302fc68baa6783d1338 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 06:07:39 +0530 Subject: [PATCH 585/764] handle long titles --- docs/_sass/_main.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index 0689c1b39b56..f0713796b68e 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -350,6 +350,7 @@ button { h1 { &.title { font-size: 2.25em; + flex: 1; } } @@ -873,7 +874,7 @@ button { #platform-tabs > * { cursor: pointer; border-radius: 20px; - padding: 10px 20px; + padding: 9px 20px; } #platform-tabs > .active { From 47c20b94928ba2ebf58f3d47d5cb66e50f6dc495 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 06:11:28 +0530 Subject: [PATCH 586/764] fix color --- docs/_sass/_main.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index f0713796b68e..d4ab85a2fa41 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -878,6 +878,6 @@ button { } #platform-tabs > .active { - color:#fff; - background-color: #1A3D32; + color: $color-text; + background-color: $color-button-background; } From a8468c7568fdf60dcbf5211f74d2ab12ae91965a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 30 Jan 2024 06:24:13 +0530 Subject: [PATCH 587/764] fix button size --- docs/_sass/_main.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index d4ab85a2fa41..fc95a9cce7f0 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -874,7 +874,10 @@ button { #platform-tabs > * { cursor: pointer; border-radius: 20px; - padding: 9px 20px; + padding: 10px 20px; + box-sizing: border-box; + height: 36px; + line-height: 16px; } #platform-tabs > .active { From 4be5bb247457315d805d5674f46a29663013da9d Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 30 Jan 2024 11:15:22 +0800 Subject: [PATCH 588/764] don't apply the hovered color when the option is focused --- src/components/OptionRow.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/OptionRow.tsx b/src/components/OptionRow.tsx index 97e85cacf42d..8cba73a11b5d 100644 --- a/src/components/OptionRow.tsx +++ b/src/components/OptionRow.tsx @@ -209,14 +209,14 @@ function OptionRow({ ) : ( ))} From 56d5d2c717e0da30066fee5eda7f0da605fbf50e Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 30 Jan 2024 14:29:28 +0700 Subject: [PATCH 589/764] refactor logic --- src/libs/ReportActionsUtils.ts | 5 ++++- src/libs/ReportUtils.ts | 22 +++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index b0f66ee6a99a..ba93d8169dab 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -806,6 +806,9 @@ function hasRequestFromCurrentAccount(reportID: string, currentAccountID: number return reportActions.some((action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && action.actorAccountID === currentAccountID); } +/** + * @private + */ function isReportActionUnread(reportAction: OnyxEntry, lastReadTime: string) { if (!lastReadTime) { return Boolean(!isCreatedAction(reportAction)); @@ -815,7 +818,7 @@ function isReportActionUnread(reportAction: OnyxEntry, lastReadTim } /** - * Check whether the report action of the report is unread or not + * Check whether the current report action of the report is unread or not * */ function isCurrentActionUnread(report: Report | EmptyObject, reportAction: ReportAction, reportActions: ReportActions): boolean { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 960ad55537ea..2646f6c36051 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -12,7 +12,7 @@ import * as Expensicons from '@components/Icon/Expensicons'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; import CONST from '@src/CONST'; import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; -import ONYXKEYS from '@src/ONYXKEYS'; +import ONYXKEYS, { OnyxCollectionKey } from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Beta, PersonalDetails, PersonalDetailsList, Policy, PolicyReportField, Report, ReportAction, ReportMetadata, Session, Transaction, TransactionViolation} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; @@ -4613,34 +4613,38 @@ function getAllAncestorReportActions( if (!report) { return []; } - const convertReports: OnyxCollection = {}; - const convertReportActions: OnyxCollection = {}; + const convertedReports: OnyxCollection = {}; + const convertedReportActions: OnyxCollection = {}; Object.values(reports ?? {}).forEach((itemReport) => { if (!itemReport) { return; } - convertReports[itemReport.reportID] = itemReport; + convertedReports[itemReport.reportID] = itemReport; }); Object.keys(reportActions ?? {}).forEach((actionKey) => { if (!actionKey) { return; } - const reportID = CollectionUtils.extractCollectionItemID(actionKey as `reportActions_${string}`); - convertReportActions[reportID] = reportActions?.[actionKey] ?? null; + const reportID = CollectionUtils.extractCollectionItemID(actionKey as `${OnyxCollectionKey}${string}`); + convertedReportActions[reportID] = reportActions?.[actionKey] ?? null; }); const allAncestors: Ancestor[] = []; let parentReportID = report.parentReportID; let parentReportActionID = report.parentReportActionID; + // Store the child of parent report let currentReport = report; let currentUnread = shouldHideThreadDividerLine; + while (parentReportID) { - const parentReport = convertReports?.[parentReportID]; - const parentReportAction = convertReportActions?.[parentReportID]?.[parentReportActionID ?? ''] ?? null; + const parentReport = convertedReports?.[parentReportID]; + const parentReportAction = convertedReportActions?.[parentReportID]?.[parentReportActionID ?? ''] ?? null; + if (!parentReportAction || ReportActionsUtils.isTransactionThread(parentReportAction) || !parentReport) { break; } - const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport, parentReportAction, convertReportActions?.[parentReportID] ?? {}); + + const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport, parentReportAction, convertedReportActions?.[parentReportID] ?? {}); allAncestors.push({ report: currentReport, reportAction: parentReportAction, From 84071e878eea68cbcfc224d9ce6a43359f77b53f Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Tue, 30 Jan 2024 09:49:16 +0100 Subject: [PATCH 590/764] Migrate WorkspacesListPage to TS --- ...acesListPage.js => WorkspacesListPage.tsx} | 228 +++++++++--------- src/pages/workspace/WorkspacesListRow.tsx | 4 +- 2 files changed, 118 insertions(+), 114 deletions(-) rename src/pages/workspace/{WorkspacesListPage.js => WorkspacesListPage.tsx} (66%) diff --git a/src/pages/workspace/WorkspacesListPage.js b/src/pages/workspace/WorkspacesListPage.tsx similarity index 66% rename from src/pages/workspace/WorkspacesListPage.js rename to src/pages/workspace/WorkspacesListPage.tsx index addd8c3c5e38..142571e23679 100755 --- a/src/pages/workspace/WorkspacesListPage.js +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -1,8 +1,8 @@ -import PropTypes from 'prop-types'; import React, {useCallback, useMemo, useState} from 'react'; import {FlatList, ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import Button from '@components/Button'; import ConfirmModal from '@components/ConfirmModal'; import FeatureList from '@components/FeatureList'; @@ -10,7 +10,9 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import LottieAnimations from '@components/LottieAnimations'; +import type {MenuItemProps} from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; import {PressableWithoutFeedback} from '@components/Pressable'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -19,59 +21,59 @@ import useNetwork from '@hooks/useNetwork'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import policyMemberPropType from '@pages/policyMemberPropType'; -import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import reportPropTypes from '@pages/reportPropTypes'; import * as App from '@userActions/App'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; +import type {PolicyMembers, Policy as PolicyType, ReimbursementAccount, Report} from '@src/types/onyx'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; +import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import WorkspacesListRow from './WorkspacesListRow'; -const propTypes = { - /** The list of this user's policies */ - policies: PropTypes.objectOf( - PropTypes.shape({ - /** The ID of the policy */ - ID: PropTypes.string, +type WorkspaceItem = Required> & + Pick & + Pick & + Pick & { + action: () => void; + dismissError: () => void; + iconType?: ValueOf; + policyID?: string; + adminRoom?: string | null; + announceRoom?: string | null; + }; - /** The name of the policy */ - name: PropTypes.string, +// eslint-disable-next-line react/no-unused-prop-types +type GetMenuItem = {item: WorkspaceItem; index: number}; - /** The type of the policy */ - type: PropTypes.string, +type ChatType = { + adminRoom?: string | null; + announceRoom?: string | null; +}; - /** The user's role in the policy */ - role: PropTypes.string, +type ChatPolicyType = Record; - /** The current action that is waiting to happen on the policy */ - pendingAction: PropTypes.oneOf(_.values(CONST.RED_BRICK_ROAD_PENDING_ACTION)), - }), - ), +type WorkspaceListPageOnyxProps = { + /** The list of this user's policies */ + policies: OnyxCollection; /** Bank account attached to free plan */ - reimbursementAccount: ReimbursementAccountProps.reimbursementAccountPropTypes, + reimbursementAccount: OnyxEntry; /** A collection of objects for all policies which key policy member objects by accountIDs */ - allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)), + allPolicyMembers: OnyxCollection; /** All reports shared with the user (coming from Onyx) */ - reports: PropTypes.objectOf(reportPropTypes), + reports: OnyxCollection; }; -const defaultProps = { - policies: {}, - allPolicyMembers: {}, - reimbursementAccount: {}, - reports: {}, -}; +type WorkspaceListPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceListPageOnyxProps; const workspaceFeatures = [ { @@ -90,11 +92,8 @@ const workspaceFeatures = [ /** * Dismisses the errors on one item - * - * @param {string} policyID - * @param {string} pendingAction */ -function dismissWorkspaceError(policyID, pendingAction) { +function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.PendingAction | undefined) { if (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { Policy.clearDeleteWorkspaceError(policyID); return; @@ -107,8 +106,7 @@ function dismissWorkspaceError(policyID, pendingAction) { throw new Error('Not implemented'); } -// TODO: Rewrite this component to TS according to existing migration on the main branch -function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, reports}) { +function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, reports}: WorkspaceListPageProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -116,21 +114,19 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r const {isSmallScreenWidth} = useWindowDimensions(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); - const [policyIDToDelete, setPolicyIDToDelete] = useState(null); - const [policyNameToDelete, setPolicyNameToDelete] = useState(null); + const [policyIDToDelete, setPolicyIDToDelete] = useState(''); + const [policyNameToDelete, setPolicyNameToDelete] = useState(''); const confirmDeleteAndHideModal = () => { Policy.deleteWorkspace(policyIDToDelete, [], policyNameToDelete); setIsDeleteModalOpen(false); }; + /** * Gets the menu item for each workspace - * - * @param {Object} item - * @returns {JSX} */ const getMenuItem = useCallback( - ({item}) => { + ({item, index}: GetMenuItem) => { const threeDotsMenuItems = [ // Check if the user is an admin of the workspace ...(item.role === CONST.POLICY.ROLE.ADMIN @@ -139,7 +135,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r icon: Expensicons.Trashcan, text: translate('workspace.common.delete'), onSelected: () => { - setPolicyIDToDelete(item.policyID); + setPolicyIDToDelete(item.policyID ?? ''); setPolicyNameToDelete(item.title); setIsDeleteModalOpen(true); }, @@ -147,30 +143,31 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r { icon: Expensicons.Hashtag, text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}), - onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.adminRoom)), + onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.adminRoom ?? '')), }, ] : []), { icon: Expensicons.Hashtag, text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE}), - onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.announceRoom)), + onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.announceRoom ?? '')), }, ]; return ( item.action()} + onPress={item.action} > {({hovered}) => ( - _.reduce( - reports, - (result, report) => { - if (!report || !report.reportID || !report.policyID) { - return result; - } + const policyRooms = useMemo(() => { + if (!reports || isEmptyObject(reports)) { + return; + } - if (!result[report.policyID]) { - // eslint-disable-next-line no-param-reassign - result[report.policyID] = {}; - } + return Object.values(reports).reduce((result, report) => { + if (!report?.reportID || !report.policyID) { + return result; + } - switch (report.chatType) { - case CONST.REPORT.CHAT_TYPE.POLICY_ADMINS: - // eslint-disable-next-line no-param-reassign - result[report.policyID].adminRoom = report.reportID; - break; - case CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE: - // eslint-disable-next-line no-param-reassign - result[report.policyID].announceRoom = report.reportID; - break; - default: - break; - } + if (!result[report.policyID]) { + // eslint-disable-next-line no-param-reassign + result[report.policyID] = {}; + } - return result; - }, - {}, - ), - [reports], - ); + switch (report.chatType) { + case CONST.REPORT.CHAT_TYPE.POLICY_ADMINS: + // eslint-disable-next-line no-param-reassign + result[report.policyID].adminRoom = report.reportID; + break; + case CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE: + // eslint-disable-next-line no-param-reassign + result[report.policyID].announceRoom = report.reportID; + break; + default: + break; + } + + return result; + }, {}); + }, [reports]); /** * Add free policies (workspaces) to the list of menu items and returns the list of menu items - * @returns {Array} the menu item list */ const workspaces = useMemo(() => { - const reimbursementAccountBrickRoadIndicator = !_.isEmpty(reimbursementAccount.errors) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; - return _.chain(policies) - .filter((policy) => PolicyUtils.shouldShowPolicy(policy, isOffline)) - .map((policy) => ({ - title: policy.name, - icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name), - iconType: policy.avatar ? CONST.ICON_TYPE_AVATAR : CONST.ICON_TYPE_ICON, - action: () => Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policy.id)), - iconFill: theme.textLight, - fallbackIcon: Expensicons.FallbackWorkspaceAvatar, - brickRoadIndicator: reimbursementAccountBrickRoadIndicator || PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy, allPolicyMembers), - pendingAction: policy.pendingAction, - errors: policy.errors, - dismissError: () => dismissWorkspaceError(policy.id, policy.pendingAction), - disabled: policy.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - policyID: policy.id, - adminRoom: policyRooms[policy.id] ? policyRooms[policy.id].adminRoom : null, - announceRoom: policyRooms[policy.id] ? policyRooms[policy.id].announceRoom : null, - ownerAccountID: policy.ownerAccountID, - role: policy.role, - })) - .sortBy((policy) => policy.title.toLowerCase()) - .value(); - }, [reimbursementAccount.errors, policies, isOffline, theme.textLight, allPolicyMembers, policyRooms]); + const reimbursementAccountBrickRoadIndicator = reimbursementAccount?.errors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined; + if (isEmptyObject(policies)) { + return []; + } + + return Object.values(policies) + .filter((policy): policy is PolicyType => PolicyUtils.shouldShowPolicy(policy, !!isOffline)) + .map( + (policy): WorkspaceItem => ({ + title: policy.name, + icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name), + action: () => Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policy.id)), + brickRoadIndicator: reimbursementAccountBrickRoadIndicator ?? PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy, allPolicyMembers), + pendingAction: policy.pendingAction, + errors: policy.errors, + dismissError: () => { + if (!policy.pendingAction) { + return; + } + dismissWorkspaceError(policy.id, policy.pendingAction); + }, + disabled: policy.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + iconType: policy.avatar ? CONST.ICON_TYPE_AVATAR : CONST.ICON_TYPE_ICON, + iconFill: theme.textLight, + fallbackIcon: Expensicons.FallbackWorkspaceAvatar, + policyID: policy.id, + adminRoom: policyRooms?.[policy.id] ? policyRooms[policy.id].adminRoom : null, + announceRoom: policyRooms?.[policy.id] ? policyRooms[policy.id].announceRoom : null, + ownerAccountID: policy.ownerAccountID, + role: policy.role, + type: policy.type, + }), + ) + .sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase())); + }, [reimbursementAccount?.errors, policies, isOffline, theme.textLight, allPolicyMembers, policyRooms]); - if (_.isEmpty(workspaces)) { + if (isEmptyObject(workspaces)) { return ( App.createWorkspaceWithPolicyDraftAndNavigateToIt()} + // @ts-expect-error TODO: Remove once FeatureList (https://github.com/Expensify/App/issues/25039) is migrated to TS illustration={LottieAnimations.WorkspacePlanet} illustrationBackgroundColor={theme.PAGE_THEMES[SCREENS.SETTINGS.WORKSPACES].backgroundColor} // We use this style to vertically center the illustration, as the original illustration is not centered @@ -336,6 +342,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r ({ policies: { key: ONYXKEYS.COLLECTION.POLICY, }, @@ -389,5 +393,5 @@ export default compose( reports: { key: ONYXKEYS.COLLECTION.REPORT, }, - }), -)(WorkspacesListPage); + })(WorkspacesListPage), +); diff --git a/src/pages/workspace/WorkspacesListRow.tsx b/src/pages/workspace/WorkspacesListRow.tsx index f2ba9a3e6355..0ef871ecf432 100644 --- a/src/pages/workspace/WorkspacesListRow.tsx +++ b/src/pages/workspace/WorkspacesListRow.tsx @@ -26,8 +26,8 @@ type WorkspacesListRowProps = WithCurrentUserPersonalDetailsProps & { /** Account ID of the workspace's owner */ ownerAccountID?: number; - /** Type of workspace. Type personal is not valid in this context so it's omitted */ - workspaceType: typeof CONST.POLICY.TYPE.FREE | typeof CONST.POLICY.TYPE.CORPORATE | typeof CONST.POLICY.TYPE.TEAM; + /** Type of workspace */ + workspaceType?: ValueOf; /** Icon to show next to the workspace name */ workspaceIcon?: AvatarSource; From 80dc8cb62a85374bdde1b7ef005a991dc0720dfb Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:49:22 +0100 Subject: [PATCH 591/764] fix access to WS overview (188) --- src/pages/workspace/WorkspaceOverviewPage.js | 1 + src/pages/workspace/WorkspacePageWithSections.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/WorkspaceOverviewPage.js b/src/pages/workspace/WorkspaceOverviewPage.js index 7115e1092384..dd3945136c47 100644 --- a/src/pages/workspace/WorkspaceOverviewPage.js +++ b/src/pages/workspace/WorkspaceOverviewPage.js @@ -70,6 +70,7 @@ function WorkspaceOverviewPage({policy, currencyList, route}) { shouldShowLoading={false} shouldUseScrollView shouldShowOfflineIndicatorInWideScreen + shouldShowNonAdmin > {(hasVBA) => ( <> diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 2eadc82b6c28..ce9d82ed9d9d 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -67,6 +67,9 @@ type WorkspacePageWithSectionsProps = WithPolicyAndFullscreenLoadingProps & shouldShowOfflineIndicatorInWideScreen?: boolean; + /** Whether to show this page to non admin policy members */ + shouldShowNonAdmin?: boolean; + /** Policy values needed in the component */ policy: OnyxEntry; }; @@ -94,12 +97,12 @@ function WorkspacePageWithSections({ user, shouldShowLoading = true, shouldShowOfflineIndicatorInWideScreen = false, + shouldShowNonAdmin = false, }: WorkspacePageWithSectionsProps) { const styles = useThemeStyles(); useNetwork({onReconnect: () => fetchData(shouldSkipVBBACall)}); const isLoading = reimbursementAccount?.isLoading ?? true; - const isOverview = route.name; const achState = reimbursementAccount?.achData?.state ?? ''; const isUsingECard = user?.isUsingExpensifyCard ?? false; const policyID = route.params.policyID; @@ -124,9 +127,8 @@ function WorkspacePageWithSections({ return true; } - // TODO - check is the value of isOveriew is correct - return !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy) || !isOverview; - }, [isOverview, policy]); + return (!PolicyUtils.isPolicyAdmin(policy) && !shouldShowNonAdmin) || PolicyUtils.isPendingDeletePolicy(policy); + }, [shouldShowNonAdmin, policy]); return ( Date: Tue, 30 Jan 2024 10:42:41 +0100 Subject: [PATCH 592/764] fix WS switching when non admin (209) --- src/libs/Navigation/switchPolicyID.ts | 7 ++++++- src/libs/Navigation/types.ts | 1 + src/pages/WorkspaceSwitcherPage.js | 5 +++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libs/Navigation/switchPolicyID.ts b/src/libs/Navigation/switchPolicyID.ts index fe3abaaf5546..521045ddb89f 100644 --- a/src/libs/Navigation/switchPolicyID.ts +++ b/src/libs/Navigation/switchPolicyID.ts @@ -60,7 +60,7 @@ function getActionForBottomTabNavigator(action: StackNavigationAction, state: Na }; } -export default function switchPolicyID(navigation: NavigationContainerRef | null, {policyID, route}: switchPolicyIDParams) { +export default function switchPolicyID(navigation: NavigationContainerRef | null, {policyID, route, isPolicyAdmin = true}: switchPolicyIDParams) { if (!navigation) { throw new Error("Couldn't find a navigation object. Is your component inside a screen in a navigator?"); } @@ -119,6 +119,11 @@ export default function switchPolicyID(navigation: NavigationContainerRef { - const policyID = option.policyID; + const {policyID, isPolicyAdmin} = option; if (policyID) { setSelectedOption(option); @@ -121,7 +121,7 @@ function WorkspaceSwitcherPage({policies}) { setActiveWorkspaceID(policyID); Navigation.goBack(); if (policyID !== activeWorkspaceID) { - Navigation.navigateWithSwitchPolicyID({policyID}); + Navigation.navigateWithSwitchPolicyID({policyID, isPolicyAdmin}); } }, []); @@ -147,6 +147,7 @@ function WorkspaceSwitcherPage({policies}) { ], boldStyle: hasUnreadData(policy.id), keyForList: policy.id, + isPolicyAdmin: PolicyUtils.isPolicyAdmin(policy), })) .value(), [policies, getIndicatorTypeForPolicy, hasUnreadData], From 044d52165692e71a2fe2845dbe6e8ca0fea80f57 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 30 Jan 2024 11:10:35 +0100 Subject: [PATCH 593/764] Handle displaying brick roads on the chat button tab --- .../BottomTabBar.tsx | 29 +++++---- src/libs/WorkspacesUtils.ts | 64 ++++++++++++++++--- src/pages/home/sidebar/AllSettingsScreen.tsx | 4 +- src/styles/index.ts | 6 +- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index d7e561f67b6a..0fe0e7557610 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -14,7 +14,7 @@ import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute'; import Navigation from '@libs/Navigation/Navigation'; import type {RootStackParamList} from '@libs/Navigation/types'; -import {checkIfWorkspaceHasError} from '@libs/WorkspacesUtils'; +import {checkIfWorkspaceSettingsTabHasRBR, getChatTabBrickRoad} from '@libs/WorkspacesUtils'; import BottomTabBarFloatingActionButton from '@pages/home/sidebar/BottomTabBarFloatingActionButton'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -34,7 +34,9 @@ function BottomTabBar() { return topmostBottomTabRoute?.name ?? SCREENS.HOME; }); - const showWorkspaceRedBrickRoad = checkIfWorkspaceHasError(activeWorkspaceID) && currentTabName === SCREENS.HOME; + const showWorkspaceRedBrickRoad = checkIfWorkspaceSettingsTabHasRBR(activeWorkspaceID) && currentTabName === SCREENS.HOME; + + const chatTabBrickRoad = currentTabName !== SCREENS.HOME ? getChatTabBrickRoad(activeWorkspaceID) : undefined; return ( @@ -48,12 +50,17 @@ function BottomTabBar() { wrapperStyle={styles.flexGrow1} style={styles.bottomTabBarItem} > - + + + {chatTabBrickRoad && ( + + )} + @@ -76,11 +83,7 @@ function BottomTabBar() { width={variables.iconBottomBar} height={variables.iconBottomBar} /> - {showWorkspaceRedBrickRoad && ( - - )} + {showWorkspaceRedBrickRoad && } diff --git a/src/libs/WorkspacesUtils.ts b/src/libs/WorkspacesUtils.ts index ae6489f10217..f0d93183e480 100644 --- a/src/libs/WorkspacesUtils.ts +++ b/src/libs/WorkspacesUtils.ts @@ -71,7 +71,7 @@ const getBrickRoadForPolicy = (report: Report): BrickRoad => { return shouldShowGreenDotIndicator ? CONST.BRICK_ROAD.GBR : undefined; }; -function hasGlobalWorkspaceError(policies: OnyxCollection, policyMembers: OnyxCollection) { +function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection, policyMembers: OnyxCollection) { const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => !!policy)); const cleanAllPolicyMembers = Object.fromEntries(Object.entries(policyMembers ?? {}).filter(([, policyMemberValues]) => !!policyMemberValues)); @@ -85,16 +85,52 @@ function hasGlobalWorkspaceError(policies: OnyxCollection, policyMembers return errorCheckingMethods.some((errorCheckingMethod) => errorCheckingMethod()); } -function hasWorkspaceRedBrickRoad(policy: Policy) { +function hasWorkspaceSettingsRBR(policy: Policy) { const policyMemberError = allPolicyMembers ? hasPolicyMemberError(allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policy.id}`]) : false; - return hasPolicyError(policy) || hasCustomUnitsError(policy) || policyMemberError; + return Object.keys(reimbursementAccount?.errors ?? {}).length > 0 || hasPolicyError(policy) || hasCustomUnitsError(policy) || policyMemberError; } -function checkIfWorkspaceHasError(policyID?: string) { - // TODO: Handle reimbursmentAccount error +function getChatTabBrickRoad(policyID?: string): BrickRoad | undefined { + if (!allReports) { + return undefined; + } + + let brickRoad: BrickRoad | undefined; + + Object.keys(allReports).forEach((report) => { + if (brickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR) { + return; + } + + if (policyID && policyID !== allReports?.[report]?.policyID) { + return; + } + + const policyReport = allReports ? allReports[report] : null; + + if (!policyReport) { + return; + } + + const workspaceBrickRoad = getBrickRoadForPolicy(policyReport); + + if (workspaceBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR) { + brickRoad = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + return; + } + + if (!brickRoad && workspaceBrickRoad) { + brickRoad = workspaceBrickRoad; + } + }); + + return brickRoad; +} + +function checkIfWorkspaceSettingsTabHasRBR(policyID?: string) { if (!policyID) { - return hasGlobalWorkspaceError(allPolicies, allPolicyMembers); + return hasGlobalWorkspaceSettingsRBR(allPolicies, allPolicyMembers); } const policy = allPolicies ? allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : null; @@ -102,7 +138,7 @@ function checkIfWorkspaceHasError(policyID?: string) { return false; } - return hasWorkspaceRedBrickRoad(policy); + return hasWorkspaceSettingsRBR(policy); } /** @@ -123,7 +159,7 @@ function getWorkspacesBrickRoads(): Record { return; } - if (hasWorkspaceRedBrickRoad(policy)) { + if (hasWorkspaceSettingsRBR(policy)) { workspacesBrickRoadsMap[policy.id] = CONST.BRICK_ROAD.RBR; } }); @@ -131,7 +167,7 @@ function getWorkspacesBrickRoads(): Record { Object.keys(allReports).forEach((report) => { const policyID = allReports?.[report]?.policyID ?? CONST.POLICY.EMPTY; const policyReport = allReports ? allReports[report] : null; - if (!policyID || !policyReport || workspacesBrickRoadsMap[policyID] === CONST.BRICK_ROAD.RBR) { + if (!policyReport || workspacesBrickRoadsMap[policyID] === CONST.BRICK_ROAD.RBR) { return; } const workspaceBrickRoad = getBrickRoadForPolicy(policyReport); @@ -175,5 +211,13 @@ function getWorkspacesUnreadStatuses(): Record { return workspacesUnreadStatuses; } -export {getBrickRoadForPolicy, getWorkspacesBrickRoads, getWorkspacesUnreadStatuses, hasGlobalWorkspaceError, checkIfWorkspaceHasError, hasWorkspaceRedBrickRoad}; +export { + getBrickRoadForPolicy, + getWorkspacesBrickRoads, + getWorkspacesUnreadStatuses, + hasGlobalWorkspaceSettingsRBR, + checkIfWorkspaceSettingsTabHasRBR, + hasWorkspaceSettingsRBR, + getChatTabBrickRoad, +}; export type {BrickRoad}; diff --git a/src/pages/home/sidebar/AllSettingsScreen.tsx b/src/pages/home/sidebar/AllSettingsScreen.tsx index 655bf8fd824f..200c7ca634b7 100644 --- a/src/pages/home/sidebar/AllSettingsScreen.tsx +++ b/src/pages/home/sidebar/AllSettingsScreen.tsx @@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; -import {hasGlobalWorkspaceError} from '@libs/WorkspacesUtils'; +import {hasGlobalWorkspaceSettingsRBR} from '@libs/WorkspacesUtils'; import * as Link from '@userActions/Link'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; @@ -47,7 +47,7 @@ function AllSettingsScreen({policies, policyMembers}: AllSettingsScreenProps) { })(); }, focused: !isSmallScreenWidth, - brickRoadIndicator: hasGlobalWorkspaceError(policies, policyMembers) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies, policyMembers) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { translationKey: 'allSettingsScreen.subscriptions', diff --git a/src/styles/index.ts b/src/styles/index.ts index b5ab85c6fd92..ba2f66b5d709 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1380,9 +1380,9 @@ const styles = (theme: ThemeColors) => zIndex: 10, } satisfies ViewStyle), - bottomTabStatusIndicator: { + bottomTabStatusIndicator: (backgroundColor = theme.danger) => ({ borderColor: theme.sidebar, - backgroundColor: theme.danger, + backgroundColor, borderRadius: 8, borderWidth: 2, position: 'absolute', @@ -1391,7 +1391,7 @@ const styles = (theme: ThemeColors) => height: 16, width: 16, zIndex: 10, - }, + }), floatingActionButton: { backgroundColor: theme.success, From 106e8d78161d42d279306c0e115668cd82062fa5 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 30 Jan 2024 11:24:01 +0100 Subject: [PATCH 594/764] Refactor bottomTabStatusIndicator style --- src/styles/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index ba2f66b5d709..84e23ebc652e 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1386,10 +1386,10 @@ const styles = (theme: ThemeColors) => borderRadius: 8, borderWidth: 2, position: 'absolute', - right: -10, - top: -10, - height: 16, - width: 16, + right: -3, + top: -4, + height: 12, + width: 12, zIndex: 10, }), From 22e06e0e973fd32a6d7ff35bc42e502f79ed4990 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 30 Jan 2024 11:37:58 +0100 Subject: [PATCH 595/764] Remove BrickRoadsUtils file --- src/libs/BrickRoadsUtils.ts | 74 ------------------------------------- 1 file changed, 74 deletions(-) delete mode 100644 src/libs/BrickRoadsUtils.ts diff --git a/src/libs/BrickRoadsUtils.ts b/src/libs/BrickRoadsUtils.ts deleted file mode 100644 index db7cc40a7940..000000000000 --- a/src/libs/BrickRoadsUtils.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type {OnyxCollection} from 'react-native-onyx'; -import Onyx from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {Report} from '@src/types/onyx'; -import * as OptionsListUtils from './OptionsListUtils'; -import * as ReportActionsUtils from './ReportActionsUtils'; -import * as ReportUtils from './ReportUtils'; - -let allReports: OnyxCollection; - -type BrickRoad = ValueOf | undefined; - -Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (value) => (allReports = value), -}); - -/** - * @param report - * @returns BrickRoad for the policy passed as a param - */ -const getBrickRoadForPolicy = (report: Report): BrickRoad => { - const reportActions = ReportActionsUtils.getAllReportActions(report.reportID); - const reportErrors = OptionsListUtils.getAllReportErrors(report, reportActions); - const doesReportContainErrors = Object.keys(reportErrors ?? {}).length !== 0 ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined; - if (doesReportContainErrors) { - return CONST.BRICK_ROAD.RBR; - } - - // To determine if the report requires attention from the current user, we need to load the parent report action - let itemParentReportAction = {}; - if (report.parentReportID) { - const itemParentReportActions = ReportActionsUtils.getAllReportActions(report.parentReportID); - itemParentReportAction = report.parentReportActionID ? itemParentReportActions[report.parentReportActionID] : {}; - } - const reportOption = {...report, isUnread: ReportUtils.isUnread(report), isUnreadWithMention: ReportUtils.isUnreadWithMention(report)}; - const shouldShowGreenDotIndicator = ReportUtils.requiresAttentionFromCurrentUser(reportOption, itemParentReportAction); - return shouldShowGreenDotIndicator ? CONST.BRICK_ROAD.GBR : undefined; -}; - -/** - * @returns a map where the keys are policyIDs and the values are BrickRoads for each policy - */ -function getWorkspacesBrickRoads(): Record { - if (!allReports) { - return {}; - } - - // The key in this map is the workspace id - const workspacesBrickRoadsMap: Record = {}; - - Object.keys(allReports).forEach((report) => { - const policyID = allReports?.[report]?.policyID; - const policyReport = allReports ? allReports[report] : null; - if (!policyID || !policyReport || workspacesBrickRoadsMap[policyID] === CONST.BRICK_ROAD.RBR) { - return; - } - const workspaceBrickRoad = getBrickRoadForPolicy(policyReport); - - if (!workspaceBrickRoad && !!workspacesBrickRoadsMap[policyID]) { - return; - } - - workspacesBrickRoadsMap[policyID] = workspaceBrickRoad; - }); - - return workspacesBrickRoadsMap; -} - -export {getBrickRoadForPolicy, getWorkspacesBrickRoads}; -export type {BrickRoad}; From 15cffe2c5e3d97036d855bbd8237a092cd3b29f5 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 30 Jan 2024 11:41:30 +0100 Subject: [PATCH 596/764] Fix Onyx types import --- src/components/ReportActionItem/MoneyRequestAction.tsx | 2 +- src/components/ReportActionItem/MoneyRequestPreview.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestAction.tsx b/src/components/ReportActionItem/MoneyRequestAction.tsx index 51c814c1b2c6..ff29bf5b0ee8 100644 --- a/src/components/ReportActionItem/MoneyRequestAction.tsx +++ b/src/components/ReportActionItem/MoneyRequestAction.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxEntry} from 'react-native-onyx'; import RenderHTML from '@components/RenderHTML'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; diff --git a/src/components/ReportActionItem/MoneyRequestPreview.tsx b/src/components/ReportActionItem/MoneyRequestPreview.tsx index c17c5ecd4129..bde8063690b6 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview.tsx @@ -5,7 +5,7 @@ import React from 'react'; import {View} from 'react-native'; import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxEntry} from 'react-native-onyx'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import MoneyRequestSkeletonView from '@components/MoneyRequestSkeletonView'; From 303454c85dc6f76d734e53b9ef2c50eb98ff436d Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 30 Jan 2024 11:47:24 +0100 Subject: [PATCH 597/764] Fix margin for a brick road in MenuItem --- src/components/MenuItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 10dccfcf1c5c..d93a8bbbc9ee 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -573,7 +573,7 @@ function MenuItem( )} {!!brickRoadIndicator && ( - + Date: Tue, 30 Jan 2024 11:48:11 +0100 Subject: [PATCH 598/764] Fix Onyx types import --- src/pages/settings/Security/CloseAccountPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 2287752cd786..f1a0d064fe0a 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -3,7 +3,7 @@ import Str from 'expensify-common/lib/str'; import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxEntry} from 'react-native-onyx'; import ConfirmModal from '@components/ConfirmModal'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; From 7df2fb79a1a458a448df1b9d708a58e8071f0b32 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 30 Jan 2024 18:12:28 +0700 Subject: [PATCH 599/764] merge main --- src/libs/ReportUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 2646f6c36051..c0a8337da4b2 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -12,7 +12,8 @@ import * as Expensicons from '@components/Icon/Expensicons'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; import CONST from '@src/CONST'; import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; -import ONYXKEYS, { OnyxCollectionKey } from '@src/ONYXKEYS'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type { OnyxCollectionKey } from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Beta, PersonalDetails, PersonalDetailsList, Policy, PolicyReportField, Report, ReportAction, ReportMetadata, Session, Transaction, TransactionViolation} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; From d13b95469eab345d9cc5252dcb0a1d26ff7a8074 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 30 Jan 2024 18:17:25 +0700 Subject: [PATCH 600/764] fix lint --- src/libs/ReportUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index c0a8337da4b2..e446c630b1c9 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -13,7 +13,7 @@ import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvata import CONST from '@src/CONST'; import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type { OnyxCollectionKey } from '@src/ONYXKEYS'; +import type {OnyxCollectionKey} from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Beta, PersonalDetails, PersonalDetailsList, Policy, PolicyReportField, Report, ReportAction, ReportMetadata, Session, Transaction, TransactionViolation} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; @@ -4644,7 +4644,7 @@ function getAllAncestorReportActions( if (!parentReportAction || ReportActionsUtils.isTransactionThread(parentReportAction) || !parentReport) { break; } - + const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport, parentReportAction, convertedReportActions?.[parentReportID] ?? {}); allAncestors.push({ report: currentReport, From 5cbebb3e20b38067de2732ffb44cec0d268aa4b8 Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Tue, 30 Jan 2024 12:23:25 +0100 Subject: [PATCH 601/764] CR fixes --- src/pages/workspace/WorkspacesListPage.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index 142571e23679..0dc29394b6d5 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -93,7 +93,7 @@ const workspaceFeatures = [ /** * Dismisses the errors on one item */ -function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.PendingAction | undefined) { +function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.PendingAction) { if (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { Policy.clearDeleteWorkspaceError(policyID); return; @@ -114,10 +114,14 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r const {isSmallScreenWidth} = useWindowDimensions(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); - const [policyIDToDelete, setPolicyIDToDelete] = useState(''); - const [policyNameToDelete, setPolicyNameToDelete] = useState(''); + const [policyIDToDelete, setPolicyIDToDelete] = useState(); + const [policyNameToDelete, setPolicyNameToDelete] = useState(); const confirmDeleteAndHideModal = () => { + if (!policyIDToDelete || !policyNameToDelete) { + return; + } + Policy.deleteWorkspace(policyIDToDelete, [], policyNameToDelete); setIsDeleteModalOpen(false); }; From d8b642dce2245c07579598e0f556e7a03d113190 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Tue, 30 Jan 2024 12:32:20 +0100 Subject: [PATCH 602/764] dont save not-found path --- src/libs/Navigation/NavigationRoot.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx index c424000dc2a0..f022f5c6a657 100644 --- a/src/libs/Navigation/NavigationRoot.tsx +++ b/src/libs/Navigation/NavigationRoot.tsx @@ -1,5 +1,5 @@ import type {NavigationState} from '@react-navigation/native'; -import {DefaultTheme, NavigationContainer} from '@react-navigation/native'; +import {DefaultTheme, findFocusedRoute, NavigationContainer} from '@react-navigation/native'; import React, {useEffect, useMemo, useRef} from 'react'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import useCurrentReportID from '@hooks/useCurrentReportID'; @@ -10,6 +10,7 @@ import Log from '@libs/Log'; import {getPathFromURL} from '@libs/Url'; import {updateLastVisitedPath} from '@userActions/App'; import type {Route} from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; import AppNavigator from './AppNavigator'; import getPolicyIdFromState from './getPolicyIdFromState'; import linkingConfig from './linkingConfig'; @@ -41,7 +42,12 @@ function parseAndLogRoute(state: NavigationState) { } const currentPath = customGetPathFromState(state, linkingConfig.config); - updateLastVisitedPath(currentPath); + + const focusedRoute = findFocusedRoute(state); + + if (focusedRoute?.name !== SCREENS.NOT_FOUND) { + updateLastVisitedPath(currentPath); + } // Don't log the route transitions from OldDot because they contain authTokens if (currentPath.includes('/transition')) { From 671cb6eff15305dc68c295269ad62354a8180718 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:57:42 +0100 Subject: [PATCH 603/764] fix offline indicator on full page not found view (191) --- src/pages/workspace/WorkspacePageWithSections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index ce9d82ed9d9d..736baf0ae90e 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -136,7 +136,7 @@ function WorkspacePageWithSections({ shouldEnablePickerAvoiding={false} shouldEnableMaxHeight testID={WorkspacePageWithSections.displayName} - shouldShowOfflineIndicatorInWideScreen={shouldShowOfflineIndicatorInWideScreen} + shouldShowOfflineIndicatorInWideScreen={shouldShowOfflineIndicatorInWideScreen && !shouldShow} > Date: Tue, 30 Jan 2024 14:19:22 +0100 Subject: [PATCH 604/764] Fix goBack when workspace with given policyID does not exist --- src/pages/workspace/WorkspacePageWithSections.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 3e6e47000a4a..b4aaaf76446c 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -104,7 +104,12 @@ function WorkspacePageWithSections({ const {isSmallScreenWidth} = useWindowDimensions(); const firstRender = useRef(true); - const goBack = () => Navigation.goBack(ROUTES.SETTINGS_WORKSPACES); + const goBack = () => { + Navigation.goBack(ROUTES.SETTINGS_WORKSPACES); + + // Needed when workspace with given policyID does not exist + Navigation.navigateWithSwitchPolicyID({route: ROUTES.ALL_SETTINGS}); + }; useEffect(() => { // Because isLoading is false before merging in Onyx, we need firstRender ref to display loading page as well before isLoading is change to true From e63e68c1f9945355a078dbc594395b90dbed3329 Mon Sep 17 00:00:00 2001 From: mkhutornyi Date: Tue, 30 Jan 2024 14:53:17 +0100 Subject: [PATCH 605/764] remove unused popover ref callbacks --- src/components/PopoverProvider/index.tsx | 6 ------ src/components/PopoverProvider/types.ts | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/components/PopoverProvider/index.tsx b/src/components/PopoverProvider/index.tsx index a738d1f9798a..69728d7be126 100644 --- a/src/components/PopoverProvider/index.tsx +++ b/src/components/PopoverProvider/index.tsx @@ -27,9 +27,6 @@ function PopoverContextProvider(props: PopoverContextProps) { } activePopoverRef.current.close(); - if (activePopoverRef.current.onCloseCallback) { - activePopoverRef.current.onCloseCallback(); - } activePopoverRef.current = null; setIsOpen(false); }, []); @@ -107,9 +104,6 @@ function PopoverContextProvider(props: PopoverContextProps) { closePopover(activePopoverRef.current.anchorRef); } activePopoverRef.current = popoverParams; - if (popoverParams?.onOpenCallback) { - popoverParams.onOpenCallback(); - } setIsOpen(true); }, [closePopover], diff --git a/src/components/PopoverProvider/types.ts b/src/components/PopoverProvider/types.ts index 49705d7ea7a8..2a366ae2a712 100644 --- a/src/components/PopoverProvider/types.ts +++ b/src/components/PopoverProvider/types.ts @@ -16,8 +16,6 @@ type AnchorRef = { ref: RefObject; close: (anchorRef?: RefObject) => void; anchorRef: RefObject; - onOpenCallback?: () => void; - onCloseCallback?: () => void; }; export type {PopoverContextProps, PopoverContextValue, AnchorRef}; From 67cd4c468bd94c99a61e611607d4010c70e1e6e7 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 29 Jan 2024 16:30:25 +0000 Subject: [PATCH 606/764] [TS migration] Migrate rn-fetch-block mock --- __mocks__/rn-fetch-blob.js | 4 ---- __mocks__/rn-fetch-blob.ts | 11 +++++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 __mocks__/rn-fetch-blob.js create mode 100644 __mocks__/rn-fetch-blob.ts diff --git a/__mocks__/rn-fetch-blob.js b/__mocks__/rn-fetch-blob.js deleted file mode 100644 index 4d179e730903..000000000000 --- a/__mocks__/rn-fetch-blob.js +++ /dev/null @@ -1,4 +0,0 @@ -export default { - DocumentDir: jest.fn(), - ImageCache: jest.fn(), -}; diff --git a/__mocks__/rn-fetch-blob.ts b/__mocks__/rn-fetch-blob.ts new file mode 100644 index 000000000000..80d827de32ea --- /dev/null +++ b/__mocks__/rn-fetch-blob.ts @@ -0,0 +1,11 @@ +type RnFetchBlob = { + DocumentDir: jest.Mock + ImageCache: jest.Mock +} + +const RnFetchBlobMock: RnFetchBlob = { + DocumentDir: jest.fn(), + ImageCache: jest.fn(), +} + +export default RnFetchBlobMock From a49414c8836e7df9df9ef3954449f4cf4b5aa35a Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 29 Jan 2024 17:01:30 +0000 Subject: [PATCH 607/764] [TS migration][rn-fetch-blob] Prettify and lint --- __mocks__/rn-fetch-blob.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/__mocks__/rn-fetch-blob.ts b/__mocks__/rn-fetch-blob.ts index 80d827de32ea..fb4cdf6bf958 100644 --- a/__mocks__/rn-fetch-blob.ts +++ b/__mocks__/rn-fetch-blob.ts @@ -1,11 +1,11 @@ type RnFetchBlob = { - DocumentDir: jest.Mock - ImageCache: jest.Mock -} + DocumentDir: jest.Mock; + ImageCache: jest.Mock; +}; const RnFetchBlobMock: RnFetchBlob = { DocumentDir: jest.fn(), ImageCache: jest.fn(), -} +}; -export default RnFetchBlobMock +export default RnFetchBlobMock; From 383d224410b5af27e9b1d1a71e44f2171fcd21ba Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 30 Jan 2024 16:03:01 +0100 Subject: [PATCH 608/764] Add BrickRoadIndicatorIconProps in WorkspacesListRow --- src/pages/workspace/WorkspacesListRow.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacesListRow.tsx b/src/pages/workspace/WorkspacesListRow.tsx index 6449d1f78396..2f74d265c004 100644 --- a/src/pages/workspace/WorkspacesListRow.tsx +++ b/src/pages/workspace/WorkspacesListRow.tsx @@ -51,6 +51,10 @@ type WorkspacesListRowProps = WithCurrentUserPersonalDetailsProps & { brickRoadIndicator?: ValueOf; }; +type BrickRoadIndicatorIconProps = { + brickRoadIndicator?: ValueOf; +}; + const workspaceTypeIcon = (workspaceType: WorkspacesListRowProps['workspaceType']): IconAsset => { switch (workspaceType) { case CONST.POLICY.TYPE.FREE: @@ -64,7 +68,7 @@ const workspaceTypeIcon = (workspaceType: WorkspacesListRowProps['workspaceType' } }; -function BrickRoadIndicatorIcon({brickRoadIndicator}: {brickRoadIndicator?: ValueOf}) { +function BrickRoadIndicatorIcon({brickRoadIndicator}: BrickRoadIndicatorIconProps) { const theme = useTheme(); return brickRoadIndicator ? ( From cfd4286c528a290c55971d72de83542aa590a921 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 31 Jan 2024 07:40:23 +0700 Subject: [PATCH 609/764] move transitionDuration to propTypes, remove default value of transitionDuration, fix incorrect const name --- .../SignInPageLayout/BackgroundImage/index.android.js | 10 +--------- .../SignInPageLayout/BackgroundImage/index.ios.js | 4 ---- .../signin/SignInPageLayout/BackgroundImage/index.js | 4 ---- .../SignInPageLayout/BackgroundImage/propTypes.js | 3 +++ src/pages/signin/SignInPageLayout/index.js | 2 +- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js index a3ddc3383bc4..06784ddef007 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js @@ -9,13 +9,6 @@ const defaultProps = { transitionDuration: 0, }; -const propTypes = { - /** Transition duration in milliseconds */ - transitionDuration: PropTypes.number, - - ...defaultPropTypes, -}; - function BackgroundImage(props) { const styles = useThemeStyles(); return ( @@ -29,7 +22,6 @@ function BackgroundImage(props) { } BackgroundImage.displayName = 'BackgroundImage'; -BackgroundImage.propTypes = propTypes; -BackgroundImage.defaultProps = defaultProps; +BackgroundImage.propTypes = defaultPropTypes; export default BackgroundImage; diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js index 20d5a75a8838..b426a888e8b9 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js @@ -9,16 +9,12 @@ import defaultPropTypes from './propTypes'; const defaultProps = { isSmallScreen: false, - transitionDuration: 0, }; const propTypes = { /** Is the window width narrow, like on a mobile device */ isSmallScreen: PropTypes.bool, - /** Transition duration in milliseconds */ - transitionDuration: PropTypes.number, - ...defaultPropTypes, }; function BackgroundImage(props) { diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.js index 19504852d541..96406d6f3d31 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.js +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.js @@ -8,16 +8,12 @@ import defaultPropTypes from './propTypes'; const defaultProps = { isSmallScreen: false, - transitionDuration: 0, }; const propTypes = { /** Is the window width narrow, like on a mobile device */ isSmallScreen: PropTypes.bool, - /** Tranistion duration in milisecond */ - transitionDuration: PropTypes.number, - ...defaultPropTypes, }; function BackgroundImage(props) { diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/propTypes.js b/src/pages/signin/SignInPageLayout/BackgroundImage/propTypes.js index 533d22ad12c5..d966b196b725 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/propTypes.js +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/propTypes.js @@ -6,6 +6,9 @@ const propTypes = { /** The width of the image. */ width: PropTypes.number.isRequired, + + /** Transition duration in milliseconds */ + transitionDuration: PropTypes.number, }; export default propTypes; diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js index 635f500c4aa3..fdb7221cbf15 100644 --- a/src/pages/signin/SignInPageLayout/index.js +++ b/src/pages/signin/SignInPageLayout/index.js @@ -128,7 +128,7 @@ function SignInPageLayout(props) { isSmallScreen={false} pointerEvents="none" width={variables.signInHeroBackgroundWidth} - transitionDuration={CONST.BACKGROUND_IMAGE_TRANSITION} + transitionDuration={CONST.BACKGROUND_IMAGE_TRANSITION_DURATION} /> From 3a0f56f557df430809912a2f51e34d169a90ad73 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 31 Jan 2024 08:04:35 +0700 Subject: [PATCH 610/764] fix incorrect const call --- nextjs-starter-medusa-billplz | 1 + src/pages/signin/SignInPageLayout/index.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 160000 nextjs-starter-medusa-billplz diff --git a/nextjs-starter-medusa-billplz b/nextjs-starter-medusa-billplz new file mode 160000 index 000000000000..af3c68c1557f --- /dev/null +++ b/nextjs-starter-medusa-billplz @@ -0,0 +1 @@ +Subproject commit af3c68c1557f7091cb7d9b8aeeb5e5a9b8e8ba89 diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js index fdb7221cbf15..5465a3189818 100644 --- a/src/pages/signin/SignInPageLayout/index.js +++ b/src/pages/signin/SignInPageLayout/index.js @@ -168,7 +168,7 @@ function SignInPageLayout(props) { isSmallScreen pointerEvents="none" width={variables.signInHeroBackgroundWidthMobile} - transitionDuration={CONST.BACKGROUND_IMAGE_TRANSITION} + transitionDuration={CONST.BACKGROUND_IMAGE_TRANSITION_DURATION} /> Date: Wed, 31 Jan 2024 08:22:33 +0700 Subject: [PATCH 611/764] remove unrelated file --- nextjs-starter-medusa-billplz | 1 - 1 file changed, 1 deletion(-) delete mode 160000 nextjs-starter-medusa-billplz diff --git a/nextjs-starter-medusa-billplz b/nextjs-starter-medusa-billplz deleted file mode 160000 index af3c68c1557f..000000000000 --- a/nextjs-starter-medusa-billplz +++ /dev/null @@ -1 +0,0 @@ -Subproject commit af3c68c1557f7091cb7d9b8aeeb5e5a9b8e8ba89 From 77df109cdabe30afc19c9e510d326fd6a9b78eda Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 31 Jan 2024 08:27:26 +0700 Subject: [PATCH 612/764] remove unused import and var --- .../signin/SignInPageLayout/BackgroundImage/index.android.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js index 06784ddef007..8d261134baba 100644 --- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js +++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js @@ -1,14 +1,9 @@ import {Image} from 'expo-image'; -import PropTypes from 'prop-types'; import React from 'react'; import AndroidBackgroundImage from '@assets/images/home-background--android.svg'; import useThemeStyles from '@hooks/useThemeStyles'; import defaultPropTypes from './propTypes'; -const defaultProps = { - transitionDuration: 0, -}; - function BackgroundImage(props) { const styles = useThemeStyles(); return ( From 40c979c99065e128832e5bd383555719e9fc72de Mon Sep 17 00:00:00 2001 From: Antony Kithinzi Date: Wed, 31 Jan 2024 03:07:32 +0100 Subject: [PATCH 613/764] fix --- src/components/ReportActionItem/ReportPreview.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index b2fece085f57..712dd6e56760 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -229,7 +229,10 @@ function ReportPreview({ }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; return ( - + { From a4e5fbaf085f9dfa406748d6e5a4ea17db89fc6b Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 31 Jan 2024 09:38:14 +0700 Subject: [PATCH 614/764] fix lint --- src/components/ReportActionItem/TaskView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/TaskView.tsx b/src/components/ReportActionItem/TaskView.tsx index 414bd70155f0..bdcc4d01b1a8 100644 --- a/src/components/ReportActionItem/TaskView.tsx +++ b/src/components/ReportActionItem/TaskView.tsx @@ -28,7 +28,7 @@ import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {PersonalDetailsList, Policy, Report} from '@src/types/onyx'; +import type {PersonalDetailsList, Report} from '@src/types/onyx'; type TaskViewOnyxProps = { /** All of the personal details for everyone */ From da41c762df457e061f90c33c2badddb1f2e9aa9f Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 31 Jan 2024 12:25:23 +0800 Subject: [PATCH 615/764] don't go to sign in modal if the route is empty --- src/libs/actions/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 1f6905cfb8e0..b9eb1aecb412 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1984,7 +1984,7 @@ function openReportFromDeepLink(url: string, isAuthenticated: boolean) { navigateToConciergeChat(true); return; } - if (Session.isAnonymousUser() && !Session.canAccessRouteByAnonymousUser(route)) { + if (route && Session.isAnonymousUser() && !Session.canAccessRouteByAnonymousUser(route)) { Session.signOutAndRedirectToSignIn(true); return; } From a0763958c623991b8ac85531e1bcb26f1551352f Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Wed, 31 Jan 2024 07:20:04 +0100 Subject: [PATCH 616/764] prevent crash on Backspace press when magic input is not focused --- src/components/MagicCodeInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index 4a6d87b48e38..9af07bef6af1 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -278,7 +278,7 @@ function MagicCodeInput( const indexToFocus = numbers[editIndex] === CONST.MAGIC_CODE_EMPTY_CHAR ? indexBeforeLastEditIndex : editIndex; const formElement = inputRefs.current as HTMLFormElement | null; - (formElement?.[indexToFocus] as HTMLInputElement).focus(); + (formElement?.[indexToFocus] as HTMLInputElement)?.focus(); onChangeTextProp(value.substring(0, indexToFocus)); return; From 61267ec0fd44cabd884405711e100ef9f1ed5cb4 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:08:18 +0100 Subject: [PATCH 617/764] fix not always showing announce rooms --- src/pages/workspace/WorkspacesListPage.tsx | 58 ++++++++++++---------- src/types/onyx/Policy.ts | 4 ++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index 4001e34a3529..4bd86de4001b 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -13,6 +13,7 @@ import LottieAnimations from '@components/LottieAnimations'; import type {MenuItemProps} from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; +import type {PopoverMenuItem} from '@components/PopoverMenu'; import {PressableWithoutFeedback} from '@components/Pressable'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -131,32 +132,39 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r */ const getMenuItem = useCallback( ({item, index}: GetMenuItem) => { - const threeDotsMenuItems = [ - // Check if the user is an admin of the workspace - ...(item.role === CONST.POLICY.ROLE.ADMIN - ? [ - { - icon: Expensicons.Trashcan, - text: translate('workspace.common.delete'), - onSelected: () => { - setPolicyIDToDelete(item.policyID ?? ''); - setPolicyNameToDelete(item.title); - setIsDeleteModalOpen(true); - }, - }, - { - icon: Expensicons.Hashtag, - text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}), - onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.adminRoom ?? '')), - }, - ] - : []), - { + const isAdmin = item.role === CONST.POLICY.ROLE.ADMIN; + // Menu options to navigate to the chat report of #admins and #announce room. + // For navigation, the chat report ids may be unavailable due to the missing chat reports in Onyx. + // In such cases, let us use the available chat report ids from the policy. + const threeDotsMenuItems: PopoverMenuItem[] = []; + + if (isAdmin) { + threeDotsMenuItems.push({ + icon: Expensicons.Trashcan, + text: translate('workspace.common.delete'), + onSelected: () => { + setPolicyIDToDelete(item.policyID ?? ''); + setPolicyNameToDelete(item.title); + setIsDeleteModalOpen(true); + }, + }); + } + + if (isAdmin && item.adminRoom) { + threeDotsMenuItems.push({ + icon: Expensicons.Hashtag, + text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}), + onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.adminRoom ?? '')), + }); + } + + if (item.announceRoom) { + threeDotsMenuItems.push({ icon: Expensicons.Hashtag, text: translate('workspace.common.goToRoom', {roomName: CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE}), onSelected: () => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(item.announceRoom ?? '')), - }, - ]; + }); + } return ( Date: Wed, 31 Jan 2024 08:13:49 +0100 Subject: [PATCH 618/764] fix padding (PR 35126) --- src/components/HeaderWithBackButton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index 9a50b61cb1c3..6c89221d9217 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -71,7 +71,7 @@ function HeaderWithBackButton({ // Hover on some part of close icons will not work on Electron if dragArea is true // https://github.com/Expensify/App/issues/29598 dataSet={{dragArea: false}} - style={[styles.headerBar, shouldShowBorderBottom && styles.borderBottom, shouldShowBackButton ? styles.pl2 : styles.pl5, shouldOverlay && StyleSheet.absoluteFillObject]} + style={[styles.headerBar, shouldShowBorderBottom && styles.borderBottom, shouldShowBackButton ? styles.pl0 : styles.pl5, shouldOverlay && StyleSheet.absoluteFillObject]} > {shouldShowBackButton && ( From a5344d7ced07f765c98a4b9dd416ab624f56e0f9 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:27:05 +0100 Subject: [PATCH 619/764] center vertically HeaderSkeletonView --- src/components/ReportHeaderSkeletonView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/ReportHeaderSkeletonView.tsx b/src/components/ReportHeaderSkeletonView.tsx index 8b8bb721a5dc..2113abd85e88 100644 --- a/src/components/ReportHeaderSkeletonView.tsx +++ b/src/components/ReportHeaderSkeletonView.tsx @@ -25,7 +25,7 @@ function ReportHeaderSkeletonView({shouldAnimate = true, onBackButtonPress = () return ( - + {isSmallScreenWidth && ( From 2c67081ebf689e8fa7100cbd243c5ce648ecf11b Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 09:25:57 +0100 Subject: [PATCH 620/764] fix sharecode width --- src/pages/ShareCodePage.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/pages/ShareCodePage.js b/src/pages/ShareCodePage.js index 1f5dab566e2c..8c84313a7f68 100644 --- a/src/pages/ShareCodePage.js +++ b/src/pages/ShareCodePage.js @@ -91,12 +91,7 @@ class ShareCodePage extends React.Component { /> - + Date: Wed, 31 Jan 2024 09:38:53 +0100 Subject: [PATCH 621/764] fix types --- src/components/AttachmentModal.tsx | 2 +- src/libs/Navigation/Navigation.ts | 6 +++++- src/libs/actions/Report.ts | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 5d826da71e90..45f8aa4de0e5 100755 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -281,7 +281,7 @@ function AttachmentModal({ const deleteAndCloseModal = useCallback(() => { IOU.detachReceipt(transaction?.transactionID); setIsDeleteReceiptConfirmModalVisible(false); - Navigation.dismissModalWithReportID(report?.reportID ?? ''); + Navigation.dismissModalWithReportID(report?.reportID); }, [transaction, report]); const isValidFile = useCallback((fileObject: FileObject) => { diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index f293ac1a9127..c0afc7f6c798 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -58,7 +58,11 @@ const dismissModal = (ref = navigationRef) => originalDismissModal(ref); // Then we can pass the report as a param without getting it from the Onyx. const dismissModalWithReport = (report: Report | EmptyObject, ref = navigationRef) => originalDismissModalWithReport(report, ref); -const dismissModalWithReportID = (reportID: string, ref = navigationRef) => { +const dismissModalWithReportID = (reportID?: string, ref = navigationRef) => { + if (!reportID) { + dismissModal(ref); + return; + } const report = getReport(reportID); originalDismissModalWithReport({reportID, ...report}, ref); }; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 0370a4bff97a..b1596cf43461 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1553,7 +1553,7 @@ function navigateToConciergeChat(ignoreConciergeReportID = false, shouldDismissM navigateToAndOpenReport([CONST.EMAIL.CONCIERGE], shouldDismissModal); }); } else if (shouldDismissModal) { - Navigation.dismissModal(conciergeChatReportID); + Navigation.dismissModalWithReportID(conciergeChatReportID); } else { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeChatReportID)); } From 4c3945f0095da3db4cc6b9fc8971d52965951792 Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Wed, 31 Jan 2024 10:19:31 +0100 Subject: [PATCH 622/764] Fix TS on WorkspacesListPage --- src/pages/workspace/WorkspacesListPage.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index 4bd86de4001b..9442ffafa862 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -25,6 +25,7 @@ import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import type {AvatarSource} from '@libs/UserUtils'; import * as App from '@userActions/App'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; @@ -38,10 +39,11 @@ import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import WorkspacesListRow from './WorkspacesListRow'; -type WorkspaceItem = Required> & +type WorkspaceItem = Required> & Pick & Pick & Pick & { + icon: AvatarSource; action: () => void; dismissError: () => void; iconType?: ValueOf; From 5b42bdf2aa0c06f83d8965bc168556716861621f Mon Sep 17 00:00:00 2001 From: Krishna Gupta Date: Wed, 31 Jan 2024 15:15:48 +0530 Subject: [PATCH 623/764] update: callback function to hook. Signed-off-by: Krishna Gupta --- src/hooks/useSearchTermAndSearch.ts | 22 +++++++++++++++++++ src/pages/NewChatPage.js | 14 +++--------- ...yForRefactorRequestParticipantsSelector.js | 14 ++---------- .../MoneyRequestParticipantsSelector.js | 18 ++++----------- 4 files changed, 31 insertions(+), 37 deletions(-) create mode 100644 src/hooks/useSearchTermAndSearch.ts diff --git a/src/hooks/useSearchTermAndSearch.ts b/src/hooks/useSearchTermAndSearch.ts new file mode 100644 index 000000000000..827b6c6d8bd1 --- /dev/null +++ b/src/hooks/useSearchTermAndSearch.ts @@ -0,0 +1,22 @@ +import type {Dispatch} from 'react'; +import {useCallback} from 'react'; +import * as Report from '@userActions/Report'; + +/** + * Hook for fetching reports when user updated search term and hasn't selected max number of participants + */ +const useSearchTermAndSearch = (setSearchTerm: Dispatch>, maxParticipantsReached: boolean) => { + const setSearchTermAndSearchInServer = useCallback( + (text = '') => { + if (text && !maxParticipantsReached) { + Report.searchInServer(text); + } + setSearchTerm(text); + }, + [maxParticipantsReached, setSearchTerm], + ); + + return setSearchTermAndSearchInServer; +}; + +export default useSearchTermAndSearch; diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 9624967a89a3..7dd328e6a0bd 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -11,6 +11,7 @@ import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useNetwork from '@hooks/useNetwork'; +import useSearchTermAndSearch from '@hooks/useSearchTermAndSearch'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import compose from '@libs/compose'; @@ -64,6 +65,8 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); const maxParticipantsReached = selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; + const setSearchTermAndSearchInServer = useSearchTermAndSearch(setSearchTerm, maxParticipantsReached); + const headerMessage = OptionsListUtils.getHeaderMessage( filteredPersonalDetails.length + filteredRecentReports.length !== 0, Boolean(filteredUserToInvite), @@ -229,17 +232,6 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i updateOptions(); }, [didScreenTransitionEnd, updateOptions]); - // When search term updates & user hasn't selected max number of participants we will fetch any reports - const setSearchTermAndSearchInServer = useCallback( - (text = '') => { - if (text && !maxParticipantsReached) { - Report.searchInServer(text); - } - setSearchTerm(text); - }, - [maxParticipantsReached], - ); - const {inputCallbackRef} = useAutoFocusInput(); return ( diff --git a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js index b25b545a5382..e47b0b8198ea 100644 --- a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js +++ b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js @@ -13,8 +13,8 @@ import SelectCircle from '@components/SelectCircle'; import SelectionList from '@components/SelectionList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useSearchTermAndSearch from '@hooks/useSearchTermAndSearch'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Report from '@libs/actions/Report'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -88,6 +88,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ const offlineMessage = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; + const setSearchTermAndSearchInServer = useSearchTermAndSearch(setSearchTerm, maxParticipantsReached); /** * Returns the sections needed for the OptionsSelector @@ -244,17 +245,6 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ [maxParticipantsReached, newChatOptions, participants, searchTerm], ); - // When search term updates & user hasn't selected max number of participants we will fetch any reports - const setSearchTermAndSearchInServer = useCallback( - (text = '') => { - if (text && !maxParticipantsReached) { - Report.searchInServer(text); - } - setSearchTerm(text); - }, - [maxParticipantsReached], - ); - // Right now you can't split a request with a workspace and other additional participants // This is getting properly fixed in https://github.com/Expensify/App/issues/27508, but as a stop-gap to prevent // the app from crashing on native when you try to do this, we'll going to hide the button if you have a workspace and other participants diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index e62d77f1a52a..daaa63aae147 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -13,8 +13,8 @@ import SelectCircle from '@components/SelectCircle'; import SelectionList from '@components/SelectionList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useSearchTermAndSearch from '@hooks/useSearchTermAndSearch'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Report from '@libs/actions/Report'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import reportPropTypes from '@pages/reportPropTypes'; @@ -89,6 +89,9 @@ function MoneyRequestParticipantsSelector({ const {isOffline} = useNetwork(); const personalDetails = usePersonalDetails(); + const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; + const setSearchTermAndSearchInServer = useSearchTermAndSearch(setSearchTerm, maxParticipantsReached); + const offlineMessage = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; const newChatOptions = useMemo(() => { @@ -124,8 +127,6 @@ function MoneyRequestParticipantsSelector({ }; }, [betas, reports, participants, personalDetails, searchTerm, iouType, isDistanceRequest]); - const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; - /** * Returns the sections needed for the OptionsSelector * @@ -260,17 +261,6 @@ function MoneyRequestParticipantsSelector({ [maxParticipantsReached, newChatOptions.personalDetails.length, newChatOptions.recentReports.length, newChatOptions.userToInvite, participants, searchTerm], ); - // When search term updates & user hasn't selected max number of participants we will fetch any reports - const setSearchTermAndSearchInServer = useCallback( - (text = '') => { - if (text && !maxParticipantsReached) { - Report.searchInServer(text); - } - setSearchTerm(text); - }, - [maxParticipantsReached], - ); - // Right now you can't split a request with a workspace and other additional participants // This is getting properly fixed in https://github.com/Expensify/App/issues/27508, but as a stop-gap to prevent // the app from crashing on native when you try to do this, we'll going to show error message if you have a workspace and other participants From 1424356bf4928202676746dd0fe0ad0424cb75bf Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 31 Jan 2024 11:00:08 +0100 Subject: [PATCH 624/764] Fix showing not-found when the new workspace is created (215) --- src/pages/workspace/WorkspacePageWithSections.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 3f9205fb3eb8..605eed9f64b5 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -2,8 +2,8 @@ import type {RouteProp} from '@react-navigation/native'; import type {ReactNode} from 'react'; import React, {useEffect, useMemo, useRef} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -83,6 +83,7 @@ function WorkspacePageWithSections({ guidesCallTaskID = '', headerText, policy, + policyDraft, reimbursementAccount = ReimbursementAccountProps.reimbursementAccountDefaultProps, route, shouldUseScrollView = false, @@ -95,7 +96,6 @@ function WorkspacePageWithSections({ useNetwork({onReconnect: () => fetchData(shouldSkipVBBACall)}); const isLoading = reimbursementAccount?.isLoading ?? true; - const isOverview = route.name; const achState = reimbursementAccount?.achData?.state ?? ''; const isUsingECard = user?.isUsingExpensifyCard ?? false; const policyID = route.params.policyID; @@ -121,13 +121,13 @@ function WorkspacePageWithSections({ }, [shouldSkipVBBACall]); const shouldShow = useMemo(() => { - if (isEmptyObject(policy)) { + if (isEmptyObject(policy) && isEmptyObject(policyDraft)) { return true; } - // TODO - check is the value of isOveriew is correct - return !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy) || !isOverview; - }, [isOverview, policy]); + return (!isEmptyObject(policy) && !PolicyUtils.isPolicyAdmin(policy)) || PolicyUtils.isPendingDeletePolicy(policy); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [policy]); return ( Date: Wed, 31 Jan 2024 10:12:25 +0100 Subject: [PATCH 625/764] cleanup --- src/libs/Navigation/Navigation.ts | 4 ++-- src/libs/Navigation/switchPolicyID.ts | 11 ++++++----- src/libs/Navigation/types.ts | 4 ++-- src/pages/ShareCodePage.js | 4 ++-- src/pages/WorkspaceSwitcherPage.js | 12 ++++-------- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index c0afc7f6c798..31c40759802a 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -18,7 +18,7 @@ import linkingConfig from './linkingConfig'; import linkTo from './linkTo'; import navigationRef from './navigationRef'; import switchPolicyID from './switchPolicyID'; -import type {State, StateOrRoute, switchPolicyIDParams} from './types'; +import type {State, StateOrRoute, SwitchPolicyIDParams} from './types'; let resolveNavigationIsReadyPromise: () => void; const navigationIsReadyPromise = new Promise((resolve) => { @@ -327,7 +327,7 @@ function waitForProtectedRoutes() { }); } -function navigateWithSwitchPolicyID(params: switchPolicyIDParams) { +function navigateWithSwitchPolicyID(params: SwitchPolicyIDParams) { if (!canNavigate('navigateWithSwitchPolicyID')) { return; } diff --git a/src/libs/Navigation/switchPolicyID.ts b/src/libs/Navigation/switchPolicyID.ts index 521045ddb89f..2130fdfb6f99 100644 --- a/src/libs/Navigation/switchPolicyID.ts +++ b/src/libs/Navigation/switchPolicyID.ts @@ -1,7 +1,7 @@ import {getActionFromState} from '@react-navigation/core'; import type {NavigationAction, NavigationContainerRef, NavigationState, PartialState} from '@react-navigation/native'; import {getPathFromState} from '@react-navigation/native'; -import type {Writable} from 'type-fest'; +import type {ValueOf, Writable} from 'type-fest'; import getIsSmallScreenWidth from '@libs/getIsSmallScreenWidth'; import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; @@ -11,7 +11,7 @@ import getStateFromPath from './getStateFromPath'; import getTopmostCentralPaneRoute from './getTopmostCentralPaneRoute'; import linkingConfig from './linkingConfig'; import TAB_TO_CENTRAL_PANE_MAPPING from './linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING'; -import type {NavigationRoot, RootStackParamList, StackNavigationAction, State, switchPolicyIDParams} from './types'; +import type {CentralPaneNavigatorParamList, NavigationRoot, RootStackParamList, StackNavigationAction, State, SwitchPolicyIDParams} from './types'; type ActionPayloadParams = { screen?: string; @@ -60,7 +60,7 @@ function getActionForBottomTabNavigator(action: StackNavigationAction, state: Na }; } -export default function switchPolicyID(navigation: NavigationContainerRef | null, {policyID, route, isPolicyAdmin = true}: switchPolicyIDParams) { +export default function switchPolicyID(navigation: NavigationContainerRef | null, {policyID, route, isPolicyAdmin = false}: SwitchPolicyIDParams) { if (!navigation) { throw new Error("Couldn't find a navigation object. Is your component inside a screen in a navigator?"); } @@ -110,17 +110,18 @@ export default function switchPolicyID(navigation: NavigationContainerRef); // Only workspace settings screens have to store the policyID in the params. // In other case, the policyID is read from the BottomTab params. - if (!screen?.startsWith('Workspace_')) { + if (!isWorkspaceScreen) { delete params.policyID; } else { params.policyID = policyID; } // We need to redirect non admin users to overview screen, when switching workspace. - if (!isPolicyAdmin && screen !== SCREENS.WORKSPACE.OVERVIEW) { + if (!isPolicyAdmin && isWorkspaceScreen && screen !== SCREENS.WORKSPACE.OVERVIEW) { screen = SCREENS.WORKSPACE.OVERVIEW; } diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 2ccecc709bca..02d0af545710 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -470,7 +470,7 @@ type CentralPaneName = keyof CentralPaneNavigatorParamList; type FullScreenName = keyof SettingsCentralPaneNavigatorParamList; -type switchPolicyIDParams = { +type SwitchPolicyIDParams = { policyID?: string; route?: Routes; isPolicyAdmin?: boolean; @@ -520,5 +520,5 @@ export type { ReimbursementAccountNavigatorParamList, State, WorkspaceSwitcherNavigatorParamList, - switchPolicyIDParams, + SwitchPolicyIDParams, }; diff --git a/src/pages/ShareCodePage.js b/src/pages/ShareCodePage.js index 8c84313a7f68..3f0ef6ca138e 100644 --- a/src/pages/ShareCodePage.js +++ b/src/pages/ShareCodePage.js @@ -90,8 +90,8 @@ class ShareCodePage extends React.Component { shouldShowBackButton={isReport || this.props.isSmallScreenWidth} /> - - + + { + const selectPolicy = (option) => { const {policyID, isPolicyAdmin} = option; if (policyID) { @@ -123,11 +123,7 @@ function WorkspaceSwitcherPage({policies}) { if (policyID !== activeWorkspaceID) { Navigation.navigateWithSwitchPolicyID({policyID, isPolicyAdmin}); } - }, []); - - const onChangeText = useCallback((newSearchTerm) => { - setSearchTerm(newSearchTerm); - }, []); + }; const usersWorkspaces = useMemo( () => @@ -248,7 +244,7 @@ function WorkspaceSwitcherPage({policies}) { sections={[usersWorkspacesSectionData]} value={searchTerm} shouldShowTextInput={usersWorkspaces.length >= CONST.WORKSPACE_SWITCHER.MINIMUM_WORKSPACES_TO_SHOW_SEARCH} - onChangeText={onChangeText} + onChangeText={(newSearchTerm) => setSearchTerm(newSearchTerm)} selectedOptions={selectedOption ? [selectedOption] : []} onSelectRow={selectPolicy} shouldPreventDefaultFocusOnSelectRow @@ -270,7 +266,7 @@ function WorkspaceSwitcherPage({policies}) { )} ), - [inputCallbackRef, onChangeText, searchTerm, selectPolicy, selectedOption, styles, theme.textSupporting, translate, usersWorkspaces.length, usersWorkspacesSectionData], + [inputCallbackRef, setSearchTerm, searchTerm, selectPolicy, selectedOption, styles, theme.textSupporting, translate, usersWorkspaces.length, usersWorkspacesSectionData], ); useEffect(() => { From 6ee3a1dd5f66691456c9e0340da81ecb282a022c Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Wed, 31 Jan 2024 11:18:25 +0100 Subject: [PATCH 626/764] Fix active state (212,211) --- src/pages/WorkspaceSwitcherPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/WorkspaceSwitcherPage.js b/src/pages/WorkspaceSwitcherPage.js index 05edef8fc2bd..e6cd8f5ff9a7 100644 --- a/src/pages/WorkspaceSwitcherPage.js +++ b/src/pages/WorkspaceSwitcherPage.js @@ -261,8 +261,8 @@ function WorkspaceSwitcherPage({policies}) { showTitleTooltip={false} contentContainerStyles={[styles.pt0, styles.mt0]} textIconLeft={MagnifyingGlass} - // It has to be set to null or -1 to avoid focus on any element at the beggining - initiallyFocusedOptionKey={null} + // Null is to avoid selecting unfocused option when Global selected, undefined is to focus selected workspace + initiallyFocusedOptionKey={!activeWorkspaceID ? null : undefined} /> ) : ( From 16cac424959a2da4a9161819793a453dfa209c72 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:23:51 +0100 Subject: [PATCH 627/764] center search bar text --- src/styles/index.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 0050692559bc..f895352d6d68 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -3197,6 +3197,7 @@ const styles = (theme: ThemeColors) => paddingHorizontal: 24, backgroundColor: theme.hoverComponentBG, borderRadius: variables.componentBorderRadiusRounded, + justifyContent: 'center', }, searchContainerHovered: { @@ -3703,10 +3704,6 @@ const styles = (theme: ThemeColors) => ...flex.alignItemsCenter, }, - shareCodePage: { - paddingHorizontal: 38.5, - }, - shareCodeContainer: { width: '100%', alignItems: 'center', From 4a01664b8147857e878222b3f93073181afe3117 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 31 Jan 2024 11:38:09 +0100 Subject: [PATCH 628/764] add temporary fix for splash screen --- src/Expensify.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Expensify.js b/src/Expensify.js index 407e5ae09c2d..be01159c95d7 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -4,6 +4,7 @@ import React, {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useStat import {AppState, Linking} from 'react-native'; import Onyx, {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; +import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute'; import ConfirmModal from './components/ConfirmModal'; import DeeplinkWrapper from './components/DeeplinkWrapper'; import EmojiPicker from './components/EmojiPicker/EmojiPicker'; @@ -23,7 +24,7 @@ import compose from './libs/compose'; import * as Growl from './libs/Growl'; import Log from './libs/Log'; import migrateOnyx from './libs/migrateOnyx'; -import Navigation from './libs/Navigation/Navigation'; +import Navigation, {navigationRef} from './libs/Navigation/Navigation'; import NavigationRoot from './libs/Navigation/NavigationRoot'; import NetworkConnection from './libs/NetworkConnection'; import PushNotification from './libs/Notification/PushNotification'; @@ -37,6 +38,7 @@ import Visibility from './libs/Visibility'; import ONYXKEYS from './ONYXKEYS'; import PopoverReportActionContextMenu from './pages/home/report/ContextMenu/PopoverReportActionContextMenu'; import * as ReportActionContextMenu from './pages/home/report/ContextMenu/ReportActionContextMenu'; +import SCREENS from './SCREENS'; Onyx.registerLogger(({level, message}) => { if (level === 'alert') { @@ -130,7 +132,16 @@ function Expensify(props) { [isSplashHidden], ); - const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && hasAttemptedToOpenPublicRoom; + // This is a temporary fix to handle more that one possible screen in the sidebar. + const isSidebarLoaded = useMemo(() => { + if (!isNavigationReady) { + return false; + } + + return getTopmostBottomTabRoute(navigationRef.getState()).name === SCREENS.HOME ? props.isSidebarLoaded : true; + }, [isNavigationReady, props.isSidebarLoaded]); + + const shouldInit = isNavigationReady && (!isAuthenticated || isSidebarLoaded) && hasAttemptedToOpenPublicRoom; const shouldHideSplash = shouldInit && !isSplashHidden; const initializeClient = () => { From 16f8040da7b6f37c01fc63b914aed53059734dea Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:39:14 +0100 Subject: [PATCH 629/764] fix settings status button --- .../home/sidebar/AvatarWithOptionalStatus.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/pages/home/sidebar/AvatarWithOptionalStatus.js b/src/pages/home/sidebar/AvatarWithOptionalStatus.js index e1ff3982a0cc..80130d50555c 100644 --- a/src/pages/home/sidebar/AvatarWithOptionalStatus.js +++ b/src/pages/home/sidebar/AvatarWithOptionalStatus.js @@ -29,14 +29,13 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const showStatusPage = useCallback(() => { + const showSettingsPage = useCallback(() => { if (isCreateMenuOpen) { // Prevent opening Settings page when click profile avatar quickly after clicking FAB icon return; } - Navigation.setShouldPopAllStateOnUP(); - Navigation.navigate(ROUTES.SETTINGS_STATUS); + Navigation.navigate(ROUTES.SETTINGS); }, [isCreateMenuOpen]); return ( @@ -45,17 +44,15 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) { - - - {emojiStatus} - - + + {emojiStatus} + ); From 7291cdfe6158d0508227a7f99e6933d87089b66c Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:44:14 +0100 Subject: [PATCH 630/764] refactor dismissModal function --- src/components/AttachmentModal.tsx | 2 +- src/libs/Navigation/Navigation.ts | 18 ++++++++---------- src/libs/actions/IOU.js | 12 ++++++------ src/libs/actions/Report.ts | 4 ++-- src/libs/actions/Task.ts | 2 +- src/libs/actions/TeachersUnite.ts | 4 ++-- src/pages/AddPersonalBankAccountPage.tsx | 2 +- src/pages/EditRequestDistancePage.js | 6 +++--- src/pages/SearchPage.js | 2 +- src/pages/SearchPage/index.js | 2 +- src/pages/settings/Preferences/ThemePage.js | 2 +- src/pages/tasks/TaskAssigneeSelectorModal.js | 2 +- src/pages/tasks/TaskDescriptionPage.js | 4 ++-- src/pages/tasks/TaskTitlePage.js | 4 ++-- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- tests/actions/IOUTest.js | 2 +- 16 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 45f8aa4de0e5..f3e8ed316c52 100755 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -281,7 +281,7 @@ function AttachmentModal({ const deleteAndCloseModal = useCallback(() => { IOU.detachReceipt(transaction?.transactionID); setIsDeleteReceiptConfirmModalVisible(false); - Navigation.dismissModalWithReportID(report?.reportID); + Navigation.dismissModal(report?.reportID); }, [transaction, report]); const isValidFile = useCallback((fileObject: FileObject) => { diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 31c40759802a..188d8b5f337f 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -51,21 +51,20 @@ const getTopmostReportId = (state = navigationRef.getState()) => originalGetTopm const getTopmostReportActionId = (state = navigationRef.getState()) => originalGetTopmostReportActionId(state); // Re-exporting the dismissModal here to fill in default value for navigationRef. The dismissModal isn't defined in this file to avoid cyclic dependencies. -const dismissModal = (ref = navigationRef) => originalDismissModal(ref); - -// Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies. -// This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet. -// Then we can pass the report as a param without getting it from the Onyx. -const dismissModalWithReport = (report: Report | EmptyObject, ref = navigationRef) => originalDismissModalWithReport(report, ref); - -const dismissModalWithReportID = (reportID?: string, ref = navigationRef) => { +const dismissModal = (reportID?: string, ref = navigationRef) => { if (!reportID) { - dismissModal(ref); + originalDismissModal(ref); return; } const report = getReport(reportID); originalDismissModalWithReport({reportID, ...report}, ref); }; + +// Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies. +// This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet. +// Then we can pass the report as a param without getting it from the Onyx. +const dismissModalWithReport = (report: Report | EmptyObject, ref = navigationRef) => originalDismissModalWithReport(report, ref); + /** Method for finding on which index in stack we are. */ function getActiveRouteIndex(stateOrRoute: StateOrRoute, index?: number): number | undefined { if ('routes' in stateOrRoute && stateOrRoute.routes) { @@ -341,7 +340,6 @@ export default { setParams, dismissModal, dismissModalWithReport, - dismissModalWithReportID, isActiveRoute, getActiveRoute, getActiveRouteWithoutParams, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index d7857954ebe5..5e7396e5cd8f 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -936,7 +936,7 @@ function createDistanceRequest(report, participant, comment, created, category, }, onyxData, ); - Navigation.dismissModalWithReportID(isMoneyRequestReport ? report.reportID : chatReport.reportID); + Navigation.dismissModal(isMoneyRequestReport ? report.reportID : chatReport.reportID); Report.notifyNewAction(chatReport.reportID, userAccountID); } @@ -1364,7 +1364,7 @@ function requestMoney( onyxData, ); resetMoneyRequestInfo(); - Navigation.dismissModalWithReportID(activeReportID); + Navigation.dismissModal(activeReportID); Report.notifyNewAction(activeReportID, payeeAccountID); } @@ -1806,7 +1806,7 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou ); resetMoneyRequestInfo(); - Navigation.dismissModalWithReportID(splitData.chatReportID); + Navigation.dismissModal(splitData.chatReportID); Report.notifyNewAction(splitData.chatReportID, currentUserAccountID); } @@ -2288,7 +2288,7 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi }, {optimisticData, successData, failureData}, ); - Navigation.dismissModalWithReportID(chatReportID); + Navigation.dismissModal(chatReportID); Report.notifyNewAction(chatReportID, sessionAccountID); } @@ -3244,7 +3244,7 @@ function sendMoneyElsewhere(report, amount, currency, comment, managerID, recipi API.write('SendMoneyElsewhere', params, {optimisticData, successData, failureData}); resetMoneyRequestInfo(); - Navigation.dismissModalWithReportID(params.chatReportID); + Navigation.dismissModal(params.chatReportID); Report.notifyNewAction(params.chatReportID, managerID); } @@ -3262,7 +3262,7 @@ function sendMoneyWithWallet(report, amount, currency, comment, managerID, recip API.write('SendMoneyWithWallet', params, {optimisticData, successData, failureData}); resetMoneyRequestInfo(); - Navigation.dismissModalWithReportID(params.chatReportID); + Navigation.dismissModal(params.chatReportID); Report.notifyNewAction(params.chatReportID, managerID); } diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index b1596cf43461..028c409ee8fa 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1553,7 +1553,7 @@ function navigateToConciergeChat(ignoreConciergeReportID = false, shouldDismissM navigateToAndOpenReport([CONST.EMAIL.CONCIERGE], shouldDismissModal); }); } else if (shouldDismissModal) { - Navigation.dismissModalWithReportID(conciergeChatReportID); + Navigation.dismissModal(conciergeChatReportID); } else { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeChatReportID)); } @@ -1641,7 +1641,7 @@ function addPolicyReport(policyReport: ReportUtils.OptimisticChatReport) { }; API.write(WRITE_COMMANDS.ADD_WORKSPACE_ROOM, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModalWithReportID(policyReport.reportID); + Navigation.dismissModal(policyReport.reportID); } /** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */ diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 45c036f9edb9..a7aab98f02c6 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -244,7 +244,7 @@ function createTaskAndNavigate( API.write(WRITE_COMMANDS.CREATE_TASK, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModalWithReportID(parentReportID); + Navigation.dismissModal(parentReportID); } /** diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index c0259de50f60..055d1f2b53a2 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -61,7 +61,7 @@ function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, l }; API.write(WRITE_COMMANDS.REFER_TEACHERS_UNITE_VOLUNTEER, parameters, {optimisticData}); - Navigation.dismissModalWithReportID(publicRoomReportID); + Navigation.dismissModal(publicRoomReportID); } /** @@ -181,7 +181,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: }; API.write(WRITE_COMMANDS.ADD_SCHOOL_PRINCIPAL, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModalWithReportID(expenseChatReportID); + Navigation.dismissModal(expenseChatReportID); } export default {referTeachersUniteVolunteer, addSchoolPrincipal}; diff --git a/src/pages/AddPersonalBankAccountPage.tsx b/src/pages/AddPersonalBankAccountPage.tsx index f7963976dc05..1876992f9ced 100644 --- a/src/pages/AddPersonalBankAccountPage.tsx +++ b/src/pages/AddPersonalBankAccountPage.tsx @@ -47,7 +47,7 @@ function AddPersonalBankAccountPage({personalBankAccount, plaidData}: AddPersona const onSuccessFallbackRoute = personalBankAccount?.onSuccessFallbackRoute ?? ''; if (exitReportID) { - Navigation.dismissModalWithReportID(exitReportID); + Navigation.dismissModal(exitReportID); } else if (shouldContinue && onSuccessFallbackRoute) { PaymentMethods.continueSetup(onSuccessFallbackRoute); } else { diff --git a/src/pages/EditRequestDistancePage.js b/src/pages/EditRequestDistancePage.js index f4c5fbe0446f..f3ea76a3390a 100644 --- a/src/pages/EditRequestDistancePage.js +++ b/src/pages/EditRequestDistancePage.js @@ -60,7 +60,7 @@ function EditRequestDistancePage({report, route, transaction, transactionBackup} // When the loading goes from true to false, then we know the transaction has just been // saved to the server. Check for errors. If there are no errors, then the modal can be closed. if (prevIsLoading && !transaction.isLoading && !hasWaypointError.current) { - Navigation.dismissModalWithReportID(report.reportID); + Navigation.dismissModal(report.reportID); } }, [transaction, prevIsLoading, report]); @@ -75,7 +75,7 @@ function EditRequestDistancePage({report, route, transaction, transactionBackup} const oldAddresses = _.mapObject(oldWaypoints, (waypoint) => _.pick(waypoint, 'address')); const addresses = _.mapObject(waypoints, (waypoint) => _.pick(waypoint, 'address')); if (_.isEqual(oldAddresses, addresses)) { - Navigation.dismissModalWithReportID(report.reportID); + Navigation.dismissModal(report.reportID); return; } @@ -84,7 +84,7 @@ function EditRequestDistancePage({report, route, transaction, transactionBackup} // If the client is offline, then the modal can be closed as well (because there are no errors or other feedback to show them // until they come online again and sync with the server). if (isOffline) { - Navigation.dismissModalWithReportID(report.reportID); + Navigation.dismissModal(report.reportID); } }; diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 76931d73e18f..d0d2a23bb563 100755 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -155,7 +155,7 @@ function SearchPage({betas, personalDetails, reports, isSearchingForReports, nav return; } if (option.reportID) { - Navigation.dismissModalWithReportID(option.reportID); + Navigation.dismissModal(option.reportID); } else { Report.navigateToAndOpenReport([option.login]); } diff --git a/src/pages/SearchPage/index.js b/src/pages/SearchPage/index.js index 3fd28a39f64b..211f3622e06c 100644 --- a/src/pages/SearchPage/index.js +++ b/src/pages/SearchPage/index.js @@ -123,7 +123,7 @@ function SearchPage({betas, reports}) { if (option.reportID) { setSearchValue(''); - Navigation.dismissModalWithReportID(option.reportID); + Navigation.dismissModal(option.reportID); } else { Report.navigateToAndOpenReport([option.login]); } diff --git a/src/pages/settings/Preferences/ThemePage.js b/src/pages/settings/Preferences/ThemePage.js index 95b280f76076..4907056be761 100644 --- a/src/pages/settings/Preferences/ThemePage.js +++ b/src/pages/settings/Preferences/ThemePage.js @@ -41,7 +41,7 @@ function ThemePage(props) { title={translate('themePage.theme')} shouldShowBackButton onBackButtonPress={() => Navigation.goBack()} - onCloseButtonPress={() => Navigation.dismissModal(true)} + onCloseButtonPress={() => Navigation.dismissModal()} /> {translate('themePage.chooseThemeBelowOrSync')} diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js index 6ab37b1196b9..f3627a9bd04d 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.js +++ b/src/pages/tasks/TaskAssigneeSelectorModal.js @@ -139,7 +139,7 @@ function TaskAssigneeSelectorModal(props) { if (report && !ReportUtils.isTaskReport(report)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModalWithReportID(report.reportID); + Navigation.dismissModal(report.reportID); }); } diff --git a/src/pages/tasks/TaskDescriptionPage.js b/src/pages/tasks/TaskDescriptionPage.js index bc2ade3aad0a..3a6999d4408a 100644 --- a/src/pages/tasks/TaskDescriptionPage.js +++ b/src/pages/tasks/TaskDescriptionPage.js @@ -60,14 +60,14 @@ function TaskDescriptionPage(props) { Task.editTask(props.report, {description: values.description}); } - Navigation.dismissModalWithReportID(props.report.reportID); + Navigation.dismissModal(props.report.reportID); }, [props], ); if (!ReportUtils.isTaskReport(props.report)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModalWithReportID(props.report.reportID); + Navigation.dismissModal(props.report.reportID); }); } const inputRef = useRef(null); diff --git a/src/pages/tasks/TaskTitlePage.js b/src/pages/tasks/TaskTitlePage.js index 351540b64e31..9b393a8a2374 100644 --- a/src/pages/tasks/TaskTitlePage.js +++ b/src/pages/tasks/TaskTitlePage.js @@ -66,14 +66,14 @@ function TaskTitlePage(props) { Task.editTask(props.report, {title: values.title}); } - Navigation.dismissModalWithReportID(props.report.reportID); + Navigation.dismissModal(props.report.reportID); }, [props], ); if (!ReportUtils.isTaskReport(props.report)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModalWithReportID(props.report.reportID); + Navigation.dismissModal(props.report.reportID); }); } diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index e3068ffb1de8..b616b519ff32 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -175,7 +175,7 @@ function WorkspaceNewRoomPage(props) { if (!(((wasLoading && !props.formState.isLoading) || (isOffline && props.formState.isLoading)) && _.isEmpty(props.formState.errorFields))) { return; } - Navigation.dismissModalWithReportID(newRoomReportID); + Navigation.dismissModal(newRoomReportID); // eslint-disable-next-line react-hooks/exhaustive-deps -- we just want this to update on changing the form State }, [props.formState]); diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js index cc5088ebd4c9..9c3c5a756faf 100644 --- a/tests/actions/IOUTest.js +++ b/tests/actions/IOUTest.js @@ -24,7 +24,7 @@ jest.mock('../../src/libs/Navigation/Navigation', () => ({ navigate: jest.fn(), dismissModal: jest.fn(), dismissModalWithReport: jest.fn(), - dismissModalWithReportID: jest.fn(), + dismissModal: jest.fn(), goBack: jest.fn(), })); From a47c9b2644e3c497656e040720f5ec4969344416 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 31 Jan 2024 11:50:46 +0100 Subject: [PATCH 631/764] fix lint --- src/Expensify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Expensify.js b/src/Expensify.js index be01159c95d7..d9282229b749 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -4,7 +4,6 @@ import React, {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useStat import {AppState, Linking} from 'react-native'; import Onyx, {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute'; import ConfirmModal from './components/ConfirmModal'; import DeeplinkWrapper from './components/DeeplinkWrapper'; import EmojiPicker from './components/EmojiPicker/EmojiPicker'; @@ -24,6 +23,7 @@ import compose from './libs/compose'; import * as Growl from './libs/Growl'; import Log from './libs/Log'; import migrateOnyx from './libs/migrateOnyx'; +import getTopmostBottomTabRoute from './libs/Navigation/getTopmostBottomTabRoute'; import Navigation, {navigationRef} from './libs/Navigation/Navigation'; import NavigationRoot from './libs/Navigation/NavigationRoot'; import NetworkConnection from './libs/NetworkConnection'; From b33e251bd0876f3a04f036658680664c653d0e61 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:24:30 +0100 Subject: [PATCH 632/764] modify margins for workspace switcher (200) --- src/pages/WorkspaceSwitcherPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/WorkspaceSwitcherPage.js b/src/pages/WorkspaceSwitcherPage.js index 05edef8fc2bd..23d79898e58c 100644 --- a/src/pages/WorkspaceSwitcherPage.js +++ b/src/pages/WorkspaceSwitcherPage.js @@ -213,7 +213,7 @@ function WorkspaceSwitcherPage({policies}) { const workspacesSection = useMemo( () => ( <> - 0 ? [styles.mb1] : [styles.mb3])]}> + 0 ? [styles.mb0] : [styles.mb3])]}> Date: Wed, 31 Jan 2024 12:31:04 +0100 Subject: [PATCH 633/764] Revert optional status changes --- .../home/sidebar/AvatarWithOptionalStatus.js | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/pages/home/sidebar/AvatarWithOptionalStatus.js b/src/pages/home/sidebar/AvatarWithOptionalStatus.js index 80130d50555c..e1ff3982a0cc 100644 --- a/src/pages/home/sidebar/AvatarWithOptionalStatus.js +++ b/src/pages/home/sidebar/AvatarWithOptionalStatus.js @@ -29,13 +29,14 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const showSettingsPage = useCallback(() => { + const showStatusPage = useCallback(() => { if (isCreateMenuOpen) { // Prevent opening Settings page when click profile avatar quickly after clicking FAB icon return; } - Navigation.navigate(ROUTES.SETTINGS); + Navigation.setShouldPopAllStateOnUP(); + Navigation.navigate(ROUTES.SETTINGS_STATUS); }, [isCreateMenuOpen]); return ( @@ -44,15 +45,17 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) { - - {emojiStatus} - + + + {emojiStatus} + + ); From e6e22bf0796f57af56ba1168c0d4b47df7f69704 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:33:48 +0100 Subject: [PATCH 634/764] fix lint --- src/libs/Navigation/switchPolicyID.ts | 2 +- tests/actions/IOUTest.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/Navigation/switchPolicyID.ts b/src/libs/Navigation/switchPolicyID.ts index 2130fdfb6f99..0cbd4874e7ae 100644 --- a/src/libs/Navigation/switchPolicyID.ts +++ b/src/libs/Navigation/switchPolicyID.ts @@ -11,7 +11,7 @@ import getStateFromPath from './getStateFromPath'; import getTopmostCentralPaneRoute from './getTopmostCentralPaneRoute'; import linkingConfig from './linkingConfig'; import TAB_TO_CENTRAL_PANE_MAPPING from './linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING'; -import type {CentralPaneNavigatorParamList, NavigationRoot, RootStackParamList, StackNavigationAction, State, SwitchPolicyIDParams} from './types'; +import type {NavigationRoot, RootStackParamList, StackNavigationAction, State, SwitchPolicyIDParams} from './types'; type ActionPayloadParams = { screen?: string; diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js index 9c3c5a756faf..92b39fc3ac50 100644 --- a/tests/actions/IOUTest.js +++ b/tests/actions/IOUTest.js @@ -24,7 +24,6 @@ jest.mock('../../src/libs/Navigation/Navigation', () => ({ navigate: jest.fn(), dismissModal: jest.fn(), dismissModalWithReport: jest.fn(), - dismissModal: jest.fn(), goBack: jest.fn(), })); From e7ff2176847948ce3c0a5d5121393c08bbabd5e0 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 31 Jan 2024 12:39:06 +0100 Subject: [PATCH 635/764] Fix TS issues after merging main --- src/components/DotIndicatorMessage.tsx | 5 ++--- src/components/MessagesRow.tsx | 3 ++- src/components/OfflineWithFeedback.tsx | 5 +++-- src/components/ReportActionItem/MoneyRequestView.tsx | 6 +++++- src/libs/Localize/index.ts | 6 +++++- src/libs/ReceiptUtils.ts | 2 +- src/types/onyx/Transaction.ts | 2 +- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/components/DotIndicatorMessage.tsx b/src/components/DotIndicatorMessage.tsx index d18704fdfb05..d2143f5b48da 100644 --- a/src/components/DotIndicatorMessage.tsx +++ b/src/components/DotIndicatorMessage.tsx @@ -8,13 +8,12 @@ import useThemeStyles from '@hooks/useThemeStyles'; import fileDownload from '@libs/fileDownload'; import * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; +import type {ReceiptError} from '@src/types/onyx/Transaction'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import {PressableWithoutFeedback} from './Pressable'; import Text from './Text'; -type ReceiptError = {error?: string; source: string; filename: string}; - type DotIndicatorMessageProps = { /** * In most cases this should just be errors from onxyData @@ -23,7 +22,7 @@ type DotIndicatorMessageProps = { * timestamp: 'message', * } */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx index cfec6fd292e9..7c764ec94fcd 100644 --- a/src/components/MessagesRow.tsx +++ b/src/components/MessagesRow.tsx @@ -6,6 +6,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import type * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; +import type {ReceiptError} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DotIndicatorMessage from './DotIndicatorMessage'; import Icon from './Icon'; @@ -15,7 +16,7 @@ import Tooltip from './Tooltip'; type MessagesRowProps = { /** The messages to display */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx index 1a8f313af267..2fad21fb54ef 100644 --- a/src/components/OfflineWithFeedback.tsx +++ b/src/components/OfflineWithFeedback.tsx @@ -8,6 +8,7 @@ import mapChildrenFlat from '@libs/mapChildrenFlat'; import shouldRenderOffscreen from '@libs/shouldRenderOffscreen'; import CONST from '@src/CONST'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import type {ReceiptError, ReceiptErrors} from '@src/types/onyx/Transaction'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import MessagesRow from './MessagesRow'; @@ -26,7 +27,7 @@ type OfflineWithFeedbackProps = ChildrenProps & { shouldHideOnDelete?: boolean; /** The errors to display */ - errors?: OnyxCommon.Errors | null; + errors?: OnyxCommon.Errors | ReceiptErrors | null; /** Whether we should show the error messages */ shouldShowErrorMessages?: boolean; @@ -84,7 +85,7 @@ function OfflineWithFeedback({ const hasErrors = !isEmptyObject(errors ?? {}); // Some errors have a null message. This is used to apply opacity only and to avoid showing redundant messages. - const errorMessages = omitBy(errors, (e) => e === null); + const errorMessages = omitBy(errors, (e: string | ReceiptError) => e === null); const hasErrorMessages = !isEmptyObject(errorMessages); const isOfflinePendingAction = !!isOffline && !!pendingAction; const isUpdateOrDeleteError = hasErrors && (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 6e814811f858..ee727ad81518 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -205,9 +205,13 @@ function MoneyRequestView({ {hasReceipt && ( { + if (!transaction?.transactionID) { + return; + } + Transaction.clearError(transaction.transactionID); }} > diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index bc40f93dd13b..46ca550eaa1a 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -7,6 +7,7 @@ import CONST from '@src/CONST'; import translations from '@src/languages/translations'; import type {TranslationFlatObject, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {ReceiptError} from '@src/types/onyx/Transaction'; import LocaleListener from './LocaleListener'; import BaseLocaleListener from './LocaleListener/BaseLocaleListener'; @@ -102,7 +103,10 @@ type MaybePhraseKey = string | [string, Record & {isTranslated? /** * Return translated string for given error. */ -function translateIfPhraseKey(message: MaybePhraseKey): string { +function translateIfPhraseKey(message: MaybePhraseKey): string; +function translateIfPhraseKey(message: ReceiptError): ReceiptError; +function translateIfPhraseKey(message: MaybePhraseKey | ReceiptError): string | ReceiptError; +function translateIfPhraseKey(message: MaybePhraseKey | ReceiptError): string | ReceiptError { if (!message || (Array.isArray(message) && message.length === 0)) { return ''; } diff --git a/src/libs/ReceiptUtils.ts b/src/libs/ReceiptUtils.ts index cbffb5b454b3..444b9b0f3954 100644 --- a/src/libs/ReceiptUtils.ts +++ b/src/libs/ReceiptUtils.ts @@ -37,7 +37,7 @@ function getThumbnailAndImageURIs(transaction: OnyxEntry, receiptPa } // URI to image, i.e. blob:new.expensify.com/9ef3a018-4067-47c6-b29f-5f1bd35f213d or expensify.com/receipts/w_e616108497ef940b7210ec6beb5a462d01a878f4.jpg // If there're errors, we need to display them in preview. We can store many files in errors, but we just need to get the last one - const errors = _.findLast(transaction.errors) as ReceiptError | undefined; + const errors = _.findLast(transaction?.errors) as ReceiptError | undefined; const path = errors?.source ?? transaction?.receipt?.source ?? receiptPath ?? ''; // filename of uploaded image or last part of remote URI const filename = errors?.filename ?? transaction?.filename ?? receiptFileName ?? ''; diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 8f2b9d03dc9e..fe7ca7436a81 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -103,4 +103,4 @@ type Transaction = { }; export default Transaction; -export type {WaypointCollection, Comment, Receipt, Waypoint, ReceiptError, TransactionPendingFieldsKey}; +export type {WaypointCollection, Comment, Receipt, Waypoint, ReceiptError, ReceiptErrors, TransactionPendingFieldsKey}; From 73c6c75ee0d010ddde9e8f7034c75a9fede32286 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:42:44 +0100 Subject: [PATCH 636/764] fix loading indicator in the header --- src/pages/home/HeaderView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 1e3d34af64e7..c2d1ecffc2a7 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -227,7 +227,7 @@ function HeaderView(props) { dataSet={{dragArea: true}} > - + {isLoading ? ( ) : ( From 8ed596858c400051ab3e3d2899141f3082416ed0 Mon Sep 17 00:00:00 2001 From: caitlinwhite1 Date: Wed, 31 Jan 2024 06:19:49 -0600 Subject: [PATCH 637/764] Update redirects.csv URL was missing for global reimbursmenets --- docs/redirects.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/redirects.csv b/docs/redirects.csv index 4881e3f50a31..1f90b1565771 100644 --- a/docs/redirects.csv +++ b/docs/redirects.csv @@ -30,7 +30,7 @@ https://community.expensify.com/discussion/5124/how-to-add-your-name-and-photo-t https://community.expensify.com/discussion/5149/how-to-manage-your-devices-in-expensify,https://help.expensify.com/articles/expensify-classic/account-settings/Account-Details https://community.expensify.com/discussion/4432/how-to-add-a-secondary-login,https://help.expensify.com/articles/expensify-classic/account-settings/Account-Details https://community.expensify.com/discussion/6794/how-to-change-your-email-in-expensify,https://help.expensify.com/articles/expensify-classic/account-settings/Account-Details -Reimbursements,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/Global-Reimbursements +https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/International-Reimbursements,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/Global-Reimbursements https://community.expensify.com/discussion/4452/how-to-merge-accounts,https://help.expensify.com/articles/expensify-classic/account-settings/Merge-Accounts#gsc.tab=0 https://community.expensify.com/discussion/4783/how-to-add-or-remove-a-copilot#latest,https://help.expensify.com/articles/expensify-classic/account-settings/Copilot#gsc.tab=0 https://community.expensify.com/discussion/4343/expensify-anz-partnership-announcement,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Connect-ANZ From dd95e9b93d4594d25b1b38e0e164d94bd226a8b0 Mon Sep 17 00:00:00 2001 From: Github Date: Wed, 31 Jan 2024 13:39:50 +0100 Subject: [PATCH 638/764] Change navigation mock in perf tests for SignInPage --- tests/perf-test/SignInPage.perf-test.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/perf-test/SignInPage.perf-test.tsx b/tests/perf-test/SignInPage.perf-test.tsx index 80964c3c49cd..dde8596fb2ae 100644 --- a/tests/perf-test/SignInPage.perf-test.tsx +++ b/tests/perf-test/SignInPage.perf-test.tsx @@ -18,17 +18,6 @@ import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; -jest.mock('../../src/libs/Navigation/Navigation', () => { - const actualNav = jest.requireActual('../../src/libs/Navigation/Navigation'); - return { - ...actualNav, - navigationRef: { - addListener: () => jest.fn(), - removeListener: () => jest.fn(), - }, - } as typeof Navigation; -}); - const mockedNavigate = jest.fn(); jest.mock('@react-navigation/native', () => { const actualNav = jest.requireActual('@react-navigation/native'); @@ -43,7 +32,10 @@ jest.mock('@react-navigation/native', () => { navigate: jest.fn(), addListener: () => jest.fn(), }), - createNavigationContainerRef: jest.fn(), + createNavigationContainerRef: () => ({ + addListener: () => jest.fn(), + removeListener: () => jest.fn(), + }), } as typeof NativeNavigation; }); From 7ce42f46f13c59ed13ae2a738d7ae7ab26ca0f1d Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 31 Jan 2024 15:29:38 +0100 Subject: [PATCH 639/764] Fix NewExpensify icon color --- assets/images/new-expensify.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/images/new-expensify.svg b/assets/images/new-expensify.svg index 264821d4f86e..89102ecbc5e4 100644 --- a/assets/images/new-expensify.svg +++ b/assets/images/new-expensify.svg @@ -1 +1 @@ - + From 75d6d88ef7d7bd392967984fe0644da3a1d9c6bd Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 31 Jan 2024 15:32:07 +0100 Subject: [PATCH 640/764] fix previous temporary fix --- src/Expensify.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Expensify.js b/src/Expensify.js index d9282229b749..dfb59a0f8848 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -23,8 +23,7 @@ import compose from './libs/compose'; import * as Growl from './libs/Growl'; import Log from './libs/Log'; import migrateOnyx from './libs/migrateOnyx'; -import getTopmostBottomTabRoute from './libs/Navigation/getTopmostBottomTabRoute'; -import Navigation, {navigationRef} from './libs/Navigation/Navigation'; +import Navigation from './libs/Navigation/Navigation'; import NavigationRoot from './libs/Navigation/NavigationRoot'; import NetworkConnection from './libs/NetworkConnection'; import PushNotification from './libs/Notification/PushNotification'; @@ -38,7 +37,6 @@ import Visibility from './libs/Visibility'; import ONYXKEYS from './ONYXKEYS'; import PopoverReportActionContextMenu from './pages/home/report/ContextMenu/PopoverReportActionContextMenu'; import * as ReportActionContextMenu from './pages/home/report/ContextMenu/ReportActionContextMenu'; -import SCREENS from './SCREENS'; Onyx.registerLogger(({level, message}) => { if (level === 'alert') { @@ -64,7 +62,8 @@ const propTypes = { /** Whether a new update is available and ready to install. */ updateAvailable: PropTypes.bool, - /** Tells us if the sidebar has rendered */ + /** Tells us if the sidebar has rendered - TODO: We don't use it as temporary solution to fix not hidding splashscreen */ + // eslint-disable-next-line react/no-unused-prop-types isSidebarLoaded: PropTypes.bool, /** Information about a screen share call requested by a GuidesPlus agent */ @@ -132,16 +131,7 @@ function Expensify(props) { [isSplashHidden], ); - // This is a temporary fix to handle more that one possible screen in the sidebar. - const isSidebarLoaded = useMemo(() => { - if (!isNavigationReady) { - return false; - } - - return getTopmostBottomTabRoute(navigationRef.getState()).name === SCREENS.HOME ? props.isSidebarLoaded : true; - }, [isNavigationReady, props.isSidebarLoaded]); - - const shouldInit = isNavigationReady && (!isAuthenticated || isSidebarLoaded) && hasAttemptedToOpenPublicRoom; + const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom; const shouldHideSplash = shouldInit && !isSplashHidden; const initializeClient = () => { From 88d27a0e312ee856f54adb4d28a6acfbcbeaad6c Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 31 Jan 2024 17:32:20 +0300 Subject: [PATCH 641/764] Update docs/assets/js/main.js Co-authored-by: Nikki Wines --- docs/assets/js/main.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index 473bd544c7b8..6b3390148ff0 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -216,13 +216,11 @@ window.addEventListener('DOMContentLoaded', () => { const expensifyClassicContent = document.getElementById('expensify-classic'); const newExpensifyContent = document.getElementById('new-expensify'); - let contentSelector; + let contentSelector = '.article-toc-content'; if (expensifyClassicContent) { contentSelector = '#expensify-classic'; } else if (newExpensifyContent) { contentSelector = '#new-expensify'; - } else { - contentSelector = '.article-toc-content'; } if (window.tocbot) { From db2937ae9fd931949aaa5e8ddbecc6bb571bba43 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 31 Jan 2024 20:03:10 +0530 Subject: [PATCH 642/764] rm breaker --- docs/assets/js/platform-tabs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/assets/js/platform-tabs.js b/docs/assets/js/platform-tabs.js index 18746efc5a84..e677e58b1e97 100644 --- a/docs/assets/js/platform-tabs.js +++ b/docs/assets/js/platform-tabs.js @@ -1,6 +1,5 @@ const expensifyClassicContent = document.getElementById('expensify-classic'); const newExpensifyContent = document.getElementById('new-expensify'); - const platformTabs = document.getElementById('platform-tabs'); if (expensifyClassicContent) { From ed3b10b4fe00ee96e2bedc4c54831a63dd5b7aaa Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:50:56 +0100 Subject: [PATCH 643/764] Fix padding android --- src/styles/theme/themes/dark.ts | 4 ++++ src/styles/theme/themes/light.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/styles/theme/themes/dark.ts b/src/styles/theme/themes/dark.ts index 4ab481d34e9b..0417f4a7920b 100644 --- a/src/styles/theme/themes/dark.ts +++ b/src/styles/theme/themes/dark.ts @@ -91,6 +91,10 @@ const darkTheme = { // The route urls from ROUTES.ts are only used for deep linking and configuring URLs on web. // The screen name (see SCREENS.ts) is the name of the screen as far as react-navigation is concerned, and the linkingConfig maps screen names to URLs PAGE_THEMES: { + [SCREENS.HOME]: { + backgroundColor: colors.productDark200, + statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT, + }, [SCREENS.REPORT]: { backgroundColor: colors.productDark100, statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT, diff --git a/src/styles/theme/themes/light.ts b/src/styles/theme/themes/light.ts index 643fdfa19460..7632562c47d7 100644 --- a/src/styles/theme/themes/light.ts +++ b/src/styles/theme/themes/light.ts @@ -91,6 +91,10 @@ const lightTheme = { // The route urls from ROUTES.ts are only used for deep linking and configuring URLs on web. // The screen name (see SCREENS.ts) is the name of the screen as far as react-navigation is concerned, and the linkingConfig maps screen names to URLs PAGE_THEMES: { + [SCREENS.HOME]: { + backgroundColor: colors.productLight200, + statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT, + }, [SCREENS.REPORT]: { backgroundColor: colors.productLight100, statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT, From 5b6cf79f404cb5d6a3677871622e62f7e0badd7a Mon Sep 17 00:00:00 2001 From: Antony Kithinzi Date: Wed, 31 Jan 2024 17:33:14 +0100 Subject: [PATCH 644/764] prettier --- src/components/ReportActionItem/ReportPreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 712dd6e56760..d9146c25edcf 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -229,7 +229,7 @@ function ReportPreview({ }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; return ( - From 3a2108a4e9fda4ea682f36a58650ae20fd2b12d3 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 31 Jan 2024 17:35:34 +0100 Subject: [PATCH 645/764] Add hovered effect on the workspace switcher button (210) --- src/components/SubscriptAvatar.tsx | 5 ++++- src/components/WorkspaceSwitcherButton.tsx | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/components/SubscriptAvatar.tsx b/src/components/SubscriptAvatar.tsx index 71b63cb07ca1..c2de41d8b4db 100644 --- a/src/components/SubscriptAvatar.tsx +++ b/src/components/SubscriptAvatar.tsx @@ -20,6 +20,9 @@ type SubIcon = { /** Height of the icon */ height?: number; + + /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue'. */ + fill?: string; }; type SubscriptAvatarProps = { @@ -120,7 +123,7 @@ function SubscriptAvatar({mainAvatar, secondaryAvatar, subscriptIcon, size = CON width={subscriptIcon.width} height={subscriptIcon.height} additionalStyles={styles.alignSelfCenter} - fill={theme.icon} + fill={subscriptIcon.fill ?? theme.icon} /> )} diff --git a/src/components/WorkspaceSwitcherButton.tsx b/src/components/WorkspaceSwitcherButton.tsx index b76503c0c6e9..b7485fbab7a8 100644 --- a/src/components/WorkspaceSwitcherButton.tsx +++ b/src/components/WorkspaceSwitcherButton.tsx @@ -2,6 +2,7 @@ import React, {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import Navigation from '@libs/Navigation/Navigation'; import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils'; @@ -21,6 +22,7 @@ type WorkspaceSwitcherButtonProps = {activeWorkspaceID?: string} & WorkspaceSwit function WorkspaceSwitcherButton({activeWorkspaceID, policy}: WorkspaceSwitcherButtonProps) { const {translate} = useLocalize(); + const theme = useTheme(); const {source, name, type} = useMemo(() => { if (!activeWorkspaceID) { @@ -46,12 +48,19 @@ function WorkspaceSwitcherButton({activeWorkspaceID, policy}: WorkspaceSwitcherB }) } > - + {({hovered}) => ( + + )} ); } From 5595560e1b3faf78f9bec4498308e4b47d9565e8 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 31 Jan 2024 09:39:20 -0700 Subject: [PATCH 646/764] show card for corporate cards --- src/components/ReportActionItem/MoneyRequestPreview.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js index 7b38dcd34109..13f75b9869a0 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.js +++ b/src/components/ReportActionItem/MoneyRequestPreview.js @@ -165,7 +165,7 @@ function MoneyRequestPreview(props) { const isScanning = hasReceipt && TransactionUtils.isReceiptBeingScanned(props.transaction); const hasFieldErrors = TransactionUtils.hasMissingSmartscanFields(props.transaction); const isDistanceRequest = TransactionUtils.isDistanceRequest(props.transaction); - const isExpensifyCardTransaction = TransactionUtils.isExpensifyCardTransaction(props.transaction); + const isCardTransaction = TransactionUtils.isCardTransaction(props.transaction); const isSettled = ReportUtils.isSettled(props.iouReport.reportID); const isDeleted = lodashGet(props.action, 'pendingAction', null) === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; @@ -184,7 +184,7 @@ function MoneyRequestPreview(props) { const receiptImages = hasReceipt ? [ReceiptUtils.getThumbnailAndImageURIs(props.transaction)] : []; const getSettledMessage = () => { - if (isExpensifyCardTransaction) { + if (isCardTransaction) { return translate('common.done'); } return translate('iou.settledExpensify'); @@ -207,7 +207,7 @@ function MoneyRequestPreview(props) { return translate('iou.split'); } - if (isExpensifyCardTransaction) { + if (isCardTransaction) { let message = translate('iou.card'); if (TransactionUtils.isPending(props.transaction)) { message += ` • ${translate('iou.pending')}`; From 7860696cba7d465c404b30a17e0b9e8772e8eb4f Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 31 Jan 2024 18:01:18 +0100 Subject: [PATCH 647/764] fix for goBack on ProfilePage and WorkspacesListPage --- src/pages/ProfilePage.js | 2 +- src/pages/workspace/WorkspacesListPage.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index bf99b3ef0a45..11e2afeb6e95 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -133,7 +133,7 @@ function ProfilePage(props) { const hasStatus = !!statusEmojiCode; const statusContent = `${statusEmojiCode} ${statusText}`; - const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.HOME); + const navigateBackTo = lodashGet(props.route, 'params.backTo'); const shouldShowNotificationPreference = !_.isEmpty(props.report) && props.report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN; const notificationPreference = shouldShowNotificationPreference ? props.translate(`notificationPreferencesPage.notificationPreferences.${props.report.notificationPreference}`) : ''; diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index 9442ffafa862..5b499fe7a3ee 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -322,7 +322,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r Navigation.goBack(ROUTES.ALL_SETTINGS)} + onBackButtonPress={() => Navigation.goBack()} >