Skip to content

Commit

Permalink
Fix/app search (#456)
Browse files Browse the repository at this point in the history
* Auto open search correctly in global search

* Update search input when navigating to previous/next location

* Revert: Navigate to previous page when canceling search

Has to many edge cases and fixing them would require a global history stack which gets saved in the location state.
This then would lead to the apps internal back navigation to be the same as the browsers which is not wanted, since you should not get moved deeper into the apps navigation when clicking the back button

* Correctly autofocus search input

Sometimes the autofocus did not work, since the input did not exist yet by the time the timeout was triggered

* Restore search input open state when navigation to previous/next location

* Restore search input focus when navigating to previous/next location
  • Loading branch information
schroda authored Nov 12, 2023
1 parent 35c34b6 commit 8d46874
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 32 deletions.
73 changes: 50 additions & 23 deletions src/components/util/AppbarSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { IconButton, Input, Tooltip } from '@mui/material';
import CancelIcon from '@mui/icons-material/Cancel';
import { useQueryParam, StringParam } from 'use-query-params';
import { useTranslation } from 'react-i18next';
import { useBackButton } from '@/util/useBackButton.ts';
import { useLocation, useNavigate } from 'react-router-dom';

interface IProps {
autoOpen?: boolean;
Expand All @@ -23,19 +23,33 @@ const defaultProps = {
};

export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
const { autoOpen } = props;

const { t } = useTranslation();
const handleBack = useBackButton();

const { autoOpen } = props;
const { pathname, search: locationSearch, state: fullLocationState } = useLocation<{ wasSearchOpen?: boolean }>();
const { wasSearchOpen, ...locationState } = fullLocationState ?? {};

const navigate = useNavigate();

const [query, setQuery] = useQueryParam('query', StringParam);
const [searchOpen, setSearchOpen] = useState(!!query);
const inputRef = React.useRef<HTMLInputElement>();

const [searchString, setSearchString] = useState(query ?? '');

const updateSearchOpenState = (open: boolean) => {
setSearchOpen(open);

// try to focus input component since in case of navigating to the previous/next page in the browser history
// the "openSearch" state might not change and thus, won't trigger a focus
if (open) {
inputRef.current?.focus();
}
};

function handleChange(newQuery: string) {
if (newQuery === '') {
handleBack();
return;
}

Expand All @@ -44,25 +58,17 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {

const cancelSearch = () => {
setSearchString('');
setSearchOpen(false);

handleBack();
setQuery(undefined);
updateSearchOpenState(false);
};
const handleBlur = () => {
if (!searchString) setSearchOpen(false);
};
const openSearch = () => {
setSearchOpen(true);
// Put Focus Action at the end of the Callstack so Input actually exists on the dom
setTimeout(() => {
if (inputRef && inputRef.current) inputRef.current.focus();
});
if (!searchString) updateSearchOpenState(false);
};

const handleKeyboardEvent = (e: KeyboardEvent) => {
if (e.code === 'F3' || (e.ctrlKey && e.code === 'KeyF')) {
e.preventDefault();
openSearch();
updateSearchOpenState(true);
return;
}

Expand All @@ -73,21 +79,42 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
};

useEffect(() => {
if (autoOpen) {
openSearch();
if ((autoOpen && wasSearchOpen === undefined) || (wasSearchOpen && query)) {
updateSearchOpenState(true);
return;
}

updateSearchOpenState(false);
}, [autoOpen, pathname]);

useEffect(() => {
if (!searchOpen || !inputRef.current) {
return;
}

inputRef.current.focus();
}, [searchOpen, inputRef.current]);

useEffect(() => {
if (wasSearchOpen === searchOpen) {
return;
}
}, []);

navigate(
{ pathname, search: locationSearch },
{ replace: true, state: { ...locationState, wasSearchOpen: searchOpen } },
);
}, [searchOpen]);

useEffect(() => {
if (query === undefined && searchString !== undefined) {
setSearchString('');
setSearchOpen(false);
return;
}

if (searchString === '' && !!query) {
if (query && searchString !== query) {
setSearchString(query);
setSearchOpen(true);
updateSearchOpenState(true);
}
}, [query]);

Expand Down Expand Up @@ -117,7 +144,7 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {

return (
<Tooltip title={t('search.title.search')}>
<IconButton onClick={openSearch}>
<IconButton onClick={() => updateSearchOpenState(true)}>
<SearchIcon />
</IconButton>
</Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion src/screens/SearchAll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export const SearchAll: React.FC = () => {

const { setTitle, setAction } = useContext(NavBarContext);

useSetDefaultBackTo('sources/all/search');
useSetDefaultBackTo('sources');

const [query] = useQueryParam('query', StringParam);
const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD);
Expand Down
14 changes: 6 additions & 8 deletions src/screens/SourceMangas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,17 @@ export function SourceMangas() {
const { sourceId } = useParams<{ sourceId: string }>();

const navigate = useNavigate();
const { pathname, state: locationState } =
useLocation<{
contentType: SourceContentType;
filtersToApply: IPos[];
clearCache: boolean;
}>() ?? {};
const {
contentType: currentLocationContentType = SourceContentType.POPULAR,
filtersToApply: currentLocationFiltersToApply = [],
clearCache = false,
} = locationState ?? {};
} = useLocation<{
contentType: SourceContentType;
filtersToApply: IPos[];
clearCache: boolean;
}>().state ?? {};

useSetDefaultBackTo(pathname);
useSetDefaultBackTo('sources');

const { options } = useLibraryOptionsContext();
const [query] = useQueryParam('query', StringParam);
Expand Down

0 comments on commit 8d46874

Please sign in to comment.