refactor(SideDrawer): simplify refs handing

This commit is contained in:
Timothy Z. 2025-06-20 12:08:55 +03:00
parent 00d89aec75
commit a3c895dfc6
3 changed files with 21 additions and 29 deletions

View file

@ -5,15 +5,15 @@ type Props = {
children: JSX.Element, children: JSX.Element,
when: boolean, when: boolean,
name: string, name: string,
onTransitionEnd?: () => void
}; };
const Transition = ({ children, when, name, onTransitionEnd }: Props) => { const Transition = ({ children, when, name }: Props) => {
const [element, setElement] = useState<HTMLElement | null>(null); const [element, setElement] = useState<HTMLElement | null>(null);
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [state, setState] = useState('enter'); const [state, setState] = useState('enter');
const [active, setActive] = useState(false); const [active, setActive] = useState(false);
const [transitionEnded, setTransitionEnded] = useState(false);
const callbackRef = useCallback((element: HTMLElement | null) => { const callbackRef = useCallback((element: HTMLElement | null) => {
setElement(element); setElement(element);
@ -30,20 +30,15 @@ const Transition = ({ children, when, name, onTransitionEnd }: Props) => {
); );
}, [name, state, active, children]); }, [name, state, active, children]);
const handleTransitionEnd = useCallback(() => { const onTransitionEnd = useCallback(() => {
switch (state) { setTransitionEnded(true);
case 'enter': state === 'exit' && setMounted(false);
onTransitionEnd?.();
break;
case 'exit':
setMounted(false);
break;
}
}, [state]); }, [state]);
useEffect(() => { useEffect(() => {
setState(when ? 'enter' : 'exit'); setState(when ? 'enter' : 'exit');
when && setMounted(true); when && setMounted(true);
setTransitionEnded(false);
}, [when]); }, [when]);
useEffect(() => { useEffect(() => {
@ -53,14 +48,15 @@ const Transition = ({ children, when, name, onTransitionEnd }: Props) => {
}, [element]); }, [element]);
useEffect(() => { useEffect(() => {
element?.addEventListener('transitionend', handleTransitionEnd); element?.addEventListener('transitionend', onTransitionEnd);
return () => element?.removeEventListener('transitionend', handleTransitionEnd); return () => element?.removeEventListener('transitionend', onTransitionEnd);
}, [element, onTransitionEnd]); }, [element, onTransitionEnd]);
return ( return (
mounted && cloneElement(children, { mounted && cloneElement(children, {
ref: callbackRef, ref: callbackRef,
className, className,
transitionEnded
}) })
); );
}; };

View file

@ -45,7 +45,6 @@ const Player = ({ urlParams, queryParams }) => {
const routeFocused = useRouteFocused(); const routeFocused = useRouteFocused();
const toast = useToast(); const toast = useToast();
const [sideDrawerTransitionEnded, setSideDrawerTransitionEnded] = React.useState(false);
const [seeking, setSeeking] = React.useState(false); const [seeking, setSeeking] = React.useState(false);
const [casting, setCasting] = React.useState(() => { const [casting, setCasting] = React.useState(() => {
@ -511,10 +510,6 @@ const Player = ({ urlParams, queryParams }) => {
} }
}, [settings.pauseOnMinimize, shell.windowClosed, shell.windowHidden]); }, [settings.pauseOnMinimize, shell.windowClosed, shell.windowHidden]);
React.useEffect(() => {
if (!sideDrawerOpen) setSideDrawerTransitionEnded(false);
}, [sideDrawerOpen]);
React.useLayoutEffect(() => { React.useLayoutEffect(() => {
const onKeyDown = (event) => { const onKeyDown = (event) => {
switch (event.code) { switch (event.code) {
@ -831,14 +826,13 @@ const Player = ({ urlParams, queryParams }) => {
: :
null null
} }
<Transition when={sideDrawerOpen} name={'slide-left'} onTransitionEnd={() => setSideDrawerTransitionEnded(true)}> <Transition when={sideDrawerOpen} name={'slide-left'}>
<SideDrawer <SideDrawer
className={classnames(styles['layer'], styles['side-drawer-layer'])} className={classnames(styles['layer'], styles['side-drawer-layer'])}
metaItem={player.metaItem?.content} metaItem={player.metaItem?.content}
seriesInfo={player.seriesInfo} seriesInfo={player.seriesInfo}
closeSideDrawer={closeSideDrawer} closeSideDrawer={closeSideDrawer}
selectedVideoID={player.selected?.streamRequest.path.id} selected={player.selected?.streamRequest.path.id}
transitionEnded={sideDrawerTransitionEnded}
/> />
</Transition> </Transition>
{ {

View file

@ -13,14 +13,15 @@ type Props = {
className?: string; className?: string;
seriesInfo: SeriesInfo; seriesInfo: SeriesInfo;
metaItem: MetaItem; metaItem: MetaItem;
selectedVideoID: string;
transitionEnded: boolean;
closeSideDrawer: () => void; closeSideDrawer: () => void;
selected: string;
transitionEnded: boolean;
}; };
const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, className, closeSideDrawer, ...props }: Props, ref) => { const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, className, closeSideDrawer, selected, transitionEnded, ...props }: Props, ref) => {
const { core } = useServices(); const { core } = useServices();
const [season, setSeason] = useState<number>(seriesInfo?.season); const [season, setSeason] = useState<number>(seriesInfo?.season);
const selectedVideoRef = useRef<HTMLDivElement>(null);
const metaItem = useMemo(() => { const metaItem = useMemo(() => {
return seriesInfo ? return seriesInfo ?
{ {
@ -77,12 +78,13 @@ const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, classNa
event.stopPropagation(); event.stopPropagation();
}; };
const selectedVideoRef = useRef<HTMLDivElement>(null); const getSelectedRef = useCallback((video: Video) => {
return video.id === selected ? selectedVideoRef : null;
}, [selected]);
useEffect(() => { useEffect(() => {
props.transitionEnded && transitionEnded && selectedVideoRef?.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
selectedVideoRef?.current?.scrollIntoView({ behavior: 'smooth', block: 'center' }); }, [transitionEnded]);
}, [props.transitionEnded]);
return ( return (
<div ref={ref} className={classNames(styles['side-drawer'], className)} onMouseDown={onMouseDown}> <div ref={ref} className={classNames(styles['side-drawer'], className)} onMouseDown={onMouseDown}>
@ -129,7 +131,7 @@ const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, classNa
scheduled={video.scheduled} scheduled={video.scheduled}
onMarkVideoAsWatched={onMarkVideoAsWatched} onMarkVideoAsWatched={onMarkVideoAsWatched}
onMarkSeasonAsWatched={onMarkSeasonAsWatched} onMarkSeasonAsWatched={onMarkSeasonAsWatched}
ref={video.id === props.selectedVideoID ? selectedVideoRef : null} ref={getSelectedRef(video)}
/> />
))} ))}
</div> </div>