feat(draw): lock shape

This commit is contained in:
alt1o
2022-07-28 18:56:39 +08:00
parent 5a78afceb2
commit fbce0e11dc
7 changed files with 170 additions and 1 deletions

View File

@@ -22,3 +22,4 @@ export * from './translate-shapes';
export * from './ungroup-shapes';
export * from './update-shapes';
export * from './set-shapes-props';
export * from './set-shapes-lock-status';

View File

@@ -0,0 +1,59 @@
import type {
TDShape,
TldrawCommand,
} from '@toeverything/components/board-types';
import type { TldrawApp } from '@toeverything/components/board-state';
export function setShapesLockStatus<T extends TDShape>(
app: TldrawApp,
ids: string[],
isLocked: boolean
): TldrawCommand {
const { currentPageId, selectedIds } = app;
const initialShapes = ids.map(id => app.getShape<T>(id));
const before: Record<string, Partial<TDShape>> = {};
const after: Record<string, Partial<TDShape>> = {};
initialShapes.forEach(shape => {
before[shape.id] = {
isLocked: shape.isLocked,
};
after[shape.id] = {
isLocked,
};
});
return {
id: 'set_shapes_lock_status',
before: {
document: {
pages: {
[currentPageId]: {
shapes: before,
},
},
pageStates: {
[currentPageId]: {
selectedIds,
},
},
},
},
after: {
document: {
pages: {
[currentPageId]: {
shapes: after,
},
},
pageStates: {
[currentPageId]: {
selectedIds,
},
},
},
},
};
}

View File

@@ -9,6 +9,7 @@ import { FontSizeConfig } from './FontSizeConfig';
import { StrokeLineStyleConfig } from './stroke-line-style-config';
import { Group, UnGroup } from './GroupOperation';
import { DeleteShapes } from './DeleteOperation';
import { Lock, Unlock } from './LockOperation';
export const CommandPanel: FC<{ app: TldrawApp }> = ({ app }) => {
const state = app.useStore();
@@ -63,6 +64,16 @@ export const CommandPanel: FC<{ app: TldrawApp }> = ({ app }) => {
shapes={config.ungroup.selectedShapes}
/>
) : null,
lock: config.lock.selectedShapes.length ? (
<Lock key="lock" app={app} shapes={config.lock.selectedShapes} />
) : null,
unlock: config.unlock.selectedShapes.length ? (
<Unlock
key="unlock"
app={app}
shapes={config.unlock.selectedShapes}
/>
) : null,
delete: (
<DeleteShapes
key="deleteShapes"

View File

@@ -0,0 +1,38 @@
import type { FC } from 'react';
import type { TldrawApp } from '@toeverything/components/board-state';
import type { TDShape } from '@toeverything/components/board-types';
import { IconButton, Tooltip } from '@toeverything/components/ui';
import { LockIcon, UnlockIcon } from '@toeverything/components/icons';
import { getShapeIds } from './utils';
interface GroupAndUnGroupProps {
app: TldrawApp;
shapes: TDShape[];
}
export const Lock: FC<GroupAndUnGroupProps> = ({ app, shapes }) => {
const lock = () => {
app.lock(getShapeIds(shapes));
};
return (
<Tooltip content="Lock">
<IconButton onClick={lock}>
<UnlockIcon />
</IconButton>
</Tooltip>
);
};
export const Unlock: FC<GroupAndUnGroupProps> = ({ app, shapes }) => {
const unlock = () => {
app.unlock(getShapeIds(shapes));
};
return (
<Tooltip content="Unlock">
<IconButton onClick={unlock}>
<LockIcon />
</IconButton>
</Tooltip>
);
};

View File

@@ -4,7 +4,15 @@ import { TDShapeType } from '@toeverything/components/board-types';
import { TLDR } from '@toeverything/components/board-state';
interface Config {
type: 'stroke' | 'fill' | 'font' | 'group' | 'ungroup' | 'deleteShapes';
type:
| 'stroke'
| 'fill'
| 'font'
| 'group'
| 'ungroup'
| 'deleteShapes'
| 'lock'
| 'unlock';
selectedShapes: TDShape[];
}
@@ -34,6 +42,14 @@ const _createInitConfig = (): Record<Config['type'], Config> => {
type: 'deleteShapes',
selectedShapes: [],
},
lock: {
type: 'lock',
selectedShapes: [],
},
unlock: {
type: 'unlock',
selectedShapes: [],
},
};
};
@@ -64,6 +80,17 @@ const _isSupportFill = (shape: TDShape): boolean => {
].some(type => type === shape.type);
};
const _isSupportFont = (shape: TDShape): boolean => {
return [
TDShapeType.Rectangle,
TDShapeType.Ellipse,
TDShapeType.Hexagon,
TDShapeType.Triangle,
TDShapeType.WhiteArrow,
TDShapeType.Pentagram,
].some(type => type === shape.type);
};
export const useConfig = (app: TldrawApp): Record<Config['type'], Config> => {
const state = app.useStore();
const selectedShapes = TLDR.get_selected_shapes(state, app.currentPageId);
@@ -74,6 +101,8 @@ export const useConfig = (app: TldrawApp): Record<Config['type'], Config> => {
}
if (_isSupportFill(cur)) {
acc.fill.selectedShapes.push(cur);
}
if (_isSupportFont(cur)) {
acc.font.selectedShapes.push(cur);
}
return acc;
@@ -81,6 +110,7 @@ export const useConfig = (app: TldrawApp): Record<Config['type'], Config> => {
_createInitConfig()
);
// group
if (
selectedShapes.length === 1 &&
selectedShapes[0].type === TDShapeType.Group
@@ -91,6 +121,13 @@ export const useConfig = (app: TldrawApp): Record<Config['type'], Config> => {
config.group.selectedShapes = selectedShapes;
}
// lock
if (selectedShapes.length === 1 && selectedShapes[0].isLocked) {
config.unlock.selectedShapes = selectedShapes;
} else {
config.lock.selectedShapes = selectedShapes;
}
config.deleteShapes.selectedShapes = selectedShapes;
return config;

View File

@@ -3577,6 +3577,24 @@ export class TldrawApp extends StateManager<TDSnapshot> {
);
};
lock = (ids = this.selectedIds): this => {
if (ids.length === 0) {
return this;
}
return this.set_state(
this.commands.setShapesLockStatus(this, ids, true)
);
};
unlock = (ids = this.selectedIds): this => {
if (ids.length === 0) {
return this;
}
return this.set_state(
this.commands.setShapesLockStatus(this, ids, false)
);
};
/**
* Toggle the fixed-aspect-ratio property of one or more shapes.
* @param ids The ids to change (defaults to selection).

View File

@@ -102,4 +102,9 @@ export interface Commands {
updates: ({ id: string } & Partial<TDShape>)[],
pageId: string
): TldrawCommand;
setShapesLockStatus(
app: TldrawApp,
ids: string[],
isLocked: boolean
): TldrawCommand;
}