mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
feat(mobile): auto show text keyboard subtoolbar when selecting text (#9256)
Close [BS-1924](https://linear.app/affine-design/issue/BS-1924/文本选中后-切换toolbar) https://github.com/user-attachments/assets/2361dfb9-82ae-4be3-808c-6ea33a70c84d
This commit is contained in:
@@ -9,6 +9,7 @@ import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
createDefaultDoc,
|
||||
openFileOrFiles,
|
||||
type Signal,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||
import { viewPresets } from '@blocksuite/data-view/view-presets';
|
||||
@@ -54,6 +55,7 @@ import {
|
||||
YesterdayIcon,
|
||||
YoutubeDuotoneIcon,
|
||||
} from '@blocksuite/icons/lit';
|
||||
import { computed } from '@preact/signals-core';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
@@ -113,6 +115,10 @@ export type KeyboardToolbarActionItem = {
|
||||
export type KeyboardSubToolbarConfig = {
|
||||
icon: KeyboardIconType;
|
||||
items: KeyboardToolbarItem[];
|
||||
/**
|
||||
* It will enter this sub-toolbar when the condition is met.
|
||||
*/
|
||||
autoShow?: (ctx: KeyboardToolbarContext) => Signal<boolean>;
|
||||
};
|
||||
|
||||
export type KeyboardToolbarContext = {
|
||||
@@ -868,6 +874,13 @@ const textSubToolbarConfig: KeyboardSubToolbarConfig = {
|
||||
},
|
||||
highlightToolPanel,
|
||||
],
|
||||
autoShow: ({ std }) => {
|
||||
return computed(() => {
|
||||
const selection =
|
||||
std.command.exec('getTextSelection').currentTextSelection;
|
||||
return selection ? !selection.isCollapsed() : false;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultKeyboardToolbarConfig: KeyboardToolbarConfig = {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
||||
import { ArrowLeftBigIcon, KeyboardIcon } from '@blocksuite/icons/lit';
|
||||
import { effect, signal } from '@preact/signals-core';
|
||||
import { effect, type Signal, signal } from '@preact/signals-core';
|
||||
import { html } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
@@ -283,6 +283,48 @@ export class AffineKeyboardToolbar extends SignalWatcher(
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
this._watchAutoShow();
|
||||
}
|
||||
|
||||
private _watchAutoShow() {
|
||||
const autoShowSubToolbars: { path: number[]; signal: Signal<boolean> }[] =
|
||||
[];
|
||||
|
||||
const traverse = (item: KeyboardToolbarItem, path: number[]) => {
|
||||
if (isKeyboardSubToolBarConfig(item) && item.autoShow) {
|
||||
autoShowSubToolbars.push({
|
||||
path,
|
||||
signal: item.autoShow(this._context),
|
||||
});
|
||||
|
||||
item.items.forEach((subItem, index) => {
|
||||
traverse(subItem, [...path, index]);
|
||||
});
|
||||
}
|
||||
};
|
||||
this.config.items.forEach((item, index) => {
|
||||
traverse(item, [index]);
|
||||
});
|
||||
|
||||
const samePath = (a: number[], b: number[]) =>
|
||||
a.length === b.length && a.every((v, i) => v === b[i]);
|
||||
|
||||
let prevPath = this._path$.peek();
|
||||
this.disposables.add(
|
||||
effect(() => {
|
||||
autoShowSubToolbars.forEach(({ path, signal }) => {
|
||||
if (signal.value) {
|
||||
if (samePath(this._path$.peek(), path)) return;
|
||||
|
||||
prevPath = this._path$.peek();
|
||||
this._path$.value = path;
|
||||
} else {
|
||||
this._path$.value = prevPath;
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
override disconnectedCallback() {
|
||||
|
||||
Reference in New Issue
Block a user