mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-21 16:26:58 +08:00
refactor(editor): edgeless toolbar lock and unlock actions (#10878)
This commit is contained in:
@@ -128,6 +128,82 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
: null;
|
||||
}
|
||||
|
||||
updateWithSurface(
|
||||
ctx: ToolbarContext,
|
||||
activated: boolean,
|
||||
elementIds: string[]
|
||||
) {
|
||||
const gfx = ctx.gfx;
|
||||
const surface = gfx.surface;
|
||||
let flavour = 'affine:surface';
|
||||
let elements: GfxModel[] = [];
|
||||
let hasLocked = false;
|
||||
let sideOptions = null;
|
||||
let paired: [string, GfxModel[]][] = [];
|
||||
|
||||
if (activated && surface) {
|
||||
elements = elementIds
|
||||
.map(id => gfx.getElementById(id))
|
||||
.filter(model => model !== null) as GfxModel[];
|
||||
|
||||
hasLocked = elements.some(e => e.isLocked());
|
||||
|
||||
const grouped = groupBy(
|
||||
elements.map(model => {
|
||||
let flavour = surface.flavour;
|
||||
|
||||
if (model instanceof GfxBlockElementModel) {
|
||||
flavour += `:${model.flavour.split(':').pop()}`;
|
||||
} else if (model instanceof GfxPrimitiveElementModel) {
|
||||
flavour += `:${model.type}`;
|
||||
}
|
||||
|
||||
return { model, flavour };
|
||||
}),
|
||||
e => e.flavour
|
||||
);
|
||||
|
||||
paired = toPairs(grouped).map(([flavour, items]) => [
|
||||
flavour,
|
||||
items.map(({ model }) => model),
|
||||
]);
|
||||
|
||||
if (hasLocked) {
|
||||
flavour = 'affine:surface:locked';
|
||||
} else {
|
||||
if (paired.length === 1) {
|
||||
flavour = paired[0][0];
|
||||
if (flavour === 'affine:surface:shape' && paired[0][1].length === 1) {
|
||||
sideOptions = sideMap.get(flavour) ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sideOptions) {
|
||||
const flavours = new Set(paired.map(([f]) => f));
|
||||
if (flavours.has('affine:surface:frame')) {
|
||||
sideOptions = sideMap.get('affine:surface:frame') ?? null;
|
||||
} else if (flavours.has('affine:surface:group')) {
|
||||
sideOptions = sideMap.get('affine:surface:group') ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
batch(() => {
|
||||
ctx.flags.toggle(Flag.Surface, activated);
|
||||
|
||||
ctx.elementsMap$.value = new Map(paired);
|
||||
|
||||
if (!activated || !flavour) return;
|
||||
|
||||
this.setReferenceElementWithElements(gfx, elements);
|
||||
|
||||
this.sideOptions$.value = sideOptions;
|
||||
ctx.flavour$.value = flavour;
|
||||
this.placement$.value = hasLocked ? 'top' : 'top-start';
|
||||
ctx.flags.refresh(Flag.Surface);
|
||||
});
|
||||
}
|
||||
|
||||
toolbar = new EditorToolbar();
|
||||
|
||||
get toolbarRegistry() {
|
||||
@@ -147,7 +223,7 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
host,
|
||||
std,
|
||||
} = this;
|
||||
const { flags, flavour$, message$, elementsMap$ } = toolbarRegistry;
|
||||
const { flags, flavour$, message$ } = toolbarRegistry;
|
||||
const context = new ToolbarContext(std);
|
||||
|
||||
// TODO(@fundon): fix toolbar position shaking when the wheel scrolls
|
||||
@@ -293,76 +369,9 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
.map(s => (s.editing || s.inoperable ? [] : s.elements))
|
||||
.flat();
|
||||
const count = elementIds.length;
|
||||
const gfx = context.gfx;
|
||||
const surface = gfx.surface;
|
||||
const activated =
|
||||
context.activated && Boolean(surface) && Boolean(count);
|
||||
let flavour = 'affine:surface';
|
||||
let elements: GfxModel[] = [];
|
||||
let hasLocked = false;
|
||||
let sideOptions = null;
|
||||
let paired: [string, GfxModel[]][] = [];
|
||||
const activated = context.activated && Boolean(count);
|
||||
|
||||
if (activated && surface) {
|
||||
elements = elementIds
|
||||
.map(id => gfx.getElementById(id))
|
||||
.filter(model => model !== null) as GfxModel[];
|
||||
|
||||
hasLocked = elements.some(e => e.isLocked());
|
||||
|
||||
const grouped = groupBy(
|
||||
elements.map(model => {
|
||||
let flavour = surface.flavour;
|
||||
|
||||
if (model instanceof GfxBlockElementModel) {
|
||||
flavour += `:${model.flavour.split(':').pop()}`;
|
||||
} else if (model instanceof GfxPrimitiveElementModel) {
|
||||
flavour += `:${model.type}`;
|
||||
}
|
||||
|
||||
return { model, flavour };
|
||||
}),
|
||||
e => e.flavour
|
||||
);
|
||||
|
||||
paired = toPairs(grouped).map(([flavour, items]) => [
|
||||
flavour,
|
||||
items.map(({ model }) => model),
|
||||
]);
|
||||
|
||||
if (paired.length === 1) {
|
||||
flavour = paired[0][0];
|
||||
if (
|
||||
flavour === 'affine:surface:shape' &&
|
||||
paired[0][1].length === 1
|
||||
) {
|
||||
sideOptions = sideMap.get(flavour) ?? null;
|
||||
}
|
||||
}
|
||||
if (!sideOptions) {
|
||||
const flavours = new Set(paired.map(([f]) => f));
|
||||
if (flavours.has('affine:surface:frame')) {
|
||||
sideOptions = sideMap.get('affine:surface:frame') ?? null;
|
||||
} else if (flavours.has('affine:surface:group')) {
|
||||
sideOptions = sideMap.get('affine:surface:group') ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
batch(() => {
|
||||
flags.toggle(Flag.Surface, activated);
|
||||
|
||||
elementsMap$.value = new Map(paired);
|
||||
|
||||
if (!activated || !flavour) return;
|
||||
|
||||
this.setReferenceElementWithElements(gfx, elements);
|
||||
|
||||
sideOptions$.value = sideOptions;
|
||||
flavour$.value = flavour;
|
||||
placement$.value = hasLocked ? 'top' : 'top-start';
|
||||
flags.refresh(Flag.Surface);
|
||||
});
|
||||
this.updateWithSurface(context, activated, elementIds);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -452,7 +461,12 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
}
|
||||
|
||||
if (flags.isSurface()) {
|
||||
flags.refresh(Flag.Surface);
|
||||
const elementIds = context.gfx.selection.selectedIds;
|
||||
this.updateWithSurface(
|
||||
context,
|
||||
context.activated && Boolean(elementIds.length),
|
||||
elementIds
|
||||
);
|
||||
return;
|
||||
}
|
||||
})
|
||||
@@ -460,14 +474,18 @@ export class AffineToolbarWidget extends WidgetComponent {
|
||||
|
||||
// Handles elemets when updating
|
||||
disposables.add(
|
||||
effect(() => {
|
||||
const surface = context.gfx.surface$.value;
|
||||
context.gfx.surface$.subscribe(surface => {
|
||||
if (!surface) return;
|
||||
|
||||
const subscription = surface.elementUpdated.subscribe(() => {
|
||||
if (!flags.isSurface()) return;
|
||||
|
||||
flags.refresh(Flag.Surface);
|
||||
const elementIds = context.gfx.selection.selectedIds;
|
||||
this.updateWithSurface(
|
||||
context,
|
||||
context.activated && Boolean(elementIds.length),
|
||||
elementIds
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
|
||||
Reference in New Issue
Block a user