From 926c982097ace4c7015decdf949afa3c86914d8d Mon Sep 17 00:00:00 2001 From: ammarahm-ed Date: Sun, 19 Dec 2021 00:31:26 +0500 Subject: [PATCH] add searchreplace in toolbar --- .../src/views/Editor/tiny/toolbar/index.js | 97 +++--- .../Editor/tiny/toolbar/searchreplace.js | 276 ++++++++++++++++++ 2 files changed, 329 insertions(+), 44 deletions(-) create mode 100644 apps/mobile/src/views/Editor/tiny/toolbar/searchreplace.js diff --git a/apps/mobile/src/views/Editor/tiny/toolbar/index.js b/apps/mobile/src/views/Editor/tiny/toolbar/index.js index 47cbc761b..c23670bce 100644 --- a/apps/mobile/src/views/Editor/tiny/toolbar/index.js +++ b/apps/mobile/src/views/Editor/tiny/toolbar/index.js @@ -1,19 +1,22 @@ -import React, {useEffect} from 'react'; -import {Platform} from 'react-native'; -import {ScrollView, View} from 'react-native'; -import {useTracked} from '../../../../provider'; -import {normalize} from '../../../../utils/SizeUtils'; +import React, { useEffect } from 'react'; +import { ScrollView, View } from 'react-native'; +import { useTracked } from '../../../../provider'; +import { useEditorStore } from '../../../../provider/stores'; +import { normalize } from '../../../../utils/SizeUtils'; import HistoryComponent from '../../HistoryComponent'; -import {TOOLBAR_CONFIG} from './config'; -import {properties, toolbarRef} from './constants'; +import { TOOLBAR_CONFIG } from './config'; +import { properties, toolbarRef } from './constants'; import ToolbarGroup from './group'; +import SearcReplace from './searchreplace'; import Tooltip from './tooltip'; + const EditorToolbar = React.memo( () => { const [state] = useTracked(); const {colors} = state; const config = TOOLBAR_CONFIG; + const searchReplace = useEditorStore(state => state.searchReplace); useEffect(() => { properties.selection = {}; @@ -28,44 +31,50 @@ const EditorToolbar = React.memo( style={{ width: '100%', minHeight: normalize(50), - position: 'relative', + position: 'relative' }}> - - - - {config.map((item, index) => - typeof item !== 'string' ? ( - - ) : ( - - ) - )} - + {searchReplace ? ( + + ) : ( + <> + + + + {config.map((item, index) => + typeof item !== 'string' ? ( + + ) : ( + + ) + )} + + + )} ); diff --git a/apps/mobile/src/views/Editor/tiny/toolbar/searchreplace.js b/apps/mobile/src/views/Editor/tiny/toolbar/searchreplace.js new file mode 100644 index 000000000..28717235b --- /dev/null +++ b/apps/mobile/src/views/Editor/tiny/toolbar/searchreplace.js @@ -0,0 +1,276 @@ +import React, {useEffect, useRef, useState} from 'react'; +import {View} from 'react-native'; +import {Button} from '../../../../components/Button'; +import Input from '../../../../components/Input'; +import {useTracked} from '../../../../provider'; +import {useSettingStore} from '../../../../provider/stores'; +import {showTooltip, TOOLTIP_POSITIONS} from '../../../../utils'; +import {SIZE} from '../../../../utils/SizeUtils'; +import {EditorWebView} from '../../Functions'; +import tiny from '../tiny'; +import {endSearch} from './commands'; + +const SearcReplace = () => { + const [state] = useTracked(); + const {colors} = state; + const [focusType, setFocusType] = useState(0); + const [enableReplace, setEnableReplace] = useState(false); + const [menu, setMenu] = useState(false); + const deviceMode = useSettingStore(state => state.deviceMode); + const findRef = useRef(); + const [config, setConfig] = useState({ + matchCase: false, + matchWholeWord: false + }); + const values = useRef({ + find: null, + replace: null + }); + + useEffect(() => { + setTimeout(() => { + findRef.current?.focus(); + }, 300); + }, []); + + function find() { + if (!values.current?.find) return; + tiny.call( + EditorWebView, + `tinymce.activeEditor.plugins.searchreplace.find("${values.current?.find}",${config.matchCase},${config.matchWholeWord})` + ); + } + + function replace(all = false) { + if (!values.current?.replace) return; + tiny.call( + EditorWebView, + `tinymce.activeEditor.plugins.searchreplace.replace("${ + values.current?.replace + }",true${all ? ',true' : ''})` + ); + } + + function next() { + tiny.call( + EditorWebView, + `tinymce.activeEditor.plugins.searchreplace.next()` + ); + } + + function prev() { + tiny.call( + EditorWebView, + `tinymce.activeEditor.plugins.searchreplace.prev()` + ); + } + + function done() { + endSearch(); + } + + function toggleMatchCase() { + setConfig(c => { + c.matchCase = !c.matchCase; + return {...c}; + }); + } + + function toggleMatchWholeWord() { + setConfig(c => { + c.matchWholeWord = !c.matchWholeWord; + return {...c}; + }); + } + + const menuButtons = [ + { + icon: 'chevron-left', + type: 'gray', + press: () => setMenu(false), + fullname: 'Go back' + }, + { + icon: 'format-letter-case', + type: 'gray', + press: toggleMatchCase, + on: config.matchCase, + fullname: 'Match case' + }, + { + icon: 'format-letter-matches', + type: 'gray', + press: toggleMatchWholeWord, + on: config.matchWholeWord, + fullname: 'Match whole word' + } + ]; + + const searchButtons = menu + ? menuButtons + : [ + { + icon: 'arrow-up', + type: 'gray', + press: prev, + fullname: 'Previous' + }, + { + icon: 'arrow-down', + type: 'gray', + press: next, + fullname: 'Next' + }, + { + icon: 'close', + type: 'gray', + press: done, + fullname: 'End search' + }, + { + icon: 'dots-vertical', + type: 'gray', + press: () => setMenu(true), + fullname: 'Show options' + } + ]; + + const replaceButtons = [ + { + text: 'Replace', + type: 'grayBg', + press: replace + }, + { + text: 'Replace all', + type: 'gray', + press: () => replace(true) + } + ]; + + return ( + +