From e1144c098e9963a0cd5964eb98fa7d5af31b88fb Mon Sep 17 00:00:00 2001 From: Caleb John Date: Sat, 8 Aug 2020 03:11:55 -0600 Subject: [PATCH] Desktop: Fixed scrolling issue when editing while searching in CodeMirror (#3593) Only scroll to search matchs when the user changes the search or explicitly changes the search index https://discourse.joplinapp.org/t/codemirror-feedback/10397 --- .../CodeMirror/utils/useEditorSearch.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts b/ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts index 4e0200d91..1ce275f46 100644 --- a/ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts +++ b/ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.ts @@ -6,6 +6,7 @@ export default function useEditorSearch(CodeMirror: any) { const [overlay, setOverlay] = useState(null); const [scrollbarMarks, setScrollbarMarks] = useState(null); const [previousKeywordValue, setPreviousKeywordValue] = useState(null); + const [previousIndex, setPreviousIndex] = useState(null); const [overlayTimeout, setOverlayTimeout] = useState(null); const overlayTimeoutRef = useRef(null); overlayTimeoutRef.current = overlayTimeout; @@ -49,12 +50,10 @@ export default function useEditorSearch(CodeMirror: any) { // Highlights the currently active found work // It's possible to get tricky with this fucntions and just use findNext/findPrev // but this is fast enough and works more naturally with the current search logic - function highlightSearch(cm: any, searchTerm: RegExp, index: number) { - const marks: any = []; - + function highlightSearch(cm: any, searchTerm: RegExp, index: number, scrollTo: boolean) { const cursor = cm.getSearchCursor(searchTerm); - let match = null; + let match: any = null; for (let j = 0; j < index + 1; j++) { if (!cursor.findNext()) { // If we run out of matches then just highlight the final match @@ -64,11 +63,11 @@ export default function useEditorSearch(CodeMirror: any) { } if (match) { - marks.push(cm.markText(match.from, match.to, { className: 'cm-search-marker-selected' })); - cm.scrollIntoView(match); + if (scrollTo) cm.scrollIntoView(match); + return cm.markText(match.from, match.to, { className: 'cm-search-marker-selected' }); } - return marks; + return null; } // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping @@ -98,7 +97,7 @@ export default function useEditorSearch(CodeMirror: any) { // HIGHLIGHT KEYWORDS // When doing a global search it's possible to have multiple keywords // This means we need to highlight each one - let marks: any = []; + const marks: any = []; for (let i = 0; i < keywords.length; i++) { const keyword = keywords[i]; @@ -106,10 +105,15 @@ export default function useEditorSearch(CodeMirror: any) { const searchTerm = getSearchTerm(keyword); - marks = marks.concat(highlightSearch(this, searchTerm, options.selectedIndex)); + // We only want to scroll the first keyword into view in the case of a multi keyword search + const scrollTo = i === 0 && (previousKeywordValue !== keyword.value || previousIndex !== options.selectedIndex); + + const match = highlightSearch(this, searchTerm, options.selectedIndex, scrollTo); + if (match) marks.push(match); } setMarkers(marks); + setPreviousIndex(options.selectedIndex); // SEARCHOVERLAY // We only want to highlight all matches when there is only 1 search term