Feature/improve restoring grid snapshots (#713)

* Update local storage functions

* Update local storage hooks

* Add session storage

* Improve storing virtuoso grid snapshot

* Use "useSyncExternalStore" for browser storage access

* Get rid of location replacements in "AppbarSearch"

Use session storage instead to prevent reloading the page all the time due to changing the location

* Get rid of location replacements in "SourceMangas"

Use session storage instead to prevent reloading the page all the time due to changing the location
This commit is contained in:
schroda
2024-04-07 15:22:03 +02:00
committed by GitHub
parent ea2f9dc5a4
commit aab3e25031
20 changed files with 220 additions and 190 deletions

View File

@@ -11,35 +11,44 @@ import SearchIcon from '@mui/icons-material/Search';
import { IconButton, Tooltip } from '@mui/material';
import { useQueryParam, StringParam } from 'use-query-params';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
import { SearchTextField } from '@/components/atoms/SearchTextField.tsx';
import { useSessionStorage } from '@/util/useStorage.tsx';
interface IProps {
autoOpen?: boolean;
isClosable?: boolean;
}
const defaultProps = {
autoOpen: false,
};
export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
const { autoOpen } = props;
const { isClosable = true } = props;
const { t } = useTranslation();
const { pathname, search: locationSearch, state: fullLocationState } = useLocation<{ wasSearchOpen?: boolean }>();
const { wasSearchOpen, ...locationState } = fullLocationState ?? {};
const navigate = useNavigate();
const [prevLocationKey, setPrevLocationKey] = useState<string>();
const location = useLocation();
const [query, setQuery] = useQueryParam('query', StringParam);
const [searchOpen, setSearchOpen] = useState(!!query);
const [isSearchOpen, setIsSearchOpen] = useState(!isClosable || !!query);
const inputRef = React.useRef<HTMLInputElement>();
const [searchString, setSearchString] = useState(query ?? '');
const [locationQuery, setLocationQuery] = useSessionStorage<string | null>(`appbarsearch-location-${location.key}`);
if (prevLocationKey !== location.key) {
setPrevLocationKey(location.key);
setLocationQuery(query);
setSearchString(locationQuery ?? '');
setIsSearchOpen(!isClosable || !!locationQuery);
}
const isOpen = isSearchOpen || !!locationQuery;
const updateSearchOpenState = (open: boolean) => {
setSearchOpen(open);
if (!isClosable) {
return;
}
setIsSearchOpen(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
@@ -54,6 +63,7 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
}
setQuery(newQuery);
updateSearchOpenState(false);
}
const cancelSearch = () => {
@@ -72,46 +82,6 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
}
};
useEffect(() => {
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('');
return;
}
if (query && searchString !== query) {
setSearchString(query);
updateSearchOpenState(true);
}
}, [query]);
useEffect(() => {
window.addEventListener('keydown', handleKeyboardEvent);
@@ -120,9 +90,10 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
};
}, [handleKeyboardEvent]);
if (searchOpen) {
if (isOpen) {
return (
<SearchTextField
autoFocus
variant="standard"
value={searchString}
onCancel={cancelSearch}
@@ -146,5 +117,3 @@ export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
</Tooltip>
);
};
AppbarSearch.defaultProps = defaultProps;