Skip to content

Commit

Permalink
Merge pull request Expensify#47577 from shubham1206agra/migrate-notif…
Browse files Browse the repository at this point in the history
…ication-preference

Migrate notification preference
  • Loading branch information
puneetlath authored Sep 7, 2024
2 parents 7537bfb + 26f8695 commit 7ebfaa0
Show file tree
Hide file tree
Showing 23 changed files with 258 additions and 181 deletions.
6 changes: 3 additions & 3 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ function createOption(
result.isWaitingOnBankAccount = report.isWaitingOnBankAccount;
result.policyID = report.policyID;
result.isSelfDM = ReportUtils.isSelfDM(report);
result.notificationPreference = report.notificationPreference;
result.notificationPreference = ReportUtils.getReportNotificationPreference(report);

const visibleParticipantAccountIDs = ReportUtils.getParticipantsAccountIDsForDisplay(report, true);

Expand Down Expand Up @@ -849,7 +849,7 @@ function getPolicyExpenseReportOption(participant: Participant | ReportUtils.Opt
const expenseReport = ReportUtils.isPolicyExpenseChat(participant) ? ReportUtils.getReportOrDraftReport(participant.reportID) : null;

const visibleParticipantAccountIDs = Object.entries(expenseReport?.participants ?? {})
.filter(([, reportParticipant]) => reportParticipant && !reportParticipant.hidden)
.filter(([, reportParticipant]) => reportParticipant && reportParticipant.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN)
.map(([accountID]) => Number(accountID));

const option = createOption(
Expand Down Expand Up @@ -2500,7 +2500,7 @@ function getEmptyOptions(): Options {
}

function shouldUseBoldText(report: ReportUtils.OptionData): boolean {
return report.isUnread === true && report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
return report.isUnread === true && ReportUtils.getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
}

export {
Expand Down
89 changes: 52 additions & 37 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ type OptimisticExpenseReport = Pick<
| 'statusNum'
| 'total'
| 'nonReimbursableTotal'
| 'notificationPreference'
| 'parentReportID'
| 'lastVisibleActionCreated'
| 'parentReportActionID'
| 'participants'
| 'fieldList'
>;

Expand Down Expand Up @@ -274,7 +274,6 @@ type OptimisticChatReport = Pick<
| 'lastMessageText'
| 'lastReadTime'
| 'lastVisibleActionCreated'
| 'notificationPreference'
| 'oldPolicyName'
| 'ownerAccountID'
| 'pendingFields'
Expand Down Expand Up @@ -355,7 +354,6 @@ type OptimisticTaskReport = Pick<
| 'policyID'
| 'stateNum'
| 'statusNum'
| 'notificationPreference'
| 'parentReportActionID'
| 'lastVisibleActionCreated'
| 'hasParentAccess'
Expand Down Expand Up @@ -395,7 +393,6 @@ type OptimisticIOUReport = Pick<
| 'statusNum'
| 'total'
| 'reportName'
| 'notificationPreference'
| 'parentReportID'
| 'lastVisibleActionCreated'
| 'fieldList'
Expand Down Expand Up @@ -1147,6 +1144,32 @@ function isSystemChat(report: OnyxEntry<Report>): boolean {
return getChatType(report) === CONST.REPORT.CHAT_TYPE.SYSTEM;
}

function getDefaultNotificationPreferenceForReport(report: OnyxEntry<Report>): ValueOf<typeof CONST.REPORT.NOTIFICATION_PREFERENCE> {
if (isAnnounceRoom(report)) {
return CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS;
}
if (isPublicRoom(report)) {
return CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY;
}
if (!getChatType(report) || isGroupChat(report)) {
return CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS;
}
if (isAdminRoom(report) || isPolicyExpenseChat(report) || isInvoiceRoom(report)) {
return CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS;
}
if (isSelfDM(report)) {
return CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
}
return CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY;
}

/**
* Get the notification preference given a report
*/
function getReportNotificationPreference(report: OnyxEntry<Report>): ValueOf<typeof CONST.REPORT.NOTIFICATION_PREFERENCE> {
return report?.participants?.[currentUserAccountID ?? -1]?.notificationPreference ?? getDefaultNotificationPreferenceForReport(report);
}

const CONCIERGE_ACCOUNT_ID_STRING = CONST.ACCOUNT_ID.CONCIERGE.toString();
/**
* Only returns true if this is our main 1:1 DM report with Concierge.
Expand Down Expand Up @@ -1252,7 +1275,7 @@ function hasExpensifyGuidesEmails(accountIDs: number[]): boolean {

function getMostRecentlyVisitedReport(reports: Array<OnyxEntry<Report>>, reportMetadata: OnyxCollection<ReportMetadata>): OnyxEntry<Report> {
const filteredReports = reports.filter((report) => {
const shouldKeep = !isChatThread(report) || report?.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const shouldKeep = !isChatThread(report) || getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
return shouldKeep && !!report?.reportID && !!(reportMetadata?.[`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`]?.lastVisitTime ?? report?.lastReadTime);
});
return lodashMaxBy(filteredReports, (a) => new Date(reportMetadata?.[`${ONYXKEYS.COLLECTION.REPORT_METADATA}${a?.reportID}`]?.lastVisitTime ?? a?.lastReadTime ?? '').valueOf());
Expand Down Expand Up @@ -1622,13 +1645,6 @@ function isPayer(session: OnyxEntry<Session>, iouReport: OnyxEntry<Report>) {
return isAdmin || (isMoneyRequestReport(iouReport) && isManager);
}

/**
* Get the notification preference given a report
*/
function getReportNotificationPreference(report: OnyxEntry<Report>): string | number {
return report?.notificationPreference ?? '';
}

/**
* Checks if the current user is the action's author
*/
Expand Down Expand Up @@ -2063,7 +2079,7 @@ function getParticipantsAccountIDsForDisplay(report: OnyxEntry<Report>, shouldEx
return false;
}

if (shouldExcludeHidden && reportParticipants[accountID]?.hidden) {
if (shouldExcludeHidden && reportParticipants[accountID]?.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
return false;
}

Expand Down Expand Up @@ -2116,7 +2132,7 @@ function buildParticipantsFromAccountIDs(accountIDs: number[]): Participants {
const finalParticipants: Participants = {};
return accountIDs.reduce((participants, accountID) => {
// eslint-disable-next-line no-param-reassign
participants[accountID] = {hidden: false};
participants[accountID] = {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS};
return participants;
}, finalParticipants);
}
Expand Down Expand Up @@ -4254,8 +4270,8 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number
const policy = getPolicy(policyID);

const participants: Participants = {
[payeeAccountID]: {hidden: true},
[payerAccountID]: {hidden: true},
[payeeAccountID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN},
[payerAccountID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN},
};

return {
Expand All @@ -4273,7 +4289,6 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number

// We don't translate reportName because the server response is always in English
reportName: `${payerEmail} owes ${formattedTotal}`,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
parentReportID: chatReportID,
lastVisibleActionCreated: DateUtils.getDBTime(),
fieldList: policy?.fieldList,
Expand Down Expand Up @@ -4328,7 +4343,11 @@ function buildOptimisticInvoiceReport(chatReportID: string, policyID: string, re
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
total,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
participants: {
[currentUserAccountID ?? -1]: {
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
},
parentReportID: chatReportID,
lastVisibleActionCreated: DateUtils.getDBTime(),
};
Expand Down Expand Up @@ -4378,7 +4397,11 @@ function buildOptimisticExpenseReport(
statusNum,
total: storedTotal,
nonReimbursableTotal: reimbursable ? 0 : storedTotal,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
participants: {
[payeeAccountID]: {
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
},
parentReportID: chatReportID,
lastVisibleActionCreated: DateUtils.getDBTime(),
parentReportActionID,
Expand Down Expand Up @@ -5038,12 +5061,11 @@ function buildOptimisticChatReport(
description = '',
avatarUrl = '',
optimisticReportID = '',
shouldShowParticipants = true,
): OptimisticChatReport {
const isWorkspaceChatType = chatType && isWorkspaceChat(chatType);
const participants = participantList.reduce((reportParticipants: Participants, accountID: number) => {
const participant: ReportParticipant = {
hidden: !shouldShowParticipants,
notificationPreference,
...(!isWorkspaceChatType && {role: accountID === currentUserAccountID ? CONST.REPORT.ROLE.ADMIN : CONST.REPORT.ROLE.MEMBER}),
};
// eslint-disable-next-line no-param-reassign
Expand All @@ -5064,7 +5086,6 @@ function buildOptimisticChatReport(
lastMessageText: undefined,
lastReadTime: currentTime,
lastVisibleActionCreated: currentTime,
notificationPreference,
oldPolicyName,
ownerAccountID: ownerAccountID || CONST.REPORT.OWNER_ACCOUNT_ID_FAKE,
parentReportActionID,
Expand Down Expand Up @@ -5482,9 +5503,7 @@ function buildOptimisticWorkspaceChats(policyID: string, policyName: string, exp
policyName,
undefined,
undefined,

// #announce contains all policy members so notifying always should be opt-in only.
CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY,
CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
);
const announceChatReportID = announceChatData.reportID;
const announceCreatedAction = buildOptimisticCreatedReportAction(CONST.POLICY.OWNER_EMAIL_FAKE);
Expand Down Expand Up @@ -5571,12 +5590,12 @@ function buildOptimisticTaskReport(
): OptimisticTaskReport {
const participants: Participants = {
[ownerAccountID]: {
hidden: false,
notificationPreference,
},
};

if (assigneeAccountID) {
participants[assigneeAccountID] = {hidden: false};
participants[assigneeAccountID] = {notificationPreference};
}

return {
Expand All @@ -5591,7 +5610,6 @@ function buildOptimisticTaskReport(
policyID,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
notificationPreference,
lastVisibleActionCreated: DateUtils.getDBTime(),
hasParentAccess: true,
};
Expand Down Expand Up @@ -5669,10 +5687,6 @@ function buildTransactionThread(
CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
reportAction?.reportActionID,
moneyRequestReport?.reportID,
'',
'',
'',
false,
);
}

Expand Down Expand Up @@ -6049,7 +6063,7 @@ function shouldReportBeInOptionList({

// All unread chats (even archived ones) in GSD mode will be shown. This is because GSD mode is specifically for focusing the user on the most relevant chats, primarily, the unread ones
if (isInFocusMode) {
return isUnread(report) && report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
return isUnread(report) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
}

// Archived reports should always be shown when in default (most recent) mode. This is because you should still be able to access and search for the chats to find them.
Expand Down Expand Up @@ -7441,15 +7455,15 @@ function isAdminOwnerApproverOrReportOwner(report: OnyxEntry<Report>, policy: On
/**
* Whether the user can join a report
*/
function canJoinChat(report: OnyxInputOrEntry<Report>, parentReportAction: OnyxInputOrEntry<ReportAction>, policy: OnyxInputOrEntry<Policy>): boolean {
function canJoinChat(report: OnyxEntry<Report>, parentReportAction: OnyxInputOrEntry<ReportAction>, policy: OnyxInputOrEntry<Policy>): boolean {
// We disabled thread functions for whisper action
// So we should not show join option for existing thread on whisper message that has already been left, or manually leave it
if (ReportActionsUtils.isWhisperAction(parentReportAction)) {
return false;
}

// If the notification preference of the chat is not hidden that means we have already joined the chat
if (report?.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
if (getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
return false;
}

Expand Down Expand Up @@ -7483,7 +7497,7 @@ function canLeaveChat(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>): boo
return false;
}

if (report?.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
if (getReportNotificationPreference(report) === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
return false;
}

Expand All @@ -7501,7 +7515,7 @@ function canLeaveChat(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>): boo
return canLeaveInvoiceRoom(report);
}

return (isChatThread(report) && !!report?.notificationPreference?.length) || isUserCreatedPolicyRoom(report) || isNonAdminOrOwnerOfPolicyExpenseChat(report, policy);
return (isChatThread(report) && !!getReportNotificationPreference(report)) || isUserCreatedPolicyRoom(report) || isNonAdminOrOwnerOfPolicyExpenseChat(report, policy);
}

function getReportActionActorAccountID(reportAction: OnyxInputOrEntry<ReportAction>, iouReport: OnyxInputOrEntry<Report> | undefined): number | undefined {
Expand Down Expand Up @@ -8034,6 +8048,7 @@ export {
isInvoiceRoomWithID,
isInvoiceReport,
isOpenInvoiceReport,
getDefaultNotificationPreferenceForReport,
canWriteInReport,
navigateToDetailsPage,
navigateToPrivateNotes,
Expand Down
4 changes: 2 additions & 2 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function getOrderedReportIDs(
const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`] ?? {};
const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '-1', report?.parentReportActionID ?? '-1');
const doesReportHaveViolations = OptionsListUtils.shouldShowViolations(report, transactionViolations);
const isHidden = report.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const isHidden = ReportUtils.getReportNotificationPreference(report) === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const isFocused = report.reportID === currentReportId;
const allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions) ?? {};
const transactionReportActions = ReportActionsUtils.getAllReportActions(report.reportID);
Expand Down Expand Up @@ -343,7 +343,7 @@ function getOptionData({
result.hasOutstandingChildRequest = report.hasOutstandingChildRequest;
result.parentReportID = report.parentReportID ?? '-1';
result.isWaitingOnBankAccount = report.isWaitingOnBankAccount;
result.notificationPreference = report.notificationPreference;
result.notificationPreference = ReportUtils.getReportNotificationPreference(report);
result.isAllowedToComment = ReportUtils.canUserPerformWriteAction(report);
result.chatType = report.chatType;
result.isDeletedParentAction = report.isDeletedParentAction;
Expand Down
12 changes: 7 additions & 5 deletions src/libs/UnreadIndicatorUpdater/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import type {Report} from '@src/types/onyx';
import updateUnread from './updateUnread';

function getUnreadReportsForUnreadIndicator(reports: OnyxCollection<Report>, currentReportID: string) {
return Object.values(reports ?? {}).filter(
(report) =>
return Object.values(reports ?? {}).filter((report) => {
const notificationPreference = ReportUtils.getReportNotificationPreference(report);
return (
ReportUtils.isUnread(report) &&
ReportUtils.shouldReportBeInOptionList({
report,
Expand All @@ -29,9 +30,10 @@ function getUnreadReportsForUnreadIndicator(reports: OnyxCollection<Report>, cur
* Furthermore, muted reports may or may not appear in the LHN depending on priority mode,
* but they should not be considered in the unread indicator count.
*/
report?.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN &&
report?.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE,
);
notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN &&
notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE
);
});
}

const memoizedGetUnreadReportsForUnreadIndicator = memoize(getUnreadReportsForUnreadIndicator, {maxArgs: 1});
Expand Down
12 changes: 2 additions & 10 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3867,7 +3867,7 @@ function getOrCreateOptimisticSplitChatReport(existingSplitChatReportID: string,
undefined,
undefined,
undefined,
CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
);
return {existingSplitChatReport: null, splitChatReport};
}
Expand Down Expand Up @@ -3967,11 +3967,6 @@ function createSplitsAndOnyxData(
splitChatReport.lastActorAccountID = currentUserAccountID;
splitChatReport.lastVisibleActionCreated = splitIOUReportAction.created;

let splitChatReportNotificationPreference = splitChatReport.notificationPreference;
if (splitChatReportNotificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
splitChatReportNotificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS;
}

// If we have an existing splitChatReport (group chat or workspace) use it's pending fields, otherwise indicate that we are adding a chat
if (!existingSplitChatReport) {
splitChatReport.pendingFields = {
Expand All @@ -3985,10 +3980,7 @@ function createSplitsAndOnyxData(
// and we need the data to be available when we navigate to the chat page
onyxMethod: existingSplitChatReport ? Onyx.METHOD.MERGE : Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.REPORT}${splitChatReport.reportID}`,
value: {
...splitChatReport,
notificationPreference: splitChatReportNotificationPreference,
},
value: splitChatReport,
},
{
onyxMethod: Onyx.METHOD.SET,
Expand Down
Loading

0 comments on commit 7ebfaa0

Please sign in to comment.