mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
fixed sortables rerendering
This commit is contained in:
parent
f3fa88d72c
commit
c58b4feb4a
5 changed files with 110 additions and 80 deletions
|
@ -1,4 +1,4 @@
|
||||||
import React, { FC, useCallback } from 'react';
|
import React, { FC, useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { AudioPlayer } from '~/components/media/AudioPlayer';
|
import { AudioPlayer } from '~/components/media/AudioPlayer';
|
||||||
import { AudioUpload } from '~/components/upload/AudioUpload';
|
import { AudioUpload } from '~/components/upload/AudioUpload';
|
||||||
|
@ -17,6 +17,29 @@ interface SortableAudioGridProps {
|
||||||
onDelete: (file_id: IFile['id']) => void;
|
onDelete: (file_id: IFile['id']) => void;
|
||||||
onTitleChange: (file_id: IFile['id'], title: string) => void;
|
onTitleChange: (file_id: IFile['id'], title: string) => void;
|
||||||
}
|
}
|
||||||
|
const renderItem = ({
|
||||||
|
item,
|
||||||
|
key,
|
||||||
|
onDelete,
|
||||||
|
onTitleChange,
|
||||||
|
}: {
|
||||||
|
item: IFile;
|
||||||
|
key?: string | number;
|
||||||
|
onDelete?: (id: IFile['id']) => void;
|
||||||
|
onTitleChange?: (file_id: IFile['id'], title: string) => void;
|
||||||
|
}) => (
|
||||||
|
<AudioPlayer file={item} onDelete={onDelete} isEditing onTitleChange={onTitleChange} key={key} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderLocked = ({ locked }: { locked: UploadStatus }) => (
|
||||||
|
<AudioUpload
|
||||||
|
id={locked.id}
|
||||||
|
is_uploading
|
||||||
|
title={locked.name}
|
||||||
|
progress={locked.progress}
|
||||||
|
key={locked.id}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const SortableAudioGrid: FC<SortableAudioGridProps> = ({
|
const SortableAudioGrid: FC<SortableAudioGridProps> = ({
|
||||||
items,
|
items,
|
||||||
|
@ -26,31 +49,8 @@ const SortableAudioGrid: FC<SortableAudioGridProps> = ({
|
||||||
onSortEnd,
|
onSortEnd,
|
||||||
onTitleChange,
|
onTitleChange,
|
||||||
}) => {
|
}) => {
|
||||||
const renderItem = useCallback<FC<{ item: IFile; key?: string | number }>>(
|
const renderItemProps = useMemo(() => ({ onDelete, onTitleChange }), [onDelete, onTitleChange]);
|
||||||
({ item, key }) => (
|
const renderLockedProps = useMemo(() => ({}), []);
|
||||||
<AudioPlayer
|
|
||||||
file={item}
|
|
||||||
onDelete={onDelete}
|
|
||||||
isEditing
|
|
||||||
onTitleChange={onTitleChange}
|
|
||||||
key={key}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[onTitleChange, onDelete]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderLocked = useCallback<FC<{ locked: UploadStatus }>>(
|
|
||||||
({ locked }) => (
|
|
||||||
<AudioUpload
|
|
||||||
id={locked.id}
|
|
||||||
is_uploading
|
|
||||||
title={locked.name}
|
|
||||||
progress={locked.progress}
|
|
||||||
key={locked.id}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableList
|
<SortableList
|
||||||
|
@ -59,7 +59,9 @@ const SortableAudioGrid: FC<SortableAudioGridProps> = ({
|
||||||
getID={it => it.id}
|
getID={it => it.id}
|
||||||
getLockedID={it => it.id}
|
getLockedID={it => it.id}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
|
renderItemProps={renderItemProps}
|
||||||
renderLocked={renderLocked}
|
renderLocked={renderLocked}
|
||||||
|
renderLockedProps={renderLockedProps}
|
||||||
onSortEnd={onSortEnd}
|
onSortEnd={onSortEnd}
|
||||||
className={className}
|
className={className}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -12,29 +12,38 @@ import { SortableItem } from '../SortableItem';
|
||||||
|
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
interface SortableGridProps<T extends {}, R extends {}> {
|
interface SortableGridProps<
|
||||||
items: T[];
|
ItemRendererProps extends {},
|
||||||
locked: R[];
|
LockedRendererProps extends {},
|
||||||
getID: (item: T) => number | string;
|
Item extends {},
|
||||||
getLockedID: (locked: R) => number | string;
|
Locked extends {}
|
||||||
renderItem: FC<{ item: T }>;
|
> {
|
||||||
renderLocked: FC<{ locked: R }>;
|
items: Item[];
|
||||||
onSortEnd: (newVal: T[]) => void;
|
locked: Locked[];
|
||||||
|
getID: (item: Item) => number | string;
|
||||||
|
getLockedID: (locked: Locked) => number | string;
|
||||||
|
renderItem: FC<ItemRendererProps & { item: Item }>;
|
||||||
|
renderItemProps: ItemRendererProps;
|
||||||
|
renderLocked: FC<LockedRendererProps & { locked: Locked }>;
|
||||||
|
renderLockedProps: LockedRendererProps;
|
||||||
|
onSortEnd: (newVal: Item[]) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortableGrid = <T, R>({
|
const SortableGrid = <RIP, RLP, I, L>({
|
||||||
items,
|
items,
|
||||||
locked,
|
locked,
|
||||||
getID,
|
getID,
|
||||||
getLockedID,
|
getLockedID,
|
||||||
className,
|
className,
|
||||||
renderItem,
|
renderItem,
|
||||||
|
renderItemProps,
|
||||||
renderLocked,
|
renderLocked,
|
||||||
|
renderLockedProps,
|
||||||
onSortEnd,
|
onSortEnd,
|
||||||
size,
|
size,
|
||||||
}: SortableGridProps<T, R>) => {
|
}: SortableGridProps<RIP, RLP, I, L>) => {
|
||||||
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
|
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
|
||||||
items,
|
items,
|
||||||
getID,
|
getID,
|
||||||
|
@ -66,17 +75,23 @@ const SortableGrid = <T, R>({
|
||||||
draggingItem && getID(item) === getID(draggingItem) ? styles.dragging : undefined
|
draggingItem && getID(item) === getID(draggingItem) ? styles.dragging : undefined
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{createElement(renderItem, { item })}
|
{createElement(renderItem, { ...renderItemProps, item })}
|
||||||
</SortableItem>
|
</SortableItem>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{locked.map(item =>
|
{locked.map(item =>
|
||||||
createElement(renderLocked, { locked: item, key: getLockedID(item) })
|
createElement(renderLocked, {
|
||||||
|
...renderLockedProps,
|
||||||
|
locked: item,
|
||||||
|
key: getLockedID(item),
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DragOverlay>
|
<DragOverlay>
|
||||||
{draggingItem ? (
|
{draggingItem ? (
|
||||||
<DragOverlayItem>{createElement(renderItem, { item: draggingItem })}</DragOverlayItem>
|
<DragOverlayItem>
|
||||||
|
{createElement(renderItem, { ...renderItemProps, item: draggingItem })}
|
||||||
|
</DragOverlayItem>
|
||||||
) : null}
|
) : null}
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { FC, useCallback } from 'react';
|
import React, { FC, useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { ImageUpload } from '~/components/upload/ImageUpload';
|
import { ImageUpload } from '~/components/upload/ImageUpload';
|
||||||
import { ImagePresets } from '~/constants/urls';
|
import { ImagePresets } from '~/constants/urls';
|
||||||
|
@ -18,6 +18,19 @@ interface SortableImageGridProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
const renderItem = ({ item, onDelete }: { item: IFile; onDelete: (fileId: number) => void }) => (
|
||||||
|
<ImageUpload id={item.id} thumb={getURL(item, ImagePresets.cover)} onDrop={onDelete} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderLocked = ({
|
||||||
|
locked,
|
||||||
|
onDelete,
|
||||||
|
}: {
|
||||||
|
locked: UploadStatus;
|
||||||
|
onDelete: (fileId: number) => void;
|
||||||
|
}) => (
|
||||||
|
<ImageUpload thumb={locked.thumbnail} onDrop={onDelete} progress={locked.progress} is_uploading />
|
||||||
|
);
|
||||||
|
|
||||||
const SortableImageGrid: FC<SortableImageGridProps> = ({
|
const SortableImageGrid: FC<SortableImageGridProps> = ({
|
||||||
items,
|
items,
|
||||||
|
@ -27,24 +40,7 @@ const SortableImageGrid: FC<SortableImageGridProps> = ({
|
||||||
onSortEnd,
|
onSortEnd,
|
||||||
size,
|
size,
|
||||||
}) => {
|
}) => {
|
||||||
const renderItem = useCallback<FC<{ item: IFile }>>(
|
const props = useMemo(() => ({ onDelete }), [onDelete]);
|
||||||
({ item }) => (
|
|
||||||
<ImageUpload id={item.id} thumb={getURL(item, ImagePresets.cover)} onDrop={onDelete} />
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderLocked = useCallback<FC<{ locked: UploadStatus }>>(
|
|
||||||
({ locked }) => (
|
|
||||||
<ImageUpload
|
|
||||||
thumb={locked.thumbnail}
|
|
||||||
onDrop={onDelete}
|
|
||||||
progress={locked.progress}
|
|
||||||
is_uploading
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableGrid
|
<SortableGrid
|
||||||
|
@ -53,7 +49,9 @@ const SortableImageGrid: FC<SortableImageGridProps> = ({
|
||||||
getID={it => it.id}
|
getID={it => it.id}
|
||||||
getLockedID={it => it.id}
|
getLockedID={it => it.id}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
|
renderItemProps={props}
|
||||||
renderLocked={renderLocked}
|
renderLocked={renderLocked}
|
||||||
|
renderLockedProps={props}
|
||||||
onSortEnd={onSortEnd}
|
onSortEnd={onSortEnd}
|
||||||
className={className}
|
className={className}
|
||||||
size={size}
|
size={size}
|
||||||
|
|
|
@ -1,36 +1,45 @@
|
||||||
import React, { createElement, FC } from "react";
|
import React, { createElement, FC } from 'react';
|
||||||
|
|
||||||
import { closestCenter, DndContext, DragOverlay } from "@dnd-kit/core";
|
import { closestCenter, DndContext, DragOverlay } from '@dnd-kit/core';
|
||||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
||||||
import classNames from "classnames";
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { DragOverlayItem } from "~/components/sortable/DragOverlayItem";
|
import { DragOverlayItem } from '~/components/sortable/DragOverlayItem';
|
||||||
import { SortableItem } from "~/components/sortable/SortableItem";
|
import { SortableItem } from '~/components/sortable/SortableItem';
|
||||||
import { useSortableActions } from "~/hooks/sortable";
|
import { useSortableActions } from '~/hooks/sortable';
|
||||||
|
|
||||||
import styles from "./styles.module.scss";
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
interface SortableListProps<T extends {}, R extends {}> {
|
interface SortableListProps<
|
||||||
items: T[];
|
RenderItemProps extends {},
|
||||||
locked: R[];
|
RenderLockedProps extends {},
|
||||||
getID: (item: T) => number | string;
|
Item extends {},
|
||||||
getLockedID: (locked: R) => number | string;
|
Locked extends {}
|
||||||
renderItem: FC<{ item: T }>;
|
> {
|
||||||
renderLocked: FC<{ locked: R }>;
|
items: Item[];
|
||||||
onSortEnd: (newVal: T[]) => void;
|
locked: Locked[];
|
||||||
|
getID: (item: Item) => number | string;
|
||||||
|
getLockedID: (locked: Locked) => number | string;
|
||||||
|
renderItem: FC<RenderItemProps & { item: Item }>;
|
||||||
|
renderItemProps: RenderItemProps;
|
||||||
|
renderLocked: FC<RenderLockedProps & { locked: Locked }>;
|
||||||
|
renderLockedProps: RenderLockedProps;
|
||||||
|
onSortEnd: (newVal: Item[]) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortableList = <T, R>({
|
const SortableList = <RIP, RLP, I, L>({
|
||||||
items,
|
items,
|
||||||
locked,
|
locked,
|
||||||
getID,
|
getID,
|
||||||
getLockedID,
|
getLockedID,
|
||||||
className,
|
className,
|
||||||
renderItem,
|
renderItem,
|
||||||
|
renderItemProps,
|
||||||
renderLocked,
|
renderLocked,
|
||||||
|
renderLockedProps,
|
||||||
onSortEnd,
|
onSortEnd,
|
||||||
}: SortableListProps<T, R>) => {
|
}: SortableListProps<RIP, RLP, I, L>) => {
|
||||||
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
|
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
|
||||||
items,
|
items,
|
||||||
getID,
|
getID,
|
||||||
|
@ -54,17 +63,23 @@ const SortableList = <T, R>({
|
||||||
draggingItem && getID(item) === getID(draggingItem) ? styles.dragging : undefined
|
draggingItem && getID(item) === getID(draggingItem) ? styles.dragging : undefined
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{createElement(renderItem, { item, key: getID(item) })}
|
{createElement(renderItem, { ...renderItemProps, item, key: getID(item) })}
|
||||||
</SortableItem>
|
</SortableItem>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{locked.map(item =>
|
{locked.map(item =>
|
||||||
createElement(renderLocked, { locked: item, key: getLockedID(item) })
|
createElement(renderLocked, {
|
||||||
|
...renderLockedProps,
|
||||||
|
locked: item,
|
||||||
|
key: getLockedID(item),
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DragOverlay>
|
<DragOverlay>
|
||||||
{draggingItem ? (
|
{draggingItem ? (
|
||||||
<DragOverlayItem>{createElement(renderItem, { item: draggingItem })}</DragOverlayItem>
|
<DragOverlayItem>
|
||||||
|
{createElement(renderItem, { ...renderItemProps, item: draggingItem })}
|
||||||
|
</DragOverlayItem>
|
||||||
) : null}
|
) : null}
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
</div>
|
</div>
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue