Skip to content

Commit

Permalink
Merge pull request #37165 from ishpaul777/trackExpense/selfDM
Browse files Browse the repository at this point in the history
Track expense/self dm
  • Loading branch information
thienlnam authored Mar 2, 2024
2 parents da07ed9 + 5cfb38d commit cbd13ed
Show file tree
Hide file tree
Showing 17 changed files with 135 additions and 34 deletions.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ const CONST = {
DOMAIN_ALL: 'domainAll',
POLICY_ROOM: 'policyRoom',
POLICY_EXPENSE_CHAT: 'policyExpenseChat',
SELF_DM: 'selfDM',
},
WORKSPACE_CHAT_ROOMS: {
ANNOUNCE: '#announce',
Expand Down
27 changes: 22 additions & 5 deletions src/components/ReportWelcomeText.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
Expand Down Expand Up @@ -35,7 +35,8 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP
const styles = useThemeStyles();
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report);
const isChatRoom = ReportUtils.isChatRoom(report);
const isDefault = !(isChatRoom || isPolicyExpenseChat);
const isSelfDM = ReportUtils.isSelfDM(report);
const isDefault = !(isChatRoom || isPolicyExpenseChat || isSelfDM);
const participantAccountIDs = report?.participantAccountIDs ?? [];
const isMultipleParticipant = participantAccountIDs.length > 1;
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant);
Expand All @@ -44,6 +45,7 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, policy, participantAccountIDs);
const additionalText = moneyRequestOptions.map((item) => translate(`reportActionsView.iouTypes.${item}`)).join(', ');
const canEditPolicyDescription = ReportUtils.canEditPolicyDescription(policy);
const reportName = ReportUtils.getReportName(report);

const navigateToReport = () => {
if (!report?.reportID) {
Expand All @@ -53,12 +55,22 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP
Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID));
};

const welcomeHeroText = useMemo(() => {
if (isChatRoom) {
return translate('reportActionsView.welcomeToRoom', {roomName: reportName});
}

if (isSelfDM) {
return translate('reportActionsView.yourSpace');
}

return translate('reportActionsView.sayHello');
}, [isChatRoom, isSelfDM, translate, reportName]);

return (
<>
<View>
<Text style={[styles.textHero]}>
{isChatRoom ? translate('reportActionsView.welcomeToRoom', {roomName: ReportUtils.getReportName(report)}) : translate('reportActionsView.sayHello')}
</Text>
<Text style={[styles.textHero]}>{welcomeHeroText}</Text>
</View>
<View style={[styles.mt3, styles.mw100]}>
{isPolicyExpenseChat &&
Expand Down Expand Up @@ -114,6 +126,11 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP
{roomWelcomeMessage.phrase2 !== undefined && <Text>{roomWelcomeMessage.phrase2}</Text>}
</Text>
))}
{isSelfDM && (
<Text>
<Text>{translate('reportActionsView.beginningOfChatHistorySelfDM')}</Text>
</Text>
)}
{isDefault && (
<Text>
<Text>{translate('reportActionsView.beginningOfChatHistory')}</Text>
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,10 @@ export default {
beginningOfChatHistoryPolicyExpenseChatPartOne: 'Collaboration between ',
beginningOfChatHistoryPolicyExpenseChatPartTwo: ' and ',
beginningOfChatHistoryPolicyExpenseChatPartThree: ' starts here! 🎉 This is the place to chat, request money and settle up.',
beginningOfChatHistorySelfDM: 'This is your personal space. Use it for notes, tasks, drafts, and reminders.',
chatWithAccountManager: 'Chat with your account manager here',
sayHello: 'Say hello!',
yourSpace: 'Your space',
welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Welcome to ${roomName}!`,
usePlusButton: ({additionalText}: UsePlusButtonParams) => `\nYou can also use the + button to ${additionalText}, or assign a task!`,
iouTypes: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,10 @@ export default {
beginningOfChatHistoryPolicyExpenseChatPartOne: '¡La colaboración entre ',
beginningOfChatHistoryPolicyExpenseChatPartTwo: ' y ',
beginningOfChatHistoryPolicyExpenseChatPartThree: ' empieza aquí! 🎉 Este es el lugar donde chatear, pedir dinero y pagar.',
beginningOfChatHistorySelfDM: 'Este es tu espacio personal. Úsalo para notas, tareas, borradores y recordatorios.',
chatWithAccountManager: 'Chatea con tu gestor de cuenta aquí',
sayHello: '¡Saluda!',
yourSpace: 'Tu espacio',
welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `¡Bienvenido a ${roomName}!`,
usePlusButton: ({additionalText}: UsePlusButtonParams) => `\n¡También puedes usar el botón + de abajo para ${additionalText}, o asignar una tarea!`,
iouTypes: {
Expand Down
16 changes: 15 additions & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type GetOptionsConfig = {
includeMultipleParticipantReports?: boolean;
includePersonalDetails?: boolean;
includeRecentReports?: boolean;
includeSelfDM?: boolean;
sortByReportTypeInSearch?: boolean;
searchInputValue?: string;
showChatPreviewLine?: boolean;
Expand Down Expand Up @@ -675,6 +676,8 @@ function createOption(
result.tooltipText = ReportUtils.getReportParticipantsTitle(report.visibleChatMemberAccountIDs ?? []);
result.isWaitingOnBankAccount = report.isWaitingOnBankAccount;
result.policyID = report.policyID;
result.isSelfDM = ReportUtils.isSelfDM(report);

hasMultipleParticipants = personalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat;
subtitle = ReportUtils.getChatRoomSubtitle(report);

Expand Down Expand Up @@ -1368,6 +1371,7 @@ function getOptions(
transactionViolations = {},
includeTaxRates,
taxRates,
includeSelfDM = false,
}: GetOptionsConfig,
): GetOptions {
if (includeCategories) {
Expand Down Expand Up @@ -1472,7 +1476,9 @@ function getOptions(
const isTaskReport = ReportUtils.isTaskReport(report);
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report);
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
const accountIDs = report.visibleChatMemberAccountIDs ?? [];
const isSelfDM = ReportUtils.isSelfDM(report);
// Currently, currentUser is not included in visibleChatMemberAccountIDs, so for selfDM we need to add the currentUser as participants.
const accountIDs = isSelfDM ? [currentUserAccountID ?? 0] : report.visibleChatMemberAccountIDs ?? [];

if (isPolicyExpenseChat && report.isOwnPolicyExpenseChat && !includeOwnedWorkspaceChats) {
return;
Expand All @@ -1483,6 +1489,10 @@ function getOptions(
return;
}

if (isSelfDM && !includeSelfDM) {
return;
}

if (isThread && !includeThreads) {
return;
}
Expand Down Expand Up @@ -1733,6 +1743,7 @@ function getSearchOptions(reports: Record<string, Report>, personalDetails: Onyx
includeThreads: true,
includeMoneyRequests: true,
includeTasks: true,
includeSelfDM: true,
});
Timing.end(CONST.TIMING.LOAD_SEARCH_OPTIONS);
Performance.markEnd(CONST.TIMING.LOAD_SEARCH_OPTIONS);
Expand Down Expand Up @@ -1808,6 +1819,7 @@ function getFilteredOptions(
includeSelectedOptions = false,
includeTaxRates = false,
taxRates: TaxRatesWithDefault = {} as TaxRatesWithDefault,
includeSelfDM = false,
) {
return getOptions(reports, personalDetails, {
betas,
Expand All @@ -1829,6 +1841,7 @@ function getFilteredOptions(
includeSelectedOptions,
includeTaxRates,
taxRates,
includeSelfDM,
});
}

Expand Down Expand Up @@ -1862,6 +1875,7 @@ function getShareDestinationOptions(
excludeLogins,
includeOwnedWorkspaceChats,
excludeUnknownUsers,
includeSelfDM: true,
});
}

Expand Down
9 changes: 7 additions & 2 deletions src/libs/PersonalDetailsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ Onyx.connect({
},
});

function getDisplayNameOrDefault(passedPersonalDetails?: Partial<PersonalDetails> | null, defaultValue = '', shouldFallbackToHidden = true): string {
const displayName = passedPersonalDetails?.displayName ? passedPersonalDetails.displayName.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, '') : '';
function getDisplayNameOrDefault(passedPersonalDetails?: Partial<PersonalDetails> | null, defaultValue = '', shouldFallbackToHidden = true, shouldAddCurrentUserPostfix = false): string {
let displayName = passedPersonalDetails?.displayName ? passedPersonalDetails.displayName.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, '') : '';
if (shouldAddCurrentUserPostfix && !!displayName) {
displayName = `${displayName} (${Localize.translateLocal('common.you').toLowerCase()})`;
}

const fallbackValue = shouldFallbackToHidden ? Localize.translateLocal('common.hidden') : '';

return displayName || defaultValue || fallbackValue;
}

Expand Down
43 changes: 37 additions & 6 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ type OptionData = {
notificationPreference?: NotificationPreference | null;
isDisabled?: boolean | null;
name?: string | null;
isSelfDM?: boolean | null;
} & Report;

type OnyxDataTaskAssigneeChat = {
Expand Down Expand Up @@ -909,6 +910,10 @@ function isDM(report: OnyxEntry<Report>): boolean {
return isChatReport(report) && !getChatType(report);
}

function isSelfDM(report: OnyxEntry<Report>): boolean {
return getChatType(report) === CONST.REPORT.CHAT_TYPE.SELF_DM;
}

/**
* Only returns true if this is our main 1:1 DM report with Concierge
*/
Expand Down Expand Up @@ -1611,6 +1616,10 @@ function getIcons(
return isPayer ? [managerIcon, ownerIcon] : [ownerIcon, managerIcon];
}

if (isSelfDM(report)) {
return getIconsForParticipants([currentUserAccountID ?? 0], personalDetails);
}

return getIconsForParticipants(report?.participantAccountIDs ?? [], personalDetails);
}

Expand All @@ -1633,7 +1642,7 @@ function getPersonalDetailsForAccountID(accountID: number): Partial<PersonalDeta
/**
* Get the displayName for a single report participant.
*/
function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = false, shouldFallbackToHidden = true): string {
function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = false, shouldFallbackToHidden = true, shouldAddCurrentUserPostfix = false): string {
if (!accountID) {
return '';
}
Expand All @@ -1648,7 +1657,10 @@ function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = f
return formattedLogin;
}

const longName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails, formattedLogin, shouldFallbackToHidden);
// For selfDM, we display the user's displayName followed by '(you)' as a postfix
const shouldAddPostfix = shouldAddCurrentUserPostfix && accountID === currentUserAccountID;

const longName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails, formattedLogin, shouldFallbackToHidden, shouldAddPostfix);

// If the user's personal details (first name) should be hidden, make sure we return "hidden" instead of the short name
if (shouldFallbackToHidden && longName === Localize.translateLocal('common.hidden')) {
Expand All @@ -1663,14 +1675,15 @@ function getDisplayNamesWithTooltips(
personalDetailsList: PersonalDetails[] | PersonalDetailsList | OptionData[],
isMultipleParticipantReport: boolean,
shouldFallbackToHidden = true,
shouldAddCurrentUserPostfix = false,
): DisplayNameWithTooltips {
const personalDetailsListArray = Array.isArray(personalDetailsList) ? personalDetailsList : Object.values(personalDetailsList);

return personalDetailsListArray
.map((user) => {
const accountID = Number(user?.accountID);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const displayName = getDisplayNameForParticipant(accountID, isMultipleParticipantReport, shouldFallbackToHidden) || user?.login || '';
const displayName = getDisplayNameForParticipant(accountID, isMultipleParticipantReport, shouldFallbackToHidden, shouldAddCurrentUserPostfix) || user?.login || '';
const avatar = UserUtils.getDefaultAvatar(accountID);

let pronouns = user?.pronouns ?? undefined;
Expand Down Expand Up @@ -2563,6 +2576,10 @@ function getReportName(report: OnyxEntry<Report>, policy: OnyxEntry<Policy> = nu
formattedName += ` (${Localize.translateLocal('common.archived')})`;
}

if (isSelfDM(report)) {
formattedName = getDisplayNameForParticipant(currentUserAccountID, undefined, undefined, true);
}

if (formattedName) {
return formattedName;
}
Expand Down Expand Up @@ -2619,6 +2636,11 @@ function getParentNavigationSubtitle(report: OnyxEntry<Report>): ParentNavigatio
function navigateToDetailsPage(report: OnyxEntry<Report>) {
const participantAccountIDs = report?.participantAccountIDs ?? [];

if (isSelfDM(report)) {
Navigation.navigate(ROUTES.PROFILE.getRoute(currentUserAccountID ?? 0));
return;
}

if (isOneOnOneChat(report)) {
Navigation.navigate(ROUTES.PROFILE.getRoute(participantAccountIDs[0]));
return;
Expand Down Expand Up @@ -3926,6 +3948,7 @@ function shouldReportBeInOptionList({
policies,
excludeEmptyChats,
doesReportHaveViolations,
includeSelfDM = false,
}: {
report: OnyxEntry<Report>;
currentReportId: string;
Expand All @@ -3934,6 +3957,7 @@ function shouldReportBeInOptionList({
policies: OnyxCollection<Policy>;
excludeEmptyChats: boolean;
doesReportHaveViolations: boolean;
includeSelfDM?: boolean;
}) {
const isInDefaultMode = !isInGSDMode;
// Exclude reports that have no data because there wouldn't be anything to show in the option item.
Expand All @@ -3955,7 +3979,8 @@ function shouldReportBeInOptionList({
!isUserCreatedPolicyRoom(report) &&
!isArchivedRoom(report) &&
!isMoneyRequestReport(report) &&
!isTaskReport(report))
!isTaskReport(report) &&
!isSelfDM(report))
) {
return false;
}
Expand Down Expand Up @@ -4017,6 +4042,10 @@ function shouldReportBeInOptionList({
return false;
}

if (isSelfDM(report)) {
return includeSelfDM;
}

return true;
}

Expand Down Expand Up @@ -4244,7 +4273,7 @@ function hasIOUWaitingOnCurrentUserBankAccount(chatReport: OnyxEntry<Report>): b
*/
function canRequestMoney(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>, otherParticipants: number[]): boolean {
// User cannot request money in chat thread or in task report or in chat room
if (isChatThread(report) || isTaskReport(report) || isChatRoom(report)) {
if (isChatThread(report) || isTaskReport(report) || isChatRoom(report) || isSelfDM(report)) {
return false;
}

Expand Down Expand Up @@ -4304,7 +4333,7 @@ function canRequestMoney(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>, o
*/
function getMoneyRequestOptions(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>, reportParticipants: number[]): Array<ValueOf<typeof CONST.IOU.TYPE>> {
// In any thread or task report, we do not allow any new money requests yet
if (isChatThread(report) || isTaskReport(report)) {
if (isChatThread(report) || isTaskReport(report) || isSelfDM(report)) {
return [];
}

Expand Down Expand Up @@ -4359,6 +4388,7 @@ function canLeaveRoom(report: OnyxEntry<Report>, isPolicyMember: boolean): boole
report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE ||
report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT ||
report?.chatType === CONST.REPORT.CHAT_TYPE.DOMAIN_ALL ||
report?.chatType === CONST.REPORT.CHAT_TYPE.SELF_DM ||
!report?.chatType
) {
// DM chats don't have a chatType
Expand Down Expand Up @@ -5187,6 +5217,7 @@ export {
getAddWorkspaceRoomOrChatReportErrors,
getReportOfflinePendingActionAndErrors,
isDM,
isSelfDM,
getPolicy,
getPolicyExpenseChatReportIDByOwner,
getWorkspaceChats,
Expand Down
18 changes: 16 additions & 2 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ function getOrderedReportIDs(
policies,
excludeEmptyChats: true,
doesReportHaveViolations,
includeSelfDM: true,
});
});

Expand Down Expand Up @@ -221,7 +222,14 @@ function getOptionData({
isDeletedParentAction: false,
};

const participantPersonalDetailList = Object.values(OptionsListUtils.getPersonalDetailsForAccountIDs(report.participantAccountIDs ?? [], personalDetails)) as PersonalDetails[];
let participantAccountIDs = report.participantAccountIDs ?? [];

// Currently, currentUser is not included in participantAccountIDs, so for selfDM we need to add the currentUser(report owner) as participants.
if (ReportUtils.isSelfDM(report)) {
participantAccountIDs = [report.ownerAccountID ?? 0];
}

const participantPersonalDetailList = Object.values(OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails)) as PersonalDetails[];
const personalDetail = participantPersonalDetailList[0] ?? {};
const hasErrors = Object.keys(result.allReportErrors ?? {}).length !== 0;

Expand Down Expand Up @@ -258,6 +266,7 @@ function getOptionData({
result.isAllowedToComment = ReportUtils.canUserPerformWriteAction(report);
result.chatType = report.chatType;
result.isDeletedParentAction = report.isDeletedParentAction;
result.isSelfDM = ReportUtils.isSelfDM(report);

const hasMultipleParticipants = participantPersonalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat || ReportUtils.isExpenseReport(report);
const subtitle = ReportUtils.getChatRoomSubtitle(report);
Expand All @@ -267,7 +276,12 @@ function getOptionData({
const formattedLogin = Str.isSMSLogin(login) ? LocalePhoneNumber.formatPhoneNumber(login) : login;

// We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade.
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips((participantPersonalDetailList || []).slice(0, 10), hasMultipleParticipants);
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(
(participantPersonalDetailList || []).slice(0, 10),
hasMultipleParticipants,
undefined,
ReportUtils.isSelfDM(report),
);

// If the last actor's details are not currently saved in Onyx Collection,
// then try to get that from the last report action if that action is valid
Expand Down
Loading

0 comments on commit cbd13ed

Please sign in to comment.