mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 07:06:28 +08:00
refactor(editor): linked doc slash menu config extension (#10682)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { BookmarkBlockSchema } from '@blocksuite/affine-model';
|
||||
import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
|
||||
import { SlashMenuConfigExtension } from '@blocksuite/affine-widget-slash-menu';
|
||||
import {
|
||||
BlockFlavourIdentifier,
|
||||
BlockViewExtension,
|
||||
@@ -10,7 +9,7 @@ import type { ExtensionType } from '@blocksuite/store';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { BookmarkBlockAdapterExtensions } from './adapters/extension';
|
||||
import { bookmarkSlashMenuConfig } from './configs/slash-menu';
|
||||
import { BookmarkSlashMenuConfigExtension } from './configs/slash-menu';
|
||||
import { builtinToolbarConfig } from './configs/toolbar';
|
||||
|
||||
const flavour = BookmarkBlockSchema.model.flavour;
|
||||
@@ -27,5 +26,5 @@ export const BookmarkBlockSpec: ExtensionType[] = [
|
||||
id: BlockFlavourIdentifier(flavour),
|
||||
config: builtinToolbarConfig,
|
||||
}),
|
||||
SlashMenuConfigExtension(flavour, bookmarkSlashMenuConfig),
|
||||
BookmarkSlashMenuConfigExtension,
|
||||
].flat();
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { toggleEmbedCardCreateModal } from '@blocksuite/affine-components/embed-card-modal';
|
||||
import { type SlashMenuConfig } from '@blocksuite/affine-widget-slash-menu';
|
||||
import { BookmarkBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
type SlashMenuConfig,
|
||||
SlashMenuConfigIdentifier,
|
||||
} from '@blocksuite/affine-widget-slash-menu';
|
||||
import { LinkIcon } from '@blocksuite/icons/lit';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { LinkTooltip } from './tooltips';
|
||||
|
||||
export const bookmarkSlashMenuConfig: SlashMenuConfig = {
|
||||
const bookmarkSlashMenuConfig: SlashMenuConfig = {
|
||||
items: [
|
||||
{
|
||||
name: 'Link',
|
||||
@@ -40,3 +45,13 @@ export const bookmarkSlashMenuConfig: SlashMenuConfig = {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const BookmarkSlashMenuConfigIdentifier = SlashMenuConfigIdentifier(
|
||||
BookmarkBlockSchema.model.flavour
|
||||
);
|
||||
|
||||
export const BookmarkSlashMenuConfigExtension: ExtensionType = {
|
||||
setup: di => {
|
||||
di.addImpl(BookmarkSlashMenuConfigIdentifier, bookmarkSlashMenuConfig);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,3 +3,4 @@ export * from './bookmark-block';
|
||||
export * from './bookmark-spec';
|
||||
export * from './commands';
|
||||
export * from './components';
|
||||
export { BookmarkSlashMenuConfigIdentifier } from './configs/slash-menu';
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { EmbedLinkedDocBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
getInlineEditorByModel,
|
||||
insertContent,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
|
||||
import { createDefaultDoc } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
type SlashMenuConfig,
|
||||
SlashMenuConfigIdentifier,
|
||||
} from '@blocksuite/affine-widget-slash-menu';
|
||||
import { LinkedPageIcon, PlusIcon } from '@blocksuite/icons/lit';
|
||||
import { type ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { LinkDocTooltip, NewDocTooltip } from './tooltips';
|
||||
|
||||
const linkedDocSlashMenuConfig: SlashMenuConfig = {
|
||||
items: [
|
||||
{
|
||||
name: 'New Doc',
|
||||
description: 'Start a new document.',
|
||||
icon: PlusIcon(),
|
||||
tooltip: {
|
||||
figure: NewDocTooltip,
|
||||
caption: 'New Doc',
|
||||
},
|
||||
group: '3_Page@0',
|
||||
when: ({ model }) =>
|
||||
model.doc.schema.flavourSchemaMap.has('affine:embed-linked-doc'),
|
||||
action: ({ std, model }) => {
|
||||
const newDoc = createDefaultDoc(std.host.doc.workspace);
|
||||
insertContent(std.host, model, REFERENCE_NODE, {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId: newDoc.id,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Linked Doc',
|
||||
description: 'Link to another document.',
|
||||
icon: LinkedPageIcon(),
|
||||
tooltip: {
|
||||
figure: LinkDocTooltip,
|
||||
caption: 'Link Doc',
|
||||
},
|
||||
searchAlias: ['dual link'],
|
||||
group: '3_Page@1',
|
||||
when: ({ std, model }) => {
|
||||
const root = model.doc.root;
|
||||
if (!root) return false;
|
||||
const linkedDocWidget = std.view.getWidget(
|
||||
'affine-linked-doc-widget',
|
||||
root.id
|
||||
);
|
||||
if (!linkedDocWidget) return false;
|
||||
|
||||
return model.doc.schema.flavourSchemaMap.has('affine:embed-linked-doc');
|
||||
},
|
||||
action: ({ model, std }) => {
|
||||
const root = model.doc.root;
|
||||
if (!root) return;
|
||||
const linkedDocWidget = std.view.getWidget(
|
||||
'affine-linked-doc-widget',
|
||||
root.id
|
||||
);
|
||||
if (!linkedDocWidget) return;
|
||||
// TODO(@L-Sun): make linked-doc-widget as extension
|
||||
// @ts-expect-error same as above
|
||||
const triggerKey = linkedDocWidget.config.triggerKeys[0];
|
||||
|
||||
insertContent(std.host, model, triggerKey);
|
||||
|
||||
const inlineEditor = getInlineEditorByModel(std.host, model);
|
||||
// Wait for range to be updated
|
||||
inlineEditor?.slots.inlineRangeSync.once(() => {
|
||||
// TODO(@L-Sun): make linked-doc-widget as extension
|
||||
// @ts-expect-error same as above
|
||||
linkedDocWidget.show({ addTriggerKey: true });
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const LinkedDocSlashMenuConfigIdentifier = SlashMenuConfigIdentifier(
|
||||
EmbedLinkedDocBlockSchema.model.flavour
|
||||
);
|
||||
|
||||
export const LinkedDocSlashMenuConfigExtension: ExtensionType = {
|
||||
setup: di => {
|
||||
di.addImpl(LinkedDocSlashMenuConfigIdentifier, linkedDocSlashMenuConfig);
|
||||
},
|
||||
};
|
||||
+13
@@ -1,4 +1,17 @@
|
||||
import { html } from 'lit';
|
||||
// prettier-ignore
|
||||
export const NewDocTooltip = html`<svg width="170" height="68" viewBox="0 0 170 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="170" height="68" rx="2" fill="white"/>
|
||||
<mask id="mask0_16460_991" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="170" height="68">
|
||||
<rect width="170" height="68" rx="2" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_16460_991)">
|
||||
<text fill="#8E8D91" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="22" font-weight="600" letter-spacing="0px"><tspan x="8" y="27.5">Title</tspan></text>
|
||||
<text fill="#8E8D91" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" letter-spacing="0px"><tspan x="8" y="44.6364">Type '/' for commands</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
// prettier-ignore
|
||||
export const LinkDocTooltip = html`<svg width="170" height="68" viewBox="0 0 170 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="170" height="68" rx="2" fill="white"/>
|
||||
@@ -8,6 +8,7 @@ import type { ExtensionType } from '@blocksuite/store';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { EmbedLinkedDocBlockAdapterExtensions } from './adapters/extension';
|
||||
import { LinkedDocSlashMenuConfigExtension } from './configs/slash-menu';
|
||||
import { builtinToolbarConfig } from './configs/toolbar';
|
||||
|
||||
const flavour = EmbedLinkedDocBlockSchema.model.flavour;
|
||||
@@ -23,4 +24,5 @@ export const EmbedLinkedDocBlockSpec: ExtensionType[] = [
|
||||
id: BlockServiceIdentifier(flavour),
|
||||
config: builtinToolbarConfig,
|
||||
}),
|
||||
LinkedDocSlashMenuConfigExtension,
|
||||
].flat();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './adapters';
|
||||
export * from './commands';
|
||||
export { LinkedDocSlashMenuConfigIdentifier } from './configs/slash-menu';
|
||||
export * from './embed-linked-doc-block';
|
||||
export * from './embed-linked-doc-spec';
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// TODO(@L-Sun): remove these utils
|
||||
export function formatDate(date: Date) {
|
||||
// yyyy-mm-dd
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const strTime = `${year}-${month}-${day}`;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
export function formatTime(date: Date) {
|
||||
// mm-dd hh:mm
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
const strTime = `${month}-${day} ${hours}:${minutes}`;
|
||||
return strTime;
|
||||
}
|
||||
@@ -101,7 +101,6 @@ import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
import type { PageRootBlockComponent } from '../../page/page-root-block.js';
|
||||
import { formatDate, formatTime } from '../../utils/misc.js';
|
||||
import type { AffineLinkedDocWidget } from '../linked-doc/index.js';
|
||||
import {
|
||||
FigmaDuotoneIcon,
|
||||
@@ -110,6 +109,7 @@ import {
|
||||
TextBackgroundDuotoneIcon,
|
||||
TextColorIcon,
|
||||
} from './icons.js';
|
||||
import { formatDate, formatTime } from './utils.js';
|
||||
|
||||
export type KeyboardToolbarConfig = {
|
||||
items: KeyboardToolbarItem[];
|
||||
|
||||
@@ -22,3 +22,22 @@ export function isKeyboardToolPanelConfig(
|
||||
): item is KeyboardToolPanelConfig {
|
||||
return 'groups' in item;
|
||||
}
|
||||
|
||||
export function formatDate(date: Date) {
|
||||
// yyyy-mm-dd
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const strTime = `${year}-${month}-${day}`;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
export function formatTime(date: Date) {
|
||||
// mm-dd hh:mm
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
const strTime = `${month}-${day} ${hours}:${minutes}`;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import { toast } from '@blocksuite/affine-components/toast';
|
||||
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
getInlineEditorByModel,
|
||||
insertContent,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
|
||||
import { createDefaultDoc } from '@blocksuite/affine-shared/utils';
|
||||
import { insertContent } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
ArrowDownBigIcon,
|
||||
ArrowUpBigIcon,
|
||||
CopyIcon,
|
||||
DeleteIcon,
|
||||
DualLinkIcon,
|
||||
LinkedPageIcon,
|
||||
NowIcon,
|
||||
PlusIcon,
|
||||
TodayIcon,
|
||||
TomorrowIcon,
|
||||
YesterdayIcon,
|
||||
@@ -38,67 +31,6 @@ export const defaultSlashMenuConfig: SlashMenuConfig = {
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
return [
|
||||
{
|
||||
name: 'New Doc',
|
||||
description: 'Start a new document.',
|
||||
icon: PlusIcon(),
|
||||
tooltip: slashMenuToolTips['New Doc'],
|
||||
group: '3_Page@0',
|
||||
when: ({ model }) =>
|
||||
model.doc.schema.flavourSchemaMap.has('affine:embed-linked-doc'),
|
||||
action: ({ std, model }) => {
|
||||
const newDoc = createDefaultDoc(std.host.doc.workspace);
|
||||
insertContent(std.host, model, REFERENCE_NODE, {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId: newDoc.id,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Linked Doc',
|
||||
description: 'Link to another document.',
|
||||
icon: LinkedPageIcon(),
|
||||
tooltip: slashMenuToolTips['Linked Doc'],
|
||||
searchAlias: ['dual link'],
|
||||
group: '3_Page@1',
|
||||
when: ({ std, model }) => {
|
||||
const root = model.doc.root;
|
||||
if (!root) return false;
|
||||
const linkedDocWidget = std.view.getWidget(
|
||||
'affine-linked-doc-widget',
|
||||
root.id
|
||||
);
|
||||
if (!linkedDocWidget) return false;
|
||||
|
||||
return model.doc.schema.flavourSchemaMap.has(
|
||||
'affine:embed-linked-doc'
|
||||
);
|
||||
},
|
||||
action: ({ model, std }) => {
|
||||
const root = model.doc.root;
|
||||
if (!root) return;
|
||||
const linkedDocWidget = std.view.getWidget(
|
||||
'affine-linked-doc-widget',
|
||||
root.id
|
||||
);
|
||||
if (!linkedDocWidget) return;
|
||||
// TODO(@L-Sun): make linked-doc-widget as extension
|
||||
// @ts-expect-error same as above
|
||||
const triggerKey = linkedDocWidget.config.triggerKeys[0];
|
||||
|
||||
insertContent(std.host, model, triggerKey);
|
||||
|
||||
const inlineEditor = getInlineEditorByModel(std.host, model);
|
||||
// Wait for range to be updated
|
||||
inlineEditor?.slots.inlineRangeSync.once(() => {
|
||||
// TODO(@L-Sun): make linked-doc-widget as extension
|
||||
// @ts-expect-error same as above
|
||||
linkedDocWidget.show({ addTriggerKey: true });
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Today',
|
||||
icon: TodayIcon(),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export const AFFINE_SLASH_MENU_WIDGET = 'affine-slash-menu-widget';
|
||||
export const AFFINE_SLASH_MENU_TRIGGER_KEY = '/';
|
||||
export const AFFINE_SLASH_MENU_TOOLTIP_TIMEOUT = 800;
|
||||
// TODO(@L-Sun): Move this to styles.ts
|
||||
export const AFFINE_SLASH_MENU_MAX_HEIGHT = 334;
|
||||
|
||||
@@ -24,7 +24,6 @@ export class SlashMenuExtension extends Extension {
|
||||
|
||||
di.add(this, [StdIdentifier]);
|
||||
|
||||
// TODO(@L-Sun): remove this after moving all configs to corresponding extensions
|
||||
SlashMenuConfigExtension('default', defaultSlashMenuConfig).setup(di);
|
||||
}
|
||||
|
||||
@@ -36,7 +35,7 @@ export class SlashMenuExtension extends Extension {
|
||||
}
|
||||
}
|
||||
|
||||
const SlashMenuConfigIdentifier = createIdentifier<SlashMenuConfig>(
|
||||
export const SlashMenuConfigIdentifier = createIdentifier<SlashMenuConfig>(
|
||||
`${AFFINE_SLASH_MENU_WIDGET}-config`
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
export { AFFINE_SLASH_MENU_WIDGET } from './consts';
|
||||
// TODO(@L-Sun): narrow the scope of the exported symbols
|
||||
export * from './extensions';
|
||||
export * from './types';
|
||||
// TODO(@L-Sun): remove this when refactoring quick search
|
||||
export * from './widget';
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
import type { SlashMenuTooltip } from '../types';
|
||||
import { CopyTooltip } from './copy';
|
||||
import { DeleteTooltip } from './delete';
|
||||
import { LinkDocTooltip } from './link-doc';
|
||||
import { MoveDownTooltip } from './move-down';
|
||||
import { MoveUpTooltip } from './move-up';
|
||||
import { NewDocTooltip } from './new-doc';
|
||||
import { NowTooltip } from './now';
|
||||
import { TodayTooltip } from './today';
|
||||
import { TomorrowTooltip } from './tomorrow';
|
||||
import { YesterdayTooltip } from './yesterday';
|
||||
|
||||
export const slashMenuToolTips: Record<string, SlashMenuTooltip> = {
|
||||
'New Doc': {
|
||||
figure: NewDocTooltip,
|
||||
caption: 'New Doc',
|
||||
},
|
||||
|
||||
'Linked Doc': {
|
||||
figure: LinkDocTooltip,
|
||||
caption: 'Link Doc',
|
||||
},
|
||||
|
||||
Today: {
|
||||
figure: TodayTooltip,
|
||||
caption: 'Today',
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { html } from 'lit';
|
||||
// prettier-ignore
|
||||
export const NewDocTooltip = html`<svg width="170" height="68" viewBox="0 0 170 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="170" height="68" rx="2" fill="white"/>
|
||||
<mask id="mask0_16460_991" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="170" height="68">
|
||||
<rect width="170" height="68" rx="2" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_16460_991)">
|
||||
<text fill="#8E8D91" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="22" font-weight="600" letter-spacing="0px"><tspan x="8" y="27.5">Title</tspan></text>
|
||||
<text fill="#8E8D91" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" letter-spacing="0px"><tspan x="8" y="44.6364">Type '/' for commands</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
@@ -12,7 +12,7 @@ export type SlashMenuTooltip = {
|
||||
caption: string;
|
||||
};
|
||||
|
||||
export type SlashMenuItemBase = {
|
||||
type SlashMenuItemBase = {
|
||||
name: string;
|
||||
description?: string;
|
||||
icon?: TemplateResult;
|
||||
@@ -24,10 +24,6 @@ export type SlashMenuItemBase = {
|
||||
*/
|
||||
group?: `${number}_${string}@${number}`;
|
||||
|
||||
// TODO(@L-Sun): move this field to SlashMenuActionItem when refactoring search
|
||||
/**
|
||||
* The alias of the menu item for search.
|
||||
*/
|
||||
searchAlias?: string[];
|
||||
/**
|
||||
* The condition to show the menu item.
|
||||
@@ -38,6 +34,10 @@ export type SlashMenuItemBase = {
|
||||
export type SlashMenuActionItem = SlashMenuItemBase & {
|
||||
action: (ctx: SlashMenuContext) => void;
|
||||
tooltip?: SlashMenuTooltip;
|
||||
/**
|
||||
* The alias of the menu item for search.
|
||||
*/
|
||||
searchAlias?: string[];
|
||||
};
|
||||
|
||||
export type SlashMenuSubMenu = SlashMenuItemBase & {
|
||||
@@ -47,7 +47,6 @@ export type SlashMenuSubMenu = SlashMenuItemBase & {
|
||||
export type SlashMenuItem = SlashMenuActionItem | SlashMenuSubMenu;
|
||||
|
||||
export type SlashMenuConfig = {
|
||||
// TODO(@L-Sun): change this type to SlashMenuItem[] and (ctx: SlashMenuContext) => SlashMenuItem[]
|
||||
/**
|
||||
* The items in the slash menu. It can be generated dynamically with the context.
|
||||
*/
|
||||
|
||||
@@ -10,14 +10,19 @@ import {
|
||||
import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links';
|
||||
import { JournalsQuickSearchSession } from '@affine/core/modules/quicksearch/impls/journals';
|
||||
import { track } from '@affine/track';
|
||||
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||
import type { QuickSearchResult } from '@blocksuite/affine/blocks';
|
||||
import type {
|
||||
QuickSearchResult,
|
||||
SlashMenuConfig,
|
||||
SlashMenuItem,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import {
|
||||
AffineSlashMenuWidget,
|
||||
BookmarkSlashMenuConfigIdentifier,
|
||||
insertLinkByQuickSearchCommand,
|
||||
LinkedDocSlashMenuConfigIdentifier,
|
||||
QuickSearchExtension,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { Text } from '@blocksuite/affine/store';
|
||||
import type { ServiceIdentifier } from '@blocksuite/affine/global/di';
|
||||
import { type ExtensionType, Text } from '@blocksuite/affine/store';
|
||||
import type { FrameworkProvider } from '@toeverything/infra';
|
||||
import { pick } from 'lodash-es';
|
||||
|
||||
@@ -120,56 +125,66 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
||||
},
|
||||
});
|
||||
|
||||
class SlashMenuQuickSearchExtension extends LifeCycleWatcher {
|
||||
static override key = 'slash-menu-quick-search-extension';
|
||||
const SlashMenuQuickSearchExtension: ExtensionType = {
|
||||
setup: di => {
|
||||
const overrideFn = (identifier: ServiceIdentifier<SlashMenuConfig>) => {
|
||||
const prev = di.getFactory(identifier);
|
||||
if (!prev) return;
|
||||
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
const component = payload.view;
|
||||
if (component instanceof AffineSlashMenuWidget) {
|
||||
component.configItemTransform = item => {
|
||||
if (
|
||||
'action' in item &&
|
||||
(item.name === 'Linked Doc' || item.name === 'Link')
|
||||
) {
|
||||
item.action = ({ std }) => {
|
||||
const [success, { insertedLinkType }] = std.command.exec(
|
||||
insertLinkByQuickSearchCommand
|
||||
);
|
||||
di.override(identifier, provider => {
|
||||
const prevConfig: SlashMenuConfig = prev(provider);
|
||||
|
||||
if (!success) return;
|
||||
if (typeof prevConfig.items === 'function') {
|
||||
const prevConfigItemGenerator = prevConfig.items;
|
||||
prevConfig.items = ctx =>
|
||||
prevConfigItemGenerator(ctx).map(modifyFn);
|
||||
} else {
|
||||
prevConfig.items = prevConfig.items.map(modifyFn);
|
||||
}
|
||||
|
||||
insertedLinkType
|
||||
?.then(type => {
|
||||
const flavour = type?.flavour;
|
||||
if (!flavour) return;
|
||||
return prevConfig;
|
||||
});
|
||||
};
|
||||
|
||||
if (flavour === 'affine:bookmark') {
|
||||
track.doc.editor.slashMenu.bookmark();
|
||||
return;
|
||||
}
|
||||
overrideFn(LinkedDocSlashMenuConfigIdentifier);
|
||||
overrideFn(BookmarkSlashMenuConfigIdentifier);
|
||||
|
||||
if (flavour === 'affine:embed-linked-doc') {
|
||||
track.doc.editor.slashMenu.linkDoc({
|
||||
control: 'linkDoc',
|
||||
});
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
}
|
||||
return item;
|
||||
const modifyFn = (item: SlashMenuItem): SlashMenuItem => {
|
||||
if (
|
||||
'action' in item &&
|
||||
(item.name === 'Linked Doc' || item.name === 'Link')
|
||||
) {
|
||||
item.action = ({ std }) => {
|
||||
const [success, { insertedLinkType }] = std.command.exec(
|
||||
insertLinkByQuickSearchCommand
|
||||
);
|
||||
|
||||
if (!success) return;
|
||||
|
||||
insertedLinkType
|
||||
?.then(type => {
|
||||
const flavour = type?.flavour;
|
||||
if (!flavour) return;
|
||||
|
||||
if (flavour === 'affine:bookmark') {
|
||||
track.doc.editor.slashMenu.bookmark();
|
||||
return;
|
||||
}
|
||||
|
||||
if (flavour === 'affine:embed-linked-doc') {
|
||||
track.doc.editor.slashMenu.linkDoc({
|
||||
control: 'linkDoc',
|
||||
});
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return item;
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return [QuickSearch, SlashMenuQuickSearchExtension];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user