diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index cfbce4358eb5..3c8c79422965 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -40,10 +40,11 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP const isSelfDM = ReportUtils.isSelfDM(report); const isInvoiceRoom = ReportUtils.isInvoiceRoom(report); const isOneOnOneChat = ReportUtils.isOneOnOneChat(report); - const isDefault = !(isChatRoom || isPolicyExpenseChat || isSelfDM || isInvoiceRoom); + const isSystemChat = ReportUtils.isSystemChat(report); + const isDefault = !(isChatRoom || isPolicyExpenseChat || isSelfDM || isInvoiceRoom || isSystemChat); const participantAccountIDs = Object.keys(report?.participants ?? {}) .map(Number) - .filter((accountID) => accountID !== session?.accountID || !isOneOnOneChat); + .filter((accountID) => accountID !== session?.accountID || (!isOneOnOneChat && !isSystemChat)); const isMultipleParticipant = participantAccountIDs.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant); const isUserPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); @@ -77,8 +78,12 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP return translate('reportActionsView.yourSpace'); } + if (isSystemChat) { + return reportName; + } + return translate('reportActionsView.sayHello'); - }, [isChatRoom, isInvoiceRoom, isSelfDM, translate, reportName]); + }, [isChatRoom, isInvoiceRoom, isSelfDM, isSystemChat, translate, reportName]); return ( <> @@ -144,6 +149,11 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP {translate('reportActionsView.beginningOfChatHistorySelfDM')} )} + {isSystemChat && ( + + {translate('reportActionsView.beginningOfChatHistorySystemDM')} + + )} {isDefault && ( {translate('reportActionsView.beginningOfChatHistory')} diff --git a/src/languages/en.ts b/src/languages/en.ts index 3ed590a4fe0c..332e64c8e2ff 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -519,6 +519,7 @@ export default { beginningOfChatHistoryPolicyExpenseChatPartTwo: ' and ', beginningOfChatHistoryPolicyExpenseChatPartThree: ' starts here! šŸŽ‰ This is the place to chat, submit expenses and settle up.', beginningOfChatHistorySelfDM: 'This is your personal space. Use it for notes, tasks, drafts, and reminders.', + beginningOfChatHistorySystemDM: "Welcome! Let's get you set up.", chatWithAccountManager: 'Chat with your account manager here', sayHello: 'Say hello!', yourSpace: 'Your space', diff --git a/src/languages/es.ts b/src/languages/es.ts index 8e1827647abb..7029d23e3a66 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -512,6 +512,7 @@ export default { beginningOfChatHistoryPolicyExpenseChatPartTwo: ' y ', beginningOfChatHistoryPolicyExpenseChatPartThree: ' empieza aquĆ­! šŸŽ‰ Este es el lugar donde chatear y presentar o pagar gastos.', beginningOfChatHistorySelfDM: 'Este es tu espacio personal. ƚsalo para notas, tareas, borradores y recordatorios.', + beginningOfChatHistorySystemDM: 'Ā”Bienvenido! Vamos a configurar tu cuenta.', chatWithAccountManager: 'Chatea con tu gestor de cuenta aquĆ­', sayHello: 'Ā”Saluda!', yourSpace: 'Tu espacio', diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index f321c10c686e..13c1527c6dc2 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1867,7 +1867,7 @@ function getOptions( allPersonalDetailsOptions = lodashOrderBy(allPersonalDetailsOptions, [(personalDetail) => personalDetail.text?.toLowerCase()], 'asc'); } - const optionsToExclude: Option[] = [{login: CONST.EMAIL.NOTIFICATIONS}]; + const optionsToExclude: Option[] = []; // If we're including selected options from the search results, we only want to exclude them if the search input is empty // This is because on certain pages, we show the selected options at the top when the search input is empty diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 690cfdafd92d..db1e9e19858c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1200,6 +1200,8 @@ function findLastAccessedReport( } if (isFirstTimeNewExpensifyUser) { + // Filter out the systemChat report from the reports list, as we don't want to drop the user into that report over Concierge when they first log in + sortedReports = sortedReports.filter((report) => !isSystemChat(report)) ?? []; if (sortedReports.length === 1) { return sortedReports[0]; } @@ -1207,6 +1209,13 @@ function findLastAccessedReport( return adminReport ?? sortedReports.find((report) => !isConciergeChatReport(report)) ?? null; } + // If we only have two reports and one of them is the system chat, filter it out so we don't + // overwrite showing the concierge chat + const hasSystemChat = sortedReports.find((report) => isSystemChat(report)) ?? false; + if (sortedReports.length === 2 && hasSystemChat) { + sortedReports = sortedReports.filter((report) => !isSystemChat(report)) ?? []; + } + return adminReport ?? sortedReports.at(-1) ?? null; } @@ -2052,6 +2061,10 @@ function getIcons( return getIconsForParticipants([currentUserAccountID ?? 0], personalDetails); } + if (isSystemChat(report)) { + return getIconsForParticipants([CONST.ACCOUNT_ID.NOTIFICATIONS ?? 0], personalDetails); + } + if (isGroupChat(report)) { const groupChatIcon = { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -3229,6 +3242,10 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu formattedName = getDisplayNameForParticipant(currentUserAccountID, undefined, undefined, true); } + if (isInvoiceRoom(report)) { + formattedName = getInvoicesChatName(report); + } + if (formattedName) { return formattedName; } @@ -5200,11 +5217,13 @@ function shouldReportBeInOptionList({ !isMoneyRequestReport(report) && !isTaskReport(report) && !isSelfDM(report) && + !isSystemChat(report) && !isGroupChat(report) && !isInvoiceRoom(report)) ) { return false; } + if (!canAccessReport(report, policies, betas)) { return false; } @@ -5267,7 +5286,7 @@ function shouldReportBeInOptionList({ } // Hide chats between two users that haven't been commented on from the LNH - if (excludeEmptyChats && isEmptyChat && isChatReport(report) && !isChatRoom(report) && !isPolicyExpenseChat(report) && !isGroupChat(report) && canHideReport) { + if (excludeEmptyChats && isEmptyChat && isChatReport(report) && !isChatRoom(report) && !isPolicyExpenseChat(report) && !isSystemChat(report) && !isGroupChat(report) && canHideReport) { return false; } @@ -5599,7 +5618,7 @@ function isGroupChatAdmin(report: OnyxEntry, accountID: number) { */ function getMoneyRequestOptions(report: OnyxEntry, policy: OnyxEntry, reportParticipants: number[], filterDeprecatedTypes = false): IOUType[] { // In any thread or task report, we do not allow any new expenses yet - if (isChatThread(report) || isTaskReport(report) || isInvoiceReport(report)) { + if (isChatThread(report) || isTaskReport(report) || isInvoiceReport(report) || isSystemChat(report)) { return []; } @@ -6614,7 +6633,7 @@ function canJoinChat(report: OnyxEntry, parentReportAction: OnyxEntry error?.[0] !== 'report.genericSmartscanFailureMessage'); - const shouldOverrideHidden = hasErrorsOtherThanFailedReceipt || isFocused || report.isPinned; + const isSystemChat = ReportUtils.isSystemChat(report); + const shouldOverrideHidden = hasErrorsOtherThanFailedReceipt || isFocused || isSystemChat || report.isPinned; if (isHidden && !shouldOverrideHidden) { return false; } diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 1436aba4e3ce..02f97397e4cd 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -88,15 +88,17 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD // eslint-disable-next-line react-hooks/exhaustive-deps -- policy is a dependency because `getChatRoomSubtitle` calls `getPolicyName` which in turn retrieves the value from the `policy` value stored in Onyx const chatRoomSubtitle = useMemo(() => ReportUtils.getChatRoomSubtitle(report), [report, policy]); const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(report); + const isSystemChat = useMemo(() => ReportUtils.isSystemChat(report), [report]); const isGroupChat = useMemo(() => ReportUtils.isGroupChat(report), [report]); const isThread = useMemo(() => ReportUtils.isThread(report), [report]); const participants = useMemo(() => { - if (isGroupChat) { - return ReportUtils.getParticipantAccountIDs(report.reportID ?? ''); + if (isGroupChat || isSystemChat) { + // Filter out the current user from the particpants of the systemChat + return ReportUtils.getParticipantAccountIDs(report.reportID ?? '').filter((accountID) => accountID !== session?.accountID && isSystemChat); } return ReportUtils.getVisibleChatMemberAccountIDs(report.reportID ?? ''); - }, [report, isGroupChat]); + }, [report, session, isGroupChat, isSystemChat]); // Get the active chat members by filtering out the pending members with delete action const activeChatMembers = participants.flatMap((accountID) => { @@ -148,7 +150,8 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD (isDefaultRoom && isChatThread && isPolicyEmployee) || (!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && (isPolicyEmployee || (isChatThread && !ReportUtils.isPublicRoom(report))))) && - !ReportUtils.isConciergeChatReport(report) + !ReportUtils.isConciergeChatReport(report) && + !isSystemChat ) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS, @@ -222,6 +225,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD return items; }, [ isSelfDM, + isSystemChat, isArchivedRoom, isGroupChat, isDefaultRoom, diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index b16fb86f9b21..70597a25ceb3 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -90,11 +90,12 @@ function HeaderView({ const isSelfDM = ReportUtils.isSelfDM(report); const isGroupChat = ReportUtils.isGroupChat(report) || ReportUtils.isDeprecatedGroupDM(report); const isOneOnOneChat = ReportUtils.isOneOnOneChat(report); + const isSystemChat = ReportUtils.isSystemChat(report); // For 1:1 chat, we don't want to include currentUser as participants in order to not mark 1:1 chats as having multiple participants const participants = Object.keys(report?.participants ?? {}) .map(Number) - .filter((accountID) => accountID !== session?.accountID || !isOneOnOneChat) + .filter((accountID) => accountID !== session?.accountID || (!isOneOnOneChat && !isSystemChat)) .slice(0, 5); const isMultipleParticipant = participants.length > 1;