From 1e1c4904e87dfc6e891c097c3de9da71391e3707 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 11:06:05 +0200 Subject: [PATCH 1/9] Add new context actions --- .../report/ContextMenu/ContextMenuActions.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index b5c9d6412a02..0f0116e17497 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -222,7 +222,21 @@ export default [ textTranslateKey: 'reportActionContextMenu.markAsUnread', icon: Expensicons.Mail, successIcon: Expensicons.Checkmark, - shouldShow: (type) => type === CONTEXT_MENU_TYPES.REPORT_ACTION, + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnread) => type === CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONTEXT_MENU_TYPES.REPORT && !isUnread), + onPress: (closePopover, {reportAction, reportID}) => { + Report.markCommentAsUnread(reportID, reportAction.created); + if (closePopover) { + hideContextMenu(true, ReportActionComposeFocusManager.focus); + } + }, + getDescription: () => {}, + }, + + { + textTranslateKey: 'reportActionContextMenu.markAsRead', + icon: Expensicons.Mail, + successIcon: Expensicons.Checkmark, + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnread) => type === CONTEXT_MENU_TYPES.REPORT && isUnread, onPress: (closePopover, {reportAction, reportID}) => { Report.markCommentAsUnread(reportID, reportAction.created); if (closePopover) { From cd7857ddf38dc808ffa0e4aa053a640e5dd41b9d Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 11:17:51 +0200 Subject: [PATCH 2/9] use last action for Mark as unread --- src/libs/actions/Report.js | 8 ++++++-- src/pages/home/report/ContextMenu/ContextMenuActions.js | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index e200bec2c39c..6255f29be31b 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -665,11 +665,15 @@ function readNewestAction(reportID) { * @param {String} reportID * @param {String} reportActionCreated */ -function markCommentAsUnread(reportID, reportActionCreated) { +function markCommentAsUnread(reportID, reportActionCreated= '') { + + // If no action created date is provided, use the last action's + const actionCreationTime = reportActionCreated || ReportActionsUtils.getLastVisibleAction(reportID).created; + // We subtract 1 millisecond so that the lastReadTime is updated to just before a given reportAction's created date // For example, if we want to mark a report action with ID 100 and created date '2014-04-01 16:07:02.999' unread, we set the lastReadTime to '2014-04-01 16:07:02.998' // Since the report action with ID 100 will be the first with a timestamp above '2014-04-01 16:07:02.998', it's the first one that will be shown as unread - const lastReadTime = DateUtils.subtractMillisecondsFromDateTime(reportActionCreated, 1); + const lastReadTime = DateUtils.subtractMillisecondsFromDateTime(actionCreationTime, 1); API.write( 'MarkAsUnread', { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 0f0116e17497..22bd2302efc6 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -237,8 +237,8 @@ export default [ icon: Expensicons.Mail, successIcon: Expensicons.Checkmark, shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnread) => type === CONTEXT_MENU_TYPES.REPORT && isUnread, - onPress: (closePopover, {reportAction, reportID}) => { - Report.markCommentAsUnread(reportID, reportAction.created); + onPress: (closePopover, {reportID}) => { + Report.readNewestAction(reportID); if (closePopover) { hideContextMenu(true, ReportActionComposeFocusManager.focus); } From 4f9efb0bc9e7154c22a24c6757dd5c42a0fbc4ba Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 11:24:36 +0200 Subject: [PATCH 3/9] pass prop all over --- src/components/LHNOptionsList/OptionRowLHN.js | 1 + src/libs/actions/Report.js | 2 +- .../home/report/ContextMenu/BaseReportActionContextMenu.js | 1 + src/pages/home/report/ContextMenu/ContextMenuActions.js | 4 ++-- .../report/ContextMenu/PopoverReportActionContextMenu.js | 6 ++++++ .../home/report/ContextMenu/ReportActionContextMenu.js | 4 +++- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 42e9168ba940..0ed5a29ec330 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -111,6 +111,7 @@ const OptionRowLHN = (props) => { false, false, optionItem.isPinned, + optionItem.isUnread, ); }; diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 6255f29be31b..776f10a14074 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -663,7 +663,7 @@ function readNewestAction(reportID) { * Sets the last read time on a report * * @param {String} reportID - * @param {String} reportActionCreated + * @param {String} [reportActionCreated] */ function markCommentAsUnread(reportID, reportActionCreated= '') { diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js index 2d85a960f66d..0a1846cfb324 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js @@ -62,6 +62,7 @@ class BaseReportActionContextMenu extends React.Component { this.props.isChronosReport, this.props.reportID, this.props.isPinnedChat, + this.props.isUnreadChat, ); /** diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 22bd2302efc6..b0e8c2f39350 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -222,7 +222,7 @@ export default [ textTranslateKey: 'reportActionContextMenu.markAsUnread', icon: Expensicons.Mail, successIcon: Expensicons.Checkmark, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnread) => type === CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONTEXT_MENU_TYPES.REPORT && !isUnread), + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat) => type === CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONTEXT_MENU_TYPES.REPORT && !isUnreadChat), onPress: (closePopover, {reportAction, reportID}) => { Report.markCommentAsUnread(reportID, reportAction.created); if (closePopover) { @@ -236,7 +236,7 @@ export default [ textTranslateKey: 'reportActionContextMenu.markAsRead', icon: Expensicons.Mail, successIcon: Expensicons.Checkmark, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnread) => type === CONTEXT_MENU_TYPES.REPORT && isUnread, + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat) => type === CONTEXT_MENU_TYPES.REPORT && isUnreadChat, onPress: (closePopover, {reportID}) => { Report.readNewestAction(reportID); if (closePopover) { diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js index 770968567139..f9dbc51382e3 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js @@ -40,6 +40,7 @@ class PopoverReportActionContextMenu extends React.Component { isArchivedRoom: false, isChronosReport: false, isPinnedChat: false, + isUnreadChat: false, }; this.onPopoverShow = () => {}; this.onPopoverHide = () => {}; @@ -128,6 +129,7 @@ class PopoverReportActionContextMenu extends React.Component { * @param {Boolean} isArchivedRoom - Whether the provided report is an archived room * @param {Boolean} isChronosReport - Flag to check if the chat participant is Chronos * @param {Boolean} isPinnedChat - Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action + * @param {Boolean} isUnreadChat - Flag to check if the chat is unread in the LHN. Used for the Mark as Read/Unread action */ showContextMenu( type, @@ -142,6 +144,7 @@ class PopoverReportActionContextMenu extends React.Component { isArchivedRoom = false, isChronosReport = false, isPinnedChat = false, + isUnreadChat = false, ) { const nativeEvent = event.nativeEvent || {}; this.contextMenuAnchor = contextMenuAnchor; @@ -173,6 +176,7 @@ class PopoverReportActionContextMenu extends React.Component { isArchivedRoom, isChronosReport, isPinnedChat, + isUnreadChat, }); }); } @@ -262,6 +266,7 @@ class PopoverReportActionContextMenu extends React.Component { isArchivedRoom: false, isChronosReport: false, isPinnedChat: false, + isUnreadChat: false, }); } @@ -309,6 +314,7 @@ class PopoverReportActionContextMenu extends React.Component { isArchivedRoom={this.state.isArchivedRoom} isChronosReport={this.state.isChronosReport} isPinnedChat={this.state.isPinnedChat} + isUnreadChat={this.state.isUnreadChat} anchor={this.contextMenuTargetNode} contentRef={this.contentRef} /> diff --git a/src/pages/home/report/ContextMenu/ReportActionContextMenu.js b/src/pages/home/report/ContextMenu/ReportActionContextMenu.js index ea68cae8c710..95ca5b0837ce 100644 --- a/src/pages/home/report/ContextMenu/ReportActionContextMenu.js +++ b/src/pages/home/report/ContextMenu/ReportActionContextMenu.js @@ -17,6 +17,7 @@ const contextMenuRef = React.createRef(); * @param {Boolean} isArchivedRoom - Whether the provided report is an archived room * @param {Boolean} isChronosReport - Flag to check if the chat participant is Chronos * @param {Boolean} isPinnedChat - Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action + * @param {Boolean} isUnreadChat - Flag to check if the chat has unread messages in the LHN. Used for the Mark as Read/Unread action */ function showContextMenu( type, @@ -31,11 +32,12 @@ function showContextMenu( isArchivedRoom = false, isChronosReport = false, isPinnedChat = false, + isUnreadChat = false, ) { if (!contextMenuRef.current) { return; } - contextMenuRef.current.showContextMenu(type, event, selection, contextMenuAnchor, reportID, reportAction, draftMessage, onShow, onHide, isArchivedRoom, isChronosReport, isPinnedChat); + contextMenuRef.current.showContextMenu(type, event, selection, contextMenuAnchor, reportID, reportAction, draftMessage, onShow, onHide, isArchivedRoom, isChronosReport, isPinnedChat, isUnreadChat); } /** From 6a9ac4f038e51caaf311ddff2b824abee9bbed3f Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 12:07:15 +0200 Subject: [PATCH 4/9] Add text and use right action --- src/languages/en.js | 1 + src/languages/es.js | 1 + src/libs/actions/Report.js | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 2e374a33dbfa..1932ff30f20a 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -265,6 +265,7 @@ export default { copyURLToClipboard: 'Copy URL to clipboard', copyEmailToClipboard: 'Copy email to clipboard', markAsUnread: 'Mark as unread', + markAsRead: 'Mark as Read', editComment: 'Edit comment', deleteAction: ({action}) => `Delete ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}`, deleteConfirmation: ({action}) => `Are you sure you want to delete this ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}?`, diff --git a/src/languages/es.js b/src/languages/es.js index 889da7379e5f..c9fb2fb84b40 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -264,6 +264,7 @@ export default { copyURLToClipboard: 'Copiar URL al portapapeles', copyEmailToClipboard: 'Copiar email al portapapeles', markAsUnread: 'Marcar como no leído', + markAsRead: 'Marcar como leído', editComment: 'Editar comentario', deleteAction: ({action}) => `Eliminar ${ReportActionsUtils.isMoneyRequestAction(action) ? 'pedido' : 'comentario'}`, deleteConfirmation: ({action}) => `¿Estás seguro de que quieres eliminar este ${ReportActionsUtils.isMoneyRequestAction(action) ? 'pedido' : 'comentario'}`, diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 776f10a14074..01098c82685a 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -666,9 +666,8 @@ function readNewestAction(reportID) { * @param {String} [reportActionCreated] */ function markCommentAsUnread(reportID, reportActionCreated= '') { - // If no action created date is provided, use the last action's - const actionCreationTime = reportActionCreated || ReportActionsUtils.getLastVisibleAction(reportID).created; + const actionCreationTime = reportActionCreated || allReports[reportID].lastVisibleActionCreated; // We subtract 1 millisecond so that the lastReadTime is updated to just before a given reportAction's created date // For example, if we want to mark a report action with ID 100 and created date '2014-04-01 16:07:02.999' unread, we set the lastReadTime to '2014-04-01 16:07:02.998' From 61a87b54e483931a643c4791f2d802a3f8b13ee2 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 12:27:14 +0200 Subject: [PATCH 5/9] hide menu when the state changes --- src/components/LHNOptionsList/OptionRowLHN.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 0ed5a29ec330..84fc08e61455 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -56,10 +56,11 @@ const defaultProps = { const OptionRowLHN = (props) => { const optionItem = SidebarUtils.getOptionData(props.reportID); const isPinned = _.get(optionItem, 'isPinned', false); + const isUnread = _.get(optionItem, 'isUnread', false); React.useEffect(() => { ReportActionContextMenu.hideContextMenu(false); - }, [isPinned]); + }, [isPinned, isUnread]); if (!optionItem) { return null; From afcdc74e8e3596d887cb33ef752b401f0d73fd3e Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 6 Jun 2023 12:59:55 +0200 Subject: [PATCH 6/9] prettier --- src/libs/actions/Report.js | 2 +- .../report/ContextMenu/ContextMenuActions.js | 3 ++- .../ContextMenu/ReportActionContextMenu.js | 16 +++++++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 01098c82685a..2c1bf81ce745 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -665,7 +665,7 @@ function readNewestAction(reportID) { * @param {String} reportID * @param {String} [reportActionCreated] */ -function markCommentAsUnread(reportID, reportActionCreated= '') { +function markCommentAsUnread(reportID, reportActionCreated = '') { // If no action created date is provided, use the last action's const actionCreationTime = reportActionCreated || allReports[reportID].lastVisibleActionCreated; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index b0e8c2f39350..41f58b0b4310 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -222,7 +222,8 @@ export default [ textTranslateKey: 'reportActionContextMenu.markAsUnread', icon: Expensicons.Mail, successIcon: Expensicons.Checkmark, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat) => type === CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONTEXT_MENU_TYPES.REPORT && !isUnreadChat), + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat) => + type === CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONTEXT_MENU_TYPES.REPORT && !isUnreadChat), onPress: (closePopover, {reportAction, reportID}) => { Report.markCommentAsUnread(reportID, reportAction.created); if (closePopover) { diff --git a/src/pages/home/report/ContextMenu/ReportActionContextMenu.js b/src/pages/home/report/ContextMenu/ReportActionContextMenu.js index 95ca5b0837ce..711a3be109d7 100644 --- a/src/pages/home/report/ContextMenu/ReportActionContextMenu.js +++ b/src/pages/home/report/ContextMenu/ReportActionContextMenu.js @@ -37,7 +37,21 @@ function showContextMenu( if (!contextMenuRef.current) { return; } - contextMenuRef.current.showContextMenu(type, event, selection, contextMenuAnchor, reportID, reportAction, draftMessage, onShow, onHide, isArchivedRoom, isChronosReport, isPinnedChat, isUnreadChat); + contextMenuRef.current.showContextMenu( + type, + event, + selection, + contextMenuAnchor, + reportID, + reportAction, + draftMessage, + onShow, + onHide, + isArchivedRoom, + isChronosReport, + isPinnedChat, + isUnreadChat, + ); } /** From b1c7dcd74e7b484532e4c30f873804b0f116cc25 Mon Sep 17 00:00:00 2001 From: Alberto Date: Wed, 7 Jun 2023 11:10:49 +0200 Subject: [PATCH 7/9] Remove conditional --- src/libs/actions/Report.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index a70cc8c6b971..eca70d971c1e 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -664,9 +664,9 @@ function readNewestAction(reportID) { * Sets the last read time on a report * * @param {String} reportID - * @param {String} [reportActionCreated] + * @param {String} reportActionCreated */ -function markCommentAsUnread(reportID, reportActionCreated = '') { +function markCommentAsUnread(reportID, reportActionCreated) { // If no action created date is provided, use the last action's const actionCreationTime = reportActionCreated || allReports[reportID].lastVisibleActionCreated; From 9365efb5a0c5b7111c1ca469fe265c54ded9c7ec Mon Sep 17 00:00:00 2001 From: Alberto Date: Wed, 7 Jun 2023 11:24:02 +0200 Subject: [PATCH 8/9] use lodashget --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index eca70d971c1e..bfbc808a3b30 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -668,7 +668,7 @@ function readNewestAction(reportID) { */ function markCommentAsUnread(reportID, reportActionCreated) { // If no action created date is provided, use the last action's - const actionCreationTime = reportActionCreated || allReports[reportID].lastVisibleActionCreated; + const actionCreationTime = reportActionCreated || lodashGet(allReports, [reportID, 'lastVisibleActionCreated'], '0'); // We subtract 1 millisecond so that the lastReadTime is updated to just before a given reportAction's created date // For example, if we want to mark a report action with ID 100 and created date '2014-04-01 16:07:02.999' unread, we set the lastReadTime to '2014-04-01 16:07:02.998' From 79046eb951272652940cffe212214e01b6f92b47 Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 15 Jun 2023 17:11:41 +0200 Subject: [PATCH 9/9] capital --- src/languages/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.js b/src/languages/en.js index ae0fe6b202e2..ad92086628c8 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -266,7 +266,7 @@ export default { copyURLToClipboard: 'Copy URL to clipboard', copyEmailToClipboard: 'Copy email to clipboard', markAsUnread: 'Mark as unread', - markAsRead: 'Mark as Read', + markAsRead: 'Mark as read', editComment: 'Edit comment', deleteAction: ({action}) => `Delete ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}`, deleteConfirmation: ({action}) => `Are you sure you want to delete this ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}?`,