-
Notifications
You must be signed in to change notification settings - Fork 17.4k
Only update overlay instead of text editor when resize occurs #15954
Conversation
spec/text-editor-component-spec.js
Outdated
@@ -1896,6 +1896,9 @@ describe('TextEditorComponent', () => { | |||
const decoration = editor.decorateMarker(marker, {type: 'overlay', item: overlayElement, class: 'a'}) | |||
await component.getNextUpdatePromise() | |||
|
|||
let overlayComponent | |||
component.overlayComponents.forEach(c => overlayComponent = c) |
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.
It looks like you are trying to assign the last element of array to the overlayComponent
variable. Perhaps it could be grabbed from the array directly using length - 1?
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.
Yea, sorry for the odd syntax. overlayComponents
is a Set
. In Set
, items don't have positions, but you can iterate over all the items in the Set
. In the case of this test, I know there's only going to be one item.
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.
Very minor, but this might be slightly clearer:
const overlayComponent = component.overlayComponents.values().next().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.
Ah, yea. That's better. I hadn't looked at the Iterator
api. Will Change.
updateOverlaysToRender () { | ||
const overlayCount = this.decorationsToRender.overlays.length | ||
if (overlayCount === 0) return null | ||
|
||
const windowInnerHeight = this.getWindowInnerHeight() | ||
const windowInnerWidth = this.getWindowInnerWidth() | ||
const contentClientRect = this.refs.content.getBoundingClientRect() | ||
for (let i = 0; i < overlayCount; i++) { |
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.
Possible to replace with this.decorationsToRender.overlays.forEach(this.updateOverlayToRender)
? Edit: probably not, might be slower if we are after performance.
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.
That's a good point and switching to .forEach
may have a minimal impact on performance, but I haven't measured it.
⚡ Awesome speedup! |
@@ -804,7 +804,15 @@ class TextEditorComponent { | |||
key: overlayProps.element, | |||
overlayComponents: this.overlayComponents, | |||
measuredDimensions: this.overlayDimensionsByElement.get(overlayProps.element), | |||
didResize: () => { this.updateSync() } | |||
didResize: (overlayComponent) => { |
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.
Good idea passing in the component reference in this callback. This is such a twisty data relationship but I think this is a reasonable way to navigate it.
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.
Looking forward to this improvement.
We took care of an unnecessary loop that was occurring when an overlay was present in #15894. However, resizes of the overlay were still taking longer than needed because they were invoking
.updateSync
on the text editor component. In this PR, we take the approach of only updating the dimensions of the overlay element and invoking a render on just the overlay component when a resize occurs. The amount of time spent in the overlay observer callback is greatly reduced which means less time spent scripting on keystrokes. This is important because any scripting that occurs as a result of a new keystroke needs to finish well ahead of the next keystroke to avoid holding up its handling.In the above image, the time spent in the resize observer callback is reduced from 2.36ms to 0.32ms, and the time to handle this frame goes from 11.75ms down to 9.10ms.
/cc @nathansobo