re-add useTransition to router

This commit is contained in:
jeffvli
2026-04-05 21:54:07 -07:00
parent 56cd50e0ed
commit c8e8f58cce
19 changed files with 375 additions and 300 deletions
@@ -1,5 +1,5 @@
import { motion } from 'motion/react';
import { createContext, ReactNode, useContext, useMemo, useRef } from 'react';
import { createContext, ReactNode, useContext, useMemo, useState } from 'react';
import styles from './list-with-sidebar-container.module.css';
@@ -8,7 +8,7 @@ import { animationProps } from '/@/shared/components/animations/animation-props'
import { Portal } from '/@/shared/components/portal/portal';
interface ListWithSidebarContainerContextValue {
sidebarRef: React.RefObject<HTMLDivElement | null>;
sidebarElement: HTMLDivElement | null;
}
const ListWithSidebarContainerContext = createContext<ListWithSidebarContainerContextValue | null>(
@@ -36,12 +36,12 @@ function Sidebar({ children }: SidebarProps) {
throw new Error('Sidebar must be used within ListWithSidebarContainer');
}
if (!context.sidebarRef?.current) {
if (!context.sidebarElement) {
return null;
}
return (
<Portal target={context.sidebarRef.current}>
<Portal target={context.sidebarElement}>
<motion.div {...animationProps.slideInLeft} style={{ height: '100%', width: '100%' }}>
{children}
</motion.div>
@@ -56,25 +56,25 @@ function SidebarPortal({ children }: SidebarPortalProps) {
throw new Error('SidebarPortal must be used within ListWithSidebarContainer');
}
if (!context.sidebarRef?.current) {
if (!context.sidebarElement) {
return null;
}
return <Portal target={context.sidebarRef.current}>{children}</Portal>;
return <Portal target={context.sidebarElement}>{children}</Portal>;
}
export const ListWithSidebarContainer = ({
children,
useBreakpoint = false,
}: ListWithSidebarContainerProps) => {
const sidebarRef = useRef<HTMLDivElement>(null);
const [sidebarElement, setSidebarElement] = useState<HTMLDivElement | null>(null);
const { isSidebarOpen = false } = useListContext();
const contextValue = useMemo(
() => ({
sidebarRef,
sidebarElement,
}),
[],
[sidebarElement],
);
return (
@@ -84,7 +84,7 @@ export const ListWithSidebarContainer = ({
data-sidebar-open={useBreakpoint ? undefined : isSidebarOpen}
data-use-breakpoint={useBreakpoint}
>
<div className={styles.sidebarContainer} ref={sidebarRef} />
<div className={styles.sidebarContainer} ref={setSidebarElement} />
<div className={styles.contentContainer}>{children}</div>
</div>
</ListWithSidebarContainerContext.Provider>
@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router';
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback';
export const useSearchTermFilter = (defaultValue?: string) => {
@@ -14,17 +15,19 @@ export const useSearchTermFilter = (defaultValue?: string) => {
}, [searchParams, defaultValue]);
const handleSetSearchTerm = (value: null | string) => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(
prev,
FILTER_KEYS.SHARED.SEARCH_TERM,
value === '' ? null : value,
);
return newParams;
},
{ replace: true },
);
runInUrlTransition(() => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(
prev,
FILTER_KEYS.SHARED.SEARCH_TERM,
value === '' ? null : value,
);
return newParams;
},
{ replace: true },
);
});
};
const debouncedSetSearchTerm = useDebouncedCallback(handleSetSearchTerm, 300);
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { useCallback, useRef } from 'react';
import { useCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation';
import { useDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation';
@@ -8,21 +8,26 @@ export const useSetFavorite = () => {
const createFavoriteMutation = useCreateFavorite({});
const deleteFavoriteMutation = useDeleteFavorite({});
const createFavoriteMutationRef = useRef(createFavoriteMutation);
const deleteFavoriteMutationRef = useRef(deleteFavoriteMutation);
createFavoriteMutationRef.current = createFavoriteMutation;
deleteFavoriteMutationRef.current = deleteFavoriteMutation;
const setFavorite = useCallback(
(serverId: string, id: string[], itemType: LibraryItem, isFavorite: boolean) => {
if (isFavorite) {
createFavoriteMutation.mutate({
createFavoriteMutationRef.current.mutate({
apiClientProps: { serverId },
query: { id, type: itemType },
});
} else {
deleteFavoriteMutation.mutate({
deleteFavoriteMutationRef.current.mutate({
apiClientProps: { serverId },
query: { id, type: itemType },
});
}
},
[createFavoriteMutation, deleteFavoriteMutation],
[],
);
return setFavorite;
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { useCallback, useRef } from 'react';
import { useSetRatingMutation } from '/@/renderer/features/shared/mutations/set-rating-mutation';
import { LibraryItem } from '/@/shared/types/domain-types';
@@ -6,14 +6,17 @@ import { LibraryItem } from '/@/shared/types/domain-types';
export const useSetRating = () => {
const setRatingMutation = useSetRatingMutation({});
const setRatingMutationRef = useRef(setRatingMutation);
setRatingMutationRef.current = setRatingMutation;
const setRating = useCallback(
(serverId: string, id: string[], itemType: LibraryItem, rating: number) => {
setRatingMutation.mutate({
setRatingMutationRef.current.mutate({
apiClientProps: { serverId },
query: { id, rating, type: itemType },
});
},
[setRatingMutation],
[],
);
return setRating;
@@ -5,6 +5,7 @@ import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
import { ItemListKey } from '/@/shared/types/types';
export const useSortByFilter = <TSortBy>(defaultValue: null | string, listKey: ItemListKey) => {
@@ -20,14 +21,16 @@ export const useSortByFilter = <TSortBy>(defaultValue: null | string, listKey: I
}, [searchParams, persisted, defaultValue]);
const handleSetSortBy = (sortBy: string) => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_BY, sortBy);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_BY, sortBy);
runInUrlTransition(() => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_BY, sortBy);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_BY, sortBy);
});
};
return {
@@ -5,6 +5,7 @@ import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { runInUrlTransition } from '/@/renderer/utils/url-transition';
import { SortOrder } from '/@/shared/types/domain-types';
import { ItemListKey } from '/@/shared/types/types';
@@ -21,14 +22,20 @@ export const useSortOrderFilter = (defaultValue: null | string, listKey: ItemLis
}, [searchParams, persisted, defaultValue]);
const handleSetSortOrder = (sortOrder: SortOrder) => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
runInUrlTransition(() => {
setSearchParams(
(prev) => {
const newParams = setSearchParam(
prev,
FILTER_KEYS.SHARED.SORT_ORDER,
sortOrder,
);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
});
};
return {