mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
chore(editor): improve selection of doc in canvas (#11314)
Close [BS-2705](https://linear.app/affine-design/issue/BS-2705/[improvement]-通过-viability-control-选择-hide-in-edgeless) This PR disabled selecting operation of notes that are only shown in page mode.
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
||||
type ConnectorElementModel,
|
||||
GroupElementModel,
|
||||
MindmapElementModel,
|
||||
NoteBlockModel,
|
||||
NoteDisplayMode,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { resetNativeSelection } from '@blocksuite/affine-shared/utils';
|
||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||
@@ -141,6 +143,12 @@ export class DefaultTool extends BaseTool {
|
||||
if (el instanceof MindmapElementModel) {
|
||||
return bound.contains(el.elementBound);
|
||||
}
|
||||
if (
|
||||
el instanceof NoteBlockModel &&
|
||||
el.props.displayMode === NoteDisplayMode.DocOnly
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,13 @@ import {
|
||||
import { GfxControllerIdentifier } from '@blocksuite/std/gfx';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import { consume } from '@lit/context';
|
||||
import { effect, signal } from '@preact/signals-core';
|
||||
import {
|
||||
batch,
|
||||
computed,
|
||||
effect,
|
||||
type Signal,
|
||||
signal,
|
||||
} from '@preact/signals-core';
|
||||
import { html, nothing } from 'lit';
|
||||
import { query } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
@@ -53,7 +59,22 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
|
||||
private readonly _edgelessOnlyNotes$ = signal<NoteBlockModel[]>([]);
|
||||
|
||||
private readonly _selectedNotes$ = signal<NoteBlockModel[]>([]);
|
||||
private readonly _selectedNotes$: Record<
|
||||
NoteDisplayMode,
|
||||
Signal<NoteBlockModel[]>
|
||||
> = {
|
||||
[NoteDisplayMode.DocOnly]: signal<NoteBlockModel[]>([]),
|
||||
[NoteDisplayMode.DocAndEdgeless]: signal<NoteBlockModel[]>([]),
|
||||
[NoteDisplayMode.EdgelessOnly]: signal<NoteBlockModel[]>([]),
|
||||
};
|
||||
|
||||
private readonly _allSelectedNotes$ = computed(() =>
|
||||
[
|
||||
NoteDisplayMode.DocAndEdgeless,
|
||||
NoteDisplayMode.DocOnly,
|
||||
NoteDisplayMode.EdgelessOnly,
|
||||
].flatMap(mode => this._selectedNotes$[mode].value)
|
||||
);
|
||||
|
||||
private _clearHighlightMask = () => {};
|
||||
|
||||
@@ -136,7 +157,7 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
if (!this.doc.root) return;
|
||||
|
||||
const pageVisibleNotes = this._pageVisibleNotes$.peek();
|
||||
const selected = this._selectedNotes$.peek();
|
||||
const selected = this._allSelectedNotes$.peek();
|
||||
const children = this.doc.root.children.slice();
|
||||
|
||||
const noteIndex = new Map<NoteBlockModel, number>();
|
||||
@@ -203,23 +224,39 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
const note = this.doc.getBlock(id)?.model;
|
||||
if (!note || !matchModels(note, [NoteBlockModel])) return;
|
||||
|
||||
let selectedNotes = this._selectedNotes$.peek();
|
||||
// map from signal to value
|
||||
const selectedNotes = Object.fromEntries(
|
||||
Object.entries(this._selectedNotes$).map(([k, v]) => [k, v.peek()])
|
||||
) as Record<NoteDisplayMode, NoteBlockModel[]>;
|
||||
|
||||
if (!selected) {
|
||||
selectedNotes = selectedNotes.filter(_note => _note !== note);
|
||||
} else if (multiselect) {
|
||||
selectedNotes = [...selectedNotes, note];
|
||||
if (multiselect) {
|
||||
selectedNotes[note.props.displayMode] = selected
|
||||
? [...selectedNotes[note.props.displayMode], note]
|
||||
: selectedNotes[note.props.displayMode].filter(_note => _note !== note);
|
||||
} else {
|
||||
selectedNotes = [note];
|
||||
selectedNotes[note.props.displayMode] = selected ? [note] : [];
|
||||
Object.keys(this._selectedNotes$).forEach(mode => {
|
||||
if (mode !== note.props.displayMode) {
|
||||
selectedNotes[mode as NoteDisplayMode] = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We use gfx.selection and effect to keep sync between canvas and outline panel
|
||||
if (editorMode === 'edgeless') {
|
||||
gfx.selection.set({
|
||||
elements: selectedNotes.map(({ id }) => id),
|
||||
elements: [...selectedNotes.both, ...selectedNotes.edgeless].map(
|
||||
({ id }) => id
|
||||
),
|
||||
editing: false,
|
||||
});
|
||||
this._selectedNotes$.doc.value = selectedNotes.doc;
|
||||
} else {
|
||||
this._selectedNotes$.value = selectedNotes;
|
||||
[NoteDisplayMode.DocOnly, NoteDisplayMode.DocAndEdgeless].forEach(
|
||||
mode => {
|
||||
this._selectedNotes$[mode].value = selectedNotes[mode];
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,13 +274,16 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
return !!model && matchModels(model, [NoteBlockModel]);
|
||||
});
|
||||
|
||||
const preSelected = this._selectedNotes$.peek();
|
||||
if (
|
||||
preSelected.length !== currSelectedNotes.length ||
|
||||
preSelected.some(note => !currSelectedNotes.includes(note))
|
||||
) {
|
||||
this._selectedNotes$.value = currSelectedNotes;
|
||||
}
|
||||
// update selected notes from edgeless selection
|
||||
batch(() => {
|
||||
[NoteDisplayMode.DocAndEdgeless, NoteDisplayMode.EdgelessOnly].forEach(
|
||||
mode => {
|
||||
this._selectedNotes$[mode].value = currSelectedNotes.filter(
|
||||
note => note.props.displayMode === mode
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -280,11 +320,6 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
std.dnd.monitor<NoteCardEntity, NoteDropPayload>({
|
||||
onDragStart: () => {
|
||||
this._dragging$.value = true;
|
||||
this._selectedNotes$.value = this._selectedNotes$
|
||||
.peek()
|
||||
.filter(note => {
|
||||
return this._pageVisibleNotes$.value.includes(note);
|
||||
});
|
||||
},
|
||||
onDrag: data => {
|
||||
const target = data.location.current.dropTargets[0];
|
||||
@@ -377,7 +412,7 @@ export class OutlinePanelBody extends SignalWatcher(
|
||||
index=${index}
|
||||
.note=${note}
|
||||
.activeHeadingId=${this._activeHeadingId$.value}
|
||||
.status=${this._selectedNotes$.value.includes(note)
|
||||
.status=${this._allSelectedNotes$.value.includes(note)
|
||||
? this._dragging$.value
|
||||
? 'dragging'
|
||||
: 'selected'
|
||||
|
||||
Reference in New Issue
Block a user