-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Performance: chat input #25758
Performance: chat input #25758
Conversation
…y-app-fork into perf/composer-investigations
…ction' of github.com:margelo/expensify-app-fork into perf/composer-investigations
…ction' of github.com:margelo/expensify-app-fork into perf/composer-investigations
…y-app-fork into refactor-report-action-compose
…ction' into refactor-report-action-compose
This reverts commit eb9baf8.
This reverts commit 9739c08.
move actionButtonRef
…actor-report-action-compose
…y-app-fork into refactor-report-action-compose
…ction' of github.com:margelo/expensify-app-fork into refactor-report-action-compose
🚀 Deployed to production by https://github.com/luacmartins in version: 1.3.58-5 🚀
|
🚀 Deployed to staging by https://github.com/mountiny in version: 1.3.59-0 🚀
|
🚀 Deployed to production by https://github.com/luacmartins in version: 1.3.59-5 🚀
|
|
||
const reportRecipient = personalDetails[participantsWithoutExpensifyAccountIDs[0]]; | ||
const shouldUseFocusedColor = !isBlockedFromConcierge && !disabled && isFocused; | ||
const isFullSizeComposerAvailable = isFullComposerAvailable && !_.isEmpty(value); |
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.
maxLines={maxComposerLines} | ||
onFocus={onFocus} | ||
onBlur={onBlur} | ||
onClick={setShouldBlockSuggestionCalc} |
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.
Is this intended? Previously we used to set shouldBlockEmojiCalc
and shouldBlockMentionCalc
to false
but now this being set to true
.
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.
I dont think there should be change in the behaviour here, not intentionally
[isKeyboardShown, isSmallScreenWidth, parentReportActions, report, reportActions, reportID, submitForm, suggestionsRef, valueRef], | ||
); | ||
|
||
const onSelectionChange = useCallback( |
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.
Coming from #26534
We should've ensured to open the suggestion list only when the composer is focused, to prevent unexpected behavior.
const {translate} = useLocalize(); | ||
|
||
const Tap = Gesture.Tap() | ||
.enabled() |
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.
Enabled condition was not preserved !(isCommentEmpty || isBlockedFromConcierge || disabled || hasExceededMaxCommentLength)
and caused regression #27779
* @param {String} reportID | ||
* @param {String} comment | ||
*/ | ||
const debouncedSaveReportComment = _.debounce((reportID, comment) => { |
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.
This caused a regression of showing draft icon - more information here - #27362 (comment)
} | ||
|
||
const valueAfterTheCursor = value.substring(selectionEnd); | ||
const indexOfFirstWhitespaceCharOrEmojiAfterTheCursor = valueAfterTheCursor.search(CONST.REGEX.NEW_LINE_OR_WHITE_SPACE_OR_EMOJI); |
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.
This regex NEW_LINE_OR_WHITE_SPACE_OR_EMOJI
never existed which caused #28754
As talked already, this caused super minor style regression: |
It seems like it caused this regression as well: #30921 (discrepancy between create and edit mode in terms of shown max message length limit error). |
|
||
const [highlightedEmojiIndex, setHighlightedEmojiIndex] = useArrowKeyFocusManager({ | ||
isActive: isEmojiSuggestionsMenuVisible, | ||
maxIndex: SuggestionsUtils.getMaxArrowIndex(suggestionValues.suggestedEmojis.length, isAutoSuggestionPickerLarge), |
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.
👋 Coming from #33613
SuggestionsUtils.getMaxArrowIndex
did return visible list length (instead of true list length), which meant that you couldn't scroll past the visible items using a keyboard
We resolved this with
maxIndex: suggestionValues.suggestedMentions.length - 1
useEffect(() => { | ||
// Value state does not have the same value as comment props when the comment gets changed from another tab. | ||
// In this case, we should synchronize the value between tabs. | ||
const shouldSyncComment = prevCommentProp !== comment && value !== comment; |
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.
this caused a race where some characters will be skipped when typing on the same interval - more info #37356
(text, shouldAddTrailSpace = true) => { | ||
const updatedText = shouldAddTrailSpace ? `${text} ` : text; | ||
const selectionSpaceLength = shouldAddTrailSpace ? CONST.SPACE_LENGTH : 0; | ||
updateComment(ComposerUtils.insertText(commentRef.current, selection, updatedText)); |
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.
This line caused this issue:
#41778
More detail about the RCA here:
#41778 (comment)
Details
This PR improves the performance of the
ReportActionCompose
component greatly.The main improvement is that we moved state down into separated components. In the
ReportActionCompose
component we render a lot of items, such as the send button, emoji button, a menu for attachments, attachment picker popups, the composer itself, comment exceeding notice, mention suggestions, emoji suggestions, etc. When we entered one letter all the top level state was updated multiple times, leading to a lot of re-renders of all the mentioned components.So, to achieve a better performance we needed to break out more separate components. This also cleaned up the
ReportActionCompose
component, it went down from1362
lines to410
lines, thus becoming a lot easier to read and maintain.However, this made the PR a bit larger than anticipated. The following gives an overview of the changes to help review this PR.
Note
I'd recommend first looking at the code itself and understanding its structure, and then checking the specific diffs of this PR.
The
ReportActionCompose
was moved into its own folder undersrc/pages/home/report/ReportActionCompose
. Here are all new split out components placed:SendButton.js
: The JSX of the send button was moved into its own component for cleanupSuggestions.js
: Before the mention and emoji suggestions were part of the main composer, and also their state was placed there. The composer itself doesn't have to re-render when we change the suggestion state, so it was moved into its own component.SuggestionMention.js
: Before the mention suggestion were re-rendering when e.g. the emoji suggestions were changing. Now they are decoupled into their own places.SuggestionEmoji.js
: Separate implementation for emoji suggestionsAttachmentPickerWithMenuItems.js
: This contains the options we show when pressing the + in the composer. The options need access to the attachment picker, so they are grouped together. They also had state that's unnecessary to other parts of the composer.ComposerWithSuggestions.js
: Here lives the actual<Composer />
and itsvalue
andselection
state. Only the<Composer />
and the<Suggestions />
need to re-render when any of the two states are changing, hence they are grouped together.SilentCommentUpdater.js
: This components subscribes to the actual draft comment, and fires a side effect for certain conditions. For the other components we don't need the draft comment, so it makes no sense re-rendering these. That's why it was split out into its own component for performance.Another note: Initially I wanted to make separate PRs for each split out component, but: the components were so entangled with each other, that it was only possible to make a full clean up 🍝😅 .
Fixed Issues
$ #25763
Tests
From
main
branchmain.mov
From this branch
improved.mov
Offline tests
n/a
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
Screen.Recording.2023-08-23.at.12.15.57.mov
Mobile Web - Chrome
Screen.Recording.2023-08-23.at.12.15.24.mov
Mobile Web - Safari
Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-08-23.at.12.20.42.mp4
Desktop
improved.mov
iOS
Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-08-23.at.12.26.56.mp4
Android
Screen.Recording.2023-08-23.at.12.12.12.mov