fix resizeobserver loop
This commit is contained in:
parent
00ec92cc02
commit
5598f49c32
6 changed files with 103 additions and 18 deletions
62
package-lock.json
generated
62
package-lock.json
generated
|
@ -21,6 +21,7 @@
|
|||
"@loadable/component": "5.15.3",
|
||||
"@mui/icons-material": "5.11.16",
|
||||
"@mui/material": "5.13.3",
|
||||
"@react-hook/resize-observer": "1.2.6",
|
||||
"@tanstack/react-query": "4.29.12",
|
||||
"@tanstack/react-query-devtools": "4.29.12",
|
||||
"blurhash": "2.0.5",
|
||||
|
@ -2980,6 +2981,11 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@juggle/resize-observer": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"node_modules/@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
||||
|
@ -3375,6 +3381,35 @@
|
|||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-hook/latest": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz",
|
||||
"integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-hook/passive-layout-effect": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz",
|
||||
"integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-hook/resize-observer": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/resize-observer/-/resize-observer-1.2.6.tgz",
|
||||
"integrity": "sha512-DlBXtLSW0DqYYTW3Ft1/GQFZlTdKY5VAFIC4+km6IK5NiPPDFchGbEJm1j6pSgMqPRHbUQgHJX7RaR76ic1LWA==",
|
||||
"dependencies": {
|
||||
"@juggle/resize-observer": "^3.3.1",
|
||||
"@react-hook/latest": "^1.0.2",
|
||||
"@react-hook/passive-layout-effect": "^1.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.1.tgz",
|
||||
|
@ -22455,6 +22490,11 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@juggle/resize-observer": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
||||
|
@ -22677,6 +22717,28 @@
|
|||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
||||
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw=="
|
||||
},
|
||||
"@react-hook/latest": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz",
|
||||
"integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@react-hook/passive-layout-effect": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz",
|
||||
"integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@react-hook/resize-observer": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/resize-observer/-/resize-observer-1.2.6.tgz",
|
||||
"integrity": "sha512-DlBXtLSW0DqYYTW3Ft1/GQFZlTdKY5VAFIC4+km6IK5NiPPDFchGbEJm1j6pSgMqPRHbUQgHJX7RaR76ic1LWA==",
|
||||
"requires": {
|
||||
"@juggle/resize-observer": "^3.3.1",
|
||||
"@react-hook/latest": "^1.0.2",
|
||||
"@react-hook/passive-layout-effect": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@remix-run/router": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.1.tgz",
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
"@loadable/component": "5.15.3",
|
||||
"@mui/icons-material": "5.11.16",
|
||||
"@mui/material": "5.13.3",
|
||||
"@react-hook/resize-observer": "1.2.6",
|
||||
"@tanstack/react-query": "4.29.12",
|
||||
"@tanstack/react-query-devtools": "4.29.12",
|
||||
"blurhash": "2.0.5",
|
||||
|
|
|
@ -10,7 +10,6 @@ enum Direction {
|
|||
}
|
||||
|
||||
interface ScrollButtonsProps {
|
||||
scrollRef?: React.MutableRefObject<HTMLElement | null>;
|
||||
scrollerFactoryRef: React.MutableRefObject<scrollerFactory | null>;
|
||||
scrollState: {
|
||||
scrollSize: number;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import useElementSize from 'hooks/useElementSize';
|
||||
import layoutManager from '../../components/layoutManager';
|
||||
import dom from '../../scripts/dom';
|
||||
import browser from '../../scripts/browser';
|
||||
|
@ -32,14 +33,14 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
isAllowNativeSmoothScrollEnabled,
|
||||
children
|
||||
}) => {
|
||||
const [scrollRef, size] = useElementSize();
|
||||
|
||||
const [showControls, setShowControls] = useState(false);
|
||||
const [scrollState, setScrollState] = useState({
|
||||
scrollSize: 0,
|
||||
scrollSize: size.width,
|
||||
scrollPos: 0,
|
||||
scrollWidth: 0
|
||||
});
|
||||
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const scrollerFactoryRef = useRef<scrollerFactory | null>(null);
|
||||
|
||||
const getScrollSlider = useCallback(() => {
|
||||
|
@ -125,7 +126,7 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
});
|
||||
}, [getScrollPosition, getScrollSize, getScrollWidth]);
|
||||
|
||||
const initCenterFocus = useCallback((elem: EventTarget, scrollerInstance: scrollerFactory) => {
|
||||
const initCenterFocus = useCallback((elem, scrollerInstance: scrollerFactory) => {
|
||||
dom.addEventListener(elem, 'focus', function (e: FocusEvent) {
|
||||
const focused = focusManager.focusableParent(e.target);
|
||||
if (focused) {
|
||||
|
@ -150,15 +151,10 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
}, [scrollerFactoryRef]);
|
||||
|
||||
useEffect(() => {
|
||||
const scrollerElement = scrollRef.current as HTMLDivElement;
|
||||
|
||||
const horizontal = isHorizontalEnabled !== false;
|
||||
const scrollbuttons = isScrollButtonsEnabled !== false;
|
||||
const mousewheel = isMouseWheelEnabled !== false;
|
||||
|
||||
const slider = scrollerElement.querySelector('.scrollSlider');
|
||||
|
||||
const scrollFrame = scrollerElement;
|
||||
const enableScrollButtons = layoutManager.desktop && horizontal && scrollbuttons;
|
||||
|
||||
const options = {
|
||||
|
@ -166,7 +162,7 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
mouseDragging: 1,
|
||||
mouseWheel: mousewheel,
|
||||
touchDragging: 1,
|
||||
slidee: slider,
|
||||
slidee: scrollRef.current?.querySelector('.scrollSlider'),
|
||||
scrollBy: 200,
|
||||
speed: horizontal ? 270 : 240,
|
||||
elasticBounds: 1,
|
||||
|
@ -183,12 +179,12 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
};
|
||||
|
||||
// If just inserted it might not have any height yet - yes this is a hack
|
||||
scrollerFactoryRef.current = new scrollerFactory(scrollFrame, options);
|
||||
scrollerFactoryRef.current = new scrollerFactory(scrollRef.current, options);
|
||||
scrollerFactoryRef.current.init();
|
||||
scrollerFactoryRef.current.reload();
|
||||
|
||||
if (layoutManager.tv && isCenterFocusEnabled) {
|
||||
initCenterFocus(scrollerElement, scrollerFactoryRef.current);
|
||||
initCenterFocus(scrollRef.current, scrollerFactoryRef.current);
|
||||
}
|
||||
|
||||
if (enableScrollButtons) {
|
||||
|
@ -200,9 +196,8 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
}
|
||||
|
||||
return () => {
|
||||
const scrollerInstance = scrollerFactoryRef.current;
|
||||
if (scrollerInstance) {
|
||||
scrollerInstance.destroy();
|
||||
if (scrollerFactoryRef.current) {
|
||||
scrollerFactoryRef.current.destroy();
|
||||
scrollerFactoryRef.current = null;
|
||||
}
|
||||
|
||||
|
@ -223,7 +218,8 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
isScrollEventEnabled,
|
||||
isSkipFocusWhenVisibleEnabled,
|
||||
onScroll,
|
||||
removeScrollEventListener
|
||||
removeScrollEventListener,
|
||||
scrollRef
|
||||
]);
|
||||
|
||||
return (
|
||||
|
@ -231,7 +227,6 @@ const Scroller: FC<ScrollerProps> = ({
|
|||
{
|
||||
showControls && scrollState.scrollWidth > scrollState.scrollSize + 20
|
||||
&& <ScrollButtons
|
||||
scrollRef={scrollRef}
|
||||
scrollerFactoryRef={scrollerFactoryRef}
|
||||
scrollState={scrollState}
|
||||
/>
|
||||
|
|
25
src/hooks/useElementSize.ts
Normal file
25
src/hooks/useElementSize.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { MutableRefObject, useLayoutEffect, useRef, useState } from 'react';
|
||||
import useResizeObserver from '@react-hook/resize-observer';
|
||||
|
||||
interface Size {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export default function useElementSize<
|
||||
T extends HTMLElement = HTMLDivElement
|
||||
>(): [MutableRefObject<T | null>, Size] {
|
||||
const target = useRef<T | null>(null);
|
||||
const [size, setSize] = useState<Size>({
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
target.current && setSize(target.current.getBoundingClientRect());
|
||||
}, [target]);
|
||||
|
||||
useResizeObserver(target, (entry) => setSize(entry.contentRect));
|
||||
|
||||
return [target, size];
|
||||
}
|
|
@ -166,6 +166,9 @@ const config = {
|
|||
path.resolve(__dirname, 'node_modules/event-target-polyfill'),
|
||||
path.resolve(__dirname, 'node_modules/rvfc-polyfill'),
|
||||
path.resolve(__dirname, 'node_modules/@jellyfin/sdk'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/latest'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/passive-layout-effect'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/resize-observer'),
|
||||
path.resolve(__dirname, 'node_modules/@remix-run/router'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/query-core'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/react-query'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue