From 4862d6fa9c49d93c315fa4d179db90f33cfd30d1 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 6 Feb 2021 19:56:59 +0000 Subject: [PATCH] editor: fix enter key keep line in view (#4639) --- src/static/js/ace2_inner.js | 2 +- src/static/js/scroll.js | 16 ++++++++++------ src/tests/frontend/specs/enter.js | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 194127c1d..e5de72f9c 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -2179,7 +2179,7 @@ function Ace2Inner() { isScrollableEditEvent(currentCallStack.type); const innerHeight = getInnerHeight(); scroll.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary( - rep, isScrollableEvent, innerHeight + rep, isScrollableEvent, innerHeight*2 ); } diff --git a/src/static/js/scroll.js b/src/static/js/scroll.js index 063e55513..86d6a3344 100644 --- a/src/static/js/scroll.js +++ b/src/static/js/scroll.js @@ -282,7 +282,7 @@ Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) { const linePosition = caretPosition.getPosition(); if (linePosition) { const distanceOfTopOfViewport = linePosition.top - viewport.top; - const distanceOfBottomOfViewport = viewport.bottom - linePosition.bottom; + const distanceOfBottomOfViewport = viewport.bottom - linePosition.bottom - linePosition.height; const caretIsAboveOfViewport = distanceOfTopOfViewport < 0; const caretIsBelowOfViewport = distanceOfBottomOfViewport < 0; if (caretIsAboveOfViewport) { @@ -290,11 +290,15 @@ Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) { distanceOfTopOfViewport - this._getPixelsRelativeToPercentageOfViewport(innerHeight, true); this._scrollYPage(pixelsToScroll); } else if (caretIsBelowOfViewport) { - const pixelsToScroll = -distanceOfBottomOfViewport + - this._getPixelsRelativeToPercentageOfViewport(innerHeight); - this._scrollYPage(pixelsToScroll); - } else { - this.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary(rep, true, innerHeight); + // setTimeout is required here as line might not be fully rendered onto the pad + setTimeout(() => { + const outer = window.parent; + // scroll to the very end of the pad outer + outer.scrollTo(0, outer[0].innerHeight); + }, 150); + // if the above setTimeout and functionality is removed then hitting an enter + // key while on the last line wont be an optimal user experience + // Details at: https://github.com/ether/etherpad-lite/pull/4639/files } } }; diff --git a/src/tests/frontend/specs/enter.js b/src/tests/frontend/specs/enter.js index 2f5a90a69..ca71d2081 100644 --- a/src/tests/frontend/specs/enter.js +++ b/src/tests/frontend/specs/enter.js @@ -6,7 +6,6 @@ describe('enter keystroke', function () { helper.newPad(cb); this.timeout(60000); }); - it('creates a new line & puts cursor onto a new line', function (done) { const inner$ = helper.padInner$; @@ -28,4 +27,32 @@ describe('enter keystroke', function () { done(); }); }); + + it('enter is always visible after event', async function () { + const originalLength = helper.padInner$('div').length; + let $lastLine = helper.padInner$('div').last(); + + // simulate key presses to enter content + let i = 0; + const numberOfLines = 15; + let previousLineLength = originalLength; + while (i < numberOfLines) { + $lastLine = helper.padInner$('div').last(); + $lastLine.sendkeys('{enter}'); + await helper.waitFor(() => helper.padInner$('div').length > previousLineLength); + previousLineLength = helper.padInner$('div').length; + // check we can see the caret.. + + i++; + } + await helper.waitFor(() => helper.padInner$('div').length === numberOfLines + originalLength); + + // is edited line fully visible? + const lastLine = helper.padInner$('div').last(); + const bottomOfLastLine = lastLine.offset().top + lastLine.height(); + const scrolledWindow = helper.padChrome$('iframe')[0]; + const scrolledAmount = scrolledWindow.contentWindow.pageYOffset + + scrolledWindow.contentWindow.innerHeight; + await helper.waitFor(() => scrolledAmount >= bottomOfLastLine); + }); });