Skip to content

Commit

Permalink
nu kak to tak
Browse files Browse the repository at this point in the history
  • Loading branch information
VanyaMate committed Aug 6, 2024
1 parent 72e7886 commit 7dfe6a8
Show file tree
Hide file tree
Showing 18 changed files with 744 additions and 42 deletions.
6 changes: 3 additions & 3 deletions src/pages/DialoguesPage/ui/DialoguesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ import {
DomainPrivateDialogueFull,
} from 'product-types/dist/private-dialogue/DomainPrivateDialogueFull';
import {
Virtual, VirtualRenderMethod,
VirtualType,
} from '@/shared/ui-kit/box/Virtual/ui/Virtual.tsx';
VirtualRenderMethod, VirtualType,
} from '@/shared/ui-kit/box/Virtual/types/types.ts';
import { Virtual } from '@/shared/ui-kit/box/Virtual/ui/Virtual.tsx';


export type DialoguesPageProps =
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useCallback, useRef, useState } from 'react';
import {
getInitialIndex,
} from '@/shared/ui-kit/box/Virtual/lib/getInitialIndex/getInitialIndex.ts';
import {
getVirtualList,
} from '@/shared/ui-kit/box/Virtual/lib/getVirtualList/getVirtualList.ts';
import {
VirtualIndexSetter, VirtualList,
VirtualType,
} from '@/shared/ui-kit/box/Virtual/types/types.ts';


export type UseVirtualListProps = {
type: VirtualType;
list: VirtualList;
showAmount: number;
}

export const useVirtualList = function (props: UseVirtualListProps) {
const { type, list, showAmount } = props;

const currentIndex = useRef<number>(
getInitialIndex({ type, showAmount, listLength: list.length }),
);
const [ virtualList, setVirtualList ] = useState<VirtualList>(
getVirtualList({ index: currentIndex.current, list, showAmount }),
);

const setIndex = useCallback<VirtualIndexSetter>((index: number) => {
currentIndex.current = index;
setVirtualList(
getVirtualList({ index, list, showAmount }),
);
}, [ list, showAmount ]);

return { currentIndex, virtualList, setIndex };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';
import { VirtualType } from '@/shared/ui-kit/box/Virtual/types/types.ts';


export type UseVirtualScrollProps = {
animationMs: number;
scrollDistance: number;
type: VirtualType;
}

export enum VirtualScrollDirection {
TOP = 'top',
BOTTOM = 'bottom',
NONE = 'none'
}

export const useVirtualScroll = function (props: UseVirtualScrollProps) {
const {
animationMs,
type,
scrollDistance,
} = props;
const containerRef = useRef<HTMLDivElement>(null);
const targetScrollPosition = useRef<number>(0);
const startTimeRef = useRef<number>(0);
const startPositionRef = useRef<number>(0);

const previousScrollHeight = useRef<number>(0);

const scrollAnimation = useCallback((timestamp?: number) => {
if (startTimeRef.current === 0) {
startTimeRef.current = timestamp;
}
const progress = timestamp - startTimeRef.current;
const easeInOutQuad = (t: number) => t < 0.5
? 2 * t * t
: -1 + (4 - 2 * t) * t;

const elapsedTime = Math.min(progress / animationMs, 1);
const ease = easeInOutQuad(elapsedTime);
const currentScrollPosition = startPositionRef.current + ease * (targetScrollPosition.current - startPositionRef.current);

containerRef.current.scrollTop = currentScrollPosition;

if (elapsedTime < 1) {
requestAnimationFrame(scrollAnimation);
}
}, [ animationMs ]);

const scrollHandler = useCallback((side: VirtualScrollDirection) => {
const { scrollTop, scrollHeight, offsetHeight } = containerRef.current;

if (type === VirtualType.TOP) {
if (side === VirtualScrollDirection.TOP) {
if (targetScrollPosition.current === 0) {
return;
}
targetScrollPosition.current = Math.max(0, targetScrollPosition.current + scrollDistance);
} else {
if (targetScrollPosition.current === scrollHeight - offsetHeight) {
return;
}
targetScrollPosition.current = Math.min(scrollHeight - offsetHeight, targetScrollPosition.current - scrollDistance);
}
} else {
if (side === VirtualScrollDirection.TOP) {
if (targetScrollPosition.current === -(scrollHeight - offsetHeight)) {
return;
}
targetScrollPosition.current = Math.max(-(scrollHeight - offsetHeight), targetScrollPosition.current - scrollDistance);
} else {
if (targetScrollPosition.current === 0) {
return;
}
targetScrollPosition.current = Math.min(0, targetScrollPosition.current + scrollDistance);
}
}

startPositionRef.current = scrollTop;
startTimeRef.current = 0;
requestAnimationFrame(scrollAnimation);
}, [ scrollAnimation, scrollDistance, type ]);

const scrollTo = useCallback((options: ScrollToOptions) => {
targetScrollPosition.current = options.top;
startTimeRef.current = 0;

if (options.behavior === 'smooth') {
startPositionRef.current = containerRef.current.scrollTop;
requestAnimationFrame(scrollAnimation);
} else {
containerRef.current.scrollTop = options.top;
}
}, [ scrollAnimation ]);

useEffect(() => {
const ref = containerRef.current;
if (ref) {
previousScrollHeight.current = ref.scrollHeight;

return () => {
console.log('[RETURN] RefContainerHeight', ref.scrollHeight);

};
}
});

useLayoutEffect(() => {
const ref = containerRef.current;

if (ref) {
const onWheelHandler = function (event: WheelEvent) {
if (event.deltaY > 0) {
scrollHandler(VirtualScrollDirection.BOTTOM);
} else {
scrollHandler(VirtualScrollDirection.TOP);
}
};

ref.addEventListener('wheel', onWheelHandler);

return () => {
ref.removeEventListener('wheel', onWheelHandler);
};
}
}, [ animationMs, scrollDistance, scrollHandler, type ]);

return { containerRef, scrollTo };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export type CalculateAnimationScrollPositionProps = {
timestamp: number;
startAnimationTime: number;
startAnimationPosition: number;
targetScrollPosition: number;
animationMs: number;
}

export const calculateAnimationScrollPosition = function (props: CalculateAnimationScrollPositionProps): number {
const {
startAnimationPosition,
startAnimationTime,
animationMs,
targetScrollPosition,
timestamp,
} = props;

const progress = timestamp - startAnimationTime;
const easeInOutQuad = (t: number) => t < 0.5
? 2 * t * t
: -1 + (4 - 2 * t) * t;

const elapsedTime = Math.min(progress / animationMs, 1);
const ease = easeInOutQuad(elapsedTime);

return startAnimationPosition + ease * (targetScrollPosition - startAnimationPosition);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type CalculateScrollPositionForVirtualBottomProps = {
offset: number;
currentTarget: number;
scrollDistance: number;
offsetHeight: number;
scrollHeight: number;
}

export const calculateScrollPositionForVirtualBottom = function (props: CalculateScrollPositionForVirtualBottomProps): number | null {
const {
offset,
scrollHeight,
offsetHeight,
currentTarget,
scrollDistance,
} = props;

const isScrollToTop = offset < 0;

if (isScrollToTop) {
return Math.max(-(scrollHeight - offsetHeight), currentTarget - scrollDistance);
}

const isScrollToBottom = offset > 0;

if (isScrollToBottom) {
return Math.min(0, currentTarget + scrollDistance);
}

return null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type CalculateScrollPositionForVirtualTopProps = {
offset: number;
currentTarget: number;
scrollDistance: number;
offsetHeight: number;
scrollHeight: number;
}

export const calculateScrollPositionForVirtualTop = function (props: CalculateScrollPositionForVirtualTopProps): number | null {
const {
offset,
scrollHeight,
offsetHeight,
currentTarget,
scrollDistance,
} = props;

const isScrollToTop = offset < 0;

if (isScrollToTop) {
return Math.max(0, currentTarget + scrollDistance);
}

const isScrollToBottom = offset > 0;

if (isScrollToBottom) {
return Math.min(scrollHeight - offsetHeight, currentTarget + scrollDistance);
}

return null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { VirtualType } from '@/shared/ui-kit/box/Virtual/ui/Virtual.tsx';
import { isTop } from '@/shared/ui-kit/box/Virtual/lib/isTop/isTop.ts';


export type GetInitialIndexProps = {
type: VirtualType;
listLength: number;
showAmount: number;
}

export const getInitialIndex = function (props: GetInitialIndexProps): number {
const { type, showAmount, listLength } = props;

if (isTop(type)) {
return 0;
}

return Math.max(0, listLength - showAmount);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { VirtualType } from '@/shared/ui-kit/box/Virtual/types/types.ts';
import { isTop } from '@/shared/ui-kit/box/Virtual/lib/isTop/isTop.ts';
import {
calculateScrollPositionForVirtualTop,
} from '@/shared/ui-kit/box/Virtual/lib/calculateScrollPositionForVirtualTop/calculateScrollPositionForVirtualTop.ts';
import {
calculateScrollPositionForVirtualBottom,
} from '@/shared/ui-kit/box/Virtual/lib/calculateScrollPositionForVirtualBottom/calculateScrollPositionForVirtualBottom.ts';


export type GetScrollTargetScrollPositionProps = {
type: VirtualType;
offset: number;
currentTarget: number;
scrollHeight: number;
offsetHeight: number;
scrollDistance: number;
}

export const getScrollTargetScrollPosition = function (props: GetScrollTargetScrollPositionProps): number | null {
const {
type,
currentTarget,
offset,
offsetHeight,
scrollHeight,
scrollDistance,
} = props;

if (isTop(type)) {
return calculateScrollPositionForVirtualTop({
scrollDistance,
scrollHeight,
offsetHeight,
currentTarget,
offset,
});
} else {
return calculateScrollPositionForVirtualBottom({
scrollDistance,
scrollHeight,
offsetHeight,
currentTarget,
offset,
});
}
};
13 changes: 13 additions & 0 deletions src/shared/ui-kit/box/Virtual/lib/getVirtualList/getVirtualList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { VirtualList } from '@/shared/ui-kit/box/Virtual/ui/Virtual.tsx';


export type GetVirtualItemsProps = {
index: number;
list: VirtualList;
showAmount: number;
}

export const getVirtualList = function (props: GetVirtualItemsProps): VirtualList {
const { list, index, showAmount } = props;
return list.slice(index, showAmount + index);
};
Loading

0 comments on commit 7dfe6a8

Please sign in to comment.