From 8ece54701d67c7d1f6cca1eab046c536e0f6be6e Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 18 May 2024 01:44:42 -0500 Subject: [PATCH 01/39] Add live scrolling to keep the preview in sync with editor position. This catchs CTRL-HOME, CTRL-END, and mouseclicks. It tests for changes on arrow keys and enter. Not sure if it's the best way to do this, but it works quickly on a large, crappy brew. --- client/homebrew/editor/editor.jsx | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 119658f8c..df674c74e 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -22,6 +22,18 @@ const DEFAULT_STYLE_TEXT = dedent` color: black; }`; +let lastPage = 0; +let liveScroll = true; + +const isElementCodeMirror=(element)=>{ + let el = element; + while( el.tagName != 'body' ) { + if( el.classList.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) + return true; + el = el.parentNode; + } + return false; +}; const Editor = createClass({ displayName : 'Editor', @@ -57,6 +69,15 @@ const Editor = createClass({ this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.addEventListener('keydown', this.handleControlKeys); + document.addEventListener('click', (e)=>{ + if(isElementCodeMirror(e.target) && liveScroll ) { + const curPage = this.getCurrentPage(); + if( curPage != lastPage ) { + this.brewJump(); + lastPage = curPage; + } + } + }); const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY); if(editorTheme) { @@ -81,10 +102,36 @@ const Editor = createClass({ }, handleControlKeys : function(e){ + if(liveScroll) { + const movementKeys = [ 13, 33, 34, 37, 38, 39, 40 ]; + if (movementKeys.includes(e.keyCode)) { + const curPage = this.getCurrentPage(); + if( curPage != lastPage ) { + this.brewJump(); + lastPage = curPage; + } + } + } if(!(e.ctrlKey || e.metaKey)) return; const J_KEY = 74; + const END_KEY = 35; + const HOME_KEY = 36; + + // Handle CTRL-HOME and CTRL-END + if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); + + // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == J_KEY)) this.brewJump(); - if (e.shiftKey && (e.keyCode == J_KEY)) this.sourceJump(); + // Source Jump on Shift-CTRL-J + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); + // Toggle Live-scrolling on Shift-CTRL-ALT-J + if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { + console.log('Trying to flip the property?') + console.log(liveScroll); + liveScroll = !liveScroll; + console.log(liveScroll); + } + if( e.keyCode == J_KEY) { e.stopPropagation(); e.preventDefault(); From b7dc47fe9e9f457f3426f89f26282d0676c072e4 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 18 May 2024 22:17:29 -0500 Subject: [PATCH 02/39] Add a Live Scroll lock/unlock below Brew/Source Jump buttons. The button displays the *next* state of the toggle. IE, if the current state is locked ( Live scrolling is active ) the icon is unlock with a corresponding mouse-over. It may be desirable to invert this. --- client/homebrew/editor/editor.jsx | 10 ++++++---- shared/naturalcrit/splitPane/splitPane.jsx | 16 ++++++++++++++++ shared/naturalcrit/splitPane/splitPane.less | 8 ++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index df674c74e..b08ee9a2b 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -28,7 +28,8 @@ let liveScroll = true; const isElementCodeMirror=(element)=>{ let el = element; while( el.tagName != 'body' ) { - if( el.classList.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) + if ( !el?.classList ) return false + if( el?.classList?.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) return true; el = el.parentNode; } @@ -43,6 +44,7 @@ const Editor = createClass({ text : '', style : '' }, + liveScroll : true, onTextChange : ()=>{}, onStyleChange : ()=>{}, @@ -99,6 +101,9 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) { this.sourceJump(); }; + if(prevProps.liveScroll !== this.props.liveScroll) { + liveScroll = !liveScroll; + }; }, handleControlKeys : function(e){ @@ -126,10 +131,7 @@ const Editor = createClass({ if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); // Toggle Live-scrolling on Shift-CTRL-ALT-J if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { - console.log('Trying to flip the property?') - console.log(liveScroll); liveScroll = !liveScroll; - console.log(liveScroll); } if( e.keyCode == J_KEY) { diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 2101480dc..0718a97b1 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -20,6 +20,7 @@ const SplitPane = createClass({ isDragging : false, moveSource : false, moveBrew : false, + liveScroll : true, showMoveArrows : true }; }, @@ -117,6 +118,20 @@ const SplitPane = createClass({ onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} > +
{ + this.setState({ liveScroll: !this.state.liveScroll }); + if(document.getElementById('scrollToggle').classList.contains('fa-unlock')) { + document.getElementById('scrollToggle').className = 'fas fa-lock'; + document.getElementById('scrollToggleDiv').className = 'arrow lock'; + } else { + document.getElementById('scrollToggle').className = 'fas fa-unlock'; + document.getElementById('scrollToggleDiv').className = 'arrow unlock'; + } + }} > + +
; } }, @@ -143,6 +158,7 @@ const SplitPane = createClass({ {React.cloneElement(this.props.children[0], { moveBrew : this.state.moveBrew, moveSource : this.state.moveSource, + liveScroll : this.state.liveScroll, setMoveArrows : this.setMoveArrows })} diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index 831b5ce47..2000db72a 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -53,6 +53,14 @@ .tooltipRight('Jump to location in Preview'); top : 60px; } + &.lock{ + .tooltipRight('Lock cursor tracking between windows.'); + top : 90px; + } + &.unlock{ + .tooltipRight('Unlock cursor tracking between windows.'); + top : 90px; + } &:hover{ background-color: #666; } From 86887b536ef18d6432f65dd53f9c50f9fd88d32f Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 19 May 2024 11:16:50 -0500 Subject: [PATCH 03/39] Update Jump keys to match parent PR and shift live scrolling to scroll-lock. Needs non-PC testing. --- client/homebrew/editor/editor.jsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index b08ee9a2b..7879b9941 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -117,24 +117,26 @@ const Editor = createClass({ } } } - if(!(e.ctrlKey || e.metaKey)) return; - const J_KEY = 74; + const M_KEY = 77; const END_KEY = 35; const HOME_KEY = 36; + const SCROLLLOCK_KEY = 145; + + // Toggle Live-scrolling on Scroll Lock + if(e.keyCode == SCROLLLOCK_KEY) { + liveScroll = !liveScroll; + } + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); // Brew Jump on CTRL-J - if((!e.shiftKey) && (e.keyCode == J_KEY)) this.brewJump(); + if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); // Source Jump on Shift-CTRL-J - if ((e.shiftKey) && (!e.altKey) && (e.keyCode == J_KEY)) this.sourceJump(); - // Toggle Live-scrolling on Shift-CTRL-ALT-J - if((e.shiftKey) && (e.altKey) && (e.keyCode == J_KEY)) { - liveScroll = !liveScroll; - } + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == M_KEY)) this.sourceJump(); - if( e.keyCode == J_KEY) { + if( e.keyCode == M_KEY) { e.stopPropagation(); e.preventDefault(); } From bacdd65025d752531518610691ae80bad48c96c7 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 19 May 2024 11:52:16 -0500 Subject: [PATCH 04/39] Add a CR. --- client/homebrew/editor/editor.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 7879b9941..4d32f36fb 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -126,6 +126,7 @@ const Editor = createClass({ if(e.keyCode == SCROLLLOCK_KEY) { liveScroll = !liveScroll; } + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END From 835ca0de3264248405ec87dea5227fd84ef6ab5b Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 20 May 2024 16:21:02 -0500 Subject: [PATCH 05/39] WIP --- client/homebrew/editor/editor.jsx | 7 ++++++- shared/naturalcrit/splitPane/splitPane.jsx | 15 ++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 4d32f36fb..185f37ac6 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -94,6 +94,11 @@ const Editor = createClass({ }, componentDidUpdate : function(prevProps, prevState, snapshot) { + console.log(this.props); + console.log(prevProps); + console.log(this.state); + console.log(prevState); + this.highlightCustomMarkdown(); if(prevProps.moveBrew !== this.props.moveBrew) { this.brewJump(); @@ -126,7 +131,7 @@ const Editor = createClass({ if(e.keyCode == SCROLLLOCK_KEY) { liveScroll = !liveScroll; } - + if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 0718a97b1..217fcc80c 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -15,13 +15,14 @@ const SplitPane = createClass({ getInitialState : function() { return { - currentDividerPos : null, - windowWidth : 0, - isDragging : false, - moveSource : false, - moveBrew : false, - liveScroll : true, - showMoveArrows : true + currentDividerPos : null, + windowWidth : 0, + isDragging : false, + moveSource : false, + moveBrew : false, + liveScroll : true, + viewablePageNumber : 0, + showMoveArrows : true }; }, From e69132b40aba81a1edd6f8bd7c9d3279ca67e108 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 20 May 2024 20:31:30 -0500 Subject: [PATCH 06/39] Constant a lookup. --- shared/naturalcrit/splitPane/splitPane.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 217fcc80c..e1b30887e 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -43,7 +43,7 @@ const SplitPane = createClass({ window.addEventListener('resize', this.handleWindowResize); }, - componentWillUnmount : function() { +componentWillUnmount : function() { window.removeEventListener('resize', this.handleWindowResize); }, @@ -123,12 +123,14 @@ const SplitPane = createClass({ style={{ left: this.state.currentDividerPos-4 }} onClick={()=>{ this.setState({ liveScroll: !this.state.liveScroll }); - if(document.getElementById('scrollToggle').classList.contains('fa-unlock')) { - document.getElementById('scrollToggle').className = 'fas fa-lock'; - document.getElementById('scrollToggleDiv').className = 'arrow lock'; + const toggle = document.getElementById('scrollToggle'); + const toggleDiv = document.getElementById('scrollToggleDiv'); + if(toggle.classList.contains('fa-unlock')) { + toggle.className = 'fas fa-lock'; + toggleDiv.className = 'arrow lock'; } else { - document.getElementById('scrollToggle').className = 'fas fa-unlock'; - document.getElementById('scrollToggleDiv').className = 'arrow unlock'; + toggle.className = 'fas fa-unlock'; + toggleDiv.className = 'arrow unlock'; } }} > From a715c9e1e611a38b6058c10293f9fab6cee8ac52 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:26:56 -0500 Subject: [PATCH 07/39] Store livescrolling in local storage Small fixes for loading the correct current state. --- client/homebrew/editor/editor.jsx | 24 +++++++---------- shared/naturalcrit/splitPane/splitPane.jsx | 29 ++++++++++++++++----- shared/naturalcrit/splitPane/splitPane.less | 4 +-- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 185f37ac6..5eaf0345d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -23,7 +23,6 @@ const DEFAULT_STYLE_TEXT = dedent` }`; let lastPage = 0; -let liveScroll = true; const isElementCodeMirror=(element)=>{ let el = element; @@ -44,7 +43,6 @@ const Editor = createClass({ text : '', style : '' }, - liveScroll : true, onTextChange : ()=>{}, onStyleChange : ()=>{}, @@ -67,12 +65,13 @@ const Editor = createClass({ isMeta : function() {return this.state.view == 'meta';}, componentDidMount : function() { + this.updateEditorSize(); this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('click', (e)=>{ - if(isElementCodeMirror(e.target) && liveScroll ) { + if(isElementCodeMirror(e.target) && this.props.liveScroll ) { const curPage = this.getCurrentPage(); if( curPage != lastPage ) { this.brewJump(); @@ -94,10 +93,6 @@ const Editor = createClass({ }, componentDidUpdate : function(prevProps, prevState, snapshot) { - console.log(this.props); - console.log(prevProps); - console.log(this.state); - console.log(prevState); this.highlightCustomMarkdown(); if(prevProps.moveBrew !== this.props.moveBrew) { @@ -106,13 +101,13 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) { this.sourceJump(); }; - if(prevProps.liveScroll !== this.props.liveScroll) { - liveScroll = !liveScroll; + if(prevProps.liveScroll != this.props.liveScroll) { + if (this.props.liveScroll) this.brewJump(); }; }, handleControlKeys : function(e){ - if(liveScroll) { + if(this.props.liveScroll) { const movementKeys = [ 13, 33, 34, 37, 38, 39, 40 ]; if (movementKeys.includes(e.keyCode)) { const curPage = this.getCurrentPage(); @@ -122,14 +117,14 @@ const Editor = createClass({ } } } - const M_KEY = 77; + const X_KEY = 88; const END_KEY = 35; const HOME_KEY = 36; const SCROLLLOCK_KEY = 145; // Toggle Live-scrolling on Scroll Lock if(e.keyCode == SCROLLLOCK_KEY) { - liveScroll = !liveScroll; + this.setState( {liveScroll: !liveScroll} ); } if(!(e.ctrlKey || e.metaKey)) return; @@ -140,9 +135,9 @@ const Editor = createClass({ // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); // Source Jump on Shift-CTRL-J - if ((e.shiftKey) && (!e.altKey) && (e.keyCode == M_KEY)) this.sourceJump(); + if ((e.shiftKey) && (!e.altKey) && (e.keyCode == X_KEY)) this.sourceJump(); - if( e.keyCode == M_KEY) { + if( e.keyCode == X_KEY) { e.stopPropagation(); e.preventDefault(); } @@ -330,6 +325,7 @@ const Editor = createClass({ // console.log(`Scroll to: p${targetPage}`); const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; + if(!window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)) return; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; const interimPos = targetPos >= 0 ? -30 : 30; diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index e1b30887e..71831fb23 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -20,7 +20,6 @@ const SplitPane = createClass({ isDragging : false, moveSource : false, moveBrew : false, - liveScroll : true, viewablePageNumber : 0, showMoveArrows : true }; @@ -41,9 +40,25 @@ const SplitPane = createClass({ }); } window.addEventListener('resize', this.handleWindowResize); + + + // This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts. + const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true'; + this.setState({ + liveScroll : loadLiveScroll + }); + const toggle = document.getElementById('scrollToggle'); + const toggleDiv = document.getElementById('scrollToggleDiv'); + if(loadLiveScroll) { + toggle.className = 'fas fa-lock'; + toggleDiv.className = 'arrow lock'; + } else { + toggle.className = 'fas fa-unlock'; + toggleDiv.className = 'arrow unlock'; + } }, -componentWillUnmount : function() { + componentWillUnmount : function() { window.removeEventListener('resize', this.handleWindowResize); }, @@ -119,21 +134,23 @@ componentWillUnmount : function() { onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} > -
{ - this.setState({ liveScroll: !this.state.liveScroll }); + const flipLiveScroll = !this.state.liveScroll; const toggle = document.getElementById('scrollToggle'); const toggleDiv = document.getElementById('scrollToggleDiv'); - if(toggle.classList.contains('fa-unlock')) { + if(flipLiveScroll) { toggle.className = 'fas fa-lock'; toggleDiv.className = 'arrow lock'; } else { toggle.className = 'fas fa-unlock'; toggleDiv.className = 'arrow unlock'; } + window.localStorage.setItem('liveScroll', String(flipLiveScroll)); + this.setState({ liveScroll: flipLiveScroll }); }} > - +
; } diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index 2000db72a..f8bc686de 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -54,11 +54,11 @@ top : 60px; } &.lock{ - .tooltipRight('Lock cursor tracking between windows.'); + .tooltipRight('Unlock cursor tracking between windows.'); top : 90px; } &.unlock{ - .tooltipRight('Unlock cursor tracking between windows.'); + .tooltipRight('Lock cursor tracking between windows.'); top : 90px; } &:hover{ From 4818f70aeda2955aaf1a0ab6a067b04786fe2e5e Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:36:44 -0500 Subject: [PATCH 08/39] Add additional visual hinting to liveScroll lock. --- shared/naturalcrit/splitPane/splitPane.less | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index f8bc686de..567c1c6d0 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -56,6 +56,7 @@ &.lock{ .tooltipRight('Unlock cursor tracking between windows.'); top : 90px; + background: #666; } &.unlock{ .tooltipRight('Lock cursor tracking between windows.'); From ea9f9a8c36ed2bbdab2106ba8c81fa4ebf4e88af Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 02:39:20 -0500 Subject: [PATCH 09/39] Missed a couple of variable repalcements. --- client/homebrew/editor/editor.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index fb842463a..147170023 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -127,13 +127,13 @@ const Editor = createClass({ // Toggle Live-scrolling on Scroll Lock if(e.keyCode == SCROLLLOCK_KEY) { - this.setState( {liveScroll: !liveScroll} ); + this.setState( {liveScroll: !this.props.liveScroll} ); } if(!(e.ctrlKey || e.metaKey)) return; // Handle CTRL-HOME and CTRL-END - if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && liveScroll) this.brewJump(); + if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); // Brew Jump on CTRL-J if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); From 510d8f410dbbe78120f72c272af3697391e1bc34 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 3 Jun 2024 22:45:22 -0500 Subject: [PATCH 10/39] Resolve timing issue with liveScroll on linking. Checks to see if prevProps.livescroll has a proper Bool value. If not, do not brewJump() in editor.componantSDidUpdate. --- client/homebrew/editor/editor.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 147170023..06375d21d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -105,7 +105,7 @@ const Editor = createClass({ this.sourceJump(); }; if(prevProps.liveScroll != this.props.liveScroll) { - if (this.props.liveScroll) this.brewJump(); + if ((prevProps.liveScroll != undefined) && (this.props.liveScroll)) this.brewJump(); }; }, @@ -328,7 +328,6 @@ const Editor = createClass({ // console.log(`Scroll to: p${targetPage}`); const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; - if(!window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)) return; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; const interimPos = targetPos >= 0 ? -30 : 30; From dcdc8b4943ac663670f111213e637e5fee2f7047 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 30 Jul 2024 02:41:03 -0500 Subject: [PATCH 11/39] Remove Livescrolling toggle hot-key. --- client/homebrew/editor/editor.jsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index f1ed28440..603dbd6f3 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -123,12 +123,6 @@ const Editor = createClass({ const X_KEY = 88; const END_KEY = 35; const HOME_KEY = 36; - const SCROLLLOCK_KEY = 145; - - // Toggle Live-scrolling on Scroll Lock - if(e.keyCode == SCROLLLOCK_KEY) { - this.setState( {liveScroll: !this.props.liveScroll} ); - } if(!(e.ctrlKey || e.metaKey)) return; From b34027699f33f6c618b73158758d3dd900119c1a Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 30 Jul 2024 03:09:25 -0500 Subject: [PATCH 12/39] Move livescrollToggle function out into a class method instead of an anonymous function. Adjust code accordingly ( event.target vs document.getElementByClassname ) --- shared/naturalcrit/splitPane/splitPane.jsx | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 8e10085c8..91faadcb5 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -105,6 +105,21 @@ const SplitPane = createClass({ userSetDividerPos : newSize }); }, + + liveScrollToggle : function(e) { + const flipLiveScroll = !this.state.liveScroll; + const toggle = e.target; + const toggleDiv = toggle.parentElement; + if(flipLiveScroll) { + toggle.className = 'fas fa-lock'; + toggleDiv.className = 'arrow lock'; + } else { + toggle.className = 'fas fa-unlock'; + toggleDiv.className = 'arrow unlock'; + } + window.localStorage.setItem('liveScroll', String(flipLiveScroll)); + this.setState({ liveScroll: flipLiveScroll }); + }, /* unFocus : function() { if(document.selection){ @@ -138,20 +153,7 @@ const SplitPane = createClass({
{ - const flipLiveScroll = !this.state.liveScroll; - const toggle = document.getElementById('scrollToggle'); - const toggleDiv = document.getElementById('scrollToggleDiv'); - if(flipLiveScroll) { - toggle.className = 'fas fa-lock'; - toggleDiv.className = 'arrow lock'; - } else { - toggle.className = 'fas fa-unlock'; - toggleDiv.className = 'arrow unlock'; - } - window.localStorage.setItem('liveScroll', String(flipLiveScroll)); - this.setState({ liveScroll: flipLiveScroll }); - }} > + onClick={this.liveScrollToggle} >
; From 695293333f7dbc80be1837ed52d92cb92cb6670a Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 21 Aug 2024 21:19:10 -0500 Subject: [PATCH 13/39] Fix merge --- client/homebrew/editor/editor.jsx | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index cf3eeab25..3164cc585 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -111,8 +111,13 @@ const Editor = createClass({ }, handleControlKeys : function(e){ + const END_KEY = 35; + const HOME_KEY = 36; + const LEFTARROW_KEY = 37; + const RIGHTARROW_KEY = 39; + if(this.props.liveScroll) { - const movementKeys = [ 13, 33, 34, 37, 38, 39, 40 ]; + const movementKeys = [ 13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40 ]; if (movementKeys.includes(e.keyCode)) { const curPage = this.getCurrentPage(); if( curPage != lastPage ) { @@ -121,30 +126,15 @@ const Editor = createClass({ } } } - const X_KEY = 88; - const END_KEY = 35; - const HOME_KEY = 36; if(!(e.ctrlKey || e.metaKey)) return; -<<<<<<< HEAD - + console.log(e); // Handle CTRL-HOME and CTRL-END if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); - // Brew Jump on CTRL-J - if((!e.shiftKey) && (e.keyCode == M_KEY)) this.brewJump(); - // Source Jump on Shift-CTRL-J - if ((e.shiftKey) && (!e.altKey) && (e.keyCode == X_KEY)) this.sourceJump(); - - if( e.keyCode == X_KEY) { -======= - console.log(e); - const LEFTARROW_KEY = 37; - const RIGHTARROW_KEY = 39; if (e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump(); if (e.shiftKey && (e.keyCode == LEFTARROW_KEY)) this.sourceJump(); if ((e.keyCode == LEFTARROW_KEY) || (e.keyCode == RIGHTARROW_KEY)) { ->>>>>>> master e.stopPropagation(); e.preventDefault(); } From e27e61aacaecb368afa5b3e625e9804a2e8ebfb4 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 24 Aug 2024 00:47:06 -0500 Subject: [PATCH 14/39] Bind livescrolling when done via scrollbars. --- client/homebrew/brewRenderer/brewRenderer.jsx | 10 +- client/homebrew/editor/editor.jsx | 91 +++++++++++++------ shared/naturalcrit/codeEditor/codeEditor.jsx | 9 ++ 3 files changed, 83 insertions(+), 27 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 4b82c6bc0..b3ec038aa 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -19,6 +19,7 @@ const DOMPurify = require('dompurify'); const purifyConfig = { FORCE_BODY: true, SANITIZE_DOM: false }; const PAGE_HEIGHT = 1056; +let isScrolling; const INITIAL_CONTENT = dedent` @@ -87,9 +88,16 @@ const BrewRenderer = (props)=>{ const handleScroll = (e)=>{ const target = e.target; + const newPage = Math.floor(target.scrollTop / target.scrollHeight * rawPages.length); + if(newPage != state.viewablePageNumber) { + window.clearTimeout(isScrolling); + isScrolling = setTimeout(function() { + window.parent.document.dispatchEvent(new CustomEvent('renderScrolled', {})); + }, 66); + } setState((prevState)=>({ ...prevState, - viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * rawPages.length) + viewablePageNumber : newPage })); }; diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 3164cc585..7555a0e58 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -23,6 +23,9 @@ const DEFAULT_STYLE_TEXT = dedent` }`; let lastPage = 0; +let lockBrewJump = false; +let lockSourceJump = false; +let scrollingJump = false; const isElementCodeMirror=(element)=>{ let el = element; @@ -73,6 +76,7 @@ const Editor = createClass({ this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys); + document.addEventListener('renderScrolled', this.handleBrewScroll); document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('click', (e)=>{ if(isElementCodeMirror(e.target) && this.props.liveScroll ) { @@ -128,7 +132,6 @@ const Editor = createClass({ } if(!(e.ctrlKey || e.metaKey)) return; - console.log(e); // Handle CTRL-HOME and CTRL-END if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); @@ -140,6 +143,19 @@ const Editor = createClass({ } }, + handleBrewScroll : function() { + if(!this.props.liveScroll) return; + scrollingJump = true; + this.sourceJump(); + scrollingJump = false; + }, + + handleSourceScroll : function(e) { + if(!this.props.liveScroll) return; + scrollingJump = true; + this.brewJump(); + scrollingJump = false; + }, updateEditorSize : function() { if(this.codeEditor.current) { @@ -318,8 +334,11 @@ const Editor = createClass({ }, brewJump : function(targetPage=this.getCurrentPage()){ + if(lockBrewJump) return; if(!window) return; - // console.log(`Scroll to: p${targetPage}`); + lockSourceJump = true; + lockBrewJump = true; + //console.log(`Scroll to: p${targetPage}`); const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; @@ -328,24 +347,33 @@ const Editor = createClass({ const bounceDelay = 100; const scrollDelay = 500; - if(!this.throttleBrewMove) { - this.throttleBrewMove = _.throttle((currentPos, interimPos, targetPos)=>{ - brewRenderer.scrollTo({ top: currentPos + interimPos, behavior: 'smooth' }); - setTimeout(()=>{ - brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'smooth', block: 'start' }); - }, bounceDelay); - }, scrollDelay, { leading: true, trailing: false }); - }; - this.throttleBrewMove(currentPos, interimPos, targetPos); + if(scrollingJump) { + brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'instant', block: 'start' }); + } else { + if(!this.throttleBrewMove) { + this.throttleBrewMove = _.throttle((currentPos, interimPos, targetPos)=>{ + brewRenderer.scrollTo({ top: currentPos + interimPos, behavior: 'smooth' }); + setTimeout(()=>{ + brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'smooth', block: 'start' }); + }, bounceDelay); + }, scrollDelay, { leading: true, trailing: false }); + }; + this.throttleBrewMove(currentPos, interimPos, targetPos); + } + lockSourceJump = false; + lockBrewJump = false; // const hashPage = (page != 1) ? `p${page}` : ''; // window.location.hash = hashPage; }, sourceJump : function(targetLine=null){ + if(lockSourceJump) return; if(this.isText()) { if(targetLine == null) { targetLine = 0; + lockBrewJump = true; + lockSourceJump = true; const pageCollection = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('page'); const brewRendererHeight = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0).getBoundingClientRect().height; @@ -368,23 +396,33 @@ const Editor = createClass({ let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - //Scroll 1/10 of the way every 10ms until 1px off. - const incrementalScroll = setInterval(()=>{ - currentY += (targetY - currentY) / 10; - this.codeEditor.current.codeMirror.scrollTo(null, currentY); + if(!scrollingJump) { + //Scroll 1/10 of the way every 10ms until 1px off. + const incrementalScroll = setInterval(()=>{ + currentY += (targetY - currentY) / 10; + this.codeEditor.current.codeMirror.scrollTo(null, currentY); - // Update target: target height is not accurate until within +-10 lines of the visible window - if(Math.abs(targetY - currentY > 100)) - targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); + // Update target: target height is not accurate until within +-10 lines of the visible window + if(Math.abs(targetY - currentY > 100)) + targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - // End when close enough - if(Math.abs(targetY - currentY) < 1) { - this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference - this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); - this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - clearInterval(incrementalScroll); - } - }, 10); + // End when close enough + if(Math.abs(targetY - currentY) < 1) { + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); + clearInterval(incrementalScroll); + lockBrewJump = false; + lockSourceJump = false; + } + }, 10); + } else { + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); + lockBrewJump = false; + lockSourceJump = false; + } } } }, @@ -415,6 +453,7 @@ const Editor = createClass({ view={this.state.view} value={this.props.brew.text} onChange={this.props.onTextChange} + onScroll={this.handleSourceScroll} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} /> ; diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index 3186e39f1..46ae64edb 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -7,6 +7,7 @@ const closeTag = require('./close-tag'); const autoCompleteEmoji = require('./autocompleteEmoji'); let CodeMirror; +let isScrolling; if(typeof window !== 'undefined'){ CodeMirror = require('codemirror'); @@ -190,6 +191,14 @@ const CodeEditor = createClass({ // Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works. this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());}); + this.codeMirror.on('scroll', (cm)=>{ + window.clearTimeout(isScrolling); + const props = this.props; + isScrolling = setTimeout(function() { + cm.setCursor({ line: cm.lineAtHeight(cm.getWrapperElement().getBoundingClientRect().top) + 1, ch: 0 }); + props.onScroll(cm.lineAtHeight(cm.getWrapperElement().getBoundingClientRect().top)); + }, 66); + }); this.updateSize(); }, From 7a37bf47c58a1e70583b3d2d1369fc85fa5f2ecd Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 7 Sep 2024 21:33:51 -0500 Subject: [PATCH 15/39] Bodge Render side mirroring back into place. --- client/homebrew/brewRenderer/brewRenderer.jsx | 2 ++ client/homebrew/editor/editor.jsx | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index d6d04d697..5cbac23f7 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -108,6 +108,8 @@ const BrewRenderer = (props)=>{ const totalScrollableHeight = scrollHeight - clientHeight; const currentPageNumber = Math.ceil((scrollTop / totalScrollableHeight) * rawPages.length); + handleScroll(e); + setState((prevState)=>({ ...prevState, currentPageNumber : currentPageNumber || 1 diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index fe05c1b93..ffeed00b0 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -119,9 +119,6 @@ const Editor = createClass({ const HOME_KEY = 36; const LEFTARROW_KEY = 37; const RIGHTARROW_KEY = 39; - if(!(e.ctrlKey && e.metaKey)) return; - - if(!e.ctrlKey) return; if(this.props.liveScroll) { const movementKeys = [13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40]; @@ -134,6 +131,10 @@ const Editor = createClass({ } } + if(!(e.ctrlKey && e.metaKey)) return; + + if(!e.ctrlKey) return; + // Handle CTRL-HOME and CTRL-END if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); if(!e.metaKey) return; From fa74fb4ada449a29dc339d3b952b82f1da5cc518 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 7 Sep 2024 21:38:07 -0500 Subject: [PATCH 16/39] Update tooltips for locking. --- shared/naturalcrit/splitPane/splitPane.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index 567c1c6d0..e5b3dd7f8 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -54,12 +54,12 @@ top : 60px; } &.lock{ - .tooltipRight('Unlock cursor tracking between windows.'); + .tooltipRight('De-sync Editor and Preview locations.'); top : 90px; background: #666; } &.unlock{ - .tooltipRight('Lock cursor tracking between windows.'); + .tooltipRight('Sync Editor and Preview locations'); top : 90px; } &:hover{ From 1e9c7423c77bac5c53a8b34c05df59616e6f8837 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 7 Sep 2024 22:36:27 -0500 Subject: [PATCH 17/39] Fix "clicked on the toggle ring" crash with scroll lock. The code was doing dom-climbing math based on clicking on the div contents but was attached to the div. Moved the onClick to the contents. --- client/homebrew/editor/editor.jsx | 1 + shared/naturalcrit/splitPane/splitPane.jsx | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index ffeed00b0..1fa720f81 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -121,6 +121,7 @@ const Editor = createClass({ const RIGHTARROW_KEY = 39; if(this.props.liveScroll) { + console.log('Should be scrollig!'); const movementKeys = [13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40]; if(movementKeys.includes(e.keyCode)) { const curPage = this.getCurrentPage(); diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 21d95f2c5..4d9dd452b 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -153,9 +153,8 @@ const SplitPane = createClass({
- + style={{ left: this.state.currentDividerPos-4 }} > +
; } From 51c8973a85a0e4a17f345744a99b84b2e444ba24 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 9 Sep 2024 23:29:10 -0400 Subject: [PATCH 18/39] Move `onClick` from the lock icon to the whole button --- shared/naturalcrit/splitPane/splitPane.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 3d6146fae..67f60db6e 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -153,8 +153,9 @@ const SplitPane = createClass({
- + style={{ left: this.state.currentDividerPos-4 }} + onClick={this.liveScrollToggle} > +
; } From 0fbb4879a921f7ac9695c87a1f1171d914531aa8 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 9 Sep 2024 23:35:18 -0400 Subject: [PATCH 19/39] Set button appearance based on state Avoid manually editing the DOM elements. Let the Render function update the appearance based on state. --- shared/naturalcrit/splitPane/splitPane.jsx | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 67f60db6e..665fe416b 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -107,19 +107,9 @@ const SplitPane = createClass({ }); }, - liveScrollToggle : function(e) { - const flipLiveScroll = !this.state.liveScroll; - const toggle = e.target; - const toggleDiv = toggle.parentElement; - if(flipLiveScroll) { - toggle.className = 'fas fa-lock'; - toggleDiv.className = 'arrow lock'; - } else { - toggle.className = 'fas fa-unlock'; - toggleDiv.className = 'arrow unlock'; - } - window.localStorage.setItem('liveScroll', String(flipLiveScroll)); - this.setState({ liveScroll: flipLiveScroll }); + liveScrollToggle : function() { + window.localStorage.setItem('liveScroll', String(!this.state.liveScroll)); + this.setState({ liveScroll: !this.state.liveScroll }); }, /* unFocus : function() { @@ -152,10 +142,10 @@ const SplitPane = createClass({ onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} > -
- +
; } From 315296458a1058c44110625b0c6858bfa24c9feb Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 9 Sep 2024 23:39:29 -0400 Subject: [PATCH 20/39] Remove setting button styles in `componentDidMount` Just set the state, and the renderer will know what to display. --- shared/naturalcrit/splitPane/splitPane.jsx | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 665fe416b..d917da3bb 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -44,21 +44,9 @@ const SplitPane = createClass({ } window.addEventListener('resize', this.handleWindowResize); - // This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts. const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true'; - this.setState({ - liveScroll : loadLiveScroll - }); - const toggle = document.getElementById('scrollToggle'); - const toggleDiv = document.getElementById('scrollToggleDiv'); - if(loadLiveScroll) { - toggle.className = 'fas fa-lock'; - toggleDiv.className = 'arrow lock'; - } else { - toggle.className = 'fas fa-unlock'; - toggleDiv.className = 'arrow unlock'; - } + this.setState({ liveScroll : loadLiveScroll }); }, componentWillUnmount : function() { From b5155ed256acbbe66ba9465a78accf885fdf9642 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 9 Sep 2024 23:40:06 -0400 Subject: [PATCH 21/39] remove unused variable --- shared/naturalcrit/splitPane/splitPane.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index d917da3bb..01807db70 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -20,7 +20,6 @@ const SplitPane = createClass({ isDragging : false, moveSource : false, moveBrew : false, - viewablePageNumber : 0, showMoveArrows : true }; }, From ec74b994d7d239fbbceb806dff7c26666b6c26be Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Tue, 10 Sep 2024 00:43:44 -0400 Subject: [PATCH 22/39] Simplify `scroll` event for source editor using lodash Throttle --- client/homebrew/editor/editor.jsx | 4 +++- shared/naturalcrit/codeEditor/codeEditor.jsx | 11 ++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 1fa720f81..3b87c7bcc 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -154,8 +154,9 @@ const Editor = createClass({ scrollingJump = false; }, - handleSourceScroll : function(e) { + handleSourceScroll : function() { if(!this.props.liveScroll) return; + console.log("handleSourceScroll") scrollingJump = true; this.brewJump(); scrollingJump = false; @@ -356,6 +357,7 @@ const Editor = createClass({ }, brewJump : function(targetPage=this.getCurrentPage()){ + console.log('jumpbrew') if(lockBrewJump) return; if(!window) return; lockSourceJump = true; diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index 46ae64edb..1387edfee 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -7,7 +7,6 @@ const closeTag = require('./close-tag'); const autoCompleteEmoji = require('./autocompleteEmoji'); let CodeMirror; -let isScrolling; if(typeof window !== 'undefined'){ CodeMirror = require('codemirror'); @@ -54,6 +53,7 @@ const CodeEditor = createClass({ value : '', wrap : true, onChange : ()=>{}, + onscroll : ()=>{}, enableFolding : true, editorTheme : 'default' }; @@ -191,14 +191,7 @@ const CodeEditor = createClass({ // Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works. this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());}); - this.codeMirror.on('scroll', (cm)=>{ - window.clearTimeout(isScrolling); - const props = this.props; - isScrolling = setTimeout(function() { - cm.setCursor({ line: cm.lineAtHeight(cm.getWrapperElement().getBoundingClientRect().top) + 1, ch: 0 }); - props.onScroll(cm.lineAtHeight(cm.getWrapperElement().getBoundingClientRect().top)); - }, 66); - }); + this.codeMirror.on('scroll', _.throttle(this.props.onScroll, 200)); this.updateSize(); }, From 45a9501459433a3b482dd4c03934300d9b0c116e Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Tue, 10 Sep 2024 01:11:28 -0400 Subject: [PATCH 23/39] Jump based on scroll position, not cursor position --- client/homebrew/editor/editor.jsx | 13 +++++++++---- shared/naturalcrit/codeEditor/codeEditor.jsx | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 3b87c7bcc..09af827fc 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -158,7 +158,7 @@ const Editor = createClass({ if(!this.props.liveScroll) return; console.log("handleSourceScroll") scrollingJump = true; - this.brewJump(); + this.brewJump(this.getCurrentPage(false)); scrollingJump = false; }, @@ -184,8 +184,13 @@ const Editor = createClass({ }); //TODO: not sure if updateeditorsize needed }, - getCurrentPage : function(){ - const lines = this.props.brew.text.split('\n').slice(0, this.codeEditor.current.getCursorPosition().line + 1); + getCurrentPage : function(atCursor = true){ + let lines = this.props.brew.text.split('\n'); + if (atCursor) + lines = lines.slice(0, this.codeEditor.current.getCursorPosition().line + 1); // get cursor page + else + lines = lines.slice(0, this.codeEditor.current.getViewport().from + 1); // get view page + return _.reduce(lines, (r, line)=>{ if( (this.props.renderer == 'legacy' && line.indexOf('\\page') !== -1) @@ -357,7 +362,7 @@ const Editor = createClass({ }, brewJump : function(targetPage=this.getCurrentPage()){ - console.log('jumpbrew') + console.log(`jumpBrew to page ${targetPage}`) if(lockBrewJump) return; if(!window) return; lockSourceJump = true; diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index 1387edfee..64dab05d0 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -399,6 +399,9 @@ const CodeEditor = createClass({ getCursorPosition : function(){ return this.codeMirror.getCursor(); }, + getViewport : function(){ + return this.codeMirror.getViewport(); + }, updateSize : function(){ this.codeMirror.refresh(); }, From e5ab2235717e6eba283a8c6765c8366e4e8dfa34 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Tue, 10 Sep 2024 01:25:26 -0400 Subject: [PATCH 24/39] Better line position (viewport has some margin) --- client/homebrew/editor/editor.jsx | 2 +- shared/naturalcrit/codeEditor/codeEditor.jsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 09af827fc..e2b28cdc1 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -189,7 +189,7 @@ const Editor = createClass({ if (atCursor) lines = lines.slice(0, this.codeEditor.current.getCursorPosition().line + 1); // get cursor page else - lines = lines.slice(0, this.codeEditor.current.getViewport().from + 1); // get view page + lines = lines.slice(0, this.codeEditor.current.getTopVisibleLine() + 1); // get view page return _.reduce(lines, (r, line)=>{ if( diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index 64dab05d0..ac930177a 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -399,8 +399,10 @@ const CodeEditor = createClass({ getCursorPosition : function(){ return this.codeMirror.getCursor(); }, - getViewport : function(){ - return this.codeMirror.getViewport(); + getTopVisibleLine : function(){ + const rect = this.codeMirror.getWrapperElement().getBoundingClientRect(); + const topVisibleLine = this.codeMirror.lineAtHeight(rect.top, "window"); + return topVisibleLine; }, updateSize : function(){ this.codeMirror.refresh(); From 3ef91cb1eaae0cf2b5d7009824138095ba69390f Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 12 Sep 2024 12:55:11 -0400 Subject: [PATCH 25/39] Add check for scroll event complete/ lift page state up --- client/homebrew/brewRenderer/brewRenderer.jsx | 19 +--- client/homebrew/editor/editor.jsx | 99 ++++++++++--------- client/homebrew/pages/editPage/editPage.jsx | 39 +++++--- client/homebrew/pages/newPage/newPage.jsx | 21 ++-- 4 files changed, 92 insertions(+), 86 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 5cbac23f7..5f7772d55 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -58,6 +58,7 @@ const BrewRenderer = (props)=>{ errors : [], currentEditorPage : 0, themeBundle : {}, + onPageChange : ()=>{}, ...props }; @@ -88,27 +89,12 @@ const BrewRenderer = (props)=>{ })); }; - const handleScroll = (e)=>{ - const target = e.target; - const newPage = Math.floor(target.scrollTop / target.scrollHeight * rawPages.length); - if(newPage != state.viewablePageNumber) { - window.clearTimeout(isScrolling); - isScrolling = setTimeout(function() { - window.parent.document.dispatchEvent(new CustomEvent('renderScrolled', {})); - }, 66); - } - setState((prevState)=>({ - ...prevState, - viewablePageNumber : newPage - })); - }; - const getCurrentPage = (e)=>{ const { scrollTop, clientHeight, scrollHeight } = e.target; const totalScrollableHeight = scrollHeight - clientHeight; const currentPageNumber = Math.ceil((scrollTop / totalScrollableHeight) * rawPages.length); - handleScroll(e); + props.onPageChange(currentPageNumber); setState((prevState)=>({ ...prevState, @@ -116,7 +102,6 @@ const BrewRenderer = (props)=>{ })); }; - const isInView = (index)=>{ if(!state.isMounted) return false; diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index e2b28cdc1..28dd6e6d7 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -23,9 +23,7 @@ const DEFAULT_STYLE_TEXT = dedent` }`; let lastPage = 0; -let lockBrewJump = false; -let lockSourceJump = false; -let scrollingJump = false; +let isJumping = false; const isElementCodeMirror=(element)=>{ let el = element; @@ -76,7 +74,6 @@ const Editor = createClass({ this.highlightCustomMarkdown(); window.addEventListener('resize', this.updateEditorSize); document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys); - document.addEventListener('renderScrolled', this.handleBrewScroll); document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('click', (e)=>{ if(isElementCodeMirror(e.target) && this.props.liveScroll ) { @@ -112,6 +109,9 @@ const Editor = createClass({ if(prevProps.liveScroll != this.props.liveScroll) { if((prevProps.liveScroll != undefined) && (this.props.liveScroll)) this.brewJump(); }; + if(prevProps.currentBrewRendererPage !== this.props.currentBrewRendererPage) { + this.handleBrewScroll(); + } }, handleControlKeys : function(e){ @@ -149,17 +149,12 @@ const Editor = createClass({ handleBrewScroll : function() { if(!this.props.liveScroll) return; - scrollingJump = true; - this.sourceJump(); - scrollingJump = false; + this.sourceJump(undefined, false); }, handleSourceScroll : function() { if(!this.props.liveScroll) return; - console.log("handleSourceScroll") - scrollingJump = true; - this.brewJump(this.getCurrentPage(false)); - scrollingJump = false; + this.brewJump(this.getCurrentPage(false), false); }, updateEditorSize : function() { @@ -361,13 +356,10 @@ const Editor = createClass({ } }, - brewJump : function(targetPage=this.getCurrentPage()){ - console.log(`jumpBrew to page ${targetPage}`) - if(lockBrewJump) return; + brewJump : function(targetPage=this.getCurrentPage(), smooth=true){ + if(isJumping) return; if(!window) return; - lockSourceJump = true; - lockBrewJump = true; - //console.log(`Scroll to: p${targetPage}`); + const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; @@ -376,9 +368,26 @@ const Editor = createClass({ const bounceDelay = 100; const scrollDelay = 500; - if(scrollingJump) { - brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'instant', block: 'start' }); - } else { + if(Math.abs(targetPos) < 1) + return; + + isJumping = true; + + // Detect end of scroll event to avoid feedback loops + let scrollingTimeout; + + const checkIfScrollComplete = () => { + clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs + scrollingTimeout = setTimeout(() => { + isJumping = false; + brewRenderer.removeEventListener('scroll', checkIfScrollComplete); + }, 150); // If 150 ms pass without a brewRenderer scroll event, assume scrolling is done + }; + + brewRenderer.addEventListener('scroll', checkIfScrollComplete); + console.log("added event listener") + + if(smooth) { if(!this.throttleBrewMove) { this.throttleBrewMove = _.throttle((currentPos, interimPos, targetPos)=>{ brewRenderer.scrollTo({ top: currentPos + interimPos, behavior: 'smooth' }); @@ -388,35 +397,19 @@ const Editor = createClass({ }, scrollDelay, { leading: true, trailing: false }); }; this.throttleBrewMove(currentPos, interimPos, targetPos); + } else { + brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'instant', block: 'start' }); } - lockSourceJump = false; - lockBrewJump = false; - - // const hashPage = (page != 1) ? `p${page}` : ''; - // window.location.hash = hashPage; }, - sourceJump : function(targetLine=null){ - if(lockSourceJump) return; + sourceJump : function(targetLine=null, smooth=true){ + if(isJumping) return; if(this.isText()) { if(targetLine == null) { targetLine = 0; - lockBrewJump = true; - lockSourceJump = true; - - const pageCollection = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('page'); - const brewRendererHeight = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0).getBoundingClientRect().height; - - let currentPage = 1; - for (const page of pageCollection) { - if(page.getBoundingClientRect().bottom > (brewRendererHeight / 2)) { - currentPage = parseInt(page.id.slice(1)) || 1; - break; - } - } const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; - const textString = this.props.brew.text.split(textSplit).slice(0, currentPage-1).join(textSplit); + const textString = this.props.brew.text.split(textSplit).slice(0, this.props.currentBrewRendererPage-1).join(textSplit); const textPosition = textString.length; const lineCount = textString.match('\n') ? textString.slice(0, textPosition).split('\n').length : 0; @@ -425,7 +418,25 @@ const Editor = createClass({ let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - if(!scrollingJump) { + if (Math.abs(targetY - currentY) < 1) + return; + + isJumping = true; + + // Detect end of scroll event to avoid feedback loops + let scrollingTimeout; + + const checkIfScrollComplete = () => { + clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs + scrollingTimeout = setTimeout(() => { + isJumping = false; + this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); + }, 150); // If 150 ms pass without a scroll event, assume scrolling is done + }; + + this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); + + if(smooth) { //Scroll 1/10 of the way every 10ms until 1px off. const incrementalScroll = setInterval(()=>{ currentY += (targetY - currentY) / 10; @@ -441,16 +452,12 @@ const Editor = createClass({ this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); clearInterval(incrementalScroll); - lockBrewJump = false; - lockSourceJump = false; } }, 10); } else { this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - lockBrewJump = false; - lockSourceJump = false; } } } diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 39a6d1931..e8afed322 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -41,22 +41,23 @@ const EditPage = createClass({ getInitialState : function() { return { - brew : this.props.brew, - isSaving : false, - isPending : false, - alertTrashedGoogleBrew : this.props.brew.trashed, - alertLoginToTransfer : false, - saveGoogle : this.props.brew.googleId ? true : false, - confirmGoogleTransfer : false, - error : null, - htmlErrors : Markdown.validate(this.props.brew.text), - url : '', - autoSave : true, - autoSaveWarning : false, - unsavedTime : new Date(), - currentEditorPage : 0, - displayLockMessage : this.props.brew.lock || false, - themeBundle : {} + brew : this.props.brew, + isSaving : false, + isPending : false, + alertTrashedGoogleBrew : this.props.brew.trashed, + alertLoginToTransfer : false, + saveGoogle : this.props.brew.googleId ? true : false, + confirmGoogleTransfer : false, + error : null, + htmlErrors : Markdown.validate(this.props.brew.text), + url : '', + autoSave : true, + autoSaveWarning : false, + unsavedTime : new Date(), + currentEditorPage : 0, + currentBrewRendererPage : 0, + displayLockMessage : this.props.brew.lock || false, + themeBundle : {} }; }, @@ -113,6 +114,10 @@ const EditPage = createClass({ this.editor.current.update(); }, + handleBrewRendererPageChange : function(pageNumber){ + this.setState(()=>({ currentBrewRendererPage : pageNumber })); + }, + handleTextChange : function(text){ //If there are errors, run the validator on every change to give quick feedback let htmlErrors = this.state.htmlErrors; @@ -413,6 +418,7 @@ const EditPage = createClass({ renderer={this.state.brew.renderer} userThemes={this.props.userThemes} snippetBundle={this.state.themeBundle.snippets} + currentBrewRendererPage={this.state.currentBrewRendererPage} /> diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 5b0f59c00..682c53654 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -39,13 +39,14 @@ const NewPage = createClass({ const brew = this.props.brew; return { - brew : brew, - isSaving : false, - saveGoogle : (global.account && global.account.googleId ? true : false), - error : null, - htmlErrors : Markdown.validate(brew.text), - currentEditorPage : 0, - themeBundle : {} + brew : brew, + isSaving : false, + saveGoogle : (global.account && global.account.googleId ? true : false), + error : null, + htmlErrors : Markdown.validate(brew.text), + currentEditorPage : 0, + currentBrewRendererPage : 0, + themeBundle : {} }; }, @@ -108,6 +109,10 @@ const NewPage = createClass({ this.editor.current.update(); }, + handleBrewRendererPageChange : function(pageNumber){ + this.setState(()=>({ currentBrewRendererPage : pageNumber })); + }, + handleTextChange : function(text){ //If there are errors, run the validator on every change to give quick feedback let htmlErrors = this.state.htmlErrors; @@ -221,6 +226,7 @@ const NewPage = createClass({ renderer={this.state.brew.renderer} userThemes={this.props.userThemes} snippetBundle={this.state.themeBundle.snippets} + currentBrewRendererPage={this.state.currentBrewRendererPage} /> From 181c6bf65aac88a443751248bf0843bec9c23670 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 14 Sep 2024 19:15:39 -0400 Subject: [PATCH 26/39] Update editor.jsx --- client/homebrew/editor/editor.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 461d43e23..8588fd7b9 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -496,8 +496,6 @@ const Editor = createClass({ view={this.state.view} value={this.props.brew.text} onChange={this.props.onTextChange} - onCursorActivity={this.props.onCursorActivity} - onScroll={this.props.onPageChange} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} /> ; From 84c0242eee9fbe773d7b80954ba6c80dfbfd41b2 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 00:13:49 -0400 Subject: [PATCH 27/39] Put page jump checks in componentDidUpdate Jump when the current page for brew or editor changes --- client/homebrew/editor/editor.jsx | 147 +++++++++++++++--------------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8588fd7b9..42431151d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -116,11 +116,18 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) { this.sourceJump(); }; - if(prevProps.liveScroll != this.props.liveScroll) { - if((prevProps.liveScroll != undefined) && (this.props.liveScroll)) this.brewJump(); - }; - if(prevProps.currentBrewRendererPage !== this.props.currentBrewRendererPage) { - this.handleBrewScroll(); + // if(prevProps.liveScroll !== this.props.liveScroll) { + // this.brewJump(); + // }; + + if(this.props.liveScroll) { + if(prevProps.currentBrewRendererPageNum !== this.props.currentBrewRendererPageNum) { + this.sourceJump(this.props.currentBrewRendererPageNum, false); + } else if(prevProps.currentEditorViewPageNum !== this.props.currentEditorViewPageNum) { + this.brewJump(this.props.currentEditorViewPageNum, false); + } else if(prevProps.currentEditorCursorPageNum !== this.props.currentEditorCursorPageNum) { + this.brewJump(this.props.currentEditorCursorPageNum, false); + } } }, @@ -131,15 +138,15 @@ const Editor = createClass({ const RIGHTARROW_KEY = 39; if(this.props.liveScroll) { - console.log('Should be scrollig!'); - const movementKeys = [13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40]; - if(movementKeys.includes(e.keyCode)) { - const curPage = this.getCurrentPage(); - if(curPage != lastPage) { - this.brewJump(); - lastPage = curPage; - } - } + //console.log('Should be scrollig!'); + //const movementKeys = [13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40]; + // if(movementKeys.includes(e.keyCode)) { + // const curPage = this.getCurrentPage(); + // if(curPage != lastPage) { + // this.brewJump(); + // lastPage = curPage; + // } + // } } if(!(e.ctrlKey && e.metaKey)) return; @@ -147,26 +154,16 @@ const Editor = createClass({ if(!e.ctrlKey) return; // Handle CTRL-HOME and CTRL-END - if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); + //if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); if(!e.metaKey) return; - if(e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump(); - if(e.shiftKey && (e.keyCode == LEFTARROW_KEY)) this.sourceJump(); + //if(e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump(); + //if(e.shiftKey && (e.keyCode == LEFTARROW_KEY)) this.sourceJump(); if((e.keyCode == LEFTARROW_KEY) || (e.keyCode == RIGHTARROW_KEY)) { e.stopPropagation(); e.preventDefault(); } }, - handleBrewScroll : function() { - if(!this.props.liveScroll) return; - this.sourceJump(undefined, false); - }, - - handleSourceScroll : function() { - if(!this.props.liveScroll) return; - this.brewJump(this.getCurrentPage(false), false); - }, - updateEditorSize : function() { if(this.codeEditor.current) { let paneHeight = this.editor.current.parentNode.clientHeight; @@ -366,8 +363,11 @@ const Editor = createClass({ brewJump : function(targetPage=this.props.currentEditorCursorPageNum, smooth=true){ if(isJumping) return; if(!window) return; + console.log(targetPage) // Get current brewRenderer scroll position and calculate target position const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; + if(!brewRenderer) return; + console.log(window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)); const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; const interimPos = targetPos >= 0 ? -30 : 30; @@ -409,63 +409,62 @@ const Editor = createClass({ } }, - sourceJump : function(targetLine=null, smooth=true){ + sourceJump : function(targetPage=this.props.currentBrewRendererPageNum, smooth=true){ if(isJumping) return; if(this.isText()) { - if(targetLine == null) { - targetLine = 0; + let targetLine = 0; - const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; - const textString = this.props.brew.text.split(textSplit).slice(0, this.props.currentBrewRendererPageNum-1).join(textSplit); - const textPosition = textString.length; - const lineCount = textString.match('\n') ? textString.slice(0, textPosition).split('\n').length : 0; + const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; + const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); + const textPosition = textString.length; + const lineCount = textString.match('\n') ? textString.slice(0, textPosition).split('\n').length : 0; - targetLine = lineCount - 1; //Scroll to `\page`, which is one line back. + targetLine = lineCount - 1; //Scroll to `\page`, which is one line back. - let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; - let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); + let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; + let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - if (Math.abs(targetY - currentY) < 1) - return; + if (Math.abs(targetY - currentY) < 1) + return; - isJumping = true; - - // Detect end of scroll event to avoid feedback loops - let scrollingTimeout; - - const checkIfScrollComplete = () => { - clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs - scrollingTimeout = setTimeout(() => { - isJumping = false; - this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); - }, 150); // If 150 ms pass without a scroll event, assume scrolling is done - }; - - this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); + isJumping = true; + + // Detect end of scroll event to avoid feedback loops + let scrollingTimeout; + + const checkIfScrollComplete = () => { + clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs + scrollingTimeout = setTimeout(() => { + isJumping = false; + this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); + }, 150); // If 150 ms pass without a scroll event, assume scrolling is done + }; + + this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); - if(smooth) { - //Scroll 1/10 of the way every 10ms until 1px off. - const incrementalScroll = setInterval(()=>{ - currentY += (targetY - currentY) / 10; - this.codeEditor.current.codeMirror.scrollTo(null, currentY); + if(smooth) { + //Scroll 1/10 of the way every 10ms until 1px off. + const incrementalScroll = setInterval(()=>{ + currentY += (targetY - currentY) / 10; + this.codeEditor.current.codeMirror.scrollTo(null, currentY); - // Update target: target height is not accurate until within +-10 lines of the visible window - if(Math.abs(targetY - currentY > 100)) - targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); + // Update target: target height is not accurate until within +-10 lines of the visible window + if(Math.abs(targetY - currentY > 100)) + targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - // End when close enough - if(Math.abs(targetY - currentY) < 1) { - this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference - this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); - this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - clearInterval(incrementalScroll); - } - }, 10); - } else { - this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference - this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); - this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - } + // End when close enough + if(Math.abs(targetY - currentY) < 1) { + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); + clearInterval(incrementalScroll); + } + }, 10); + } else { + console.log("scrolling codemirror") + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); } } }, From 85401ba71b2d01aeaabb91345b646a7182864eb4 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 21:26:49 -0400 Subject: [PATCH 28/39] Fix BrewRenderer scrolling to 0 --- client/homebrew/brewRenderer/brewRenderer.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index d5565e748..8528a734c 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -93,7 +93,7 @@ const BrewRenderer = (props)=>{ const updateCurrentPage = useCallback(_.throttle((e)=>{ const { scrollTop, clientHeight, scrollHeight } = e.target; const totalScrollableHeight = scrollHeight - clientHeight; - const currentPageNumber = Math.ceil(((scrollTop + 1) / totalScrollableHeight) * rawPages.length); + const currentPageNumber = Math.max(Math.ceil((scrollTop / totalScrollableHeight) * rawPages.length), 1); props.onPageChange(currentPageNumber); }, 200), []); From 81ab9417d39715f5dc70545905a2b4c69f262908 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 21:42:55 -0400 Subject: [PATCH 29/39] Clean up unused code --- client/homebrew/editor/editor.jsx | 57 +++------------------ client/homebrew/pages/editPage/editPage.jsx | 6 +-- client/homebrew/pages/homePage/homePage.jsx | 6 +-- client/homebrew/pages/newPage/newPage.jsx | 6 +-- 4 files changed, 16 insertions(+), 59 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 42431151d..abac1fe00 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -3,7 +3,6 @@ require('./editor.less'); const React = require('react'); const createClass = require('create-react-class'); const _ = require('lodash'); -const cx = require('classnames'); const dedent = require('dedent-tabs').default; const Markdown = require('../../../shared/naturalcrit/markdown.js'); @@ -22,20 +21,8 @@ const DEFAULT_STYLE_TEXT = dedent` color: black; }`; -let lastPage = 0; let isJumping = false; -const isElementCodeMirror=(element)=>{ - let el = element; - while( el.tagName != 'body' ) { - if ( !el?.classList ) return false - if( el?.classList?.contains('CodeMirror-code') || el.classList.contains('CodeMirror-line')) - return true; - el = el.parentNode; - } - return false; -}; - const Editor = createClass({ displayName : 'Editor', getDefaultProps : function() { @@ -56,9 +43,9 @@ const Editor = createClass({ editorTheme : 'default', renderer : 'legacy', - currentEditorCursorPageNum : 0, - currentEditorViewPageNum : 0, - currentBrewRendererPageNum : 0, + currentEditorCursorPageNum : 1, + currentEditorViewPageNum : 1, + currentBrewRendererPageNum : 1, }; }, getInitialState : function() { @@ -85,15 +72,6 @@ const Editor = createClass({ this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor())}); this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine())}, 200)); - document.addEventListener('click', (e)=>{ - if(isElementCodeMirror(e.target) && this.props.liveScroll ) { - const curPage = this.getCurrentPage(); - if( curPage != lastPage ) { - this.brewJump(); - lastPage = curPage; - } - } - }); const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY); if(editorTheme) { @@ -132,33 +110,12 @@ const Editor = createClass({ }, handleControlKeys : function(e){ - const END_KEY = 35; - const HOME_KEY = 36; + if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return; const LEFTARROW_KEY = 37; const RIGHTARROW_KEY = 39; - - if(this.props.liveScroll) { - //console.log('Should be scrollig!'); - //const movementKeys = [13, 33, 34, LEFTARROW_KEY, 38, RIGHTARROW_KEY, 40]; - // if(movementKeys.includes(e.keyCode)) { - // const curPage = this.getCurrentPage(); - // if(curPage != lastPage) { - // this.brewJump(); - // lastPage = curPage; - // } - // } - } - - if(!(e.ctrlKey && e.metaKey)) return; - - if(!e.ctrlKey) return; - - // Handle CTRL-HOME and CTRL-END - //if(((e.keyCode == END_KEY) || (e.keyCode == HOME_KEY)) && this.props.liveScroll) this.brewJump(); - if(!e.metaKey) return; - //if(e.shiftKey && (e.keyCode == RIGHTARROW_KEY)) this.brewJump(); - //if(e.shiftKey && (e.keyCode == LEFTARROW_KEY)) this.sourceJump(); - if((e.keyCode == LEFTARROW_KEY) || (e.keyCode == RIGHTARROW_KEY)) { + if (e.keyCode == RIGHTARROW_KEY) this.brewJump(); + if (e.keyCode == LEFTARROW_KEY) this.sourceJump(); + if (e.keyCode == LEFTARROW_KEY || e.keyCode == RIGHTARROW_KEY) { e.stopPropagation(); e.preventDefault(); } diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index e6a67e414..796c6755c 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -55,9 +55,9 @@ const EditPage = createClass({ autoSave : true, autoSaveWarning : false, unsavedTime : new Date(), - currentEditorViewPageNum : 0, - currentEditorCursorPageNum : 0, - currentBrewRendererPageNum : 0, + currentEditorViewPageNum : 1, + currentEditorCursorPageNum : 1, + currentBrewRendererPageNum : 1, displayLockMessage : this.props.brew.lock || false, themeBundle : {} }; diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 6e11806bd..3aaa35219 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -34,9 +34,9 @@ const HomePage = createClass({ brew : this.props.brew, welcomeText : this.props.brew.text, error : undefined, - currentEditorViewPageNum : 0, - currentEditorCursorPageNum : 0, - currentBrewRendererPageNum : 0, + currentEditorViewPageNum : 1, + currentEditorCursorPageNum : 1, + currentBrewRendererPageNum : 1, themeBundle : {} }; }, diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 115f4ea88..9297ad995 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -44,9 +44,9 @@ const NewPage = createClass({ saveGoogle : (global.account && global.account.googleId ? true : false), error : null, htmlErrors : Markdown.validate(brew.text), - currentEditorViewPageNum : 0, - currentEditorCursorPageNum : 0, - currentBrewRendererPageNum : 0, + currentEditorViewPageNum : 1, + currentEditorCursorPageNum : 1, + currentBrewRendererPageNum : 1, themeBundle : {} }; }, From c07c02f1d9ba84c68ed08865545abe17ed90fcf6 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 21:44:02 -0400 Subject: [PATCH 30/39] Remove unused variable --- client/homebrew/brewRenderer/brewRenderer.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 8528a734c..7268e4b34 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -20,7 +20,6 @@ const DOMPurify = require('dompurify'); const purifyConfig = { FORCE_BODY: true, SANITIZE_DOM: false }; const PAGE_HEIGHT = 1056; -let isScrolling; const INITIAL_CONTENT = dedent` From a353425d07cf0ea66dd2659140554cbe2c2d3c7c Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 22:13:41 -0400 Subject: [PATCH 31/39] More cleanup --- client/homebrew/editor/editor.jsx | 125 ++++++++++++++---------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index abac1fe00..2d52be0b2 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -88,15 +88,11 @@ const Editor = createClass({ componentDidUpdate : function(prevProps, prevState, snapshot) { this.highlightCustomMarkdown(); - if(prevProps.moveBrew !== this.props.moveBrew) { + if(prevProps.moveBrew !== this.props.moveBrew) this.brewJump(); - }; - if(prevProps.moveSource !== this.props.moveSource) { + + if(prevProps.moveSource !== this.props.moveSource) this.sourceJump(); - }; - // if(prevProps.liveScroll !== this.props.liveScroll) { - // this.brewJump(); - // }; if(this.props.liveScroll) { if(prevProps.currentBrewRendererPageNum !== this.props.currentBrewRendererPageNum) { @@ -318,19 +314,13 @@ const Editor = createClass({ }, brewJump : function(targetPage=this.props.currentEditorCursorPageNum, smooth=true){ - if(isJumping) return; - if(!window) return; - console.log(targetPage) + if(!window || isJumping) + return; + // Get current brewRenderer scroll position and calculate target position const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; - if(!brewRenderer) return; - console.log(window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`)); const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; - const interimPos = targetPos >= 0 ? -30 : 30; - - const bounceDelay = 100; - const scrollDelay = 500; if(Math.abs(targetPos) < 1) return; @@ -349,80 +339,79 @@ const Editor = createClass({ }; brewRenderer.addEventListener('scroll', checkIfScrollComplete); - console.log("added event listener") if(smooth) { + const bouncePos = targetPos >= 0 ? -30 : 30; //Do a little bounce before scrolling + const bounceDelay = 100; + const scrollDelay = 500; + if(!this.throttleBrewMove) { - this.throttleBrewMove = _.throttle((currentPos, interimPos, targetPos)=>{ - brewRenderer.scrollTo({ top: currentPos + interimPos, behavior: 'smooth' }); + this.throttleBrewMove = _.throttle((currentPos, bouncePos, targetPos)=>{ + brewRenderer.scrollTo({ top: currentPos + bouncePos, behavior: 'smooth' }); setTimeout(()=>{ brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'smooth', block: 'start' }); }, bounceDelay); }, scrollDelay, { leading: true, trailing: false }); }; - this.throttleBrewMove(currentPos, interimPos, targetPos); + this.throttleBrewMove(currentPos, bouncePos, targetPos); } else { brewRenderer.scrollTo({ top: currentPos + targetPos, behavior: 'instant', block: 'start' }); } }, sourceJump : function(targetPage=this.props.currentBrewRendererPageNum, smooth=true){ - if(isJumping) return; - if(this.isText()) { - let targetLine = 0; + if(!this.isText || isJumping) + return; - const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; - const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); - const textPosition = textString.length; - const lineCount = textString.match('\n') ? textString.slice(0, textPosition).split('\n').length : 0; + const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; + const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); + const lineCount = (textString.match(/\n/g) || []).length; - targetLine = lineCount - 1; //Scroll to `\page`, which is one line back. + const targetLine = lineCount - 1; //Scroll to `\page`, which is one line back. - let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; - let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); + let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; + let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - if (Math.abs(targetY - currentY) < 1) - return; + if (Math.abs(targetY - currentY) < 1) + return; - isJumping = true; - - // Detect end of scroll event to avoid feedback loops - let scrollingTimeout; - - const checkIfScrollComplete = () => { - clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs - scrollingTimeout = setTimeout(() => { - isJumping = false; - this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); - }, 150); // If 150 ms pass without a scroll event, assume scrolling is done - }; - - this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); + isJumping = true; + + // Detect end of scroll event to avoid feedback loops + let scrollingTimeout; + + const checkIfScrollComplete = () => { + clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs + scrollingTimeout = setTimeout(() => { + isJumping = false; + this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); + }, 150); // If 150 ms pass without a scroll event, assume scrolling is done + }; + + this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); - if(smooth) { - //Scroll 1/10 of the way every 10ms until 1px off. - const incrementalScroll = setInterval(()=>{ - currentY += (targetY - currentY) / 10; - this.codeEditor.current.codeMirror.scrollTo(null, currentY); + if(smooth) { + //Scroll 1/10 of the way every 10ms until 1px off. + const incrementalScroll = setInterval(()=>{ + currentY += (targetY - currentY) / 10; + this.codeEditor.current.codeMirror.scrollTo(null, currentY); - // Update target: target height is not accurate until within +-10 lines of the visible window - if(Math.abs(targetY - currentY > 100)) - targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); + // Update target: target height is not accurate until within +-10 lines of the visible window + if(Math.abs(targetY - currentY > 100)) + targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - // End when close enough - if(Math.abs(targetY - currentY) < 1) { - this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference - this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); - this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - clearInterval(incrementalScroll); - } - }, 10); - } else { - console.log("scrolling codemirror") - this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference - this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); - this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); - } + // End when close enough + if(Math.abs(targetY - currentY) < 1) { + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); + clearInterval(incrementalScroll); + } + }, 10); + } else { + this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference + this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); + this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); } }, From 25a40e31c59fc8530dd2221517baaa1ddeb544c3 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 15 Sep 2024 22:31:29 -0400 Subject: [PATCH 32/39] Remove console logs --- client/homebrew/editor/editor.jsx | 4 +--- client/homebrew/pages/editPage/editPage.jsx | 4 ---- client/homebrew/pages/homePage/homePage.jsx | 3 --- client/homebrew/pages/newPage/newPage.jsx | 3 --- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 2d52be0b2..bd21274f8 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -365,9 +365,7 @@ const Editor = createClass({ const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); - const lineCount = (textString.match(/\n/g) || []).length; - - const targetLine = lineCount - 1; //Scroll to `\page`, which is one line back. + const targetLine = (textString.match(/\n/g) || []).length; let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 796c6755c..1ff841024 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -117,23 +117,19 @@ const EditPage = createClass({ }, handleEditorViewPageChange : function(pageNumber){ - console.log(`editor view : ${pageNumber}`); this.setState({ currentEditorViewPageNum: pageNumber }); }, handleEditorCursorPageChange : function(pageNumber){ - console.log(`editor cursor : ${pageNumber}`); this.setState({ currentEditorCursorPageNum: pageNumber }); }, handleBrewRendererPageChange : function(pageNumber){ - console.log(`brewRenderer view : ${pageNumber}`); this.setState({ currentBrewRendererPageNum: pageNumber }); }, handleTextChange : function(text){ //If there are errors, run the validator on every change to give quick feedback - console.log('text change'); let htmlErrors = this.state.htmlErrors; if(htmlErrors.length) htmlErrors = Markdown.validate(text); diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 3aaa35219..ac3be81df 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -64,17 +64,14 @@ const HomePage = createClass({ }, handleEditorViewPageChange : function(pageNumber){ - console.log(`editor view : ${pageNumber}`); this.setState({ currentEditorViewPageNum: pageNumber }); }, handleEditorCursorPageChange : function(pageNumber){ - console.log(`editor cursor : ${pageNumber}`); this.setState({ currentEditorCursorPageNum: pageNumber }); }, handleBrewRendererPageChange : function(pageNumber){ - console.log(`brewRenderer view : ${pageNumber}`); this.setState({ currentBrewRendererPageNum: pageNumber }); }, diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 9297ad995..c147cd474 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -111,17 +111,14 @@ const NewPage = createClass({ }, handleEditorViewPageChange : function(pageNumber){ - console.log(`editor view : ${pageNumber}`); this.setState({ currentEditorViewPageNum: pageNumber }); }, handleEditorCursorPageChange : function(pageNumber){ - console.log(`editor cursor : ${pageNumber}`); this.setState({ currentEditorCursorPageNum: pageNumber }); }, handleBrewRendererPageChange : function(pageNumber){ - console.log(`brewRenderer view : ${pageNumber}`); this.setState({ currentBrewRendererPageNum: pageNumber }); }, From d2117259eb5dc8c9db533f9babc5d38f02040043 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 03:50:51 +0000 Subject: [PATCH 33/39] Bump express-static-gzip from 2.1.7 to 2.1.8 Bumps [express-static-gzip](https://github.com/tkoenig89/express-static-gzip) from 2.1.7 to 2.1.8. - [Release notes](https://github.com/tkoenig89/express-static-gzip/releases) - [Commits](https://github.com/tkoenig89/express-static-gzip/compare/v2.1.7...v2.1.8) --- updated-dependencies: - dependency-name: express-static-gzip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06c4350ca..16d308bf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "expr-eval": "^2.0.2", "express": "^4.21.0", "express-async-handler": "^1.2.0", - "express-static-gzip": "2.1.7", + "express-static-gzip": "2.1.8", "fs-extra": "11.2.0", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", @@ -6362,12 +6362,11 @@ "license": "MIT" }, "node_modules/express-static-gzip": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz", - "integrity": "sha512-QOCZUC+lhPPCjIJKpQGu1Oa61Axg9Mq09Qvit8Of7kzpMuwDeMSqjjQteQS3OVw/GkENBoSBheuQDWPlngImvw==", - "license": "MIT", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.8.tgz", + "integrity": "sha512-g8tiJuI9Y9Ffy59ehVXvqb0hhP83JwZiLxzanobPaMbkB5qBWA8nuVgd+rcd5qzH3GkgogTALlc0BaADYwnMbQ==", "dependencies": { - "serve-static": "^1.14.1" + "serve-static": "^1.16.2" } }, "node_modules/express/node_modules/cookie": { diff --git a/package.json b/package.json index f760cc096..ef39fbf6f 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "expr-eval": "^2.0.2", "express": "^4.21.0", "express-async-handler": "^1.2.0", - "express-static-gzip": "2.1.7", + "express-static-gzip": "2.1.8", "fs-extra": "11.2.0", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", From 48bdc417faf463d340f711d3816d06f67f87ab24 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 16 Sep 2024 00:39:04 -0400 Subject: [PATCH 34/39] More logic simplification --- client/homebrew/editor/editor.jsx | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index bd21274f8..0ecb1787f 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -322,15 +322,8 @@ const Editor = createClass({ const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; - if(Math.abs(targetPos) < 1) - return; - - isJumping = true; - - // Detect end of scroll event to avoid feedback loops - let scrollingTimeout; - const checkIfScrollComplete = () => { + let scrollingTimeout; clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs scrollingTimeout = setTimeout(() => { isJumping = false; @@ -338,6 +331,8 @@ const Editor = createClass({ }, 150); // If 150 ms pass without a brewRenderer scroll event, assume scrolling is done }; + isJumping = true; + checkIfScrollComplete(); brewRenderer.addEventListener('scroll', checkIfScrollComplete); if(smooth) { @@ -365,20 +360,13 @@ const Editor = createClass({ const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); - const targetLine = (textString.match(/\n/g) || []).length; + const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1; let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - - if (Math.abs(targetY - currentY) < 1) - return; - - isJumping = true; - - // Detect end of scroll event to avoid feedback loops - let scrollingTimeout; const checkIfScrollComplete = () => { + let scrollingTimeout; clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs scrollingTimeout = setTimeout(() => { isJumping = false; @@ -386,6 +374,8 @@ const Editor = createClass({ }, 150); // If 150 ms pass without a scroll event, assume scrolling is done }; + isJumping = true; + checkIfScrollComplete(); this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); if(smooth) { From 1645a5acf41d18bdd0b073a919d42e38b6b2b3e0 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 16 Sep 2024 01:39:44 -0400 Subject: [PATCH 35/39] Lint App.js Just whitespace changes --- server/app.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/server/app.js b/server/app.js index c03fb2dc2..c97fc302e 100644 --- a/server/app.js +++ b/server/app.js @@ -203,22 +203,22 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ }); //Serve brew metadata -app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res) => { +app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res)=>{ const { brew } = req; sanitizeBrew(brew, 'share'); - - const fields = [ 'title', 'pageCount', 'description', 'authors', 'lang', - 'published', 'views', 'shareId', 'createdAt', 'updatedAt', + + const fields = ['title', 'pageCount', 'description', 'authors', 'lang', + 'published', 'views', 'shareId', 'createdAt', 'updatedAt', 'lastViewed', 'thumbnail', 'tags' ]; - - const metadata = fields.reduce((acc, field) => { - if (brew[field] !== undefined) acc[field] = brew[field]; + + const metadata = fields.reduce((acc, field)=>{ + if(brew[field] !== undefined) acc[field] = brew[field]; return acc; }, {}); res.status(200).json(metadata); }); - + //Serve brew styling app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);}); @@ -378,7 +378,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r app.get('/account', asyncHandler(async (req, res, next)=>{ const data = {}; data.title = 'Account Information Page'; - + if(!req.account) { res.set('WWW-Authenticate', 'Bearer realm="Authorization Required"'); const error = new Error('No valid account'); @@ -462,8 +462,8 @@ app.get('/vault', asyncHandler(async(req, res, next)=>{ //Send rendered page app.use(asyncHandler(async (req, res, next)=>{ - if (!req.route) return res.redirect('/'); // Catch-all for invalid routes - + if(!req.route) return res.redirect('/'); // Catch-all for invalid routes + const page = await renderPage(req, res); if(!page) return; res.send(page); From b5490e3a5355784292d9a58200dba7aae739f19b Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 16 Sep 2024 01:40:21 -0400 Subject: [PATCH 36/39] Lint editor.jsx --- client/homebrew/editor/editor.jsx | 62 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 0ecb1787f..5c198c3b3 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -36,7 +36,7 @@ const Editor = createClass({ onStyleChange : ()=>{}, onMetaChange : ()=>{}, reportError : ()=>{}, - + onCursorPageChange : ()=>{}, onViewPageChange : ()=>{}, @@ -45,7 +45,7 @@ const Editor = createClass({ currentEditorCursorPageNum : 1, currentEditorViewPageNum : 1, - currentBrewRendererPageNum : 1, + currentBrewRendererPageNum : 1, }; }, getInitialState : function() { @@ -70,8 +70,8 @@ const Editor = createClass({ document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys); document.addEventListener('keydown', this.handleControlKeys); - this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor())}); - this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine())}, 200)); + this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());}); + this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200)); const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY); if(editorTheme) { @@ -109,9 +109,9 @@ const Editor = createClass({ if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return; const LEFTARROW_KEY = 37; const RIGHTARROW_KEY = 39; - if (e.keyCode == RIGHTARROW_KEY) this.brewJump(); - if (e.keyCode == LEFTARROW_KEY) this.sourceJump(); - if (e.keyCode == LEFTARROW_KEY || e.keyCode == RIGHTARROW_KEY) { + if(e.keyCode == RIGHTARROW_KEY) this.brewJump(); + if(e.keyCode == LEFTARROW_KEY) this.sourceJump(); + if(e.keyCode == LEFTARROW_KEY || e.keyCode == RIGHTARROW_KEY) { e.stopPropagation(); e.preventDefault(); } @@ -128,14 +128,14 @@ const Editor = createClass({ updateCurrentCursorPage : function(cursor) { const lines = this.props.brew.text.split('\n').slice(0, cursor.line + 1); const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/; - const currentPage = lines.reduce((count, line) => count + (pageRegex.test(line) ? 1 : 0), 1); + const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1); this.props.onCursorPageChange(currentPage); }, updateCurrentViewPage : function(topScrollLine) { const lines = this.props.brew.text.split('\n').slice(0, topScrollLine + 1); const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/; - const currentPage = lines.reduce((count, line) => count + (pageRegex.test(line) ? 1 : 0), 1); + const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1); this.props.onViewPageChange(currentPage); }, @@ -167,7 +167,7 @@ const Editor = createClass({ // Record details of folded sections if(mark.__isFold) { const fold = mark.find(); - foldLines.push({from: fold.from?.line, to: fold.to?.line}); + foldLines.push({ from: fold.from?.line, to: fold.to?.line }); } return !mark.__isFold; }); //Don't undo code folding @@ -185,7 +185,7 @@ const Editor = createClass({ // Don't process lines inside folded text // If the current lineNumber is inside any folded marks, skip line styling - if (foldLines.some(fold => lineNumber >= fold.from && lineNumber <= fold.to)) + if(foldLines.some((fold)=>lineNumber >= fold.from && lineNumber <= fold.to)) return; // Styling for \page breaks @@ -211,7 +211,7 @@ const Editor = createClass({ // definition lists if(line.includes('::')){ - if(/^:*$/.test(line) == true){ return }; + if(/^:*$/.test(line) == true){ return; }; const regex = /^([^\n]*?:?\s?)(::[^\n]*)(?:\n|$)/ymd; // the `d` flag, for match indices, throws an ESLint error. let match; while ((match = regex.exec(line)) != null){ @@ -219,10 +219,10 @@ const Editor = createClass({ codeMirror.markText({ line: lineNumber, ch: match.indices[1][0] }, { line: lineNumber, ch: match.indices[1][1] }, { className: 'dt-highlight' }); codeMirror.markText({ line: lineNumber, ch: match.indices[2][0] }, { line: lineNumber, ch: match.indices[2][1] }, { className: 'dd-highlight' }); const ddIndex = match.indices[2][0]; - let colons = /::/g; - let colonMatches = colons.exec(match[2]); + const colons = /::/g; + const colonMatches = colons.exec(match[2]); if(colonMatches !== null){ - codeMirror.markText({ line: lineNumber, ch: colonMatches.index + ddIndex }, { line: lineNumber, ch: colonMatches.index + colonMatches[0].length + ddIndex }, { className: 'dl-colon-highlight'} ) + codeMirror.markText({ line: lineNumber, ch: colonMatches.index + ddIndex }, { line: lineNumber, ch: colonMatches.index + colonMatches[0].length + ddIndex }, { className: 'dl-colon-highlight' }); } } } @@ -232,12 +232,12 @@ const Editor = createClass({ let startIndex = line.indexOf('^'); const superRegex = /\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^/gy; const subRegex = /\^\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^\^/gy; - + while (startIndex >= 0) { superRegex.lastIndex = subRegex.lastIndex = startIndex; let isSuper = false; - let match = subRegex.exec(line) || superRegex.exec(line); - if (match) { + const match = subRegex.exec(line) || superRegex.exec(line); + if(match) { isSuper = !subRegex.lastIndex; codeMirror.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: isSuper ? 'superscript' : 'subscript' }); } @@ -287,18 +287,18 @@ const Editor = createClass({ while (startIndex >= 0) { emojiRegex.lastIndex = startIndex; - let match = emojiRegex.exec(line); - if (match) { + const match = emojiRegex.exec(line); + if(match) { let tokens = Markdown.marked.lexer(match[0]); - tokens = tokens[0].tokens.filter(t => t.type == 'emoji') - if (!tokens.length) + tokens = tokens[0].tokens.filter((t)=>t.type == 'emoji'); + if(!tokens.length) return; - let startPos = { line: lineNumber, ch: match.index }; - let endPos = { line: lineNumber, ch: match.index + match[0].length }; + const startPos = { line: lineNumber, ch: match.index }; + const endPos = { line: lineNumber, ch: match.index + match[0].length }; // Iterate over conflicting marks and clear them - var marks = codeMirror.findMarks(startPos, endPos); + const marks = codeMirror.findMarks(startPos, endPos); marks.forEach(function(marker) { if(!marker.__isFold) marker.clear(); }); @@ -322,10 +322,10 @@ const Editor = createClass({ const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; - const checkIfScrollComplete = () => { + const checkIfScrollComplete = ()=>{ let scrollingTimeout; clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs - scrollingTimeout = setTimeout(() => { + scrollingTimeout = setTimeout(()=>{ isJumping = false; brewRenderer.removeEventListener('scroll', checkIfScrollComplete); }, 150); // If 150 ms pass without a brewRenderer scroll event, assume scrolling is done @@ -364,16 +364,16 @@ const Editor = createClass({ let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - - const checkIfScrollComplete = () => { + + const checkIfScrollComplete = ()=>{ let scrollingTimeout; clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs - scrollingTimeout = setTimeout(() => { + scrollingTimeout = setTimeout(()=>{ isJumping = false; this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete); }, 150); // If 150 ms pass without a scroll event, assume scrolling is done }; - + isJumping = true; checkIfScrollComplete(); this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete); From 5cc5eec6194016af92098c944ad3fdb984c17d64 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 16 Sep 2024 01:41:46 -0400 Subject: [PATCH 37/39] Lint toolbar and snippetbar --- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 6 +++--- client/homebrew/editor/snippetbar/snippetbar.jsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index d83fa78f9..73b48d778 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -56,7 +56,7 @@ const ToolBar = ({ onZoomChange, currentPage, onPageChange, totalPages })=>{ } else if(mode == 'fit'){ // find the page with the largest single dim (height or width) so that zoom can be adapted to fit it. - const minDimRatio = [...pages].reduce((minRatio, page) => Math.min(minRatio, iframeWidth / page.offsetWidth, iframeHeight / page.offsetHeight), Infinity); + const minDimRatio = [...pages].reduce((minRatio, page)=>Math.min(minRatio, iframeWidth / page.offsetWidth, iframeHeight / page.offsetHeight), Infinity); desiredZoom = minDimRatio * 100; } @@ -67,9 +67,9 @@ const ToolBar = ({ onZoomChange, currentPage, onPageChange, totalPages })=>{ return deltaZoom; }; - return ( + return (
- + {/*v=====----------------------< Zoom Controls >---------------------=====v*/}
; } diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx index a550ec578..bad1fbd57 100644 --- a/client/homebrew/pages/vaultPage/vaultPage.jsx +++ b/client/homebrew/pages/vaultPage/vaultPage.jsx @@ -330,7 +330,7 @@ const VaultPage = (props)=>{ if(error) { const errorText = ErrorIndex()[error.HBErrorCode.toString()] || ''; - + return (

Error: {errorText}

diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 01807db70..23ae5d321 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -15,12 +15,12 @@ const SplitPane = createClass({ getInitialState : function() { return { - currentDividerPos : null, - windowWidth : 0, - isDragging : false, - moveSource : false, - moveBrew : false, - showMoveArrows : true + currentDividerPos : null, + windowWidth : 0, + isDragging : false, + moveSource : false, + moveBrew : false, + showMoveArrows : true }; }, @@ -45,7 +45,7 @@ const SplitPane = createClass({ // This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts. const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true'; - this.setState({ liveScroll : loadLiveScroll }); + this.setState({ liveScroll: loadLiveScroll }); }, componentWillUnmount : function() { @@ -130,7 +130,7 @@ const SplitPane = createClass({
@@ -160,7 +160,7 @@ const SplitPane = createClass({ ...(this.props.showDividerButtons && { moveBrew : this.state.moveBrew, moveSource : this.state.moveSource, - liveScroll : this.state.liveScroll, + liveScroll : this.state.liveScroll, setMoveArrows : this.setMoveArrows, }), })}