mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
refactor(editor): move menu context to components (#9302)
This commit is contained in:
@@ -1 +0,0 @@
|
||||
export * from './toolbar.js';
|
||||
@@ -1,44 +0,0 @@
|
||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||
import type { BlockStdScope, EditorHost } from '@blocksuite/block-std';
|
||||
import type { GfxModel } from '@blocksuite/block-std/gfx';
|
||||
import type { BlockModel, Doc } from '@blocksuite/store';
|
||||
|
||||
export abstract class MenuContext {
|
||||
abstract get doc(): Doc;
|
||||
|
||||
get firstElement(): GfxModel | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract get host(): EditorHost;
|
||||
|
||||
abstract get selectedBlockModels(): BlockModel[];
|
||||
|
||||
abstract get std(): BlockStdScope;
|
||||
|
||||
// Sometimes we need to close the menu.
|
||||
close() {}
|
||||
|
||||
isElement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract isEmpty(): boolean;
|
||||
|
||||
abstract isMultiple(): boolean;
|
||||
|
||||
abstract isSingle(): boolean;
|
||||
}
|
||||
|
||||
export interface ToolbarMoreMenuConfig {
|
||||
configure: <T extends MenuContext>(
|
||||
groups: MenuItemGroup<T>[]
|
||||
) => MenuItemGroup<T>[];
|
||||
}
|
||||
|
||||
export function getMoreMenuConfig(std: BlockStdScope): ToolbarMoreMenuConfig {
|
||||
return {
|
||||
configure: <T extends MenuContext>(groups: MenuItemGroup<T>[]) => groups,
|
||||
...std.getConfig('affine:page')?.toolbarMoreMenu,
|
||||
};
|
||||
}
|
||||
@@ -11,6 +11,11 @@ import {
|
||||
MAX_IMAGE_WIDTH,
|
||||
ReferenceInfoSchema,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
CANVAS_EXPORT_IGNORE_TAGS,
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
EmbedOptionProvider,
|
||||
ParseDocUrlProvider,
|
||||
@@ -55,11 +60,6 @@ import {
|
||||
} from '@blocksuite/store';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
import {
|
||||
CANVAS_EXPORT_IGNORE_TAGS,
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '../../../_common/consts.js';
|
||||
import { ExportManager } from '../../../_common/export-manager/export-manager.js';
|
||||
import { getRootByEditorHost } from '../../../_common/utils/query.js';
|
||||
import { ClipboardAdapter } from '../../clipboard/adapter.js';
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
ShapeElementModel,
|
||||
TextElementModel,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||
import {
|
||||
clamp,
|
||||
@@ -57,7 +58,6 @@ import { state } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { EMBED_CARD_HEIGHT } from '../../../../_common/consts.js';
|
||||
import { isMindmapNode } from '../../../../_common/edgeless/mindmap/index.js';
|
||||
import type { EdgelessTextBlockComponent } from '../../../../edgeless-text-block/edgeless-text-block.js';
|
||||
import { EDGELESS_TEXT_BLOCK_MIN_WIDTH } from '../../../../edgeless-text-block/edgeless-text-block.js';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from './adapters/markdown.js';
|
||||
export * from './clipboard/index.js';
|
||||
export * from './configs/index.js';
|
||||
export * from './edgeless/edgeless-root-spec.js';
|
||||
export * from './edgeless/index.js';
|
||||
export { TemplateJob } from './edgeless/services/template.js';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ToolbarMoreMenuConfig } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { DatabaseOptionsConfig } from '../database-block/config.js';
|
||||
import type { ToolbarMoreMenuConfig } from './configs/index.js';
|
||||
import type { DocRemoteSelectionConfig } from './widgets/doc-remote-selection/config.js';
|
||||
import type { KeyboardToolbarConfig } from './widgets/keyboard-toolbar/config.js';
|
||||
import type { LinkedWidgetConfig } from './widgets/linked-doc/index.js';
|
||||
|
||||
@@ -1,31 +1,6 @@
|
||||
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
||||
import { asyncGetRichText } from '@blocksuite/affine-components/rich-text';
|
||||
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
|
||||
export async function onModelTextUpdated(
|
||||
editorHost: EditorHost,
|
||||
model: BlockModel,
|
||||
callback?: (text: RichText) => void
|
||||
) {
|
||||
const richText = await asyncGetRichText(editorHost, model.id);
|
||||
if (!richText) {
|
||||
console.error('RichText is not ready yet.');
|
||||
return;
|
||||
}
|
||||
await richText.updateComplete;
|
||||
const inlineEditor = richText.inlineEditor;
|
||||
if (!inlineEditor) {
|
||||
console.error('Inline editor is not ready yet.');
|
||||
return;
|
||||
}
|
||||
inlineEditor.slots.renderComplete.once(() => {
|
||||
if (callback) {
|
||||
callback(richText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Run the callback until a model's element updated.
|
||||
// Please notice that the callback will be called **once the element itself is ready**.
|
||||
// The children may be not updated.
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { type BlockModel, type Doc, Text } from '@blocksuite/store';
|
||||
|
||||
/**
|
||||
* This file should only contain functions that are used to
|
||||
* operate on block models in store, which means that this operations
|
||||
* just operate on data and will not involve in something about ui like selection reset.
|
||||
*/
|
||||
|
||||
export function mergeToCodeModel(models: BlockModel[]) {
|
||||
if (models.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const doc = models[0].doc;
|
||||
|
||||
const parent = doc.getParent(models[0]);
|
||||
if (!parent) {
|
||||
return null;
|
||||
}
|
||||
const index = parent.children.indexOf(models[0]);
|
||||
const text = models
|
||||
.map(model => {
|
||||
if (model.text instanceof Text) {
|
||||
return model.text.toString();
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
models.forEach(model => doc.deleteBlock(model));
|
||||
|
||||
const id = doc.addBlock(
|
||||
'affine:code',
|
||||
{ text: new Text(text) },
|
||||
parent,
|
||||
index
|
||||
);
|
||||
return id;
|
||||
}
|
||||
|
||||
export function transformModel(
|
||||
model: BlockModel,
|
||||
flavour: BlockSuite.Flavour,
|
||||
props?: Parameters<Doc['addBlock']>[1]
|
||||
) {
|
||||
const doc = model.doc;
|
||||
const parent = doc.getParent(model);
|
||||
assertExists(parent);
|
||||
const blockProps: {
|
||||
type?: string;
|
||||
text?: Text;
|
||||
children?: BlockModel[];
|
||||
} = {
|
||||
text: model?.text?.clone(), // should clone before `deleteBlock`
|
||||
children: model.children,
|
||||
...props,
|
||||
};
|
||||
const index = parent.children.indexOf(model);
|
||||
|
||||
// Sometimes the new block can not be added due to some reason, e.g. invalid schema check.
|
||||
// So we need to try to add the new block first, and if it fails, we will not delete the old block.
|
||||
const id = doc.addBlock(flavour, blockProps, parent, index);
|
||||
doc.deleteBlock(model, {
|
||||
deleteChildren: false,
|
||||
});
|
||||
return id;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { CodeBlockComponent } from '../../../code-block/code-block.js';
|
||||
import { MenuContext } from '../../configs/toolbar.js';
|
||||
|
||||
export class CodeBlockToolbarContext extends MenuContext {
|
||||
override close = () => {
|
||||
|
||||
@@ -3,15 +3,17 @@ import type {
|
||||
AdvancedMenuItem,
|
||||
MenuItemGroup,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import { cloneGroups } from '@blocksuite/affine-components/toolbar';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import type { CodeBlockModel } from '@blocksuite/affine-model';
|
||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||
import { WidgetComponent } from '@blocksuite/block-std';
|
||||
import { limitShift, shift } from '@floating-ui/dom';
|
||||
import { html } from 'lit';
|
||||
|
||||
import { PAGE_HEADER_HEIGHT } from '../../../_common/consts.js';
|
||||
import type { CodeBlockComponent } from '../../../code-block/code-block.js';
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import { MORE_GROUPS, PRIMARY_GROUPS } from './config.js';
|
||||
import { CodeBlockToolbarContext } from './context.js';
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
CaptionIcon,
|
||||
DownloadIcon,
|
||||
@@ -5,6 +6,10 @@ import {
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar';
|
||||
import type { AttachmentBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '@blocksuite/affine-shared/consts';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { Bound, WithDisposable } from '@blocksuite/global/utils';
|
||||
import type { TemplateResult } from 'lit';
|
||||
@@ -12,12 +17,7 @@ import { html, LitElement, nothing } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { join } from 'lit/directives/join.js';
|
||||
|
||||
import {
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '../../../_common/consts.js';
|
||||
import type { EmbedCardStyle } from '../../../_common/types.js';
|
||||
import { getEmbedCardIcons } from '../../../_common/utils/url.js';
|
||||
import type { AttachmentBlockComponent } from '../../../attachment-block/index.js';
|
||||
import { attachmentViewToggleMenu } from '../../../attachment-block/index.js';
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { getDocContentWithMaxLength } from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
getDocContentWithMaxLength,
|
||||
getEmbedCardIcons,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
CaptionIcon,
|
||||
CenterPeekIcon,
|
||||
@@ -17,6 +20,10 @@ import {
|
||||
renderToolbarSeparator,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import { type AliasInfo, BookmarkStyles } from '@blocksuite/affine-model';
|
||||
import {
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
EmbedOptionProvider,
|
||||
type EmbedOptions,
|
||||
@@ -42,12 +49,7 @@ import type {
|
||||
EmbedModel,
|
||||
} from '../../../_common/components/embed-card/type.js';
|
||||
import { isInternalEmbedModel } from '../../../_common/components/embed-card/type.js';
|
||||
import {
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
} from '../../../_common/consts.js';
|
||||
import type { EmbedCardStyle } from '../../../_common/types.js';
|
||||
import { getEmbedCardIcons } from '../../../_common/utils/url.js';
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
|
||||
import {
|
||||
isBookmarkBlock,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ConnectorCWithArrowIcon } from '@blocksuite/affine-components/icons';
|
||||
import {
|
||||
cloneGroups,
|
||||
darkToolbarStyles,
|
||||
getMoreMenuConfig,
|
||||
lightToolbarStyles,
|
||||
type MenuItemGroup,
|
||||
renderToolbarSeparator,
|
||||
@@ -38,7 +39,6 @@ import { property, state } from 'lit/decorators.js';
|
||||
import { join } from 'lit/directives/join.js';
|
||||
|
||||
import type { EmbedModel } from '../../../_common/components/embed-card/type.js';
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
|
||||
import {
|
||||
isAttachmentBlock,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { SurfaceBlockComponent } from '@blocksuite/affine-block-surface';
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
import {
|
||||
GfxPrimitiveElementModel,
|
||||
type GfxSelectionManager,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
|
||||
import { MenuContext } from '../../../configs/toolbar.js';
|
||||
import type { EdgelessRootBlockComponent } from '../../../edgeless/edgeless-root-block.js';
|
||||
import type { EdgelessRootService } from '../../../edgeless/edgeless-root-service.js';
|
||||
import {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { EmbedBlockComponent } from '../../../_common/components/embed-card/type.js';
|
||||
import { MenuContext } from '../../configs/toolbar.js';
|
||||
|
||||
export class EmbedCardToolbarContext extends MenuContext {
|
||||
override close = () => {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { getDocContentWithMaxLength } from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
getDocContentWithMaxLength,
|
||||
getEmbedCardIcons,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
CaptionIcon,
|
||||
CenterPeekIcon,
|
||||
@@ -15,6 +18,7 @@ import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
||||
import { toast } from '@blocksuite/affine-components/toast';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
type MenuItem,
|
||||
type MenuItemGroup,
|
||||
renderGroups,
|
||||
@@ -24,6 +28,7 @@ import {
|
||||
type AliasInfo,
|
||||
type BookmarkBlockModel,
|
||||
BookmarkStyles,
|
||||
type EmbedCardStyle,
|
||||
type EmbedGithubModel,
|
||||
type EmbedLinkedDocModel,
|
||||
type RootBlockModel,
|
||||
@@ -57,9 +62,6 @@ import {
|
||||
isEmbedCardBlockComponent,
|
||||
isInternalEmbedModel,
|
||||
} from '../../../_common/components/embed-card/type.js';
|
||||
import type { EmbedCardStyle } from '../../../_common/types.js';
|
||||
import { getEmbedCardIcons } from '../../../_common/utils/url.js';
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import {
|
||||
isBookmarkBlock,
|
||||
isEmbedGithubBlock,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MenuContext } from '../../configs/toolbar.js';
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { AffineFormatBarWidget } from './format-bar.js';
|
||||
|
||||
export class FormatBarContext extends MenuContext {
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { RichText } from '@blocksuite/affine-components/rich-text';
|
||||
import { isFormatSupported } from '@blocksuite/affine-components/rich-text';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
type MenuItemGroup,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
@@ -30,7 +31,6 @@ import {
|
||||
import { html, nothing } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import { ConfigRenderer } from './components/config-renderer.js';
|
||||
import {
|
||||
BUILT_IN_GROUPS,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { ImageBlockComponent } from '../../../image-block/image-block.js';
|
||||
import { MenuContext } from '../../configs/toolbar.js';
|
||||
|
||||
export class ImageToolbarContext extends MenuContext {
|
||||
override close = () => {
|
||||
|
||||
@@ -3,15 +3,17 @@ import type {
|
||||
AdvancedMenuItem,
|
||||
MenuItemGroup,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import { cloneGroups } from '@blocksuite/affine-components/toolbar';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||
import { WidgetComponent } from '@blocksuite/block-std';
|
||||
import { limitShift, shift } from '@floating-ui/dom';
|
||||
import { html } from 'lit';
|
||||
|
||||
import { PAGE_HEADER_HEIGHT } from '../../../_common/consts.js';
|
||||
import type { ImageBlockComponent } from '../../../image-block/image-block.js';
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import { MORE_GROUPS, PRIMARY_GROUPS } from './config.js';
|
||||
import { ImageToolbarContext } from './context.js';
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
import type { SurfaceRefBlockComponent } from '../../../surface-ref-block/surface-ref-block.js';
|
||||
import { MenuContext } from '../../configs/toolbar.js';
|
||||
|
||||
export class SurfaceRefToolbarContext extends MenuContext {
|
||||
override close = () => {
|
||||
|
||||
@@ -10,12 +10,14 @@ import {
|
||||
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
type MenuItem,
|
||||
type MenuItemGroup,
|
||||
renderGroups,
|
||||
renderToolbarSeparator,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import type { SurfaceRefBlockModel } from '@blocksuite/affine-model';
|
||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||
import { WidgetComponent } from '@blocksuite/block-std';
|
||||
import { offset, shift } from '@floating-ui/dom';
|
||||
import { html, nothing } from 'lit';
|
||||
@@ -23,9 +25,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { join } from 'lit/directives/join.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
import { PAGE_HEADER_HEIGHT } from '../../../_common/consts.js';
|
||||
import type { SurfaceRefBlockComponent } from '../../../surface-ref-block/index.js';
|
||||
import { getMoreMenuConfig } from '../../configs/toolbar.js';
|
||||
import { BUILT_IN_GROUPS } from './config.js';
|
||||
import { SurfaceRefToolbarContext } from './context.js';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user