Saul-Mirone
2025-03-27 05:27:59 +00:00
parent 5f5c27fbdf
commit d9d5aa407a
12 changed files with 90 additions and 45 deletions

View File

@@ -82,8 +82,10 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
private readonly _onTitleKeyDown = (event: KeyboardEvent) => {
if (event.isComposing || this.doc.readonly) return;
if (!this._std) return;
if (event.key === 'Enter') {
this._std.event.active = true;
event.preventDefault();
event.stopPropagation();
@@ -99,6 +101,7 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
if (this._std) focusTextModel(this._std, newFirstParagraphId);
}
} else if (event.key === 'ArrowDown') {
this._std.event.active = true;
event.preventDefault();
event.stopPropagation();

View File

@@ -1,8 +1,12 @@
import { changeNoteDisplayMode } from '@blocksuite/affine-block-note';
import { NoteBlockModel, NoteDisplayMode } from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { matchModels } from '@blocksuite/affine-shared/utils';
import { ShadowlessElement, SurfaceSelection } from '@blocksuite/block-std';
import { focusTitle, matchModels } from '@blocksuite/affine-shared/utils';
import {
BlockSelection,
ShadowlessElement,
SurfaceSelection,
} from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { Bound } from '@blocksuite/global/gfx';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
@@ -170,6 +174,19 @@ export class OutlinePanelBody extends SignalWatcher(
}
private async _scrollToBlock(blockId: string) {
// if focus title
if (blockId === this.doc.root?.id) {
this.editor.std.selection.setGroup('note', []);
this.editor.std.event.active = false;
focusTitle(this.editor);
} else {
this.editor.std.event.active = true;
this.editor.std.selection.setGroup('note', [
this.editor.std.selection.create(BlockSelection, {
blockId,
}),
]);
}
this._lockActiveHeadingId = true;
this._activeHeadingId$.value = blockId;
this._clearHighlightMask = await scrollToBlockWithHighlight(

View File

@@ -68,6 +68,7 @@ export function focusTextModel(
id: string,
offset: number = 0
) {
std.event.active = true;
selectTextModel(std, id, offset);
}

View File

@@ -19,6 +19,7 @@ export const focusBlockEnd: Command<{
const { selection } = std;
std.event.active = true;
if (force) selection.clear();
selection.setGroup('note', [

View File

@@ -1,5 +1,6 @@
import { DisposableGroup } from '@blocksuite/global/disposable';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import { signal } from '@preact/signals-core';
import { LifeCycleWatcher } from '../extension/index.js';
import { KeymapIdentifier } from '../identifier.js';
@@ -81,7 +82,7 @@ export class UIEventDispatcher extends LifeCycleWatcher {
static override readonly key = 'UIEventDispatcher';
private _active = false;
private readonly _active = signal(false);
private readonly _clipboardControl: ClipboardControl;
@@ -105,6 +106,10 @@ export class UIEventDispatcher extends LifeCycleWatcher {
}
get active() {
return this._active.peek();
}
get active$() {
return this._active;
}
@@ -302,19 +307,24 @@ export class UIEventDispatcher extends LifeCycleWatcher {
if (active) {
if (UIEventDispatcher._activeDispatcher !== this) {
if (UIEventDispatcher._activeDispatcher) {
UIEventDispatcher._activeDispatcher._active = false;
UIEventDispatcher._activeDispatcher._active.value = false;
}
UIEventDispatcher._activeDispatcher = this;
}
this._active = true;
this._active.value = true;
} else {
if (UIEventDispatcher._activeDispatcher === this) {
UIEventDispatcher._activeDispatcher = null;
}
this._active = false;
this._active.value = false;
}
}
set active(active: boolean) {
if (active === this._active.peek()) return;
this._setActive(active);
}
add(name: EventName, handler: UIEventHandler, options?: EventOptions) {
const runner: EventHandlerRunner = {
fn: handler,

View File

@@ -169,7 +169,10 @@ export class RangeBinding {
private readonly _onNativeSelectionChanged = async () => {
if (this.isComposing) return;
if (!this.host) return; // Unstable when switching views, card <-> embed
if (!isActiveInEditor(this.host)) return;
if (!isActiveInEditor(this.host)) {
this._prevTextSelection = null;
return;
}
await this.host.updateComplete;
@@ -251,6 +254,8 @@ export class RangeBinding {
// TODO(@mirone): this is a trade-off, we need to use separate awareness store for every store to make sure the selection is isolated.
const closestHost = document.activeElement?.closest('editor-host');
if (closestHost && closestHost !== this.host) return;
const active = this.host.event.active;
if (!active) return;
const text =
selections.find((selection): selection is TextSelection =>
@@ -266,7 +271,7 @@ export class RangeBinding {
const id = text?.blockId;
const path = id && this._computePath(id);
if (this.host.event.active) {
if (active) {
const eq =
text && this._prevTextSelection && path
? text.equals(this._prevTextSelection.selection) &&