Improve shadows in search box and fix url param parsing

SearchServers component useEffect wasn't getting an updated location.search value, so give it the same treatment as Header and keep state of initial load.
This commit is contained in:
Corey 2024-05-13 04:14:20 -04:00
parent 5d3d823c34
commit 11cb35d0ac
Signed by: coco
GPG Key ID: 051138DA6AEE3E60
3 changed files with 82 additions and 68 deletions

View File

@ -38,7 +38,7 @@ export default function Header({
const { progress, setProgress, showAlert } = useLoadingContext();
const [showSearchServer, setShowSearchServer] = useState(false);
const [filtersApplied, setFiltersApplied] = useState(false);
const [initialFetch, setInitialFetch] = useState(false);
const [initialFetch, setInitialFetch] = useState(true);
const toggleShowSearchServer = () => {
setShowSearchServer((prev) => !prev);
};
@ -69,9 +69,10 @@ export default function Header({
}, [showAlert, setServers, setProgress]);
useEffect(() => {
if (!initialFetch) {
// TODO: Check if there's a better way to do this than "initialFetch" state, see also SearchServers
if (initialFetch) {
fetchServerData();
setInitialFetch(true);
setInitialFetch(false);
}
setFiltersApplied(
JSON.stringify(searchState) !== JSON.stringify(SearchStateDefaults)

View File

@ -22,6 +22,32 @@ type SearchServersProps = {
setSearchState: React.Dispatch<React.SetStateAction<SearchState>>;
};
function parseSearchParams(searchParams: string): SearchState {
const params = new URLSearchParams(searchParams);
const parsedState = { ...SearchStateDefaults };
const keys = Object.keys(SearchStateDefaults) as Array<keyof SearchState>;
keys.forEach((key) => {
if (params.has(key)) {
const value = params.get(key) as string;
const decodedValue = decodeURIComponent(value);
if (key === 'maxLevel') {
const maxLevelArray = decodedValue.split(' ').map(Number);
parsedState[key] =
maxLevelArray.length === 1 ? [1, maxLevelArray[0]] : maxLevelArray;
} else if (key === 'expansionsEnabled') {
parsedState[key] = decodedValue.split(' ') as string[];
} else {
parsedState[key] = decodedValue;
}
}
});
return parsedState as SearchState;
}
export default function SearchServers({
showSearchServer,
searchState,
@ -31,48 +57,33 @@ export default function SearchServers({
const location = useLocation();
const [initialPath] = useState(location.pathname);
const [contentHeight, setContentHeight] = useState(0);
function parseSearchParams(searchParams: string): SearchState {
const params = new URLSearchParams(searchParams);
const parsedState = SearchStateDefaults;
const keys = Object.keys(SearchStateDefaults) as Array<keyof SearchState>;
keys.forEach((key) => {
if (params.has(key)) {
const value = params.get(key) as string;
const decodedValue = decodeURIComponent(value);
if (key === 'maxLevel') {
const maxLevelArray = decodedValue.split(',').map(Number);
parsedState[key] =
maxLevelArray.length === 1 ? [1, maxLevelArray[0]] : maxLevelArray;
} else if (key === 'expansionsEnabled') {
parsedState[key] = decodedValue.split(',') as string[];
} else {
parsedState[key] = decodedValue;
}
}
});
return parsedState as SearchState;
}
const [initialLoad, setInitialLoad] = useState(true);
useEffect(() => {
// Populate search state with URL params only if loading the home page
// Home page manages updating URL params
if (initialPath === '/') {
const params = parseSearchParams(location.search);
if (params !== SearchStateDefaults) {
setSearchState(params);
// TODO: Check if there's a better way to do this than "initialLoad" state, see also Header
if (initialLoad) {
if (initialPath === '/') {
const params = parseSearchParams(location.search);
if (JSON.stringify(params) !== JSON.stringify(SearchStateDefaults)) {
setSearchState(params);
}
}
setInitialLoad(false);
}
if (showSearchServer && containerRef.current) {
setContentHeight(containerRef.current.scrollHeight);
} else {
setContentHeight(0);
}
}, [showSearchServer, location.search, setSearchState, initialPath]);
}, [
showSearchServer,
location.search,
setSearchState,
initialPath,
initialLoad,
]);
const handleChange = (
name: string,
@ -141,11 +152,11 @@ export default function SearchServers({
theme.palette.mode === 'dark'
? 'rgba(255, 255, 255, .06)'
: 'rgba(0, 0, 0, .06)',
boxShadow: 'inset 0em 3em 5em -5em black,inset 0em -3em 5em -6em black',
boxShadow: 'inset 0em 3em 5em -6em black,inset 0em -3em 5em -7em black',
}}
>
<Container>
<Grid container spacing={2} className="py-2">
<Container className="my-2">
<Grid container spacing={2}>
{/* Name */}
<Grid item xs={12}>
<TextField
@ -686,9 +697,6 @@ export default function SearchServers({
>
<IconButton
onClick={() => {
if (location.pathname === '/') {
window.history.replaceState({}, '', '/');
}
setSearchState(SearchStateDefaults);
}}
>

View File

@ -6,37 +6,42 @@ import SettingsChipCloud from '../components/Server/SettingsChipCloud';
import { SearchState, SearchStateDefaults } from '../data/SearchState';
import { ServerData } from '../data/ServerData';
export default function Home({
servers,
searchState,
}: {
function serializeSearchState(search: SearchState): string {
const params = new URLSearchParams();
Object.entries(search).forEach(([key, value]) => {
if (
value !== null &&
value !== undefined &&
!(key === 'name' && value === SearchStateDefaults.name) &&
!(
key === 'maxLevel' &&
JSON.stringify(value) === JSON.stringify(SearchStateDefaults.maxLevel)
)
) {
if (Array.isArray(value)) {
if (key === 'maxLevel') {
if (value[0] === value[1]) {
params.append(key, JSON.stringify(value[0]));
return;
}
}
params.append(key, value.join(' '));
} else {
params.append(key, value);
}
}
});
return params.toString();
}
type HomeProps = {
servers: ServerData[];
searchState: SearchState;
}) {
function serializeSearchState(search: SearchState): string {
const params = new URLSearchParams();
Object.entries(search).forEach(([key, value]) => {
if (
value !== null &&
value !== undefined &&
!(key === 'name' && value === '') &&
!(
key === 'maxLevel' &&
JSON.stringify(value) === JSON.stringify(SearchStateDefaults.maxLevel)
)
) {
if (Array.isArray(value)) {
params.append(key, value.join(','));
} else {
params.append(key, value);
}
}
});
return params.toString();
}
};
export default function Home({ servers, searchState }: HomeProps) {
useEffect(() => {
// Update URL params whenever search state changes
const searchParams = serializeSearchState(searchState);