refactor: refactor components/upload/UploadList/index.tsx (#51074)

This commit is contained in:
afc163 2024-09-30 14:08:03 +08:00 committed by GitHub
parent d9c778ca5f
commit fc91464a9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -6,6 +6,7 @@ import PictureTwoTone from '@ant-design/icons/PictureTwoTone';
import classNames from 'classnames';
import type { CSSMotionListProps } from 'rc-motion';
import CSSMotion, { CSSMotionList } from 'rc-motion';
import omit from 'rc-util/lib/omit';
import useForceUpdate from '../../_util/hooks/useForceUpdate';
import initCollapseMotion from '../../_util/motion';
@ -18,7 +19,7 @@ import { isImageUrl, previewImage } from '../utils';
import ListItem from './ListItem';
interface UploadListRef {
handlePreview: (file: UploadFile, e?: React.SyntheticEvent<HTMLElement>) => void;
handlePreview: (file: UploadFile, e: React.SyntheticEvent<HTMLElement>) => void;
handleDownload: (file: UploadFile) => void;
}
@ -52,31 +53,26 @@ const InternalUploadList: React.ForwardRefRenderFunction<UploadListRef, UploadLi
} = props;
const forceUpdate = useForceUpdate();
const [motionAppear, setMotionAppear] = React.useState(false);
const isPictureCardOrCirle = ['picture-card', 'picture-circle'].includes(listType);
// ============================= Effect =============================
React.useEffect(() => {
if (listType !== 'picture' && listType !== 'picture-card' && listType !== 'picture-circle') {
if (!listType.startsWith('picture')) {
return;
}
(items || []).forEach((file) => {
if (
typeof document === 'undefined' ||
typeof window === 'undefined' ||
!(window as any).FileReader ||
!(window as any).File ||
!(file.originFileObj instanceof File || (file.originFileObj as any) instanceof Blob) ||
file.thumbUrl !== undefined
) {
return;
}
file.thumbUrl = '';
if (previewFile) {
previewFile(file.originFileObj as File).then((previewDataUrl: string) => {
// Need append '' to avoid dead loop
file.thumbUrl = previewDataUrl || '';
forceUpdate();
});
}
previewFile?.(file.originFileObj as File).then((previewDataUrl: string) => {
// Need append '' to avoid dead loop
file.thumbUrl = previewDataUrl || '';
forceUpdate();
});
});
}, [listType, items, previewFile]);
@ -85,11 +81,11 @@ const InternalUploadList: React.ForwardRefRenderFunction<UploadListRef, UploadLi
}, []);
// ============================= Events =============================
const onInternalPreview = (file: UploadFile, e?: React.SyntheticEvent<HTMLElement>) => {
const onInternalPreview = (file: UploadFile, e: React.SyntheticEvent<HTMLElement>) => {
if (!onPreview) {
return;
}
e?.preventDefault();
e.preventDefault();
return onPreview(file);
};
@ -110,14 +106,12 @@ const InternalUploadList: React.ForwardRefRenderFunction<UploadListRef, UploadLi
return iconRender(file, listType);
}
const isLoading = file.status === 'uploading';
const fileIcon = isImgUrl?.(file) ? <PictureTwoTone /> : <FileTwoTone />;
let icon: React.ReactNode = isLoading ? <LoadingOutlined /> : <PaperClipOutlined />;
if (listType === 'picture') {
icon = isLoading ? <LoadingOutlined /> : fileIcon;
} else if (listType === 'picture-card' || listType === 'picture-circle') {
icon = isLoading ? locale.uploading : fileIcon;
if (listType.startsWith('picture')) {
const loadingIcon = listType === 'picture' ? <LoadingOutlined /> : locale.uploading;
const fileIcon = isImgUrl?.(file) ? <PictureTwoTone /> : <FileTwoTone />;
return isLoading ? loadingIcon : fileIcon;
}
return icon;
return isLoading ? <LoadingOutlined /> : <PaperClipOutlined />;
};
const actionIconRender = (
@ -142,15 +136,15 @@ const InternalUploadList: React.ForwardRefRenderFunction<UploadListRef, UploadLi
if (acceptUploadDisabled) {
btnProps.disabled = disabled;
}
if (React.isValidElement(customIcon)) {
const btnIcon = cloneElement(customIcon, {
...customIcon.props,
onClick: () => {},
});
return <Button {...btnProps} icon={btnIcon} />;
}
return (
return React.isValidElement(customIcon) ? (
<Button
{...btnProps}
icon={cloneElement(customIcon, {
...customIcon.props,
onClick: () => {},
})}
/>
) : (
<Button {...btnProps}>
<span>{customIcon}</span>
</Button>
@ -172,39 +166,18 @@ const InternalUploadList: React.ForwardRefRenderFunction<UploadListRef, UploadLi
const listClassNames = classNames(`${prefixCls}-list`, `${prefixCls}-list-${listType}`);
// >>> Motion config
const motionKeyList = [...items.map((file) => ({ key: file.uid, file }))];
const animationDirection =
listType === 'picture-card' || listType === 'picture-circle' ? 'animate-inline' : 'animate';
// const transitionName = list.length === 0 ? '' : `${prefixCls}-${animationDirection}`;
let motionConfig: Omit<CSSMotionListProps, 'onVisibleChanged'> = {
const listItemMotion = React.useMemo(
() => omit(initCollapseMotion(rootPrefixCls), ['onAppearEnd', 'onEnterEnd', 'onLeaveEnd']),
[rootPrefixCls],
);
const motionConfig: Omit<CSSMotionListProps, 'onVisibleChanged'> = {
...(isPictureCardOrCirle ? {} : listItemMotion),
motionDeadline: 2000,
motionName: `${prefixCls}-${animationDirection}`,
keys: motionKeyList,
motionName: `${prefixCls}-${isPictureCardOrCirle ? 'animate-inline' : 'animate'}`,
keys: [...items.map((file) => ({ key: file.uid, file }))],
motionAppear,
};
const listItemMotion = React.useMemo<Partial<CSSMotionListProps>>(() => {
const motion = {
...initCollapseMotion(rootPrefixCls),
};
delete motion.onAppearEnd;
delete motion.onEnterEnd;
delete motion.onLeaveEnd;
return motion;
}, [rootPrefixCls]);
if (listType !== 'picture-card' && listType !== 'picture-circle') {
motionConfig = {
...listItemMotion,
...motionConfig,
};
}
return (
<div className={listClassNames}>
<CSSMotionList {...motionConfig} component={false}>