From e94808c85ab5568ec5de5e5746f7c79c70dea528 Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Fri, 29 Jan 2021 13:33:57 +0200 Subject: [PATCH] move find next/previous --- .../ExandedFindAndReplaceComponent.js | 22 ++- .../findAndReplace/FindAndReplaceComponent.js | 176 +++++++++++++++++- .../findAndReplace/FindComponent.js | 175 +---------------- 3 files changed, 192 insertions(+), 181 deletions(-) diff --git a/wax-prosemirror-components/src/components/findAndReplace/ExandedFindAndReplaceComponent.js b/wax-prosemirror-components/src/components/findAndReplace/ExandedFindAndReplaceComponent.js index 37702d596..492164d28 100644 --- a/wax-prosemirror-components/src/components/findAndReplace/ExandedFindAndReplaceComponent.js +++ b/wax-prosemirror-components/src/components/findAndReplace/ExandedFindAndReplaceComponent.js @@ -139,6 +139,8 @@ const PreviousNextButton = styled.span` const ExandedFindAndReplaceComponent = ({ close, + findNextMatch, + findPreviousMatch, matchCaseOption, nonExpandedText, }) => { @@ -214,14 +216,6 @@ const ExandedFindAndReplaceComponent = ({ close(); }; - const findNext = () => { - // console.log('next'); - }; - - const findPrevious = () => { - // console.log('previous'); - }; - return ( <Wrapper> <TitleContainer> @@ -260,10 +254,18 @@ const ExandedFindAndReplaceComponent = ({ <ButtonReplace onClick={replace}>Replace</ButtonReplace> <ButtonReplaceAll onClick={replaceAll}>Replace All</ButtonReplaceAll> <PreviousNextContainer> - <PreviousNextButton onClick={findPrevious} role="button" tabIndex="0"> + <PreviousNextButton + onClick={() => findPreviousMatch(searchValue, matchCaseOption)} + role="button" + tabIndex="0" + > <StyledIcon name="navigatePrevious" /> </PreviousNextButton> - <PreviousNextButton onClick={findNext} role="button" tabIndex="0"> + <PreviousNextButton + onClick={() => findNextMatch(searchValue, matchCaseOption)} + role="button" + tabIndex="0" + > <StyledIcon name="navigateNext" /> </PreviousNextButton> </PreviousNextContainer> diff --git a/wax-prosemirror-components/src/components/findAndReplace/FindAndReplaceComponent.js b/wax-prosemirror-components/src/components/findAndReplace/FindAndReplaceComponent.js index 6f85d283c..25cb906d0 100644 --- a/wax-prosemirror-components/src/components/findAndReplace/FindAndReplaceComponent.js +++ b/wax-prosemirror-components/src/components/findAndReplace/FindAndReplaceComponent.js @@ -1,9 +1,16 @@ /* eslint react/prop-types: 0 */ -import React, { useState } from 'react'; +import React, { useState, useContext, useEffect } from 'react'; +import { TextSelection } from 'prosemirror-state'; +import { WaxContext } from 'wax-prosemirror-core'; import FindComponent from './FindComponent'; import ExandedFindAndReplaceComponent from './ExandedFindAndReplaceComponent'; +import helpers from './helpers'; + +let lastActiveViewId; +let lastSelection; const FindAndReplaceComponent = ({ close }) => { + const { view, activeViewId } = useContext(WaxContext); const [isExpanded, setExpanded] = useState(false); const [nonExpandedText, setNonExpandedText] = useState(''); const [matchCaseOption, setMatchCaseOption] = useState(false); @@ -19,13 +26,173 @@ const FindAndReplaceComponent = ({ close }) => { setMatchCaseOption(matchCase); }; - const FindNextMatch = nextMatch => { - return nextMatch; + useEffect(() => { + if (view[activeViewId].state.selection.from !== 0) { + lastSelection = view[activeViewId].state.selection; + lastActiveViewId = activeViewId; + } + }, []); + + const nextInNotes = (notesIds, results, findViewWithMatches) => { + for (let i = 0; i < notesIds.length; i += 1) { + if (results[notesIds[i]].length > 0 && notesIds[i] !== lastActiveViewId) { + helpers.clearViewSelection(view, lastActiveViewId); + helpers.moveToMatch(view, notesIds[i], results, 0); + lastActiveViewId = findViewWithMatches; + lastSelection = view[lastActiveViewId].state.selection; + + break; + } + } + }; + + const findNextMatch = (searchValue, matchCaseSearch) => { + lastActiveViewId = activeViewId; + lastSelection = view[activeViewId].state.selection; + const results = helpers.getAllResultsByView( + view, + searchValue, + matchCaseSearch, + ); + const resultsFrom = helpers.getResultsFrom(results); + const notesIds = helpers.getNotesIds(view.main); + const findViewWithMatches = helpers.findViewWithMatches( + results, + view, + lastActiveViewId, + ); + /* if no matches are found on focused view */ + if (!resultsFrom[lastActiveViewId]) { + view[findViewWithMatches].dispatch( + view[findViewWithMatches].state.tr.setSelection( + new TextSelection(view[findViewWithMatches].state.tr.doc.resolve(1)), + ), + ); + view[findViewWithMatches].focus(); + lastActiveViewId = findViewWithMatches; + lastSelection = view[lastActiveViewId].state.selection; + } + + const found = helpers.getClosestMatch( + lastSelection.from, + resultsFrom[lastActiveViewId], + ); + + const position = resultsFrom[lastActiveViewId].indexOf(found); + /* User selection lesser than found */ + if (lastSelection.from < found) { + helpers.moveToMatch(view, lastActiveViewId, results, position); + } + /* User selection greater than found move to next if not already at the end of results for the view */ + if ( + lastSelection.from >= found && + position < resultsFrom[lastActiveViewId].length - 1 + ) { + helpers.moveToMatch(view, lastActiveViewId, results, position + 1); + } + + /* Last result of the specific view. Move to next view */ + if ( + (lastSelection.from === found && + position === resultsFrom[lastActiveViewId].length - 1) || + (lastSelection.from >= found && + position === resultsFrom[lastActiveViewId].length - 1) + ) { + /* End of results in notes move to main if results exist */ + if ( + notesIds.indexOf(lastActiveViewId) === notesIds.length - 1 && + results.main.length > 0 + ) { + setTimeout(() => { + lastActiveViewId = findViewWithMatches; + lastSelection = view[lastActiveViewId].state.selection; + }, 50); + helpers.moveToMatch(view, 'main', results, 0); + helpers.clearViewSelection(view, lastActiveViewId); + } else { + nextInNotes(notesIds, results, findViewWithMatches); + } + } + }; + + const findPreviousMatch = (searchValue, matchCaseSearch) => { + lastActiveViewId = activeViewId; + lastSelection = view[activeViewId].state.selection; + const results = helpers.getAllResultsByView( + view, + searchValue, + matchCaseSearch, + ); + const resultsFrom = helpers.getResultsFrom(results); + const notesIds = helpers.getNotesIds(view.main); + + const found = helpers.getClosestMatch( + lastSelection.from, + resultsFrom[lastActiveViewId], + false, + ); + const position = resultsFrom[lastActiveViewId].indexOf(found); + + /* User selection lesser than found */ + if (lastSelection.from > found) { + helpers.moveToMatch(view, lastActiveViewId, results, position); + } + + if (lastSelection.from <= found && position !== 0) { + helpers.moveToMatch(view, lastActiveViewId, results, position - 1); + } + + if (lastSelection.from === found && position === 0) { + if (lastActiveViewId === 'main') { + for (let i = notesIds.length - 1; i >= 0; i -= 1) { + if ( + results[notesIds[i]].length > 0 && + notesIds[i] !== lastActiveViewId + ) { + helpers.moveToMatch( + view, + notesIds[i], + results, + results[notesIds[i]].length - 1, + ); + lastSelection = view[activeViewId].state.selection; + lastActiveViewId = activeViewId; + helpers.clearViewSelection(view, lastActiveViewId); + break; + } + } + } else if ( + notesIds[notesIds.length - 1] === activeViewId && + notesIds.length > 1 + ) { + for (let i = notesIds.length - 1; i >= 0; i -= 1) { + if ( + results[notesIds[i]].length > 0 && + notesIds[i] !== lastActiveViewId + ) { + helpers.moveToMatch( + view, + notesIds[i], + results, + results[notesIds[i]].length - 1, + ); + lastSelection = view[activeViewId].state.selection; + lastActiveViewId = activeViewId; + helpers.clearViewSelection(view, lastActiveViewId); + break; + } else { + console.log('go to main', lastActiveViewId); + } + } + } + } }; return isExpanded ? ( <ExandedFindAndReplaceComponent close={close} + findNextMatch={findNextMatch} + findPreviousMatch={findPreviousMatch} matchCaseOption={matchCaseOption} nonExpandedText={nonExpandedText} /> @@ -33,9 +200,10 @@ const FindAndReplaceComponent = ({ close }) => { <FindComponent close={close} expand={expand} + findNextMatch={findNextMatch} + findPreviousMatch={findPreviousMatch} setMatchCaseValue={getMatchCaseOption} setPreviousSearcValue={getNonExpandedText} - FindNextMatch={FindNextMatch} /> ); }; diff --git a/wax-prosemirror-components/src/components/findAndReplace/FindComponent.js b/wax-prosemirror-components/src/components/findAndReplace/FindComponent.js index fe5146619..4b256c2c4 100644 --- a/wax-prosemirror-components/src/components/findAndReplace/FindComponent.js +++ b/wax-prosemirror-components/src/components/findAndReplace/FindComponent.js @@ -7,7 +7,6 @@ import React, { useCallback, useEffect, } from 'react'; -import { TextSelection } from 'prosemirror-state'; import { debounce, each, eachRight } from 'lodash'; import styled from 'styled-components'; import { grid } from '@pubsweet/ui-toolkit'; @@ -94,14 +93,13 @@ const Svg = styled.svg.attrs(() => ({ width: 24px; `; -let lastActiveViewId; -let lastSelection; const FindComponent = ({ close, expand, setPreviousSearcValue, setMatchCaseValue, - FindNextMatch, + findNextMatch, + findPreviousMatch, }) => { const { app, view, activeViewId } = useContext(WaxContext); const searchRef = useRef(null); @@ -128,11 +126,6 @@ const FindComponent = ({ }; useEffect(() => { - if (view[activeViewId].state.selection.from !== 0) { - lastSelection = view[activeViewId].state.selection; - lastActiveViewId = activeViewId; - } - delayedSearch(); if (isFirstRun) { setTimeout(() => { @@ -188,162 +181,6 @@ const FindComponent = ({ searchRef.current.focus(); }; - const nextInNotes = (notesIds, results, findViewWithMatches) => { - for (let i = 0; i < notesIds.length; i += 1) { - if (results[notesIds[i]].length > 0 && notesIds[i] !== lastActiveViewId) { - helpers.clearViewSelection(view, lastActiveViewId); - helpers.moveToMatch(view, notesIds[i], results, 0); - lastActiveViewId = findViewWithMatches; - lastSelection = view[lastActiveViewId].state.selection; - - break; - } - } - }; - - // eslint-disable-next-line consistent-return - const findNext = () => { - lastActiveViewId = activeViewId; - lastSelection = view[activeViewId].state.selection; - const results = helpers.getAllResultsByView( - view, - searchValue, - matchCaseSearch, - ); - const resultsFrom = helpers.getResultsFrom(results); - const notesIds = helpers.getNotesIds(view.main); - const findViewWithMatches = helpers.findViewWithMatches( - results, - view, - lastActiveViewId, - ); - /* if no matches are found on focused view */ - if (!resultsFrom[lastActiveViewId]) { - view[findViewWithMatches].dispatch( - view[findViewWithMatches].state.tr.setSelection( - new TextSelection(view[findViewWithMatches].state.tr.doc.resolve(1)), - ), - ); - view[findViewWithMatches].focus(); - lastActiveViewId = findViewWithMatches; - lastSelection = view[lastActiveViewId].state.selection; - } - - const found = helpers.getClosestMatch( - lastSelection.from, - resultsFrom[lastActiveViewId], - ); - - const position = resultsFrom[lastActiveViewId].indexOf(found); - /* User selection lesser than found */ - if (lastSelection.from < found) { - helpers.moveToMatch(view, lastActiveViewId, results, position); - } - /* User selection greater than found move to next if not already at the end of results for the view */ - if ( - lastSelection.from >= found && - position < resultsFrom[lastActiveViewId].length - 1 - ) { - helpers.moveToMatch(view, lastActiveViewId, results, position + 1); - } - - /* Last result of the specific view. Move to next view */ - if ( - (lastSelection.from === found && - position === resultsFrom[lastActiveViewId].length - 1) || - (lastSelection.from >= found && - position === resultsFrom[lastActiveViewId].length - 1) - ) { - /* End of results in notes move to main if results exist */ - if ( - notesIds.indexOf(lastActiveViewId) === notesIds.length - 1 && - results.main.length > 0 - ) { - setTimeout(() => { - lastActiveViewId = findViewWithMatches; - lastSelection = view[lastActiveViewId].state.selection; - }, 50); - helpers.moveToMatch(view, 'main', results, 0); - helpers.clearViewSelection(view, lastActiveViewId); - } else { - nextInNotes(notesIds, results, findViewWithMatches); - } - } - }; - - const findPrevious = () => { - lastActiveViewId = activeViewId; - lastSelection = view[activeViewId].state.selection; - const results = helpers.getAllResultsByView( - view, - searchValue, - matchCaseSearch, - ); - const resultsFrom = helpers.getResultsFrom(results); - const notesIds = helpers.getNotesIds(view.main); - - const found = helpers.getClosestMatch( - lastSelection.from, - resultsFrom[lastActiveViewId], - false, - ); - const position = resultsFrom[lastActiveViewId].indexOf(found); - - /* User selection lesser than found */ - if (lastSelection.from > found) { - helpers.moveToMatch(view, lastActiveViewId, results, position); - } - - if (lastSelection.from <= found && position !== 0) { - helpers.moveToMatch(view, lastActiveViewId, results, position - 1); - } - - if (lastSelection.from === found && position === 0) { - if (lastActiveViewId === 'main') { - for (let i = notesIds.length - 1; i >= 0; i -= 1) { - if ( - results[notesIds[i]].length > 0 && - notesIds[i] !== lastActiveViewId - ) { - helpers.moveToMatch( - view, - notesIds[i], - results, - results[notesIds[i]].length - 1, - ); - lastSelection = view[activeViewId].state.selection; - lastActiveViewId = activeViewId; - helpers.clearViewSelection(view, lastActiveViewId); - break; - } - } - } else if ( - notesIds[notesIds.length - 1] === activeViewId && - notesIds.length > 1 - ) { - for (let i = notesIds.length - 1; i >= 0; i -= 1) { - if ( - results[notesIds[i]].length > 0 && - notesIds[i] !== lastActiveViewId - ) { - helpers.moveToMatch( - view, - notesIds[i], - results, - results[notesIds[i]].length - 1, - ); - lastSelection = view[activeViewId].state.selection; - lastActiveViewId = activeViewId; - helpers.clearViewSelection(view, lastActiveViewId); - break; - } else { - console.log('go to main', lastActiveViewId); - } - } - } - } - }; - return ( <Wrapper> <SingleRow> @@ -363,11 +200,15 @@ const FindComponent = ({ <path d="M2.5,4v3h5v12h3V7h5V4H2.5z M21.5,9h-9v3h3v7h3v-7h3V9z" /> </Svg> </IconWrapper> - <IconWrapper onClick={findPrevious} role="button" tabIndex="0"> + <IconWrapper + onClick={() => findPreviousMatch(searchValue, matchCaseSearch)} + role="button" + tabIndex="0" + > <StyledIcon name="navigatePrevious" /> </IconWrapper> <IconWrapper - onClick={() => FindNextMatch(findNext())} + onClick={() => findNextMatch(searchValue, matchCaseSearch)} role="button" tabIndex="0" > -- GitLab