From bf24063234b29f34a3674fcedd6a2da281b04d4b Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 19 Jul 2020 23:46:58 +0100 Subject: [PATCH] Feature: Timeslider follow (#4133) When new edits come in changes are followed in the time slider. --- src/locales/en.json | 1 + src/static/js/broadcast.js | 13 ++++++ src/templates/timeslider.html | 22 ++++++---- tests/frontend/specs/timeslider_follow.js | 52 +++++++++++++++++++++++ 4 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 tests/frontend/specs/timeslider_follow.js diff --git a/src/locales/en.json b/src/locales/en.json index fff48f2b2..33c30b50a 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -104,6 +104,7 @@ "pad.chat.stick.title": "Stick chat to screen", "pad.chat.writeMessage.placeholder": "Write your message here", + "timeslider.followContents": "Follow pad content updates", "timeslider.pageTitle": "{{appTitle}} Timeslider", "timeslider.toolbar.returnbutton": "Return to pad", "timeslider.toolbar.authors": "Authors:", diff --git a/src/static/js/broadcast.js b/src/static/js/broadcast.js index 117aab671..6f86e50f6 100644 --- a/src/static/js/broadcast.js +++ b/src/static/js/broadcast.js @@ -255,6 +255,11 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro debugLog(e); } + var lineNumber = Changeset.opIterator(Changeset.unpack(changeset).ops).next().lines; + if($('#options-followContents').is(":checked") || $('#options-followContents').prop("checked")){ + goToLineNumber(lineNumber); + } + Changeset.mutateTextLines(changeset, padContents); padContents.currentRevision = revision; padContents.currentTime += timeDelta * 1000; @@ -585,6 +590,14 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro receiveAuthorData(clientVars.collab_client_vars.historicalAuthorData); return changesetLoader; + + function goToLineNumber(lineNumber){ + // Sets the Y scrolling of the browser to go to this line + var line = $('#innerdocbody').find("div:nth-child("+(lineNumber+1)+")"); + var newY = $(line)[0].offsetTop; + let ecb = document.getElementById('editorcontainerbox'); + ecb.scrollTo({top: newY, behavior: 'smooth'}); + } } exports.loadBroadcastJS = loadBroadcastJS; diff --git a/src/templates/timeslider.html b/src/templates/timeslider.html index 06de51200..ec0c7af1b 100644 --- a/src/templates/timeslider.html +++ b/src/templates/timeslider.html @@ -226,14 +226,20 @@ diff --git a/tests/frontend/specs/timeslider_follow.js b/tests/frontend/specs/timeslider_follow.js new file mode 100644 index 000000000..9f460934d --- /dev/null +++ b/tests/frontend/specs/timeslider_follow.js @@ -0,0 +1,52 @@ +describe("timeslider", function(){ + //create a new pad before each test run + beforeEach(function(cb){ + helper.newPad(cb); + this.timeout(6000); + }); + + it("follow content as it's added to timeslider", function(done) { // passes + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + + // make some changes to produce 100 revisions + var timePerRev = 900 + , revs = 5; + this.timeout(revs*timePerRev+10000); + for(var i=0; i < revs; i++) { + setTimeout(function() { + // enter 'a' in the first text element + inner$("div").last().sendkeys('a\n'); + inner$("div").last().sendkeys('{enter}'); + }, timePerRev*i); + } + + setTimeout(function() { + // go to timeslider + $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); + + setTimeout(function() { + var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; + var $sliderBar = timeslider$('#ui-slider-bar'); + + var latestContents = timeslider$('#innerdocbody').text(); + + // set to follow contents as it arrives + timeslider$('#options-followContents').prop("checked", true); + + var originalTop = timeslider$('#innerdocbody').offset(); + timeslider$('#playpause_button_icon').click(); + + setTimeout(function() { + //make sure the text has changed + var newTop = timeslider$('#innerdocbody').offset(); + expect( originalTop ).not.to.eql( newTop ); + done(); + }, 1000); + + }, 2000); + }, revs*timePerRev); + }); + +}); +