Use new ResizeObserver hook
This commit is contained in:
@@ -6,7 +6,16 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ForwardedRef, forwardRef, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import React, {
|
||||||
|
ForwardedRef,
|
||||||
|
forwardRef,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useLayoutEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import Grid, { GridTypeMap } from '@mui/material/Grid';
|
import Grid, { GridTypeMap } from '@mui/material/Grid';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { GridItemProps, GridStateSnapshot, VirtuosoGrid } from 'react-virtuoso';
|
import { GridItemProps, GridStateSnapshot, VirtuosoGrid } from 'react-virtuoso';
|
||||||
@@ -22,6 +31,7 @@ import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab.tsx';
|
|||||||
import { AppStorage } from '@/util/AppStorage.ts';
|
import { AppStorage } from '@/util/AppStorage.ts';
|
||||||
import { MangaCardProps } from '@/components/manga/MangaCard.types.tsx';
|
import { MangaCardProps } from '@/components/manga/MangaCard.types.tsx';
|
||||||
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
import { useResizeObserver } from '@/util/useResizeObserver.tsx';
|
||||||
|
|
||||||
const GridContainer = React.forwardRef<HTMLDivElement, GridTypeMap['props']>(({ children, ...props }, ref) => (
|
const GridContainer = React.forwardRef<HTMLDivElement, GridTypeMap['props']>(({ children, ...props }, ref) => (
|
||||||
<Grid {...props} ref={ref} container sx={{ paddingLeft: '5px', paddingRight: '13px' }}>
|
<Grid {...props} ref={ref} container sx={{ paddingLeft: '5px', paddingRight: '13px' }}>
|
||||||
@@ -310,39 +320,32 @@ export const MangaGrid: React.FC<IMangaGridProps> = ({
|
|||||||
return () => window.removeEventListener('resize', onResize);
|
return () => window.removeEventListener('resize', onResize);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useResizeObserver(
|
||||||
if (!gridRef.current) {
|
gridRef,
|
||||||
return () => {};
|
useCallback(
|
||||||
}
|
(entries, resizeObserver) => {
|
||||||
|
const gridHeight = entries[0].target.clientHeight;
|
||||||
|
const isScrollbarVisible = gridHeight > document.documentElement.clientHeight;
|
||||||
|
|
||||||
if (gridRef.current.offsetHeight > document.documentElement.clientHeight) {
|
if (isLoading) {
|
||||||
return () => {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver((entries) => {
|
if (!gridHeight) {
|
||||||
const gridHeight = entries[0].target.clientHeight;
|
return;
|
||||||
const isScrollbarVisible = gridHeight > document.documentElement.clientHeight;
|
}
|
||||||
|
|
||||||
if (isLoading) {
|
if (isScrollbarVisible) {
|
||||||
return;
|
resizeObserver.disconnect();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gridHeight) {
|
loadMore();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isScrollbarVisible) {
|
|
||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
return;
|
},
|
||||||
}
|
[gridRef, loadMore, isLoading],
|
||||||
|
),
|
||||||
loadMore();
|
);
|
||||||
resizeObserver.disconnect();
|
|
||||||
});
|
|
||||||
resizeObserver.observe(gridRef.current);
|
|
||||||
|
|
||||||
return () => resizeObserver.disconnect();
|
|
||||||
}, [loadMore, isLoading]);
|
|
||||||
|
|
||||||
const hasNoItems = !isLoading && mangas.length === 0;
|
const hasNoItems = !isLoading && mangas.length === 0;
|
||||||
if (hasNoItems) {
|
if (hasNoItems) {
|
||||||
|
|||||||
@@ -6,10 +6,11 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MouseEvent as ReactMouseEvent, useEffect, useLayoutEffect, useRef } from 'react';
|
import { MouseEvent as ReactMouseEvent, useCallback, useEffect, useRef } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import { Page } from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
|
import { useResizeObserver } from '@/util/useResizeObserver.tsx';
|
||||||
|
|
||||||
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
||||||
for (let i = 0; i < wrapper.children.length; i++) {
|
for (let i = 0; i < wrapper.children.length; i++) {
|
||||||
@@ -107,24 +108,21 @@ export function HorizontalPager(props: IReaderProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useResizeObserver(
|
||||||
const initialPageElement = pagesRef.current[initialPage];
|
pagesRef.current[initialPage],
|
||||||
if (!initialPageElement) {
|
useCallback(
|
||||||
return () => {};
|
(_, resizeObserver) => {
|
||||||
}
|
const initialPageElement = pagesRef.current[initialPage];
|
||||||
|
if (!initialPageElement?.offsetHeight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(() => {
|
initialPageElement.scrollIntoView({ inline: 'center' });
|
||||||
if (!initialPageElement.offsetHeight) {
|
resizeObserver.disconnect();
|
||||||
return;
|
},
|
||||||
}
|
[pagesRef.current[initialPage], initialPage],
|
||||||
|
),
|
||||||
initialPageElement.scrollIntoView({ inline: 'center' });
|
);
|
||||||
resizeObserver.disconnect();
|
|
||||||
});
|
|
||||||
resizeObserver.observe(initialPageElement);
|
|
||||||
|
|
||||||
return () => resizeObserver.disconnect();
|
|
||||||
}, [initialPage]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
selfRef.current?.addEventListener('mousedown', dragControl);
|
selfRef.current?.addEventListener('mousedown', dragControl);
|
||||||
|
|||||||
@@ -6,10 +6,11 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import { Page } from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
|
import { useResizeObserver } from '@/util/useResizeObserver.tsx';
|
||||||
|
|
||||||
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
||||||
for (let i = 0; i < wrapper.children.length; i++) {
|
for (let i = 0; i < wrapper.children.length; i++) {
|
||||||
@@ -165,24 +166,21 @@ export function VerticalPager(props: IReaderProps) {
|
|||||||
};
|
};
|
||||||
}, [go]);
|
}, [go]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useResizeObserver(
|
||||||
const initialPageElement = pagesRef.current[initialPage];
|
pagesRef.current[initialPage],
|
||||||
if (!initialPageElement) {
|
useCallback(
|
||||||
return () => {};
|
(_, resizeObserver) => {
|
||||||
}
|
const initialPageElement = pagesRef.current[initialPage];
|
||||||
|
if (!initialPageElement?.offsetHeight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(() => {
|
initialPageElement.scrollIntoView();
|
||||||
if (!initialPageElement.offsetHeight) {
|
resizeObserver.disconnect();
|
||||||
return;
|
},
|
||||||
}
|
[pagesRef.current[initialPage], initialPage],
|
||||||
|
),
|
||||||
initialPageElement.scrollIntoView();
|
);
|
||||||
resizeObserver.disconnect();
|
|
||||||
});
|
|
||||||
resizeObserver.observe(initialPageElement);
|
|
||||||
|
|
||||||
return () => resizeObserver.disconnect();
|
|
||||||
}, [initialPage]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -6,17 +6,28 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RefObject, useLayoutEffect } from 'react';
|
import { RefObject, useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export const useResizeObserver = (
|
||||||
|
ref: RefObject<HTMLElement> | HTMLElement | undefined,
|
||||||
|
callback: ResizeObserverCallback,
|
||||||
|
): (() => void) => {
|
||||||
|
const [disconnect, setDisconnect] = useState<() => void>(() => {});
|
||||||
|
|
||||||
export const useResizeObserver = (ref: RefObject<HTMLElement>, callback: ResizeObserverCallback) => {
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!ref.current) {
|
const element = ref instanceof HTMLElement ? ref : ref?.current;
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
return () => {};
|
return () => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(callback);
|
const resizeObserver = new ResizeObserver(callback);
|
||||||
resizeObserver.observe(ref.current);
|
resizeObserver.observe(element);
|
||||||
|
|
||||||
|
setDisconnect(() => () => resizeObserver.disconnect());
|
||||||
|
|
||||||
return () => resizeObserver.disconnect();
|
return () => resizeObserver.disconnect();
|
||||||
}, [ref, callback]);
|
}, [ref, callback]);
|
||||||
|
|
||||||
|
return disconnect;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user