From 47675e814fad421bbfd459d88d2ae3b524fe3b47 Mon Sep 17 00:00:00 2001 From: danidfra Date: Wed, 18 Sep 2024 18:59:53 -0300 Subject: [PATCH] Created search-zap-split --- .../compose/components/search-zap-split.tsx | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/features/compose/components/search-zap-split.tsx diff --git a/src/features/compose/components/search-zap-split.tsx b/src/features/compose/components/search-zap-split.tsx new file mode 100644 index 000000000..1d4c84aca --- /dev/null +++ b/src/features/compose/components/search-zap-split.tsx @@ -0,0 +1,168 @@ +import clsx from 'clsx'; +import debounce from 'lodash/debounce'; +import React, { useCallback, useEffect } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; +import { useHistory } from 'react-router-dom'; + +import { + changeSearch, + clearSearchResults, + setSearchAccount, + showSearch, + submitSearch, +} from 'soapbox/actions/search'; +import AutosuggestAccountInput from 'soapbox/components/autosuggest-account-input'; +import { Input } from 'soapbox/components/ui'; +import SvgIcon from 'soapbox/components/ui/icon/svg-icon'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import { Account } from 'soapbox/schemas'; +import { selectAccount } from 'soapbox/selectors'; +import { RootState } from 'soapbox/store'; + +const messages = defineMessages({ + placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }, + action: { id: 'search.action', defaultMessage: 'Search for “{query}”' }, +}); + +interface ISearchZapSplit { + autoFocus?: boolean; + autoSubmit?: boolean; + autosuggest?: boolean; + openInRoute?: boolean; + onChange: (account: Account | null) => void; +} + +const SearchZapSplit = (props: ISearchZapSplit) => { + const { + autoFocus = false, + autoSubmit = false, + autosuggest = false, + openInRoute = false, + } = props; + + const dispatch = useAppDispatch(); + const history = useHistory(); + const intl = useIntl(); + + const value = useAppSelector((state) => state.search.value); + const submitted = useAppSelector((state) => state.search.submitted); + + const debouncedSubmit = useCallback(debounce(() => { + dispatch(submitSearch()); + }, 900), []); + + const handleChange = (event: React.ChangeEvent) => { + const { value } = event.target; + + dispatch(changeSearch(value)); + + if (autoSubmit) { + debouncedSubmit(); + } + }; + + const handleClear = (event: React.MouseEvent) => { + event.preventDefault(); + + if (value.length > 0 || submitted) { + dispatch(clearSearchResults()); + } + }; + + const handleSubmit = () => { + if (openInRoute) { + dispatch(setSearchAccount(null)); + dispatch(submitSearch()); + + history.push('/search'); + } else { + dispatch(submitSearch()); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + event.preventDefault(); + + handleSubmit(); + } else if (event.key === 'Escape') { + document.querySelector('.ui')?.parentElement?.focus(); + } + }; + + const handleFocus = () => { + dispatch(showSearch()); + }; + + const getAccount = (accountId: string) => (dispatch: any, getState: () => RootState) => { + const account = selectAccount(getState(), accountId); + console.log(account); + + props.onChange(account!); + }; + + const handleSelected = (accountId: string) => { + dispatch(getAccount(accountId)); + }; + + const hasValue = value.length > 0 || submitted; + const componentProps: any = { + type: 'text', + id: 'search', + placeholder: intl.formatMessage(messages.placeholder), + value, + onChange: handleChange, + onKeyDown: handleKeyDown, + onFocus: handleFocus, + autoFocus: autoFocus, + theme: 'normal', + className: 'pr-10 rtl:pl-10 rtl:pr-3', + }; + + if (autosuggest) { + componentProps.onSelected = handleSelected; + componentProps.autoSelect = false; + } + + useEffect(() => { + return () => { + const newPath = history.location.pathname; + const shouldPersistSearch = !!newPath.match(/@.+\/posts\/[a-zA-Z0-9]+/g) + || !!newPath.match(/\/tags\/.+/g); + + if (!shouldPersistSearch) { + dispatch(changeSearch('')); + } + }; + }, []); + + return ( +
+ + +
+ {autosuggest ? ( + + ) : ( + + )} + +
+ + +
+
+
+ ); +}; + +export default SearchZapSplit;