Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add subscribe to parent comment action menu #27994

Merged
merged 23 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions assets/images/bell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions assets/images/bellSlash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/components/Icon/Expensicons.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import ArrowRightLong from '../../../assets/images/arrow-right-long.svg';
import ArrowsUpDown from '../../../assets/images/arrows-updown.svg';
import BackArrow from '../../../assets/images/back-left.svg';
import Bank from '../../../assets/images/bank.svg';
import Bell from '../../../assets/images/bell.svg';
import BellSlash from '../../../assets/images/bellSlash.svg';
import Bill from '../../../assets/images/bill.svg';
import Bolt from '../../../assets/images/bolt.svg';
import Briefcase from '../../../assets/images/briefcase.svg';
Expand Down Expand Up @@ -140,6 +142,8 @@ export {
BackArrow,
Bank,
Bill,
Bell,
BellSlash,
Bolt,
Briefcase,
Bug,
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,8 @@ export default {
deleteConfirmation: ({action}: DeleteConfirmationParams) => `Are you sure you want to delete this ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}?`,
onlyVisible: 'Only visible to',
replyInThread: 'Reply in thread',
subscribeToThread: 'Subscribe to thread',
unsubscribeFromThread: 'Unsubscribe from thread',
flagAsOffensive: 'Flag as offensive',
},
emojiReactions: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ export default {
deleteConfirmation: ({action}: DeleteConfirmationParams) => `¿Estás seguro de que quieres eliminar este ${ReportActionsUtils.isMoneyRequestAction(action) ? 'pedido' : 'comentario'}`,
onlyVisible: 'Visible sólo para',
replyInThread: 'Responder en el hilo',
subscribeToThread: 'Suscribirse al hilo',
unsubscribeFromThread: 'Darse de baja del hilo',
flagAsOffensive: 'Marcar como ofensivo',
},
emojiReactions: {
Expand Down
11 changes: 11 additions & 0 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,16 @@ function getReport(reportID) {
return lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {}) || {};
}

/**
* Returns whether or not the author of the action is this user
*
* @param {Object} reportAction
* @returns {Boolean}
*/
function isActionCreator(reportAction) {
return reportAction.actorAccountID === currentUserAccountID;
}

/**
* Can only delete if the author is this user and the action is an ADDCOMMENT action or an IOU action in an unsettled report, or if the user is a
* policy admin
Expand Down Expand Up @@ -3969,6 +3979,7 @@ export {
canEditReportAction,
canFlagReportAction,
shouldShowFlagComment,
isActionCreator,
canDeleteReportAction,
canLeaveRoom,
sortReportsByLastRead,
Expand Down
61 changes: 60 additions & 1 deletion src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -1318,8 +1318,10 @@ function saveReportActionDraftNumberOfLines(reportID, reportActionID, numberOfLi
* @param {String} previousValue
* @param {String} newValue
* @param {boolean} navigate
* @param {String} parentReportID
* @param {String} parentReportActionID
*/
function updateNotificationPreference(reportID, previousValue, newValue, navigate) {
function updateNotificationPreference(reportID, previousValue, newValue, navigate, parentReportID = 0, parentReportActionID = 0) {
if (previousValue === newValue) {
if (navigate) {
Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(reportID));
Expand All @@ -1340,12 +1342,68 @@ function updateNotificationPreference(reportID, previousValue, newValue, navigat
value: {notificationPreference: previousValue},
},
];
if (parentReportID && parentReportActionID) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`,
value: {[parentReportActionID]: {childReportNotificationPreference: newValue}},
});
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`,
value: {[parentReportActionID]: {childReportNotificationPreference: previousValue}},
});
}
API.write('UpdateReportNotificationPreference', {reportID, notificationPreference: newValue}, {optimisticData, failureData});
if (navigate) {
Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(reportID));
}
}

/**
* This will subscribe to an existing thread, or create a new one and then subsribe to it if necessary
*
* @param {String} childReportID The reportID we are trying to open
* @param {Object} parentReportAction the parent comment of a thread
* @param {String} parentReportID The reportID of the parent
* @param {String} prevNotificationPreference The previous notification preference for the child report
*
*/
function toggleSubscribeToChildReport(childReportID = '0', parentReportAction = {}, parentReportID = '0', prevNotificationPreference) {
if (childReportID !== '0') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is weird to me. I think we should return early if childReportID is 0. I don't understand why anyone would want to subscribe to a thread prematurely i.e., when a thread does not exist yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we talked about it briefly and I asked about it here which led to this change. It's basically like slack where you can Get notified about new replies.

openReport(childReportID);
const parentReportActionID = lodashGet(parentReportAction, 'reportActionID', '0');
if (!prevNotificationPreference || prevNotificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN) {
updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, false, parentReportID, parentReportActionID);
} else {
updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, false, parentReportID, parentReportActionID);
}
} else {
const participantAccountIDs = _.uniq([currentUserAccountID, Number(parentReportAction.actorAccountID)]);
const parentReport = allReports[parentReportID];
const newChat = ReportUtils.buildOptimisticChatReport(
participantAccountIDs,
lodashGet(parentReportAction, ['message', 0, 'text']),
lodashGet(parentReport, 'chatType', ''),
lodashGet(parentReport, 'policyID', CONST.POLICY.OWNER_EMAIL_FAKE),
CONST.POLICY.OWNER_ACCOUNT_ID_FAKE,
false,
'',
undefined,
undefined,
CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
parentReportAction.reportActionID,
parentReportID,
);

const participantLogins = PersonalDetailsUtils.getLoginsByAccountIDs(newChat.participantAccountIDs);
openReport(newChat.reportID, participantLogins, newChat, parentReportAction.reportActionID);
const notificationPreference =
prevNotificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
updateNotificationPreference(newChat.reportID, prevNotificationPreference, notificationPreference, false, parentReportID, parentReportAction.reportActionID);
}
}

/**
* @param {String} reportID
* @param {String} previousValue
Expand Down Expand Up @@ -2426,6 +2484,7 @@ export {
navigateToAndOpenReport,
navigateToAndOpenReportWithAccountIDs,
navigateToAndOpenChildReport,
toggleSubscribeToChildReport,
updatePolicyRoomNameAndNavigate,
clearPolicyRoomNameErrors,
clearIOUError,
Expand Down
77 changes: 77 additions & 0 deletions src/pages/home/report/ContextMenu/ContextMenuActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,83 @@ export default [
},
getDescription: () => {},
},
{
isAnonymousAction: false,
textTranslateKey: 'reportActionContextMenu.subscribeToThread',
icon: Expensicons.Bell,
successTextTranslateKey: '',
successIcon: null,
shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID) => {
let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
if (!childReportNotificationPreference) {
const isActionCreator = ReportUtils.isActionCreator(reportAction);
childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
}
const subscribed = childReportNotificationPreference !== 'hidden';
const isCommentAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT && !ReportUtils.isThreadFirstChat(reportAction, reportID);
const isReportPreviewAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from #35092, we shouldn’t display the leave thread option for IOU previews

const isIOUAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && !ReportActionsUtils.isSplitBillAction(reportAction);
return !subscribed && (isCommentAction || isReportPreviewAction || isIOUAction);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we should not show this icon if the reportAction does not have a child since that does not make sense to me. Like whats the usecase to subscribe to a thread that does not exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Yeah we talked about it briefly and I asked about it here which led to this change. It's basically like slack where you can Get notified about new replies.

},
onPress: (closePopover, {reportAction, reportID}) => {
let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
if (!childReportNotificationPreference) {
const isActionCreator = ReportUtils.isActionCreator(reportAction);
childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
}
if (closePopover) {
hideContextMenu(false, () => {
ReportActionComposeFocusManager.focus();
Report.toggleSubscribeToChildReport(lodashGet(reportAction, 'childReportID', '0'), reportAction, reportID, childReportNotificationPreference);
});
return;
}

ReportActionComposeFocusManager.focus();
Report.toggleSubscribeToChildReport(lodashGet(reportAction, 'childReportID', '0'), reportAction, reportID, childReportNotificationPreference);
},
getDescription: () => {},
},
{
isAnonymousAction: false,
textTranslateKey: 'reportActionContextMenu.unsubscribeFromThread',
icon: Expensicons.BellSlash,
successTextTranslateKey: '',
successIcon: null,
shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID) => {
let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
if (!childReportNotificationPreference) {
const isActionCreator = ReportUtils.isActionCreator(reportAction);
childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
}
const subscribed = childReportNotificationPreference !== 'hidden';
if (type !== CONTEXT_MENU_TYPES.REPORT_ACTION) {
return false;
}
const isCommentAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT && !ReportUtils.isThreadFirstChat(reportAction, reportID);
const isReportPreviewAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW;
const isIOUAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && !ReportActionsUtils.isSplitBillAction(reportAction);
return subscribed && (isCommentAction || isReportPreviewAction || isIOUAction);
},
onPress: (closePopover, {reportAction, reportID}) => {
let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
if (!childReportNotificationPreference) {
const isActionCreator = ReportUtils.isActionCreator(reportAction);
childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
}
if (closePopover) {
hideContextMenu(false, () => {
ReportActionComposeFocusManager.focus();
Report.toggleSubscribeToChildReport(lodashGet(reportAction, 'childReportID', '0'), reportAction, reportID, childReportNotificationPreference);
});
return;
}

ReportActionComposeFocusManager.focus();
Report.toggleSubscribeToChildReport(lodashGet(reportAction, 'childReportID', '0'), reportAction, reportID, childReportNotificationPreference);
},
getDescription: () => {},
},
{
isAnonymousAction: true,
textTranslateKey: 'reportActionContextMenu.copyURLToClipboard',
Expand Down
Loading