From 0ade541501b4df0ab5a866c38d881e9bcc69873d Mon Sep 17 00:00:00 2001 From: David Ralph Date: Sat, 15 Jun 2024 12:05:13 +0100 Subject: [PATCH] refactor: entirely reorganise search widget --- src/features/search/Search.jsx | 132 +++--------------- .../search/components/dropdown/Dropdown.jsx | 79 +++++++++++ .../search/components/dropdown/Icon.jsx | 50 +++++++ .../search/components/dropdown/index.jsx | 1 + 4 files changed, 149 insertions(+), 113 deletions(-) create mode 100644 src/features/search/components/dropdown/Dropdown.jsx create mode 100644 src/features/search/components/dropdown/Icon.jsx create mode 100644 src/features/search/components/dropdown/index.jsx diff --git a/src/features/search/Search.jsx b/src/features/search/Search.jsx index 34c1af20..d877f38c 100644 --- a/src/features/search/Search.jsx +++ b/src/features/search/Search.jsx @@ -1,12 +1,14 @@ import variables from 'config/variables'; + import { memo, createRef, useEffect, useState } from 'react'; import { useDebouncedCallback } from 'use-debounce'; -import { MdSearch, MdMic, MdScreenSearchDesktop } from 'react-icons/md'; -import { BsGoogle } from 'react-icons/bs'; -import { SiDuckduckgo, SiMicrosoftbing, SiBaidu, SiNaver } from 'react-icons/si'; -import { FaYandex, FaYahoo } from 'react-icons/fa'; + +import { MdSearch, MdMic } from 'react-icons/md'; + import { Tooltip } from 'components/Elements'; import { Autocomplete as AutocompleteInput } from './components/autocomplete'; +import Icon from './components/dropdown/Icon'; +import Dropdown from './components/dropdown/Dropdown'; import EventBus from 'utils/eventbus'; @@ -20,11 +22,12 @@ function Search() { const [query, setQuery] = useState(''); const [microphone, setMicrophone] = useState(null); const [suggestions, setSuggestions] = useState([]); + const [currentSearch, setCurrentSearch] = useState(''); const [searchDropdown, setSearchDropdown] = useState(false); + const [classList] = useState( localStorage.getItem('widgetStyle') === 'legacy' ? 'searchIcons old' : 'searchIcons', ); - const [currentSearch, setCurrentSearch] = useState(''); useEffect(() => { EventBus.on('refresh', (data) => { @@ -46,10 +49,6 @@ function Search() { let micIcon = createRef(); - const customText = variables - .getMessage('modals.main.settings.sections.search.custom') - .split(' ')[0]; - function init() { let _url; let _query = 'q'; @@ -141,87 +140,11 @@ function Search() { const getSuggestionsDebounced = useDebouncedCallback(getSuggestions, 100); - /** - * If the user selects a search engine from the dropdown menu, the function will set the state of the - * search engine to the selected search engine. - * @param {string} name - The name of the search engine - * @param {boolean} custom - If the search engine is custom - */ - function setSearch(name, custom) { - let _url; - let _query = 'q'; - const info = searchEngines.find((i) => i.name === name); - - if (info !== undefined) { - _url = info.url; - if (info.query) { - _query = info.query; - } - } - - if (custom) { - const customSetting = localStorage.getItem('customSearchEngine'); - if (customSetting !== null) { - _url = customSetting; - } else { - _url = url; - } - } else { - localStorage.setItem('searchEngine', info.settingsName); - } - - setURL(_url); - setQuery(_query); - setCurrentSearch(name); - setSearchDropdown(false); - } - - /** - * Gets the icon for the search engine dropdown. - * @param {string} name - The name of the search engine. - * @returns A React component. - */ - function getSearchDropdownicon(name) { - switch (name) { - case 'Google': - return ; - case 'DuckDuckGo': - return ; - case 'Bing': - return ; - case 'Yahoo': - case 'Yahoo! JAPAN': - return ; - case 'Яндекс': - return ; - case '百度': - return ; - case 'NAVER': - return ; - default: - return ; - } - } - return (
- {localStorage.getItem('searchDropdown') === 'true' ? ( - - - - ) : ( - '' - )} + @@ -246,33 +169,16 @@ function Search() {
- {localStorage.getItem('searchDropdown') === 'true' && searchDropdown === true && ( -
- {searchEngines.map(({ name }, key) => { - return ( - setSearch(name)} - key={key} - > - {name} - - ); - })} - setSearch(customText, 'custom')} - > - {customText} - -
- )} +
); diff --git a/src/features/search/components/dropdown/Dropdown.jsx b/src/features/search/components/dropdown/Dropdown.jsx new file mode 100644 index 00000000..181038c2 --- /dev/null +++ b/src/features/search/components/dropdown/Dropdown.jsx @@ -0,0 +1,79 @@ +import variables from 'config/variables'; + +function Dropdown({ + url, + setURL, + setQuery, + setCurrentSearch, + currentSearch, + searchDropdown, + setSearchDropdown, + searchEngines +}) { + const customText = variables + .getMessage('modals.main.settings.sections.search.custom') + .split(' ')[0]; + + function setSearch(name, custom) { + let _url; + let _query = 'q'; + const info = searchEngines.find((i) => i.name === name); + + if (info !== undefined) { + _url = info.url; + if (info.query) { + _query = info.query; + } + } + + if (custom) { + const customSetting = localStorage.getItem('customSearchEngine'); + if (customSetting !== null) { + _url = customSetting; + } else { + _url = url; + } + } else { + localStorage.setItem('searchEngine', info.settingsName); + } + + setURL(_url); + setQuery(_query); + setCurrentSearch(name); + setSearchDropdown(false); + } + + const dropdownEnabled = localStorage.getItem('searchDropdown') === 'true'; + + if (!dropdownEnabled || !searchDropdown) { + return null; + } + + return ( +
+ {searchEngines.map(({ name }, key) => { + return ( + setSearch(name)} + key={key} + > + {name} + + ); + })} + setSearch(customText, 'custom')} + > + {customText} + +
+ ); +} + +export { Dropdown as default, Dropdown }; diff --git a/src/features/search/components/dropdown/Icon.jsx b/src/features/search/components/dropdown/Icon.jsx new file mode 100644 index 00000000..0027ec95 --- /dev/null +++ b/src/features/search/components/dropdown/Icon.jsx @@ -0,0 +1,50 @@ +import variables from 'config/variables'; +import { MdScreenSearchDesktop } from 'react-icons/md'; +import { BsGoogle } from 'react-icons/bs'; +import { SiDuckduckgo, SiMicrosoftbing, SiBaidu, SiNaver } from 'react-icons/si'; +import { FaYandex, FaYahoo } from 'react-icons/fa'; +import { Tooltip } from 'components/Elements'; + +function Icon({ currentSearch, searchDropdown, setSearchDropdown }) { + function getSearchDropdownicon(name) { + switch (name) { + case 'Google': + return ; + case 'DuckDuckGo': + return ; + case 'Bing': + return ; + case 'Yahoo': + case 'Yahoo! JAPAN': + return ; + case 'Яндекс': + return ; + case '百度': + return ; + case 'NAVER': + return ; + default: + return ; + } + } + + const dropdownEnabled = localStorage.getItem('searchDropdown') === 'true'; + + if (!dropdownEnabled) { + return null; + } + + return ( + + + + ); +} + +export { Icon as default, Icon }; diff --git a/src/features/search/components/dropdown/index.jsx b/src/features/search/components/dropdown/index.jsx new file mode 100644 index 00000000..bb76d09b --- /dev/null +++ b/src/features/search/components/dropdown/index.jsx @@ -0,0 +1 @@ +export * from './Dropdown'; \ No newline at end of file