-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Clean up various buildOptimistic* methods. Clarify sequenceNumber usage in doc comments.
#11219
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
Merged
marcaaron
merged 5 commits into
main
from
marcaaron-refactorCreateOptimisticReportAction
Sep 23, 2022
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
7b5670c
Moveall buildOptimisticSomething methods to ReportUtils
marcaaron 69a3117
Clarify sequenceNumber usage
marcaaron b19add5
clean up providedPersonalDetails
marcaaron 0397940
Update comment
marcaaron 7c26084
Fix some dead code
marcaaron File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import Str from 'expensify-common/lib/str'; | |
| import lodashGet from 'lodash/get'; | ||
| import Onyx from 'react-native-onyx'; | ||
| import moment from 'moment'; | ||
| import ExpensiMark from 'expensify-common/lib/ExpensiMark'; | ||
| import ONYXKEYS from '../ONYXKEYS'; | ||
| import CONST from '../CONST'; | ||
| import * as Localize from './Localize'; | ||
|
|
@@ -46,10 +47,14 @@ Onyx.connect({ | |
| }, | ||
| }); | ||
|
|
||
| let allPersonalDetails; | ||
| let currentUserPersonalDetails; | ||
| Onyx.connect({ | ||
| key: ONYXKEYS.PERSONAL_DETAILS, | ||
| callback: val => currentUserPersonalDetails = lodashGet(val, currentUserEmail), | ||
| callback: (val) => { | ||
| currentUserPersonalDetails = lodashGet(val, currentUserEmail); | ||
| allPersonalDetails = val; | ||
| }, | ||
| }); | ||
|
|
||
| /** | ||
|
|
@@ -573,6 +578,63 @@ function hasReportNameError(report) { | |
| return !_.isEmpty(lodashGet(report, 'errorFields.reportName', {})); | ||
| } | ||
|
|
||
| /** | ||
| * @param {Number} sequenceNumber sequenceNumber must be provided and it must be a number. It cannot and should not be a clientID, | ||
| * reportActionID, or anything else besides an estimate of what the next sequenceNumber will be for the | ||
| * optimistic report action. Until we deprecate sequenceNumbers please assume that all report actions | ||
| * have them and they should be numbers. | ||
| * @param {String} [text] | ||
| * @param {File} [file] | ||
| * @returns {Object} | ||
| */ | ||
| function buildOptimisticReportAction(sequenceNumber, 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(); | ||
| const commentText = text.length < 10000 ? parser.replace(text) : text; | ||
| const isAttachment = _.isEmpty(text) && file !== undefined; | ||
| const attachmentInfo = isAttachment ? file : {}; | ||
| const htmlForNewComment = isAttachment ? 'Uploading Attachment...' : commentText; | ||
|
|
||
| // Remove HTML from text when applying optimistic offline comment | ||
| const textForNewComment = isAttachment ? '[Attachment]' | ||
| : parser.htmlToText(htmlForNewComment); | ||
|
|
||
| return { | ||
| commentText, | ||
| reportAction: { | ||
| reportActionID: NumberUtils.rand64(), | ||
| actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, | ||
| actorEmail: currentUserEmail, | ||
| actorAccountID: currentUserAccountID, | ||
| person: [ | ||
| { | ||
| style: 'strong', | ||
| text: lodashGet(allPersonalDetails, [currentUserEmail, 'displayName'], currentUserEmail), | ||
| type: 'TEXT', | ||
| }, | ||
| ], | ||
| automatic: false, | ||
| sequenceNumber, | ||
| clientID: NumberUtils.generateReportActionClientID(), | ||
| avatar: lodashGet(allPersonalDetails, [currentUserEmail, 'avatar'], getDefaultAvatar(currentUserEmail)), | ||
| timestamp: moment().unix(), | ||
| message: [ | ||
| { | ||
| type: CONST.REPORT.MESSAGE.TYPE.COMMENT, | ||
| html: htmlForNewComment, | ||
| text: textForNewComment, | ||
| }, | ||
| ], | ||
| isFirstItem: false, | ||
| isAttachment, | ||
| attachmentInfo, | ||
| pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, | ||
| shouldShow: true, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| /* | ||
| * Builds an optimistic IOU report with a randomly generated reportID | ||
| */ | ||
|
|
@@ -599,6 +661,7 @@ function buildOptimisticIOUReport(ownerEmail, recipientEmail, total, chatReportI | |
| /** | ||
| * Builds an optimistic IOU reportAction object | ||
| * | ||
| * @param {Number} sequenceNumber - Caller is responsible for providing a best guess at what the next sequenceNumber will be. | ||
| * @param {String} type - IOUReportAction type. Can be oneOf(create, decline, cancel, pay). | ||
| * @param {Number} amount - IOU amount in cents. | ||
| * @param {String} comment - User comment for the IOU. | ||
|
|
@@ -608,11 +671,10 @@ function buildOptimisticIOUReport(ownerEmail, recipientEmail, total, chatReportI | |
| * | ||
| * @returns {Object} | ||
| */ | ||
| function buildOptimisticIOUReportAction(type, amount, comment, paymentType = '', existingIOUTransactionID = '', existingIOUReportID = 0) { | ||
| function buildOptimisticIOUReportAction(sequenceNumber, type, amount, comment, paymentType = '', existingIOUTransactionID = '', existingIOUReportID = 0) { | ||
| const currency = lodashGet(currentUserPersonalDetails, 'localCurrencyCode'); | ||
| const IOUTransactionID = existingIOUTransactionID || NumberUtils.rand64(); | ||
| const IOUReportID = existingIOUReportID || generateReportID(); | ||
| const sequenceNumber = NumberUtils.generateReportActionSequenceNumber(); | ||
| const originalMessage = { | ||
| amount, | ||
| comment, | ||
|
|
@@ -637,10 +699,7 @@ function buildOptimisticIOUReportAction(type, amount, comment, paymentType = '', | |
| actorEmail: currentUserEmail, | ||
| automatic: false, | ||
| avatar: lodashGet(currentUserPersonalDetails, 'avatar', getDefaultAvatar(currentUserEmail)), | ||
|
|
||
| // For now, the clientID and sequenceNumber are the same. | ||
| // We are changing that as we roll out the optimisticReportAction IDs and related refactors. | ||
| clientID: sequenceNumber, | ||
| clientID: NumberUtils.generateReportActionClientID(), | ||
| isAttachment: false, | ||
| originalMessage, | ||
| person: [{ | ||
|
|
@@ -656,6 +715,132 @@ function buildOptimisticIOUReportAction(type, amount, comment, paymentType = '', | |
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Builds an optimistic chat report with a randomly generated reportID and as much information as we currently have | ||
| * | ||
| * @param {Array} participantList | ||
| * @param {String} reportName | ||
| * @param {String} chatType | ||
| * @param {String} policyID | ||
| * @param {String} ownerEmail | ||
| * @param {Boolean} isOwnPolicyExpenseChat | ||
| * @param {String} oldPolicyName | ||
| * @param {String} visibility | ||
| * @returns {Object} | ||
| */ | ||
| function buildOptimisticChatReport( | ||
| participantList, | ||
| reportName = 'Chat Report', | ||
| chatType = '', | ||
| policyID = CONST.POLICY.OWNER_EMAIL_FAKE, | ||
| ownerEmail = CONST.REPORT.OWNER_EMAIL_FAKE, | ||
| isOwnPolicyExpenseChat = false, | ||
| oldPolicyName = '', | ||
| visibility = undefined, | ||
| ) { | ||
| return { | ||
| chatType, | ||
| hasOutstandingIOU: false, | ||
| isOwnPolicyExpenseChat, | ||
| isPinned: false, | ||
| lastActorEmail: '', | ||
| lastMessageHtml: '', | ||
| lastMessageText: null, | ||
| lastReadSequenceNumber: 0, | ||
| lastMessageTimestamp: 0, | ||
| lastVisitedTimestamp: 0, | ||
| maxSequenceNumber: 0, | ||
| notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY, | ||
| oldPolicyName, | ||
| ownerEmail, | ||
| participants: participantList, | ||
| policyID, | ||
| reportID: generateReportID(), | ||
| reportName, | ||
| stateNum: 0, | ||
| statusNum: 0, | ||
| visibility, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the necessary reportAction onyx data to indicate that the chat has been created optimistically | ||
|
Contributor
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. NAB, but maybe we should use this opportunity to better align the function comments, which are quite different:
|
||
| * @param {String} ownerEmail | ||
| * @returns {Object} | ||
| */ | ||
| function buildOptimisticCreatedReportAction(ownerEmail) { | ||
| return { | ||
| 0: { | ||
| actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, | ||
| pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, | ||
| actorAccountID: currentUserAccountID, | ||
| message: [ | ||
| { | ||
| type: CONST.REPORT.MESSAGE.TYPE.TEXT, | ||
| style: 'strong', | ||
| text: ownerEmail === currentUserEmail ? 'You' : ownerEmail, | ||
| }, | ||
| { | ||
| type: CONST.REPORT.MESSAGE.TYPE.TEXT, | ||
| style: 'normal', | ||
| text: ' created this report', | ||
| }, | ||
| ], | ||
| person: [ | ||
| { | ||
| type: CONST.REPORT.MESSAGE.TYPE.TEXT, | ||
| style: 'strong', | ||
| text: lodashGet(allPersonalDetails, [currentUserEmail, 'displayName'], currentUserEmail), | ||
| }, | ||
| ], | ||
| automatic: false, | ||
| sequenceNumber: 0, | ||
| avatar: lodashGet(allPersonalDetails, [currentUserEmail, 'avatar'], getDefaultAvatar(currentUserEmail)), | ||
| timestamp: moment().unix(), | ||
| shouldShow: true, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @param {String} policyID | ||
| * @param {String} policyName | ||
| * @returns {Object} | ||
| */ | ||
| function buildOptimisticWorkspaceChats(policyID, policyName) { | ||
| const announceChatData = buildOptimisticChatReport( | ||
| [currentUserEmail], | ||
| CONST.REPORT.WORKSPACE_CHAT_ROOMS.ANNOUNCE, | ||
| CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, | ||
| policyID, | ||
| null, | ||
| false, | ||
| policyName, | ||
| ); | ||
| const announceChatReportID = announceChatData.reportID; | ||
| const announceReportActionData = buildOptimisticCreatedReportAction(announceChatData.ownerEmail); | ||
|
|
||
| const adminsChatData = buildOptimisticChatReport([currentUserEmail], CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS, CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, null, false, policyName); | ||
| const adminsChatReportID = adminsChatData.reportID; | ||
| const adminsReportActionData = buildOptimisticCreatedReportAction(adminsChatData.ownerEmail); | ||
|
|
||
| const expenseChatData = buildOptimisticChatReport([currentUserEmail], '', CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, currentUserEmail, true, policyName); | ||
| const expenseChatReportID = expenseChatData.reportID; | ||
| const expenseReportActionData = buildOptimisticCreatedReportAction(expenseChatData.ownerEmail); | ||
|
|
||
| return { | ||
| announceChatReportID, | ||
| announceChatData, | ||
| announceReportActionData, | ||
| adminsChatReportID, | ||
| adminsChatData, | ||
| adminsReportActionData, | ||
| expenseChatReportID, | ||
| expenseChatData, | ||
| expenseReportActionData, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @param {Object} report | ||
| * @returns {Boolean} | ||
|
|
@@ -697,7 +882,11 @@ export { | |
| navigateToDetailsPage, | ||
| generateReportID, | ||
| hasReportNameError, | ||
| isUnread, | ||
| buildOptimisticWorkspaceChats, | ||
| buildOptimisticChatReport, | ||
| buildOptimisticCreatedReportAction, | ||
| buildOptimisticIOUReport, | ||
| buildOptimisticIOUReportAction, | ||
| isUnread, | ||
| buildOptimisticReportAction, | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
NAB