0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-03-27 12:28:11 +00:00

fix brewjump functions

This commit is contained in:
Víctor Losada Hernández
2026-03-27 11:59:56 +01:00
parent 55d93a0e5f
commit 9edb0e2fc6
2 changed files with 55 additions and 32 deletions

View File

@@ -76,12 +76,12 @@ const createHighlightPlugin = (renderer, tab)=>{
} else {
decos.push(Decoration.line({ class: `cm-${tok.type}` }).range(line.from));
if(tok.type === 'pageLine' && tab === "brewText") {
if(tok.type === 'pageLine' && tab === 'brewText') {
pageCount++;
line.from === 0 && pageCount--;
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++;
decos.push(Decoration.widget({ widget: new countWidget(snippetCount), side: 2 }).range(line.to));
}
@@ -101,6 +101,8 @@ const CodeEditor = forwardRef(
{
value = '',
onChange = ()=>{},
onCursorChange = ()=>{},
onViewChange = ()=>{},
language = '',
tab = 'brewText',
editorTheme = 'default',
@@ -121,6 +123,18 @@ const CodeEditor = forwardRef(
if(update.docChanged) {
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'
@@ -267,9 +281,29 @@ const CodeEditor = forwardRef(
getCursorPosition : ()=>viewRef.current.state.selection.main.head,
setCursorPosition : (pos)=>{
viewRef.current.dispatch({ selection: { anchor: pos } });
viewRef.current.focus();
getScrollTop : ()=>viewRef.current.scrollDOM.scrollTop,
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),

View File

@@ -75,9 +75,6 @@ const Editor = createReactClass({
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));
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
if(editorTheme) {
this.setState({
@@ -130,15 +127,15 @@ const Editor = createReactClass({
}
},
updateCurrentCursorPage : function(cursor) {
const lines = this.props.brew.text.split('\n').slice(1, cursor.line + 1);
updateCurrentCursorPage : function(lineNumber) {
const lines = this.props.brew.text.split('\n').slice(0, lineNumber);
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
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(1, topScrollLine + 1);
updateCurrentViewPage : function(topLine) {
const lines = this.props.brew.text.split('\n').slice(0, topLine);
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
this.props.onViewPageChange(currentPage);
@@ -205,51 +202,41 @@ const Editor = createReactClass({
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 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;
let targetY = this.codeEditor.current.codeMirror?.heightAtLine(targetLine, 'local', true);
const editor = this.codeEditor.current;
let currentY = editor.getScrollTop();
const targetY = editor.getLineTop(targetLine);
let scrollingTimeout;
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
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
};
isJumping = true;
checkIfScrollComplete();
if(this.codeEditor.current?.codeMirror) {
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);
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) {
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');
editor.scrollToY(targetY);
editor.setCursorToLine(targetLine);
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');
editor.scrollToY(targetY);
editor.setCursorToLine(targetLine);
}
},
//Called when there are changes to the editor's dimensions
update : function(){},
@@ -275,6 +262,8 @@ const Editor = createReactClass({
view={this.state.view}
value={this.props.brew.text}
onChange={this.props.onBrewChange('text')}
onCursorChange={(line)=>this.updateCurrentCursorPage(line)}
onViewChange={(line)=>this.updateCurrentViewPage(line)}
editorTheme={this.state.editorTheme}
renderer={this.props.brew.renderer}
rerenderParent={this.rerenderParent}