TelegramPWA/src/components/right/hooks/useProfileState.ts
2023-04-25 17:27:14 +04:00

111 lines
3.2 KiB
TypeScript

import { useCallback, useEffect } from '../../../lib/teact/teact';
import { ProfileState } from '../../../types';
import animateScroll from '../../../util/animateScroll';
import { throttle } from '../../../util/schedulers';
import useEffectWithPrevDeps from '../../../hooks/useEffectWithPrevDeps';
const TRANSITION_DURATION = 300;
const PROGRAMMATIC_SCROLL_TIMEOUT_MS = 350;
const runThrottledForScroll = throttle((cb) => cb(), 250, false);
let isScrollingProgrammatically = false;
export default function useProfileState(
containerRef: { current: HTMLDivElement | null },
tabType: string,
profileState: ProfileState,
onProfileStateChange: (state: ProfileState) => void,
) {
// Scroll to tabs if needed
useEffectWithPrevDeps(([prevTabType]) => {
if (prevTabType && prevTabType !== tabType) {
const container = containerRef.current!;
const tabsEl = container.querySelector<HTMLDivElement>('.TabList')!;
if (container.scrollTop < tabsEl.offsetTop) {
onProfileStateChange(tabType === 'members' ? ProfileState.MemberList : ProfileState.SharedMedia);
isScrollingProgrammatically = true;
animateScroll(container, tabsEl, 'start', undefined, undefined, undefined, TRANSITION_DURATION);
setTimeout(() => {
isScrollingProgrammatically = false;
}, PROGRAMMATIC_SCROLL_TIMEOUT_MS);
}
}
}, [tabType, onProfileStateChange, containerRef]);
// Scroll to top
useEffectWithPrevDeps(([prevProfileState]) => {
if (profileState !== ProfileState.Profile || profileState === prevProfileState) {
return;
}
const container = containerRef.current;
if (!container) {
return;
}
const tabListEl = container.querySelector<HTMLDivElement>('.TabList');
if (!tabListEl || tabListEl.offsetTop > container.scrollTop) {
return;
}
isScrollingProgrammatically = true;
animateScroll(
container,
container.firstElementChild as HTMLElement,
'start',
undefined,
container.offsetHeight * 2,
);
setTimeout(() => {
isScrollingProgrammatically = false;
}, PROGRAMMATIC_SCROLL_TIMEOUT_MS);
onProfileStateChange(profileState);
}, [profileState, containerRef, onProfileStateChange]);
const determineProfileState = useCallback(() => {
const container = containerRef.current;
if (!container) {
return;
}
const tabListEl = container.querySelector<HTMLDivElement>('.TabList');
if (!tabListEl) {
return;
}
let state: ProfileState = ProfileState.Profile;
if (container.scrollTop >= tabListEl.offsetTop) {
state = tabType === 'members'
? ProfileState.MemberList
: ProfileState.SharedMedia;
}
onProfileStateChange(state);
}, [containerRef, onProfileStateChange, tabType]);
// Determine profile state when switching tabs
useEffect(() => {
if (isScrollingProgrammatically) {
return;
}
determineProfileState();
}, [determineProfileState, tabType]);
// Determine profile state when scrolling
const handleScroll = useCallback(() => {
if (isScrollingProgrammatically) {
return;
}
runThrottledForScroll(determineProfileState);
}, [determineProfileState]);
return { handleScroll };
}