diff --git a/src/libs/AccountUtils.ts b/src/libs/AccountUtils.ts index d903584e15b4..8bc7037e9682 100644 --- a/src/libs/AccountUtils.ts +++ b/src/libs/AccountUtils.ts @@ -5,4 +5,6 @@ import type {Account} from '@src/types/onyx'; const isValidateCodeFormSubmitting = (account: OnyxEntry) => !!account?.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); -export default {isValidateCodeFormSubmitting}; +const isAccountIDOddNumber = (accountID: number) => accountID % 2 === 1; + +export default {isValidateCodeFormSubmitting, isAccountIDOddNumber}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7da99d3ca8e6..a4a8de357c84 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4997,8 +4997,6 @@ function shouldReportBeInOptionList({ report?.reportName === undefined || // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing report?.isHidden || - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - report?.participantAccountIDs?.includes(CONST.ACCOUNT_ID.NOTIFICATIONS) || (report?.participantAccountIDs?.length === 0 && !isChatThread(report) && !isPublicRoom(report) && @@ -5085,6 +5083,17 @@ function shouldReportBeInOptionList({ return true; } +/** + * Returns the system report from the list of reports. + */ +function getSystemChat(): OnyxEntry { + if (!allReports) { + return null; + } + + return Object.values(allReports ?? {}).find((report) => report?.chatType === CONST.REPORT.CHAT_TYPE.SYSTEM) ?? null; +} + /** * Attempts to find a report in onyx with the provided list of participants. Does not include threads, task, expense, room, and policy expense chat. */ @@ -6581,6 +6590,7 @@ export { getRoomWelcomeMessage, getRootParentReport, getRouteFromLink, + getSystemChat, getTaskAssigneeChatOnyxData, getTransactionDetails, getTransactionReportName, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 0172b137d8ca..c36543b527ea 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -8,6 +8,7 @@ import Onyx from 'react-native-onyx'; import type {PartialDeep, ValueOf} from 'type-fest'; import type {Emoji} from '@assets/emojis/types'; import type {FileObject} from '@components/AttachmentModal'; +import AccountUtils from '@libs/AccountUtils'; import * as ActiveClientManager from '@libs/ActiveClientManager'; import * as API from '@libs/API'; import type { @@ -350,7 +351,10 @@ function subscribeToReportTypingEvents(reportID: string) { delete typingWatchTimers[reportUserIdentifier]; }, 1500); }).catch((error) => { - Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', {errorType: error.type, pusherChannelName}); + Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', { + errorType: error.type, + pusherChannelName, + }); }); } @@ -381,7 +385,10 @@ function subscribeToReportLeavingEvents(reportID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, true); }).catch((error) => { - Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', {errorType: error.type, pusherChannelName}); + Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', { + errorType: error.type, + pusherChannelName, + }); }); } @@ -914,7 +921,11 @@ function openReport( if (isFromDeepLink) { // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT, parameters, {optimisticData, successData, failureData}).finally(() => { + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT, parameters, { + optimisticData, + successData, + failureData, + }).finally(() => { Onyx.set(ONYXKEYS.IS_CHECKING_PUBLIC_ROOM, false); }); } else { @@ -1894,7 +1905,10 @@ function updateDescription(reportID: string, previousValue: string, newValue: st { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: {description: parsedDescription, pendingFields: {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}, + value: { + description: parsedDescription, + pendingFields: {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, + }, }, ]; const failureData: OnyxUpdate[] = [ @@ -1969,6 +1983,17 @@ function navigateToConciergeChat(shouldDismissModal = false, checkIfCurrentPageA } } +/** + * Navigates to the 1:1 system chat + */ +function navigateToSystemChat() { + const systemChatReport = ReportUtils.getSystemChat(); + + if (systemChatReport && systemChatReport.reportID) { + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(systemChatReport.reportID)); + } +} + /** Add a policy report (workspace room) optimistically and navigate to it. */ function addPolicyReport(policyReport: ReportUtils.OptimisticChatReport) { const createdReportAction = ReportUtils.buildOptimisticCreatedReportAction(CONST.POLICY.OWNER_EMAIL_FAKE); @@ -2246,7 +2271,10 @@ function shouldShowReportActionNotification(reportID: string, action: ReportActi // If this notification was delayed and the user saw the message already, don't show it if (action && report?.lastReadTime && report.lastReadTime >= action.created) { - Log.info(`${tag} No notification because the comment was already read`, false, {created: action.created, lastReadTime: report.lastReadTime}); + Log.info(`${tag} No notification because the comment was already read`, false, { + created: action.created, + lastReadTime: report.lastReadTime, + }); return false; } @@ -2274,7 +2302,10 @@ function showReportActionNotification(reportID: string, reportAction: ReportActi const report = allReports?.[reportID] ?? null; if (!report) { - Log.hmmm("[LocalNotification] couldn't show report action notification because the report wasn't found", {reportID, reportActionID: reportAction.reportActionID}); + Log.hmmm("[LocalNotification] couldn't show report action notification because the report wasn't found", { + reportID, + reportActionID: reportAction.reportActionID, + }); return; } @@ -3055,7 +3086,9 @@ function completeOnboarding( }, adminsChatReportID?: string, ) { - const targetEmail = CONST.EMAIL.CONCIERGE; + const isAccountIDOdd = AccountUtils.isAccountIDOddNumber(currentUserAccountID ?? 0); + const targetEmail = isAccountIDOdd ? CONST.EMAIL.NOTIFICATIONS : CONST.EMAIL.CONCIERGE; + const actorAccountID = PersonalDetailsUtils.getAccountIDsByLogins([targetEmail])[0]; const targetChatReport = ReportUtils.getChatByParticipants([actorAccountID]); const {reportID: targetChatReportID = '', policyID: targetChatPolicyID = ''} = targetChatReport ?? {}; @@ -3694,6 +3727,7 @@ export { saveReportActionDraft, deleteReportComment, navigateToConciergeChat, + navigateToSystemChat, addPolicyReport, deleteReport, navigateToConciergeChatAndDeleteReport, diff --git a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx index 7fcb5c1c5de6..216d23128d74 100644 --- a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx +++ b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx @@ -7,6 +7,7 @@ import type {FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import KeyboardAvoidingView from '@components/KeyboardAvoidingView'; import OfflineIndicator from '@components/OfflineIndicator'; +import {useSession} from '@components/OnyxProvider'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; @@ -16,6 +17,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnboardingLayout from '@hooks/useOnboardingLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import AccountUtils from '@libs/AccountUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ValidationUtils from '@libs/ValidationUtils'; @@ -36,6 +38,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat const {shouldUseNarrowLayout} = useOnboardingLayout(); const {inputCallbackRef} = useAutoFocusInput(); const [shouldValidateOnChange, setShouldValidateOnChange] = useState(false); + const {accountID} = useSession(); useDisableModalDismissOnEscape(); @@ -69,6 +72,8 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat // Otherwise stay on the chats screen. if (isSmallScreenWidth) { Navigation.navigate(ROUTES.HOME); + } else if (AccountUtils.isAccountIDOddNumber(accountID ?? 0)) { + Report.navigateToSystemChat(); } else { Report.navigateToConciergeChat(); } @@ -79,7 +84,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat Navigation.navigate(ROUTES.WELCOME_VIDEO_ROOT); }, variables.welcomeVideoDelay); }, - [currentUserPersonalDetails.login, isSmallScreenWidth, onboardingPurposeSelected, onboardingAdminsChatReportID], + [currentUserPersonalDetails.login, isSmallScreenWidth, onboardingPurposeSelected, onboardingAdminsChatReportID, accountID], ); const validate = (values: FormOnyxValues<'onboardingPersonalDetailsForm'>) => { diff --git a/src/pages/OnboardingWork/BaseOnboardingWork.tsx b/src/pages/OnboardingWork/BaseOnboardingWork.tsx index 8fdbed73111e..6524e3021a3d 100644 --- a/src/pages/OnboardingWork/BaseOnboardingWork.tsx +++ b/src/pages/OnboardingWork/BaseOnboardingWork.tsx @@ -7,6 +7,7 @@ import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import KeyboardAvoidingView from '@components/KeyboardAvoidingView'; import OfflineIndicator from '@components/OfflineIndicator'; +import {useSession} from '@components/OnyxProvider'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useDisableModalDismissOnEscape from '@hooks/useDisableModalDismissOnEscape'; @@ -14,6 +15,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnboardingLayout from '@hooks/useOnboardingLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import AccountUtils from '@libs/AccountUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ValidationUtils from '@libs/ValidationUtils'; @@ -32,6 +34,7 @@ function BaseOnboardingWork({shouldUseNativeStyles, onboardingPurposeSelected}: const {translate} = useLocalize(); const {isSmallScreenWidth} = useWindowDimensions(); const {shouldUseNarrowLayout} = useOnboardingLayout(); + const {accountID} = useSession(); useDisableModalDismissOnEscape();