-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Replace Report_AddComment with AddComment (Part 2) #9350
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
Changes from all commits
aac44cb
ae0e541
984f41e
4b4bceb
0ea7e2d
5759035
05d540d
631932f
665b93b
bf90793
33eb904
d798541
a7174be
7ba89c1
950ea10
a6ad485
99306f1
de49280
d5131e5
3686169
8761aa6
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 |
---|---|---|
|
@@ -115,21 +115,38 @@ function startCurrentDateUpdater() { | |
}); | ||
} | ||
|
||
/* | ||
* Updates user's timezone, if their timezone is set to automatic and | ||
* is different from current timezone | ||
/** | ||
* @returns {Object} | ||
*/ | ||
function updateTimezone() { | ||
function getCurrentTimezone() { | ||
const currentTimezone = moment.tz.guess(true); | ||
if (timezone.automatic && timezone.selected !== currentTimezone) { | ||
PersonalDetails.setPersonalDetails({timezone: {...timezone, selected: currentTimezone}}); | ||
return {...timezone, selected: currentTimezone}; | ||
} | ||
return timezone; | ||
} | ||
|
||
/* | ||
* Returns a version of updateTimezone function throttled by 5 minutes | ||
* Updates user's timezone, if their timezone is set to automatic and | ||
* is different from current timezone | ||
*/ | ||
function updateTimezone() { | ||
PersonalDetails.setPersonalDetails({timezone: getCurrentTimezone()}); | ||
} | ||
|
||
// Used to throttle updates to the timezone when necessary | ||
let lastUpdatedTimezoneTime = moment(); | ||
|
||
/** | ||
* @returns {Boolean} | ||
*/ | ||
const throttledUpdateTimezone = _.throttle(() => updateTimezone(), 1000 * 60 * 5); | ||
function canUpdateTimezone() { | ||
return lastUpdatedTimezoneTime.isBefore(moment().subtract(5, 'minutes')); | ||
} | ||
|
||
Comment on lines
+143
to
+146
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 know this is just a refactor but why do we try to update every 5 minutes? feels like way too often, it probably only matters when a user is traveling but even then I don't really need my timezone updated every step of the way, just like when I arrive to my destination. actually thinking about this more (i know this is all one comment but time passed between the first paragraph and this one)... why put a time limit on it at all? why not just check if the current timezone is different than the one in onyx and only attempt to set it if they are different? 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. That could work. I'm not sure why we chose every 5 minutes or whether it would be easier to check if the timezone has changed. I think there is some kind of cost associated with trying to "guess" the timezone and maybe that's why this is throttled, but not really focused on improving this particular feature. |
||
function setTimezoneUpdated() { | ||
lastUpdatedTimezoneTime = moment(); | ||
} | ||
|
||
/** | ||
* @namespace DateUtils | ||
|
@@ -139,8 +156,10 @@ const DateUtils = { | |
timestampToDateTime, | ||
startCurrentDateUpdater, | ||
updateTimezone, | ||
throttledUpdateTimezone, | ||
getLocalMomentFromTimestamp, | ||
getCurrentTimezone, | ||
canUpdateTimezone, | ||
setTimezoneUpdated, | ||
}; | ||
|
||
export default DateUtils; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,6 @@ import * as Pusher from '../Pusher/pusher'; | |
import LocalNotification from '../Notification/LocalNotification'; | ||
import PushNotification from '../Notification/PushNotification'; | ||
import * as PersonalDetails from './PersonalDetails'; | ||
import * as User from './User'; | ||
import Navigation from '../Navigation/Navigation'; | ||
import * as ActiveClientManager from '../ActiveClientManager'; | ||
import Visibility from '../Visibility'; | ||
|
@@ -27,6 +26,7 @@ import * as ReportActions from './ReportActions'; | |
import Growl from '../Growl'; | ||
import * as Localize from '../Localize'; | ||
import PusherUtils from '../PusherUtils'; | ||
import DateUtils from '../DateUtils'; | ||
|
||
let currentUserEmail; | ||
let currentUserAccountID; | ||
|
@@ -534,54 +534,6 @@ function updateReportActionMessage(reportID, sequenceNumber, message) { | |
}); | ||
} | ||
|
||
/** | ||
* Updates a report in the store with a new report action | ||
* | ||
* @param {Number} reportID | ||
* @param {Object} reportAction | ||
* @param {String} [notificationPreference] On what cadence the user would like to be notified | ||
*/ | ||
function updateReportWithNewAction( | ||
reportID, | ||
reportAction, | ||
notificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, | ||
) { | ||
const messageHtml = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED | ||
? lodashGet(reportAction, 'originalMessage.html', '') | ||
: lodashGet(reportAction, ['message', 0, 'html'], ''); | ||
|
||
const parser = new ExpensiMark(); | ||
const messageText = parser.htmlToText(messageHtml); | ||
|
||
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, | ||
maxSequenceNumber: reportAction.sequenceNumber, | ||
notificationPreference, | ||
lastMessageTimestamp: reportAction.timestamp, | ||
lastMessageText: ReportUtils.formatReportLastMessageText(messageText), | ||
lastActorEmail: reportAction.actorEmail, | ||
}; | ||
|
||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, updatedReportObject); | ||
|
||
const reportActionsToMerge = {}; | ||
if (reportAction.clientID) { | ||
// Remove the optimistic action from the report since we are about to replace it | ||
// with the real one (which has the true sequenceNumber) | ||
reportActionsToMerge[reportAction.clientID] = null; | ||
} | ||
|
||
// Add the action into Onyx | ||
reportActionsToMerge[reportAction.sequenceNumber] = { | ||
...reportAction, | ||
isAttachment: ReportUtils.isReportMessageAttachment(lodashGet(reportAction, ['message', 0], {})), | ||
loading: false, | ||
}; | ||
|
||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, reportActionsToMerge); | ||
} | ||
|
||
/** | ||
* Get the private pusher channel name for a Report. | ||
* | ||
|
@@ -606,13 +558,6 @@ function subscribeToUserEvents() { | |
return; | ||
} | ||
|
||
// Live-update a report's actions when a 'report comment' event is received. | ||
PusherUtils.subscribeToPrivateUserChannelEvent( | ||
Pusher.TYPE.REPORT_COMMENT, | ||
currentUserAccountID, | ||
pushJSON => updateReportWithNewAction(pushJSON.reportID, pushJSON.reportAction, pushJSON.notificationPreference), | ||
); | ||
|
||
// Live-update a report's actions when an 'edit comment' event is received. | ||
PusherUtils.subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT_EDIT, | ||
currentUserAccountID, | ||
|
@@ -623,9 +568,9 @@ function subscribeToUserEvents() { | |
* Setup reportComment push notification callbacks. | ||
*/ | ||
function subscribeToReportCommentPushNotifications() { | ||
PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, reportAction}) => { | ||
PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, onyxData}) => { | ||
Log.info('[Report] Handled event sent by Airship', false, {reportID}); | ||
updateReportWithNewAction(reportID, reportAction); | ||
Onyx.update(onyxData); | ||
}); | ||
|
||
// Open correct report when push notification is clicked | ||
|
@@ -903,7 +848,7 @@ function fetchAllReports( | |
* @param {String} text | ||
* @param {File} [file] | ||
*/ | ||
function addAction(reportID, text, file) { | ||
function addComment(reportID, text, file) { | ||
// For comments shorter than 10k chars, convert the comment from MD into HTML because that's how it is stored in the database | ||
// For longer comments, skip parsing and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!! | ||
const parser = new ExpensiMark(); | ||
|
@@ -921,12 +866,12 @@ function addAction(reportID, text, file) { | |
: parser.htmlToText(htmlForNewComment); | ||
|
||
// Update the report in Onyx to have the new sequence number | ||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, { | ||
const optimisticReport = { | ||
maxSequenceNumber: newSequenceNumber, | ||
lastMessageTimestamp: moment().unix(), | ||
lastMessageText: ReportUtils.formatReportLastMessageText(textForNewComment), | ||
lastActorEmail: currentUserEmail, | ||
}); | ||
}; | ||
Luke9389 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Generate a clientID so we can save the optimistic action to storage with the clientID as key. Later, we will | ||
// remove the optimistic action when we add the real action created in the server. We do this because it's not | ||
|
@@ -942,12 +887,10 @@ function addAction(reportID, text, file) { | |
// Store the optimistic action ID on the report the comment was added to. It will be removed later when refetching | ||
// report actions in order to clear out any stuck actions (i.e. actions where the client never received a Pusher | ||
// event, for whatever reason, from the server with the new action data | ||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, { | ||
optimisticReportActionIDs: [...(optimisticReportActionIDs[reportID] || []), optimisticReportActionID], | ||
}); | ||
optimisticReport.optimisticReportActionIDs = [...(optimisticReportActionIDs[reportID] || []), optimisticReportActionID]; | ||
|
||
// Optimistically add the new comment to the store before waiting to save it to the server | ||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { | ||
const optimisticReportActions = { | ||
[optimisticReportActionID]: { | ||
actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, | ||
actorEmail: currentUserEmail, | ||
|
@@ -976,41 +919,70 @@ function addAction(reportID, text, file) { | |
isFirstItem: false, | ||
isAttachment, | ||
attachmentInfo, | ||
loading: true, | ||
isLoading: true, | ||
shouldShow: true, | ||
}, | ||
}); | ||
}; | ||
|
||
DeprecatedAPI.Report_AddComment({ | ||
const parameters = { | ||
reportID, | ||
file, | ||
reportComment: commentText, | ||
clientID: optimisticReportActionID, | ||
persist: true, | ||
}) | ||
.then((response) => { | ||
if (response.jsonCode === 408) { | ||
Growl.error(Localize.translateLocal('reportActionCompose.fileUploadFailed')); | ||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { | ||
[optimisticReportActionID]: null, | ||
}); | ||
console.error(response.message); | ||
return; | ||
} | ||
|
||
if (response.jsonCode === 666 && reportID === conciergeChatReportID) { | ||
Growl.error(Localize.translateLocal('reportActionCompose.blockedFromConcierge')); | ||
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { | ||
[optimisticReportActionID]: null, | ||
}); | ||
}; | ||
|
||
// The fact that the API is returning this error means the BLOCKED_FROM_CONCIERGE nvp in the user details has changed since the last time we checked, so let's update | ||
User.getUserDetails(); | ||
return; | ||
} | ||
const optimisticData = [ | ||
{ | ||
onyxMethod: CONST.ONYX.METHOD.MERGE, | ||
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, | ||
value: optimisticReport, | ||
}, | ||
{ | ||
onyxMethod: CONST.ONYX.METHOD.MERGE, | ||
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, | ||
value: optimisticReportActions, | ||
}, | ||
]; | ||
|
||
updateReportWithNewAction(reportID, response.reportAction); | ||
// Update the timezone if it's been 5 minutes from the last time the user added a comment | ||
if (DateUtils.canUpdateTimezone()) { | ||
const timezone = DateUtils.getCurrentTimezone(); | ||
parameters.timezone = JSON.stringify(timezone); | ||
optimisticData.push({ | ||
onyxMethod: CONST.ONYX.METHOD.MERGE, | ||
key: ONYXKEYS.MY_PERSONAL_DETAILS, | ||
value: {timezone}, | ||
}); | ||
optimisticData.push({ | ||
onyxMethod: CONST.ONYX.METHOD.MERGE, | ||
key: ONYXKEYS.PERSONAL_DETAILS, | ||
value: {[currentUserEmail]: timezone}, | ||
}); | ||
DateUtils.setTimezoneUpdated(); | ||
} | ||
|
||
API.write(isAttachment ? 'AddAttachment' : 'AddComment', parameters, { | ||
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 here I might have preferred a separate variable like const command = isAttachment ? 'AddAttachment' : 'AddComment';
API.write(command, parameters, ...); or maybe even getting rid of 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. eh i guess looking back we use 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. Don't really have strong feelings one way or the other on this. |
||
optimisticData, | ||
failureData: [ | ||
{ | ||
onyxMethod: CONST.ONYX.METHOD.MERGE, | ||
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, | ||
value: { | ||
[optimisticReportActionID]: { | ||
isLoading: false, | ||
}, | ||
}, | ||
}, | ||
], | ||
}); | ||
} | ||
|
||
/** | ||
* @param {Number} reportID | ||
* @param {Object} file | ||
*/ | ||
function addAttachment(reportID, file) { | ||
addComment(reportID, '', file); | ||
} | ||
|
||
/** | ||
|
@@ -1521,7 +1493,8 @@ export { | |
fetchChatReportsByIDs, | ||
fetchIOUReportByID, | ||
fetchIOUReportByIDAndUpdateChatReport, | ||
addAction, | ||
addComment, | ||
addAttachment, | ||
updateLastReadActionID, | ||
updateNotificationPreference, | ||
setNewMarkerPosition, | ||
|
Uh oh!
There was an error while loading. Please reload this page.