-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[No QA] Report_AddComment Refactor Part 1 #9328
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -591,42 +591,20 @@ function updateReportWithNewAction( | |
reportAction, | ||
notificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, | ||
) { | ||
const newMaxSequenceNumber = reportAction.sequenceNumber; | ||
const isFromCurrentUser = reportAction.actorAccountID === currentUserAccountID; | ||
const initialLastReadSequenceNumber = lastReadSequenceNumbers[reportID] || 0; | ||
const messageText = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED | ||
? lodashGet(reportAction, 'originalMessage.html', '') | ||
: lodashGet(reportAction, ['message', 0, 'text'], ''); | ||
|
||
// When handling an action from the current users we can assume that their | ||
// last read actionID has been updated in the server but not necessarily reflected | ||
// locally so we must first update it and then calculate the unread (which should be 0) | ||
if (isFromCurrentUser) { | ||
setLocalLastRead(reportID, newMaxSequenceNumber); | ||
} | ||
|
||
let messageText = lodashGet(reportAction, ['message', 0, 'text'], ''); | ||
if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) { | ||
messageText = lodashGet(reportAction, 'originalMessage.html', ''); | ||
} | ||
|
||
// Always merge the reportID into Onyx | ||
// If the report doesn't exist in Onyx yet, then all the rest of the data will be filled out | ||
// by handleReportChanged | ||
const updatedReportObject = { | ||
// Always merge the reportID into Onyx. If the report doesn't exist in Onyx yet, then all the rest of the data will be filled out by handleReportChanged | ||
reportID, | ||
|
||
// Use updated lastReadSequenceNumber, value may have been modified by setLocalLastRead | ||
// Here deletedComments count does not include the new action being added. We can safely assume that newly received action is not deleted. | ||
unreadActionCount: newMaxSequenceNumber - (lastReadSequenceNumbers[reportID] || 0) - ReportActions.getDeletedCommentsCount(reportID, lastReadSequenceNumbers[reportID] || 0), | ||
maxSequenceNumber: reportAction.sequenceNumber, | ||
notificationPreference, | ||
lastMessageTimestamp: reportAction.timestamp, | ||
lastMessageText: ReportUtils.formatReportLastMessageText(messageText), | ||
lastActorEmail: reportAction.actorEmail, | ||
}; | ||
|
||
// If the report action from pusher is a higher sequence number than we know about (meaning it has come from | ||
// a chat participant in another application), then the last message text and author needs to be updated as well | ||
if (newMaxSequenceNumber > initialLastReadSequenceNumber) { | ||
updatedReportObject.lastMessageTimestamp = reportAction.timestamp; | ||
updatedReportObject.lastMessageText = ReportUtils.formatReportLastMessageText(messageText); | ||
updatedReportObject.lastActorEmail = reportAction.actorEmail; | ||
} | ||
|
||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, updatedReportObject); | ||
|
||
const reportActionsToMerge = {}; | ||
|
@@ -644,63 +622,6 @@ function updateReportWithNewAction( | |
}; | ||
|
||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, reportActionsToMerge); | ||
|
||
// If chat report receives an action with IOU and we have an IOUReportID, update IOU object | ||
if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && reportAction.originalMessage.IOUReportID) { | ||
const iouReportID = reportAction.originalMessage.IOUReportID; | ||
|
||
// If the IOUDetails object exists we are in the Send Money flow, and we should not fetch and update the chatReport | ||
// as this would overwrite any existing IOUs. For all other cases we must update the chatReport with the iouReportID as | ||
// if we don't, new IOUs would not be displayed and paid IOUs would still show as unpaid. | ||
if (reportAction.originalMessage.IOUDetails === undefined) { | ||
fetchIOUReportByIDAndUpdateChatReport(iouReportID, reportID); | ||
} | ||
} | ||
|
||
if (!ActiveClientManager.isClientTheLeader()) { | ||
Log.info('[LOCAL_NOTIFICATION] Skipping notification because this client is not the leader'); | ||
return; | ||
} | ||
|
||
// We don't want to send a local notification if the user preference is daily or mute | ||
if (notificationPreference === 'mute' || notificationPreference === 'daily') { | ||
// eslint-disable-next-line max-len | ||
Log.info(`[LOCAL_NOTIFICATION] No notification because user preference is to be notified: ${notificationPreference}`); | ||
return; | ||
} | ||
|
||
// If this comment is from the current user we don't want to parrot whatever they wrote back to them. | ||
if (isFromCurrentUser) { | ||
Log.info('[LOCAL_NOTIFICATION] No notification because comment is from the currently logged in user'); | ||
return; | ||
} | ||
|
||
// If we are currently viewing this report do not show a notification. | ||
if (reportID === lastViewedReportID && Visibility.isVisible()) { | ||
Log.info('[LOCAL_NOTIFICATION] No notification because it was a comment for the current report'); | ||
return; | ||
} | ||
|
||
// If the comment came from Concierge let's not show a notification since we already show one for expensify.com | ||
if (lodashGet(reportAction, 'actorEmail') === CONST.EMAIL.CONCIERGE) { | ||
return; | ||
} | ||
|
||
// When a new message comes in, if the New marker is not already set (newMarkerSequenceNumber === 0), set the | ||
// marker above the incoming message. | ||
if (lodashGet(allReports, [reportID, 'newMarkerSequenceNumber'], 0) === 0 | ||
&& updatedReportObject.unreadActionCount > 0) { | ||
const oldestUnreadSeq = (updatedReportObject.maxSequenceNumber - updatedReportObject.unreadActionCount) + 1; | ||
setNewMarkerPosition(reportID, oldestUnreadSeq); | ||
} | ||
Log.info('[LOCAL_NOTIFICATION] Creating notification'); | ||
LocalNotification.showCommentNotification({ | ||
reportAction, | ||
onClick: () => { | ||
// Navigate to this report onClick | ||
Navigation.navigate(ROUTES.getReportRoute(reportID)); | ||
}, | ||
}); | ||
} | ||
|
||
/** | ||
|
@@ -1543,6 +1464,112 @@ function renameReport(reportID, reportName) { | |
.finally(() => Onyx.set(ONYXKEYS.IS_LOADING_RENAME_POLICY_ROOM, false)); | ||
} | ||
|
||
/** | ||
* @param {Number} reportID | ||
* @param {Object} action | ||
*/ | ||
function viewNewReportAction(reportID, action) { | ||
const newMaxSequenceNumber = action.sequenceNumber; | ||
const isFromCurrentUser = action.actorAccountID === currentUserAccountID; | ||
|
||
// When handling an action from the current users we can assume that their | ||
// last read actionID has been updated in the server but not necessarily reflected | ||
// locally so we must first update it and then calculate the unread (which should be 0) | ||
if (isFromCurrentUser) { | ||
setLocalLastRead(reportID, newMaxSequenceNumber); | ||
} | ||
|
||
const updatedReportObject = { | ||
// Use updated lastReadSequenceNumber, value may have been modified by setLocalLastRead | ||
// Here deletedComments count does not include the new action being added. We can safely assume that newly received action is not deleted. | ||
unreadActionCount: newMaxSequenceNumber - (lastReadSequenceNumbers[reportID] || 0) - ReportActions.getDeletedCommentsCount(reportID, lastReadSequenceNumbers[reportID] || 0), | ||
}; | ||
|
||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, updatedReportObject); | ||
|
||
// If chat report receives an action with IOU and we have an IOUReportID, update IOU object | ||
if (action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && action.originalMessage.IOUReportID) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar comment for this logic as for above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the answer is the same here. If you miss this update then we just need to have the "reconnection" callbacks account for this data. All the IOU reports should ideally be sent whenever we are "reconnecting". |
||
const iouReportID = action.originalMessage.IOUReportID; | ||
|
||
// If the IOUDetails object exists we are in the Send Money flow, and we should not fetch and update the chatReport | ||
// as this would overwrite any existing IOUs. For all other cases we must update the chatReport with the iouReportID as | ||
// if we don't, new IOUs would not be displayed and paid IOUs would still show as unpaid. | ||
if (action.originalMessage.IOUDetails === undefined) { | ||
fetchIOUReportByIDAndUpdateChatReport(iouReportID, reportID); | ||
} | ||
} | ||
|
||
const notificationPreference = lodashGet(allReports, [reportID, 'notificationPreference'], CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS); | ||
if (!ActiveClientManager.isClientTheLeader()) { | ||
Log.info('[LOCAL_NOTIFICATION] Skipping notification because this client is not the leader'); | ||
return; | ||
} | ||
|
||
// We don't want to send a local notification if the user preference is daily or mute | ||
if (notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE || notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY) { | ||
Log.info(`[LOCAL_NOTIFICATION] No notification because user preference is to be notified: ${notificationPreference}`); | ||
return; | ||
} | ||
|
||
// If this comment is from the current user we don't want to parrot whatever they wrote back to them. | ||
if (isFromCurrentUser) { | ||
Log.info('[LOCAL_NOTIFICATION] No notification because comment is from the currently logged in user'); | ||
return; | ||
} | ||
|
||
// If we are currently viewing this report do not show a notification. | ||
if (reportID === lastViewedReportID && Visibility.isVisible()) { | ||
Log.info('[LOCAL_NOTIFICATION] No notification because it was a comment for the current report'); | ||
return; | ||
} | ||
Comment on lines
+1520
to
+1524
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We didn't consider whether the window has focus, which led to a regression here |
||
|
||
// If the comment came from Concierge let's not show a notification since we already show one for expensify.com | ||
if (lodashGet(action, 'actorEmail') === CONST.EMAIL.CONCIERGE) { | ||
return; | ||
} | ||
|
||
// When a new message comes in, if the New marker is not already set (newMarkerSequenceNumber === 0), set the marker above the incoming message. | ||
const report = lodashGet(allReports, 'reportID', {}); | ||
if (lodashGet(report, 'newMarkerSequenceNumber', 0) === 0 && report.unreadActionCount > 0) { | ||
const oldestUnreadSeq = (report.maxSequenceNumber - report.unreadActionCount) + 1; | ||
setNewMarkerPosition(reportID, oldestUnreadSeq); | ||
} | ||
|
||
Log.info('[LOCAL_NOTIFICATION] Creating notification'); | ||
LocalNotification.showCommentNotification({ | ||
reportAction: action, | ||
onClick: () => { | ||
// Navigate to this report onClick | ||
Navigation.navigate(ROUTES.getReportRoute(reportID)); | ||
}, | ||
}); | ||
} | ||
|
||
Onyx.connect({ | ||
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, | ||
initWithStoredValues: false, | ||
callback: (actions, key) => { | ||
// reportID can be derived from the Onyx key | ||
const reportID = parseInt(key.split('_')[1], 10); | ||
if (!reportID) { | ||
return; | ||
} | ||
|
||
_.each(actions, (action) => { | ||
if (!action.timestamp) { | ||
return; | ||
} | ||
|
||
// If we are past the deadline to notify for this comment don't do it | ||
if (moment.utc(action.timestamp * 1000).isBefore(moment.utc().subtract(10, 'seconds'))) { | ||
return; | ||
} | ||
marcaaron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
viewNewReportAction(reportID, action); | ||
}); | ||
}, | ||
}); | ||
|
||
export { | ||
fetchAllReports, | ||
fetchActions, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking from an offline perspective. Let's say I'm offline and eventually I receive the new report action. If the 10-second check returns early we won't run this code and thus won't update the
unreadActionCount
, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are offline then you can't get any Pusher updates at all. There is no "eventually" - you missed it and it's never coming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're asking what happens when we come back online - then we would fetch the reports which should update the
unreadActionCount
for any reports. If you manage to miss a report action update because you're offline and then come back online before the 10 second window - I guess you'd see a notification - which seems alright.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay, thanks for clarifying!