mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 18:26:05 +08:00
fix: split view focus (#11217)
# After: https://github.com/user-attachments/assets/990d500d-2da7-488e-ac32-dd7bd229f896 # Before: https://github.com/user-attachments/assets/6676766a-c76a-414b-a35e-53d2cda10c24
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -68,6 +68,7 @@ export function focusTextModel(
|
||||
id: string,
|
||||
offset: number = 0
|
||||
) {
|
||||
std.event.active = true;
|
||||
selectTextModel(std, id, offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ export const focusBlockEnd: Command<{
|
||||
|
||||
const { selection } = std;
|
||||
|
||||
std.event.active = true;
|
||||
if (force) selection.clear();
|
||||
|
||||
selection.setGroup('note', [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
Reference in New Issue
Block a user