mirror of
https://github.com/Sonarr/Sonarr
synced 2024-12-21 23:33:00 +00:00
useMeasure instead of Measure in TypeScript components
This commit is contained in:
parent
a500f4ed14
commit
251f3a89b9
3 changed files with 35 additions and 44 deletions
|
@ -1,10 +1,9 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import AppState from 'App/State/AppState';
|
import AppState from 'App/State/AppState';
|
||||||
import * as commandNames from 'Commands/commandNames';
|
import * as commandNames from 'Commands/commandNames';
|
||||||
import Measure from 'Components/Measure';
|
|
||||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
|
@ -12,6 +11,7 @@ import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||||
|
import useMeasure from 'Helpers/Hooks/useMeasure';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons } from 'Helpers/Props';
|
||||||
import NoSeries from 'Series/NoSeries';
|
import NoSeries from 'Series/NoSeries';
|
||||||
import {
|
import {
|
||||||
|
@ -96,27 +96,13 @@ function CalendarPage() {
|
||||||
const customFilters = useSelector(createCustomFiltersSelector('calendar'));
|
const customFilters = useSelector(createCustomFiltersSelector('calendar'));
|
||||||
const hasSeries = !!useSelector(createSeriesCountSelector());
|
const hasSeries = !!useSelector(createSeriesCountSelector());
|
||||||
|
|
||||||
|
const [pageContentRef, { width }] = useMeasure();
|
||||||
const [isCalendarLinkModalOpen, setIsCalendarLinkModalOpen] = useState(false);
|
const [isCalendarLinkModalOpen, setIsCalendarLinkModalOpen] = useState(false);
|
||||||
const [isOptionsModalOpen, setIsOptionsModalOpen] = useState(false);
|
const [isOptionsModalOpen, setIsOptionsModalOpen] = useState(false);
|
||||||
const [width, setWidth] = useState(0);
|
|
||||||
|
|
||||||
const isMeasured = width > 0;
|
const isMeasured = width > 0;
|
||||||
const PageComponent = hasSeries ? Calendar : NoSeries;
|
const PageComponent = hasSeries ? Calendar : NoSeries;
|
||||||
|
|
||||||
const handleMeasure = useCallback(
|
|
||||||
({ width: newWidth }: { width: number }) => {
|
|
||||||
setWidth(newWidth);
|
|
||||||
|
|
||||||
const dayCount = Math.max(
|
|
||||||
3,
|
|
||||||
Math.min(7, Math.floor(newWidth / MINIMUM_DAY_WIDTH))
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(setCalendarDaysCount({ dayCount }));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleGetCalendarLinkPress = useCallback(() => {
|
const handleGetCalendarLinkPress = useCallback(() => {
|
||||||
setIsCalendarLinkModalOpen(true);
|
setIsCalendarLinkModalOpen(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -152,6 +138,19 @@ function CalendarPage() {
|
||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (width === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dayCount = Math.max(
|
||||||
|
3,
|
||||||
|
Math.min(7, Math.floor(width / MINIMUM_DAY_WIDTH))
|
||||||
|
);
|
||||||
|
|
||||||
|
dispatch(setCalendarDaysCount({ dayCount }));
|
||||||
|
}, [width, dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title={translate('Calendar')}>
|
<PageContent title={translate('Calendar')}>
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
|
@ -200,13 +199,11 @@ function CalendarPage() {
|
||||||
</PageToolbar>
|
</PageToolbar>
|
||||||
|
|
||||||
<PageContentBody
|
<PageContentBody
|
||||||
|
ref={pageContentRef}
|
||||||
className={styles.calendarPageBody}
|
className={styles.calendarPageBody}
|
||||||
innerClassName={styles.calendarInnerPageBody}
|
innerClassName={styles.calendarInnerPageBody}
|
||||||
>
|
>
|
||||||
<Measure whitelist={['width']} onMeasure={handleMeasure}>
|
{isMeasured ? <PageComponent totalItems={0} /> : <div />}
|
||||||
{isMeasured ? <PageComponent totalItems={0} /> : <div />}
|
|
||||||
</Measure>
|
|
||||||
|
|
||||||
{hasSeries && <Legend />}
|
{hasSeries && <Legend />}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ import { Manager, Popper, Reference } from 'react-popper';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import Measure from 'Components/Measure';
|
|
||||||
import Modal from 'Components/Modal/Modal';
|
import Modal from 'Components/Modal/Modal';
|
||||||
import ModalBody from 'Components/Modal/ModalBody';
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
import Portal from 'Components/Portal';
|
import Portal from 'Components/Portal';
|
||||||
import Scroller from 'Components/Scroller/Scroller';
|
import Scroller from 'Components/Scroller/Scroller';
|
||||||
|
import useMeasure from 'Helpers/Hooks/useMeasure';
|
||||||
import { icons, scrollDirections, sizes } from 'Helpers/Props';
|
import { icons, scrollDirections, sizes } from 'Helpers/Props';
|
||||||
import ArrayElement from 'typings/Helpers/ArrayElement';
|
import ArrayElement from 'typings/Helpers/ArrayElement';
|
||||||
import { EnhancedSelectInputChanged, InputChanged } from 'typings/inputs';
|
import { EnhancedSelectInputChanged, InputChanged } from 'typings/inputs';
|
||||||
|
@ -160,13 +160,13 @@ function EnhancedSelectInput<T extends EnhancedSelectInputValue<V>, V>(
|
||||||
onOpen,
|
onOpen,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const [measureRef, { width }] = useMeasure();
|
||||||
const updater = useRef<(() => void) | null>(null);
|
const updater = useRef<(() => void) | null>(null);
|
||||||
const buttonId = useMemo(() => getUniqueElementId(), []);
|
const buttonId = useMemo(() => getUniqueElementId(), []);
|
||||||
const optionsId = useMemo(() => getUniqueElementId(), []);
|
const optionsId = useMemo(() => getUniqueElementId(), []);
|
||||||
const [selectedIndex, setSelectedIndex] = useState(
|
const [selectedIndex, setSelectedIndex] = useState(
|
||||||
getSelectedIndex(value, values)
|
getSelectedIndex(value, values)
|
||||||
);
|
);
|
||||||
const [width, setWidth] = useState(0);
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const isMobile = useMemo(() => isMobileUtil(), []);
|
const isMobile = useMemo(() => isMobileUtil(), []);
|
||||||
|
|
||||||
|
@ -381,13 +381,6 @@ function EnhancedSelectInput<T extends EnhancedSelectInputValue<V>, V>(
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMeasure = useCallback(
|
|
||||||
({ width: newWidth }: { width: number }) => {
|
|
||||||
setWidth(newWidth);
|
|
||||||
},
|
|
||||||
[setWidth]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleOptionsModalClose = useCallback(() => {
|
const handleOptionsModalClose = useCallback(() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}, [setIsOpen]);
|
}, [setIsOpen]);
|
||||||
|
@ -421,7 +414,7 @@ function EnhancedSelectInput<T extends EnhancedSelectInputValue<V>, V>(
|
||||||
<Reference>
|
<Reference>
|
||||||
{({ ref }) => (
|
{({ ref }) => (
|
||||||
<div ref={ref} id={buttonId}>
|
<div ref={ref} id={buttonId}>
|
||||||
<Measure whitelist={['width']} onMeasure={handleMeasure}>
|
<div ref={measureRef}>
|
||||||
{isEditable && typeof value === 'string' ? (
|
{isEditable && typeof value === 'string' ? (
|
||||||
<div className={styles.editableContainer}>
|
<div className={styles.editableContainer}>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
@ -495,7 +488,7 @@ function EnhancedSelectInput<T extends EnhancedSelectInputValue<V>, V>(
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</Measure>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
|
@ -4,9 +4,9 @@ import React, {
|
||||||
ComponentProps,
|
ComponentProps,
|
||||||
ForwardedRef,
|
ForwardedRef,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
MutableRefObject,
|
|
||||||
ReactNode,
|
ReactNode,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { ScrollDirection } from 'Helpers/Props/scrollDirections';
|
import { ScrollDirection } from 'Helpers/Props/scrollDirections';
|
||||||
|
@ -43,13 +43,14 @@ const Scroller = forwardRef(
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const internalRef = useRef();
|
const internalRef = useRef<HTMLDivElement>(null);
|
||||||
const currentRef = (ref as MutableRefObject<HTMLDivElement>) ?? internalRef;
|
|
||||||
|
useImperativeHandle(ref, () => internalRef.current!, []);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
if (initialScrollTop != null) {
|
if (initialScrollTop != null) {
|
||||||
currentRef.current.scrollTop = initialScrollTop;
|
internalRef.current!.scrollTop = initialScrollTop;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
@ -58,16 +59,16 @@ const Scroller = forwardRef(
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (scrollTop != null) {
|
if (scrollTop != null) {
|
||||||
currentRef.current.scrollTop = scrollTop;
|
internalRef.current!.scrollTop = scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoFocus && scrollDirection !== 'none') {
|
if (autoFocus && scrollDirection !== 'none') {
|
||||||
currentRef.current.focus({ preventScroll: true });
|
internalRef.current!.focus({ preventScroll: true });
|
||||||
}
|
}
|
||||||
}, [autoFocus, currentRef, scrollDirection, scrollTop]);
|
}, [autoFocus, scrollDirection, scrollTop]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const div = currentRef.current;
|
const div = internalRef.current!;
|
||||||
|
|
||||||
const handleScroll = throttle(() => {
|
const handleScroll = throttle(() => {
|
||||||
const scrollLeft = div.scrollLeft;
|
const scrollLeft = div.scrollLeft;
|
||||||
|
@ -76,17 +77,17 @@ const Scroller = forwardRef(
|
||||||
onScroll?.({ scrollLeft, scrollTop });
|
onScroll?.({ scrollLeft, scrollTop });
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
div.addEventListener('scroll', handleScroll);
|
div?.addEventListener('scroll', handleScroll);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
div.removeEventListener('scroll', handleScroll);
|
div?.removeEventListener('scroll', handleScroll);
|
||||||
};
|
};
|
||||||
}, [currentRef, onScroll]);
|
}, [onScroll]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
ref={currentRef}
|
ref={internalRef}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
styles.scroller,
|
styles.scroller,
|
||||||
|
|
Loading…
Reference in a new issue