refactor: use @dnd-kit/core" instead of react-sortable-hoc

This commit is contained in:
tiddlygit-test 2021-03-12 00:36:43 +08:00
parent 2b08317b90
commit bbb53c12cc
5 changed files with 119 additions and 93 deletions

64
package-lock.json generated
View file

@ -2694,6 +2694,42 @@
"@date-io/core": "^2.10.6"
}
},
"@dnd-kit/accessibility": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-1.0.2.tgz",
"integrity": "sha512-aQq+B4But+369cYYtmXPUhqf26Fy9b/nR+uAP4cbhf3TXMlCqorT7bO7dT7cNe+me2DOf61GVr0mkrWtfsvR3A==",
"requires": {
"tslib": "^2.0.0"
}
},
"@dnd-kit/core": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-1.0.2.tgz",
"integrity": "sha512-etf7LmAye+Y3TDiHAivGPr4TXyDVtyV7jMxPPAVErdPoxKUcVjibnRhDeJlA7cRhioQE+rKmvs/EZ0XijuqrbQ==",
"requires": {
"@dnd-kit/accessibility": "^1.0.2",
"@dnd-kit/utilities": "^1.0.2",
"tslib": "^2.0.0"
}
},
"@dnd-kit/sortable": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-1.0.2.tgz",
"integrity": "sha512-lma9+LBATJ5A7hdnDqtD4Nam1dEX4fQYxi8W+C6qNk3nhG1AT1fjZ+GwokvDCEbGCD6GNDHlWZybJdc7dqb7mQ==",
"requires": {
"@dnd-kit/core": "^1.0.2",
"@dnd-kit/utilities": "^1.0.2",
"tslib": "^2.0.0"
}
},
"@dnd-kit/utilities": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-1.0.2.tgz",
"integrity": "sha512-RC3c9OVfr9Nx5acNwy278RCI0UOr8e08XQmws1w0lx+i+YIu74lQqat0MXR3zyQHimrduXRG/ctciuwj1JOgkQ==",
"requires": {
"tslib": "^2.0.0"
}
},
"@dsherret/to-absolute-glob": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
@ -4951,11 +4987,6 @@
"integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
"dev": true
},
"array-move": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/array-move/-/array-move-3.0.1.tgz",
"integrity": "sha512-H3Of6NIn2nNU1gsVDqDnYKY/LCdWvCMMOWifNGhKcVQgiZ6nOek39aESOvro6zmueP07exSl93YLvkN4fZOkSg=="
},
"array-reduce": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz",
@ -12433,15 +12464,6 @@
"p-is-promise": "^1.1.0"
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dev": true,
"requires": {
"loose-envify": "^1.0.0"
}
},
"inversify": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.5.tgz",
@ -16148,17 +16170,6 @@
"react-is": "^16.13.1"
}
},
"react-sortable-hoc": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.11.0.tgz",
"integrity": "sha512-v1CDCvdfoR3zLGNp6qsBa4J1BWMEVH25+UKxF/RvQRh+mrB+emqtVHMgZ+WreUiKJoEaiwYoScaueIKhMVBHUg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.2.0",
"invariant": "^2.2.4",
"prop-types": "^15.5.7"
}
},
"react-transition-group": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
@ -18751,8 +18762,7 @@
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
},
"tsutils": {
"version": "3.21.0",

View file

@ -68,10 +68,12 @@
}
},
"dependencies": {
"@dnd-kit/core": "^1.0.2",
"@dnd-kit/sortable": "^1.0.2",
"@dnd-kit/utilities": "^1.0.2",
"@material-ui/styled-engine-sc": "^5.0.0-alpha.25",
"@rematch/core": "^2.0.0",
"@tiddlygit/tiddlywiki": "5.1.24-prerelease.20210103",
"array-move": "^3.0.1",
"beautiful-react-hooks": "^0.31.0",
"bluebird": "^3.7.2",
"chokidar": "^3.5.1",
@ -187,7 +189,6 @@
"react-dom": "17.0.1",
"react-i18next": "^11.8.6",
"react-redux": "7.2.2",
"react-sortable-hoc": "1.11.0",
"redux": "4.0.5",
"rimraf": "^3.0.2",
"simplebar": "6.0.0-beta.4",

View file

@ -1,72 +1,76 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { SortableContainer as sortableContainer, SortableElement as sortableElement } from 'react-sortable-hoc';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { WindowNames } from '@services/windows/WindowProperties';
import WorkspaceSelector from './WorkspaceSelector';
import { IWorkspace } from '@services/workspaces/interface';
import defaultIcon from '../../images/default-icon.png';
export const SortableContainer = sortableContainer(({ children }: { children: React.ReactNode }) => <div>{children}</div>);
export interface ISortableItemProps {
index: number;
workspace: IWorkspace;
}
function SortableWorkspaceSelector({ index, workspace }: ISortableItemProps) {
export function SortableWorkspaceSelector({ index, workspace }: ISortableItemProps) {
const { t } = useTranslation();
const { active, id, name, picturePath, hibernated, transparentBackground, isSubWiki, tagName } = workspace;
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
};
return (
<WorkspaceSelector
active={active}
id={id}
key={id}
workspaceName={name}
picturePath={picturePath ?? defaultIcon}
transparentBackground={transparentBackground}
order={index}
hibernated={hibernated}
onClick={async () => {
if (isSubWiki) {
await window.service.wiki.requestOpenTiddlerInWiki(tagName);
} else {
const activeWorkspace = await window.service.workspace.getActiveWorkspace();
if (activeWorkspace?.id === id) {
await window.service.wiki.requestWikiSendActionMessage('tm-home');
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
<WorkspaceSelector
active={active}
id={id}
key={id}
workspaceName={name}
picturePath={picturePath ?? defaultIcon}
transparentBackground={transparentBackground}
order={index}
hibernated={hibernated}
onClick={async () => {
if (isSubWiki) {
await window.service.wiki.requestOpenTiddlerInWiki(tagName);
} else {
await window.service.workspaceView.setActiveWorkspaceView(id);
const activeWorkspace = await window.service.workspace.getActiveWorkspace();
if (activeWorkspace?.id === id) {
await window.service.wiki.requestWikiSendActionMessage('tm-home');
} else {
await window.service.workspaceView.setActiveWorkspaceView(id);
}
}
}
}}
onContextMenu={() => {
const template = [
{
label: t('WorkspaceSelector.EditWorkspace'),
click: async () => await window.service.window.open(WindowNames.editWorkspace, { workspaceID: id }),
},
{
label: t('WorkspaceSelector.RemoveWorkspace'),
click: async () => await window.service.workspaceView.removeWorkspaceView(id),
},
];
if (!active && !isSubWiki) {
template.splice(1, 0, {
label: hibernated ? 'Wake Up Workspace' : 'Hibernate Workspace',
click: async () => {
if (hibernated) {
return await window.service.workspaceView.wakeUpWorkspaceView(id);
}
return await window.service.workspaceView.hibernateWorkspaceView(id);
}}
onContextMenu={() => {
const template = [
{
label: t('WorkspaceSelector.EditWorkspace'),
click: async () => await window.service.window.open(WindowNames.editWorkspace, { workspaceID: id }),
},
});
}
{
label: t('WorkspaceSelector.RemoveWorkspace'),
click: async () => await window.service.workspaceView.removeWorkspaceView(id),
},
];
void window.service.menu.buildContextMenuAndPopup(template);
}}
/>
if (!active && !isSubWiki) {
template.splice(1, 0, {
label: hibernated ? 'Wake Up Workspace' : 'Hibernate Workspace',
click: async () => {
if (hibernated) {
return await window.service.workspaceView.wakeUpWorkspaceView(id);
}
return await window.service.workspaceView.hibernateWorkspaceView(id);
},
});
}
void window.service.menu.buildContextMenuAndPopup(template);
}}
/>
</div>
);
}
export default sortableElement(SortableWorkspaceSelector);

View file

@ -1,11 +1,13 @@
import Promise from 'bluebird';
import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import BadgeRaw from '@material-ui/core/Badge';
import styled, { css } from 'styled-components';
import defaultIcon from '../../images/default-icon.png';
Promise.config({ cancellation: true });
// TODO: &:hover { background: theme.palette.action.hover;
const Root = styled.div<{ hibernated?: boolean; active?: boolean }>`
height: fit-content;
@ -125,10 +127,14 @@ export default function WorkspaceSelector({
const { t } = useTranslation();
const [shortWorkspaceName, shortWorkspaceNameSetter] = useState<string>(t('Loading'));
useEffect(() => {
void (async () => {
const baseName = await window.service.context.getBaseName(workspaceName);
const setBaseNamePromise = new Promise<string | undefined>((resolve) => {
window.service.context.getBaseName(workspaceName).then((baseName) => resolve(baseName));
});
setBaseNamePromise.then((baseName) => {
shortWorkspaceNameSetter(baseName !== undefined ? baseName : t('WorkspaceSelector.BadWorkspacePath'));
})();
});
return () => setBaseNamePromise.cancel();
}, [workspaceName]);
return (
<Root role="button" hibernated={hibernated} active={active} onClick={onClick} onKeyDown={onClick} onContextMenu={onContextMenu} tabIndex={0}>

View file

@ -1,7 +1,8 @@
import React from 'react';
import arrayMove from 'array-move';
import styled, { css } from 'styled-components';
import { AsyncReturnType } from 'type-fest';
import { DndContext } from '@dnd-kit/core';
import { SortableContext, arrayMove, verticalListSortingStrategy } from '@dnd-kit/sortable';
import SimpleBar from 'simplebar-react';
import 'simplebar/dist/simplebar.min.css';
@ -24,7 +25,7 @@ import DraggableRegion from './DraggableRegion';
import arrowWhite from '@/images/arrow-white.png';
import arrowBlack from '@/images/arrow-black.png';
import SortableWorkspaceSelector, { SortableContainer } from './SortableWorkspaceSelector';
import { SortableWorkspaceSelector } from './SortableWorkspaceSelector';
import { IWorkspace } from '@services/workspaces/interface';
import { IPreferences } from '@services/preferences/interface';
@ -180,6 +181,7 @@ export default function Main(): JSX.Element {
}, {} as AsyncReturnType<typeof window.service.workspace.getMetaData>);
const requestReload = async (): Promise<void> => await window.service.window.reload(window.meta.windowName);
const workspaceIDs = workspacesList.map((workspace) => workspace.id);
return (
<OuterRoot>
{workspacesList.length > 0 && <DraggableRegion />}
@ -187,10 +189,11 @@ export default function Main(): JSX.Element {
{sidebar === true && (
<SidebarContainer>
<SidebarTop fullscreen={isFullScreen === true || titleBar || attachToMenubar}>
<SortableContainer
distance={10}
onSortEnd={async ({ oldIndex, newIndex }) => {
if (oldIndex === newIndex) return;
<DndContext
onDragEnd={async ({ active, over }) => {
if (over === null || active.id === over.id) return;
const oldIndex = workspaceIDs.indexOf(active.id);
const newIndex = workspaceIDs.indexOf(over.id);
const newWorkspacesList = arrayMove(workspacesList, oldIndex, newIndex);
const newWorkspaces: Record<string, IWorkspace> = {};
@ -201,10 +204,12 @@ export default function Main(): JSX.Element {
await window.service.workspace.setWorkspaces(newWorkspaces);
}}>
{workspacesList.map((workspace, index) => (
<SortableWorkspaceSelector key={`item-${workspace.id}`} index={index} workspace={workspace} />
))}
</SortableContainer>
<SortableContext items={workspaceIDs} strategy={verticalListSortingStrategy}>
{workspacesList.map((workspace, index) => (
<SortableWorkspaceSelector key={`item-${workspace.id}`} index={index} workspace={workspace} />
))}
</SortableContext>
</DndContext>
<WorkspaceSelector id="add" onClick={async () => await window.service.window.open(WindowNames.addWorkspace)} />
</SidebarTop>
<End>