From c1c9d3f75f184313100fd9434fd8dbd2449c0034 Mon Sep 17 00:00:00 2001 From: Linus Eriksson Date: Thu, 19 Oct 2017 21:39:59 +0200 Subject: [PATCH] Handle edits that scroll up due to hiding the horizontal scrollbar --- spec/text-editor-component-spec.js | 66 +++++++++++++++--------------- src/text-editor-component.js | 19 ++++++--- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index 475a68f7d..a4dc7412d 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -896,6 +896,39 @@ describe('TextEditorComponent', () => { expect(component.getLineNumberGutterWidth()).toBe(originalLineNumberGutterWidth) }) + it('gracefully handles edits that change the maxScrollTop by causing the horizontal scrollbar to disappear', async () => { + const rowsPerTile = 1 + const {component, element, editor} = buildComponent({rowsPerTile, autoHeight: false}) + + await setEditorHeightInLines(component, 1) + await setEditorWidthInCharacters(component, 7) + + element.focus() + component.setScrollTop(component.measurements.lineHeight) + + component.scheduleUpdate() + await component.getNextUpdatePromise() + + editor.setSelectedBufferRange(new Range(Point(0,1),Point(12,2))) + editor.backspace() + + // component.scheduleUpdate() + await component.getNextUpdatePromise() + + expect(component.getScrollTop()).toBe(0) + + const renderedLines = queryOnScreenLineElements(element).sort((a, b) => a.dataset.screenRow - b.dataset.screenRow) + const renderedLineNumbers = queryOnScreenLineNumberElements(element).sort((a, b) => a.dataset.screenRow - b.dataset.screenRow) + const renderedStartRow = component.getRenderedStartRow() + const expectedLines = editor.displayLayer.getScreenLines(renderedStartRow, component.getRenderedEndRow()) + + expect(renderedLines.length).toBe(expectedLines.length) + expect(renderedLineNumbers.length).toBe(expectedLines.length) + + element.remove() + editor.destroy() + }) + describe('randomized tests', () => { let originalTimeout @@ -908,38 +941,7 @@ describe('TextEditorComponent', () => { jasmine.getEnv().defaultTimeoutInterval = originalTimeout }) - it('failing test', async () => { - const rowsPerTile = 1 - const {component, element, editor} = buildComponent({rowsPerTile, autoHeight: false}) - - await setEditorHeightInLines(component, 1) - await setEditorWidthInCharacters(component, 7) - - element.focus() - component.setScrollTop(component.measurements.lineHeight) - - component.scheduleUpdate() - await component.getNextUpdatePromise() - - editor.setSelectedBufferRange(new Range(Point(0,1),Point(12,2))) - editor.backspace() - - component.scheduleUpdate() - await component.getNextUpdatePromise() - - const renderedLines = queryOnScreenLineElements(element).sort((a, b) => a.dataset.screenRow - b.dataset.screenRow) - const renderedLineNumbers = queryOnScreenLineNumberElements(element).sort((a, b) => a.dataset.screenRow - b.dataset.screenRow) - const renderedStartRow = component.getRenderedStartRow() - const expectedLines = editor.displayLayer.getScreenLines(renderedStartRow, component.getRenderedEndRow()) - - expect(renderedLines.length).toBe(expectedLines.length) - expect(renderedLineNumbers.length).toBe(expectedLines.length) - - element.remove() - editor.destroy() - }) - - xit('renders the visible rows correctly after randomly mutating the editor', async () => { + it('renders the visible rows correctly after randomly mutating the editor', async () => { const initialSeed = Date.now() for (var i = 0; i < 1; i++) { let seed = initialSeed + i diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 8dda2297d..a6505d760 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -266,9 +266,13 @@ class TextEditorComponent { if (useScheduler === true) { const scheduler = etch.getScheduler() scheduler.readDocument(() => { - this.measureContentDuringUpdateSync() + const restartFrame = this.measureContentDuringUpdateSync() scheduler.updateDocument(() => { - this.updateSyncAfterMeasuringContent() + if (restartFrame) { + this.updateSync(true) + } else { + this.updateSyncAfterMeasuringContent() + } }) }) } else { @@ -391,15 +395,16 @@ class TextEditorComponent { this.measureHorizontalPositions() this.updateAbsolutePositionedDecorations() + const isHorizontalScrollbarVisible = ( + this.canScrollHorizontally() && + this.getHorizontalScrollbarHeight() > 0 + ) + if (this.pendingAutoscroll) { this.derivedDimensionsCache = {} const {screenRange, options} = this.pendingAutoscroll this.autoscrollHorizontally(screenRange, options) - const isHorizontalScrollbarVisible = ( - this.canScrollHorizontally() && - this.getHorizontalScrollbarHeight() > 0 - ) if (!wasHorizontalScrollbarVisible && isHorizontalScrollbarVisible) { this.autoscrollVertically(screenRange, options) } @@ -408,6 +413,8 @@ class TextEditorComponent { this.linesToMeasure.clear() this.measuredContent = true + + return wasHorizontalScrollbarVisible !== isHorizontalScrollbarVisible } updateSyncAfterMeasuringContent () {