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

Update to React 18

This commit is contained in:
grafixeyehero 2024-06-02 20:58:11 +03:00
parent b5d6e37fb3
commit be891c3a98
36 changed files with 339 additions and 311 deletions

View file

@ -1,8 +1,27 @@
import escapeHTML from 'escape-html';
import React, { FunctionComponent } from 'react';
import React, { type FC } from 'react';
import globalize from '../scripts/globalize';
const createCheckBoxElement = ({ labelClassName, className, id, dataFilter, dataItemType, dataId, checkedAttribute, renderContent }: { labelClassName?: string, type?: string, className?: string, id?: string, dataFilter?: string, dataItemType?: string, dataId?: string, checkedAttribute?: string, renderContent?: string }) => ({
const createCheckBoxElement = ({
labelClassName,
className,
id,
dataFilter,
dataItemType,
dataId,
checkedAttribute,
renderContent
}: {
labelClassName?: string;
type?: string;
className?: string;
id?: string;
dataFilter?: string;
dataItemType?: string;
dataId?: string;
checkedAttribute?: string;
renderContent?: string;
}) => ({
__html: `<label ${labelClassName}>
<input
is="emby-checkbox"
@ -18,20 +37,31 @@ const createCheckBoxElement = ({ labelClassName, className, id, dataFilter, data
</label>`
});
type IProps = {
interface CheckBoxElementProps {
labelClassName?: string;
className?: string;
elementId?: string;
dataFilter?: string;
itemType?: string;
itemId?: string;
itemAppName?: string;
itemId?: string | null;
itemAppName?: string | null;
itemCheckedAttribute?: string;
itemName?: string
title?: string
};
itemName?: string | null;
title?: string;
}
const CheckBoxElement: FunctionComponent<IProps> = ({ labelClassName, className, elementId, dataFilter, itemType, itemId, itemAppName, itemCheckedAttribute, itemName, title }: IProps) => {
const CheckBoxElement: FC<CheckBoxElementProps> = ({
labelClassName,
className,
elementId,
dataFilter,
itemType,
itemId,
itemAppName,
itemCheckedAttribute,
itemName,
title
}) => {
const appName = itemAppName ? `- ${itemAppName}` : '';
const renderContent = itemName ?
`<span>${escapeHTML(itemName || '')} ${appName}</span>` :
@ -41,13 +71,17 @@ const CheckBoxElement: FunctionComponent<IProps> = ({ labelClassName, className,
<div
className='sectioncheckbox'
dangerouslySetInnerHTML={createCheckBoxElement({
labelClassName: labelClassName ? `class='${labelClassName}'` : '',
labelClassName: labelClassName ?
`class='${labelClassName}'` :
'',
className: className,
id: elementId ? `id='${elementId}'` : '',
dataFilter: dataFilter ? `data-filter='${dataFilter}'` : '',
dataItemType: itemType ? `data-itemtype='${itemType}'` : '',
dataId: itemId ? `data-id='${itemId}'` : '',
checkedAttribute: itemCheckedAttribute ? itemCheckedAttribute : '',
checkedAttribute: itemCheckedAttribute ?
itemCheckedAttribute :
'',
renderContent: renderContent
})}
/>

View file

@ -1,11 +1,21 @@
import classNames from 'classnames';
import React, { type DetailedHTMLProps, type InputHTMLAttributes, useState, useCallback, forwardRef } from 'react';
import React, {
type DetailedHTMLProps,
type InputHTMLAttributes,
useState,
useCallback,
forwardRef
} from 'react';
import './emby-input.scss';
interface InputProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
id: string,
label?: string
interface InputProps
extends DetailedHTMLProps<
InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
> {
id: string;
label?: string;
}
const Input = forwardRef<HTMLInputElement, InputProps>(
@ -13,7 +23,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
const [isFocused, setIsFocused] = useState(false);
const onBlurInternal = useCallback(
(e) => {
(e: React.FocusEvent<HTMLInputElement, Element>) => {
setIsFocused(false);
onBlur?.(e);
},
@ -21,7 +31,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
);
const onFocusInternal = useCallback(
(e) => {
(e: React.FocusEvent<HTMLInputElement, Element>) => {
setIsFocused(true);
onFocus?.(e);
},

View file

@ -1,3 +1,4 @@
import { ApiClient } from 'jellyfin-apiclient';
import React, { type FC, useCallback, useEffect, useState } from 'react';
import Events, { Event } from 'utils/events';
import serverNotifications from 'scripts/serverNotifications';
@ -50,7 +51,7 @@ interface RefreshIndicatorProps {
const RefreshIndicator: FC<RefreshIndicatorProps> = ({ item, className }) => {
const [progress, setProgress] = useState(item.RefreshProgress || 0);
const onRefreshProgress = useCallback((_e: Event, apiClient, info) => {
const onRefreshProgress = useCallback((_e: Event, _apiClient: ApiClient, info: { ItemId: string | null | undefined; Progress: string; }) => {
if (info.ItemId === item?.Id) {
setProgress(parseFloat(info.Progress));
}

View file

@ -3,13 +3,13 @@ import {
type LibraryUpdateInfo
} from '@jellyfin/sdk/lib/generated-client';
import { ApiClient } from 'jellyfin-apiclient';
import React, { type FC, useCallback, useEffect, useRef } from 'react';
import React, { type FC, type PropsWithChildren, useCallback, useEffect, useRef } from 'react';
import classNames from 'classnames';
import Box from '@mui/material/Box';
import Sortable from 'sortablejs';
import { useQueryClient } from '@tanstack/react-query';
import { usePlaylistsMoveItemMutation } from 'hooks/useFetchItems';
import Events, { Event } from 'utils/events';
import Events, { type Event } from 'utils/events';
import serverNotifications from 'scripts/serverNotifications';
import inputManager from 'scripts/inputManager';
import dom from 'scripts/dom';
@ -48,7 +48,7 @@ interface ItemsContainerProps {
queryKey?: string[]
}
const ItemsContainer: FC<ItemsContainerProps> = ({
const ItemsContainer: FC<PropsWithChildren<ItemsContainerProps>> = ({
className,
isContextMenuEnabled,
isMultiSelectEnabled,

View file

@ -1,4 +1,4 @@
import React, { type FC, useCallback, useEffect, useRef, useState } from 'react';
import React, { type FC, type PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import useElementSize from 'hooks/useElementSize';
import layoutManager from '../../components/layoutManager';
@ -21,7 +21,7 @@ interface ScrollerProps {
isAllowNativeSmoothScrollEnabled?: boolean;
}
const Scroller: FC<ScrollerProps> = ({
const Scroller: FC<PropsWithChildren<ScrollerProps>> = ({
className,
isHorizontalEnabled,
isMouseWheelEnabled,
@ -126,7 +126,7 @@ const Scroller: FC<ScrollerProps> = ({
});
}, [getScrollPosition, getScrollSize, getScrollWidth]);
const initCenterFocus = useCallback((elem, scrollerInstance: ScrollerFactory) => {
const initCenterFocus = useCallback((elem: HTMLElement, scrollerInstance: ScrollerFactory) => {
dom.addEventListener(elem, 'focus', function (e: FocusEvent) {
const focused = focusManager.focusableParent(e.target);
if (focused) {
@ -138,19 +138,26 @@ const Scroller: FC<ScrollerProps> = ({
});
}, []);
const addScrollEventListener = useCallback((fn, options) => {
const addScrollEventListener = useCallback((fn: () => void, options: AddEventListenerOptions | undefined) => {
if (scrollerFactoryRef.current) {
dom.addEventListener(scrollerFactoryRef.current.getScrollFrame(), scrollerFactoryRef.current.getScrollEventName(), fn, options);
}
}, [scrollerFactoryRef]);
const removeScrollEventListener = useCallback((fn, options) => {
const removeScrollEventListener = useCallback((fn: () => void, options: AddEventListenerOptions | undefined) => {
if (scrollerFactoryRef.current) {
dom.removeEventListener(scrollerFactoryRef.current.getScrollFrame(), scrollerFactoryRef.current.getScrollEventName(), fn, options);
}
}, [scrollerFactoryRef]);
useEffect(() => {
const frame = scrollRef.current;
if (!frame) {
console.error('Unexpected null reference');
return;
}
const horizontal = isHorizontalEnabled !== false;
const scrollbuttons = isScrollButtonsEnabled !== false;
const mousewheel = isMouseWheelEnabled !== false;
@ -179,12 +186,12 @@ const Scroller: FC<ScrollerProps> = ({
};
// If just inserted it might not have any height yet - yes this is a hack
scrollerFactoryRef.current = new ScrollerFactory(scrollRef.current, options);
scrollerFactoryRef.current = new ScrollerFactory(frame, options);
scrollerFactoryRef.current.init();
scrollerFactoryRef.current.reload();
if (layoutManager.tv && isCenterFocusEnabled) {
initCenterFocus(scrollRef.current, scrollerFactoryRef.current);
initCenterFocus(frame, scrollerFactoryRef.current);
}
if (enableScrollButtons) {