1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

fix resizeobserver loop

This commit is contained in:
grafixeyehero 2023-06-29 23:17:59 +03:00
parent 00ec92cc02
commit 5598f49c32
6 changed files with 103 additions and 18 deletions

62
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -10,7 +10,6 @@ enum Direction {
}
interface ScrollButtonsProps {
scrollRef?: React.MutableRefObject<HTMLElement | null>;
scrollerFactoryRef: React.MutableRefObject<scrollerFactory | null>;
scrollState: {
scrollSize: number;

View file

@ -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}
/>

View 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];
}

View file

@ -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'),