refactor(editor): use extension level config (#12110)

Closes: BS-3396

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced structured and validated configuration options for database and linked document views, allowing for more flexible and reliable customization.
  - Enhanced view manager to conditionally enable AI-related paragraph placeholders and database/linked document extensions based on configuration.
- **Chores**
  - Updated dependencies to include the latest version of the Zod validation library.
  - Simplified and consolidated internal configuration and registration logic for AI and widget-related extensions.
- **Refactor**
  - Streamlined configuration types and removed unused or redundant configuration utilities to improve maintainability.
  - Improved robustness of linked widget configuration retrieval to handle optional service availability gracefully.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Saul-Mirone
2025-05-04 13:53:25 +00:00
parent a23112c12a
commit f3b5c36cf7
11 changed files with 156 additions and 118 deletions

View File

@@ -1,14 +1,10 @@
import { WorkspaceServerService } from '@affine/core/modules/cloud';
import { EditorSettingService } from '@affine/core/modules/editor-setting';
import { DatabaseConfigExtension } from '@blocksuite/affine/blocks/database';
import { ToolbarMoreMenuConfigExtension } from '@blocksuite/affine/components/toolbar';
import { EditorSettingExtension } from '@blocksuite/affine/shared/services';
import type { ExtensionType } from '@blocksuite/affine/store';
import { LinkedWidgetConfigExtension } from '@blocksuite/affine/widgets/linked-doc';
import type { FrameworkProvider } from '@toeverything/infra';
import { createDatabaseOptionsConfig } from './database';
import { createLinkedWidgetConfig } from './linked';
import {
createCustomToolbarExtension,
createToolbarMoreMenuConfig,
@@ -27,8 +23,6 @@ export function getEditorConfigExtension(
setting$: editorSettingService.editorSetting.settingSignal,
set: (k, v) => editorSettingService.editorSetting.set(k, v),
}),
DatabaseConfigExtension(createDatabaseOptionsConfig(framework)),
LinkedWidgetConfigExtension(createLinkedWidgetConfig(framework)),
ToolbarMoreMenuConfigExtension(createToolbarMoreMenuConfig(framework)),
createCustomToolbarExtension(editorSettingService.editorSetting, baseUrl),

View File

@@ -4,6 +4,8 @@ import { type FrameworkProvider } from '@toeverything/infra';
export function createLinkedWidgetConfig(
framework: FrameworkProvider
): Partial<LinkedWidgetConfig> {
return framework.get(AtMenuConfigService).getConfig();
): Partial<LinkedWidgetConfig> | undefined {
const service = framework.getOptional(AtMenuConfigService);
if (!service) return;
return service.getConfig();
}

View File

@@ -21,7 +21,6 @@ import {
getThemeExtension,
} from '@affine/core/blocksuite/extensions/theme';
import { PeekViewService } from '@affine/core/modules/peek-view';
import { ParagraphBlockConfigExtension } from '@blocksuite/affine/blocks/paragraph';
import {
type ViewExtensionContext,
ViewExtensionProvider,
@@ -60,58 +59,37 @@ export class AffineCommonViewExtension extends ViewExtensionProvider<
) {
context.register(AIChatBlockSpec);
context.register(AITranscriptionBlockSpec);
context.register(
[
AICodeBlockWatcher,
context.register([
AICodeBlockWatcher,
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:image'),
config: imageToolbarAIEntryConfig(),
}),
]);
if (context.scope === 'edgeless' || context.scope === 'page') {
context.register([
aiPanelWidget,
AiSlashMenuConfigExtension(),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:image'),
config: imageToolbarAIEntryConfig(),
id: BlockFlavourIdentifier('custom:affine:note'),
config: toolbarAIEntryConfig(),
}),
ParagraphBlockConfigExtension({
getPlaceholder: model => {
const placeholders = {
text: "Type '/' for commands, 'space' for AI",
h1: 'Heading 1',
h2: 'Heading 2',
h3: 'Heading 3',
h4: 'Heading 4',
h5: 'Heading 5',
h6: 'Heading 6',
quote: '',
};
return placeholders[model.props.type];
},
}),
].flat()
);
]);
}
if (context.scope === 'edgeless') {
context.register([
CopilotTool,
aiPanelWidget,
edgelessCopilotWidget,
getAIEdgelessRootWatcher(framework),
// In note
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:note'),
config: toolbarAIEntryConfig(),
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:surface:*'),
config: edgelessToolbarAIEntryConfig(),
}),
AiSlashMenuConfigExtension(),
]);
}
if (context.scope === 'page') {
context.register([
aiPanelWidget,
getAIPageRootWatcher(framework),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('custom:affine:note'),
config: toolbarAIEntryConfig(),
}),
AiSlashMenuConfigExtension(),
]);
context.register(getAIPageRootWatcher(framework));
}
}

View File

@@ -1,10 +1,15 @@
import { createDatabaseOptionsConfig } from '@affine/core/blocksuite/extensions/editor-config/database';
import { createLinkedWidgetConfig } from '@affine/core/blocksuite/extensions/editor-config/linked';
import { AffineCommonViewExtension } from '@affine/core/blocksuite/manager/common-view';
import {
AffineEditorViewExtension,
type AffineEditorViewOptions,
} from '@affine/core/blocksuite/manager/editor-view';
import { DatabaseViewExtension } from '@blocksuite/affine/blocks/database/view';
import { ParagraphViewExtension } from '@blocksuite/affine/blocks/paragraph/view';
import { ViewExtensionManager } from '@blocksuite/affine/ext-loader';
import { getInternalViewExtensions } from '@blocksuite/affine/extensions/view';
import { LinkedDocViewExtension } from '@blocksuite/affine/widgets/linked-doc/view';
import type { FrameworkProvider } from '@toeverything/infra';
const manager = new ViewExtensionManager([
@@ -24,5 +29,34 @@ export function getViewManager(
enableAI,
});
manager.configure(AffineEditorViewExtension, options);
if (framework) {
manager.configure(
DatabaseViewExtension,
createDatabaseOptionsConfig(framework)
);
manager.configure(
LinkedDocViewExtension,
createLinkedWidgetConfig(framework)
);
}
if (enableAI) {
manager.configure(ParagraphViewExtension, {
getPlaceholder: model => {
const placeholders = {
text: "Type '/' for commands, 'space' for AI",
h1: 'Heading 1',
h2: 'Heading 2',
h3: 'Heading 3',
h4: 'Heading 4',
h5: 'Heading 5',
h6: 'Heading 6',
quote: '',
};
return placeholders[model.props.type] ?? '';
},
});
}
return manager;
}