mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-03-27 14:38:11 +00:00
fix brewjump functions
This commit is contained in:
@@ -76,12 +76,12 @@ const createHighlightPlugin = (renderer, tab)=>{
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
decos.push(Decoration.line({ class: `cm-${tok.type}` }).range(line.from));
|
decos.push(Decoration.line({ class: `cm-${tok.type}` }).range(line.from));
|
||||||
if(tok.type === 'pageLine' && tab === "brewText") {
|
if(tok.type === 'pageLine' && tab === 'brewText') {
|
||||||
pageCount++;
|
pageCount++;
|
||||||
line.from === 0 && pageCount--;
|
line.from === 0 && pageCount--;
|
||||||
decos.push(Decoration.widget({ widget: new countWidget(pageCount), side: 2 }).range(line.to));
|
decos.push(Decoration.widget({ widget: new countWidget(pageCount), side: 2 }).range(line.to));
|
||||||
}
|
}
|
||||||
if(tok.type === 'snippetLine' && tab === "brewSnippets") {
|
if(tok.type === 'snippetLine' && tab === 'brewSnippets') {
|
||||||
snippetCount++;
|
snippetCount++;
|
||||||
decos.push(Decoration.widget({ widget: new countWidget(snippetCount), side: 2 }).range(line.to));
|
decos.push(Decoration.widget({ widget: new countWidget(snippetCount), side: 2 }).range(line.to));
|
||||||
}
|
}
|
||||||
@@ -101,6 +101,8 @@ const CodeEditor = forwardRef(
|
|||||||
{
|
{
|
||||||
value = '',
|
value = '',
|
||||||
onChange = ()=>{},
|
onChange = ()=>{},
|
||||||
|
onCursorChange = ()=>{},
|
||||||
|
onViewChange = ()=>{},
|
||||||
language = '',
|
language = '',
|
||||||
tab = 'brewText',
|
tab = 'brewText',
|
||||||
editorTheme = 'default',
|
editorTheme = 'default',
|
||||||
@@ -121,6 +123,18 @@ const CodeEditor = forwardRef(
|
|||||||
if(update.docChanged) {
|
if(update.docChanged) {
|
||||||
onChange(update.state.doc.toString());
|
onChange(update.state.doc.toString());
|
||||||
}
|
}
|
||||||
|
if(update.selectionSet) {
|
||||||
|
const pos = update.state.selection.main.head;
|
||||||
|
const line = update.state.doc.lineAt(pos).number;
|
||||||
|
|
||||||
|
onCursorChange(line);
|
||||||
|
}
|
||||||
|
if(update.viewportChanged) {
|
||||||
|
const { from } = update.view.viewport;
|
||||||
|
const line = update.state.doc.lineAt(from).number;
|
||||||
|
|
||||||
|
onViewChange(line);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const highlightExtension = renderer === 'V3'
|
const highlightExtension = renderer === 'V3'
|
||||||
@@ -267,9 +281,29 @@ const CodeEditor = forwardRef(
|
|||||||
|
|
||||||
getCursorPosition : ()=>viewRef.current.state.selection.main.head,
|
getCursorPosition : ()=>viewRef.current.state.selection.main.head,
|
||||||
|
|
||||||
setCursorPosition : (pos)=>{
|
getScrollTop : ()=>viewRef.current.scrollDOM.scrollTop,
|
||||||
viewRef.current.dispatch({ selection: { anchor: pos } });
|
|
||||||
viewRef.current.focus();
|
scrollToY : (y)=>{
|
||||||
|
viewRef.current.scrollDOM.scrollTo({ top: y });
|
||||||
|
},
|
||||||
|
|
||||||
|
getLineTop : (lineNumber)=>{
|
||||||
|
const view = viewRef.current;
|
||||||
|
if(!view) return 0;
|
||||||
|
|
||||||
|
const line = view.state.doc.line(lineNumber);
|
||||||
|
return view.coordsAtPos(line.from)?.top ?? 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
setCursorToLine : (lineNumber)=>{
|
||||||
|
const view = viewRef.current;
|
||||||
|
const line = view.state.doc.line(lineNumber);
|
||||||
|
|
||||||
|
view.dispatch({
|
||||||
|
selection : { anchor: line.from }
|
||||||
|
});
|
||||||
|
|
||||||
|
view.focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
undo : ()=>undo(viewRef.current),
|
undo : ()=>undo(viewRef.current),
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ const Editor = createReactClass({
|
|||||||
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
|
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
|
||||||
document.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));
|
|
||||||
|
|
||||||
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
||||||
if(editorTheme) {
|
if(editorTheme) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -130,15 +127,15 @@ const Editor = createReactClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateCurrentCursorPage : function(cursor) {
|
updateCurrentCursorPage : function(lineNumber) {
|
||||||
const lines = this.props.brew.text.split('\n').slice(1, cursor.line + 1);
|
const lines = this.props.brew.text.split('\n').slice(0, lineNumber);
|
||||||
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\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);
|
this.props.onCursorPageChange(currentPage);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateCurrentViewPage : function(topScrollLine) {
|
updateCurrentViewPage : function(topLine) {
|
||||||
const lines = this.props.brew.text.split('\n').slice(1, topScrollLine + 1);
|
const lines = this.props.brew.text.split('\n').slice(0, topLine);
|
||||||
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\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);
|
this.props.onViewPageChange(currentPage);
|
||||||
@@ -205,51 +202,41 @@ const Editor = createReactClass({
|
|||||||
|
|
||||||
const textSplit = this.props.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
const textSplit = this.props.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
||||||
const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit);
|
const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit);
|
||||||
const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1;
|
const targetLine = textString.match('\n') ? textString.split('\n').length : 1;
|
||||||
|
|
||||||
let currentY = this.codeEditor.current.codeMirror?.getScrollInfo().top;
|
const editor = this.codeEditor.current;
|
||||||
let targetY = this.codeEditor.current.codeMirror?.heightAtLine(targetLine, 'local', true);
|
|
||||||
|
let currentY = editor.getScrollTop();
|
||||||
|
const targetY = editor.getLineTop(targetLine);
|
||||||
|
|
||||||
let scrollingTimeout;
|
let scrollingTimeout;
|
||||||
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
|
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
|
||||||
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
|
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
|
||||||
scrollingTimeout = setTimeout(()=>{
|
scrollingTimeout = setTimeout(()=>{
|
||||||
isJumping = false;
|
isJumping = false;
|
||||||
this.codeEditor.current.codeMirror?.off('scroll', checkIfScrollComplete);
|
|
||||||
}, 150); // If 150 ms pass without a scroll event, assume scrolling is done
|
}, 150); // If 150 ms pass without a scroll event, assume scrolling is done
|
||||||
};
|
};
|
||||||
|
|
||||||
isJumping = true;
|
isJumping = true;
|
||||||
checkIfScrollComplete();
|
checkIfScrollComplete();
|
||||||
if(this.codeEditor.current?.codeMirror) {
|
|
||||||
this.codeEditor.current.codeMirror?.on('scroll', checkIfScrollComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(smooth) {
|
if(smooth) {
|
||||||
//Scroll 1/10 of the way every 10ms until 1px off.
|
//Scroll 1/10 of the way every 10ms until 1px off.
|
||||||
const incrementalScroll = setInterval(()=>{
|
const incrementalScroll = setInterval(()=>{
|
||||||
currentY += (targetY - currentY) / 10;
|
currentY += (targetY - currentY) / 10;
|
||||||
this.codeEditor.current.codeMirror?.scrollTo(null, currentY);
|
editor.scrollToY(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);
|
|
||||||
|
|
||||||
// End when close enough
|
|
||||||
if(Math.abs(targetY - currentY) < 1) {
|
if(Math.abs(targetY - currentY) < 1) {
|
||||||
this.codeEditor.current.codeMirror?.scrollTo(null, targetY); // Scroll any remaining difference
|
editor.scrollToY(targetY);
|
||||||
this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 });
|
editor.setCursorToLine(targetLine);
|
||||||
this.codeEditor.current.codeMirror?.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
|
|
||||||
clearInterval(incrementalScroll);
|
clearInterval(incrementalScroll);
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
} else {
|
} else {
|
||||||
this.codeEditor.current.codeMirror?.scrollTo(null, targetY); // Scroll any remaining difference
|
editor.scrollToY(targetY);
|
||||||
this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 });
|
editor.setCursorToLine(targetLine);
|
||||||
this.codeEditor.current.codeMirror?.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//Called when there are changes to the editor's dimensions
|
//Called when there are changes to the editor's dimensions
|
||||||
update : function(){},
|
update : function(){},
|
||||||
|
|
||||||
@@ -275,6 +262,8 @@ const Editor = createReactClass({
|
|||||||
view={this.state.view}
|
view={this.state.view}
|
||||||
value={this.props.brew.text}
|
value={this.props.brew.text}
|
||||||
onChange={this.props.onBrewChange('text')}
|
onChange={this.props.onBrewChange('text')}
|
||||||
|
onCursorChange={(line)=>this.updateCurrentCursorPage(line)}
|
||||||
|
onViewChange={(line)=>this.updateCurrentViewPage(line)}
|
||||||
editorTheme={this.state.editorTheme}
|
editorTheme={this.state.editorTheme}
|
||||||
renderer={this.props.brew.renderer}
|
renderer={this.props.brew.renderer}
|
||||||
rerenderParent={this.rerenderParent}
|
rerenderParent={this.rerenderParent}
|
||||||
|
|||||||
Reference in New Issue
Block a user