mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
feat(editor): replace spec provider with extension manager (#11861)
Closes: BS-3273
This commit is contained in:
@@ -208,7 +208,9 @@
|
|||||||
"./model": "./src/model/index.ts",
|
"./model": "./src/model/index.ts",
|
||||||
"./sync": "./src/sync/index.ts",
|
"./sync": "./src/sync/index.ts",
|
||||||
"./adapters": "./src/adapters/index.ts",
|
"./adapters": "./src/adapters/index.ts",
|
||||||
"./extensions": "./src/extensions/index.ts"
|
"./extensions": "./src/extensions/index.ts",
|
||||||
|
"./extensions/store": "./src/extensions/store.ts",
|
||||||
|
"./extensions/view": "./src/extensions/view.ts"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
|
|||||||
153
blocksuite/affine/all/src/extensions/migrating.ts
Normal file
153
blocksuite/affine/all/src/extensions/migrating.ts
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
|
||||||
|
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
||||||
|
import { CalloutBlockSpec } from '@blocksuite/affine-block-callout';
|
||||||
|
import { CodeBlockSpec } from '@blocksuite/affine-block-code';
|
||||||
|
import { DataViewBlockSpec } from '@blocksuite/affine-block-data-view';
|
||||||
|
import { DatabaseBlockSpec } from '@blocksuite/affine-block-database';
|
||||||
|
import { DividerBlockSpec } from '@blocksuite/affine-block-divider';
|
||||||
|
import { EdgelessTextBlockSpec } from '@blocksuite/affine-block-edgeless-text';
|
||||||
|
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
||||||
|
import { FrameBlockSpec } from '@blocksuite/affine-block-frame';
|
||||||
|
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
||||||
|
import { LatexBlockSpec } from '@blocksuite/affine-block-latex';
|
||||||
|
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
||||||
|
import {
|
||||||
|
EdgelessNoteBlockSpec,
|
||||||
|
NoteBlockSpec,
|
||||||
|
} from '@blocksuite/affine-block-note';
|
||||||
|
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
||||||
|
import {
|
||||||
|
EdgelessBuiltInSpecs,
|
||||||
|
PageRootBlockSpec,
|
||||||
|
PreviewEdgelessRootBlockSpec,
|
||||||
|
PreviewPageRootBlockSpec,
|
||||||
|
ReadOnlyClipboard,
|
||||||
|
} from '@blocksuite/affine-block-root';
|
||||||
|
import {
|
||||||
|
EdgelessSurfaceBlockAdapterExtensions,
|
||||||
|
EdgelessSurfaceBlockSpec,
|
||||||
|
PageSurfaceBlockSpec,
|
||||||
|
SurfaceBlockAdapterExtensions,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
|
import {
|
||||||
|
EdgelessSurfaceRefBlockSpec,
|
||||||
|
PageSurfaceRefBlockSpec,
|
||||||
|
} from '@blocksuite/affine-block-surface-ref';
|
||||||
|
import { TableBlockSpec } from '@blocksuite/affine-block-table';
|
||||||
|
import {
|
||||||
|
brushToMarkdownAdapterMatcher,
|
||||||
|
brushToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-brush';
|
||||||
|
import {
|
||||||
|
connectorToMarkdownAdapterMatcher,
|
||||||
|
connectorToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-connector';
|
||||||
|
import {
|
||||||
|
groupToMarkdownAdapterMatcher,
|
||||||
|
groupToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-group';
|
||||||
|
import {
|
||||||
|
mindmapToMarkdownAdapterMatcher,
|
||||||
|
mindmapToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-mindmap';
|
||||||
|
import {
|
||||||
|
shapeToMarkdownAdapterMatcher,
|
||||||
|
shapeToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-shape';
|
||||||
|
import {
|
||||||
|
textToMarkdownAdapterMatcher,
|
||||||
|
textToPlainTextAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-gfx-text';
|
||||||
|
import { inlinePresetExtensions } from '@blocksuite/affine-inline-preset';
|
||||||
|
import {
|
||||||
|
DefaultOpenDocExtension,
|
||||||
|
DocDisplayMetaService,
|
||||||
|
EditPropsStore,
|
||||||
|
FontLoaderService,
|
||||||
|
} from '@blocksuite/affine-shared/services';
|
||||||
|
import type { ExtensionType } from '@blocksuite/store';
|
||||||
|
|
||||||
|
const elementToPlainTextAdapterMatchers = [
|
||||||
|
groupToPlainTextAdapterMatcher,
|
||||||
|
shapeToPlainTextAdapterMatcher,
|
||||||
|
connectorToPlainTextAdapterMatcher,
|
||||||
|
brushToPlainTextAdapterMatcher,
|
||||||
|
textToPlainTextAdapterMatcher,
|
||||||
|
mindmapToPlainTextAdapterMatcher,
|
||||||
|
];
|
||||||
|
|
||||||
|
const elementToMarkdownAdapterMatchers = [
|
||||||
|
groupToMarkdownAdapterMatcher,
|
||||||
|
shapeToMarkdownAdapterMatcher,
|
||||||
|
connectorToMarkdownAdapterMatcher,
|
||||||
|
brushToMarkdownAdapterMatcher,
|
||||||
|
textToMarkdownAdapterMatcher,
|
||||||
|
mindmapToMarkdownAdapterMatcher,
|
||||||
|
];
|
||||||
|
|
||||||
|
const CommonBlockSpecs: ExtensionType[] = [
|
||||||
|
inlinePresetExtensions,
|
||||||
|
DocDisplayMetaService,
|
||||||
|
EditPropsStore,
|
||||||
|
LatexBlockSpec,
|
||||||
|
ListBlockSpec,
|
||||||
|
DatabaseBlockSpec,
|
||||||
|
TableBlockSpec,
|
||||||
|
DataViewBlockSpec,
|
||||||
|
DividerBlockSpec,
|
||||||
|
BookmarkBlockSpec,
|
||||||
|
EmbedExtensions,
|
||||||
|
AttachmentBlockSpec,
|
||||||
|
CodeBlockSpec,
|
||||||
|
ImageBlockSpec,
|
||||||
|
ParagraphBlockSpec,
|
||||||
|
DefaultOpenDocExtension,
|
||||||
|
FontLoaderService,
|
||||||
|
CalloutBlockSpec,
|
||||||
|
FrameBlockSpec,
|
||||||
|
|
||||||
|
elementToPlainTextAdapterMatchers,
|
||||||
|
elementToMarkdownAdapterMatchers,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
const PageFirstPartyBlockSpecs: ExtensionType[] = [
|
||||||
|
CommonBlockSpecs,
|
||||||
|
NoteBlockSpec,
|
||||||
|
PageSurfaceBlockSpec,
|
||||||
|
PageSurfaceRefBlockSpec,
|
||||||
|
|
||||||
|
...SurfaceBlockAdapterExtensions,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
const EdgelessFirstPartyBlockSpecs: ExtensionType[] = [
|
||||||
|
CommonBlockSpecs,
|
||||||
|
|
||||||
|
EdgelessNoteBlockSpec,
|
||||||
|
EdgelessSurfaceBlockSpec,
|
||||||
|
EdgelessSurfaceRefBlockSpec,
|
||||||
|
EdgelessTextBlockSpec,
|
||||||
|
|
||||||
|
...EdgelessSurfaceBlockAdapterExtensions,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
export const MigratingEdgelessEditorBlockSpecs: ExtensionType[] = [
|
||||||
|
EdgelessBuiltInSpecs,
|
||||||
|
EdgelessFirstPartyBlockSpecs,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
export const MigratingPageEditorBlockSpecs: ExtensionType[] = [
|
||||||
|
PageRootBlockSpec,
|
||||||
|
PageFirstPartyBlockSpecs,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
export const MigratingPreviewEdgelessEditorBlockSpecs: ExtensionType[] = [
|
||||||
|
PreviewEdgelessRootBlockSpec,
|
||||||
|
EdgelessFirstPartyBlockSpecs,
|
||||||
|
ReadOnlyClipboard,
|
||||||
|
].flat();
|
||||||
|
|
||||||
|
export const MigratingPreviewPageEditorBlockSpecs: ExtensionType[] = [
|
||||||
|
PreviewPageRootBlockSpec,
|
||||||
|
PageFirstPartyBlockSpecs,
|
||||||
|
ReadOnlyClipboard,
|
||||||
|
].flat();
|
||||||
@@ -4,6 +4,10 @@ import { EmbedIframeConfigExtensions } from '@blocksuite/affine-block-embed';
|
|||||||
import { ImageStoreSpec } from '@blocksuite/affine-block-image';
|
import { ImageStoreSpec } from '@blocksuite/affine-block-image';
|
||||||
import { SurfaceBlockSchemaExtension } from '@blocksuite/affine-block-surface';
|
import { SurfaceBlockSchemaExtension } from '@blocksuite/affine-block-surface';
|
||||||
import { TableSelectionExtension } from '@blocksuite/affine-block-table';
|
import { TableSelectionExtension } from '@blocksuite/affine-block-table';
|
||||||
|
import {
|
||||||
|
type StoreExtensionContext,
|
||||||
|
StoreExtensionProvider,
|
||||||
|
} from '@blocksuite/affine-ext-loader';
|
||||||
import {
|
import {
|
||||||
AttachmentBlockSchemaExtension,
|
AttachmentBlockSchemaExtension,
|
||||||
BookmarkBlockSchemaExtension,
|
BookmarkBlockSchemaExtension,
|
||||||
@@ -110,3 +114,12 @@ export const StoreExtensions: ExtensionType[] = [
|
|||||||
EmbedIframeConfigExtensions,
|
EmbedIframeConfigExtensions,
|
||||||
EmbedIframeService,
|
EmbedIframeService,
|
||||||
].flat();
|
].flat();
|
||||||
|
|
||||||
|
export class MigratingStoreExtension extends StoreExtensionProvider {
|
||||||
|
override name = 'migrating';
|
||||||
|
|
||||||
|
override setup(context: StoreExtensionContext) {
|
||||||
|
super.setup(context);
|
||||||
|
context.register(StoreExtensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
42
blocksuite/affine/all/src/extensions/view.ts
Normal file
42
blocksuite/affine/all/src/extensions/view.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import {
|
||||||
|
type ViewExtensionContext,
|
||||||
|
ViewExtensionProvider,
|
||||||
|
} from '@blocksuite/affine-ext-loader';
|
||||||
|
|
||||||
|
import { effects } from '../effects';
|
||||||
|
import {
|
||||||
|
MigratingEdgelessEditorBlockSpecs,
|
||||||
|
MigratingPageEditorBlockSpecs,
|
||||||
|
MigratingPreviewEdgelessEditorBlockSpecs,
|
||||||
|
MigratingPreviewPageEditorBlockSpecs,
|
||||||
|
} from './migrating';
|
||||||
|
|
||||||
|
export class MigratingViewExtension extends ViewExtensionProvider {
|
||||||
|
override name = 'migrating';
|
||||||
|
|
||||||
|
override effect() {
|
||||||
|
super.effect();
|
||||||
|
effects();
|
||||||
|
}
|
||||||
|
|
||||||
|
override setup(context: ViewExtensionContext) {
|
||||||
|
super.setup(context);
|
||||||
|
const scope = context.scope;
|
||||||
|
if (scope === 'preview-page') {
|
||||||
|
context.register(MigratingPreviewPageEditorBlockSpecs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scope === 'preview-edgeless') {
|
||||||
|
context.register(MigratingPreviewEdgelessEditorBlockSpecs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scope === 'page' || scope === 'mobile-page') {
|
||||||
|
context.register(MigratingPageEditorBlockSpecs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scope === 'edgeless' || scope === 'mobile-edgeless') {
|
||||||
|
context.register(MigratingEdgelessEditorBlockSpecs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
|
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import {
|
import {
|
||||||
type DocMode,
|
type DocMode,
|
||||||
ImageBlockModel,
|
ImageBlockModel,
|
||||||
@@ -9,7 +10,7 @@ import {
|
|||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts';
|
import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||||
import { NotificationProvider } from '@blocksuite/affine-shared/services';
|
import { NotificationProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { matchModels, SpecProvider } from '@blocksuite/affine-shared/utils';
|
import { matchModels } from '@blocksuite/affine-shared/utils';
|
||||||
import { BlockStdScope, EditorLifeCycleExtension } from '@blocksuite/std';
|
import { BlockStdScope, EditorLifeCycleExtension } from '@blocksuite/std';
|
||||||
import {
|
import {
|
||||||
type BlockModel,
|
type BlockModel,
|
||||||
@@ -202,10 +203,13 @@ async function renderNoteContent(
|
|||||||
match: ids.map(id => ({ id, viewType: 'display' })),
|
match: ids.map(id => ({ id, viewType: 'display' })),
|
||||||
};
|
};
|
||||||
const previewDoc = doc.doc.getStore({ query });
|
const previewDoc = doc.doc.getStore({ query });
|
||||||
const previewSpec = SpecProvider._.getSpec('preview:page');
|
const std = card.host.std;
|
||||||
|
const previewSpec = std
|
||||||
|
.get(ViewExtensionManagerIdentifier)
|
||||||
|
.get('preview-page');
|
||||||
const previewStd = new BlockStdScope({
|
const previewStd = new BlockStdScope({
|
||||||
store: previewDoc,
|
store: previewDoc,
|
||||||
extensions: previewSpec.value,
|
extensions: previewSpec,
|
||||||
});
|
});
|
||||||
const previewTemplate = previewStd.render();
|
const previewTemplate = previewStd.render();
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
<div class="affine-page-viewport" data-theme=${appTheme}>
|
<div class="affine-page-viewport" data-theme=${appTheme}>
|
||||||
${new BlockStdScope({
|
${new BlockStdScope({
|
||||||
store: syncedDoc,
|
store: syncedDoc,
|
||||||
extensions: this._buildPreviewSpec('preview:page'),
|
extensions: this._buildPreviewSpec('preview-page'),
|
||||||
}).render()}
|
}).render()}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@@ -81,7 +81,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
<div class="affine-edgeless-viewport" data-theme=${edgelessTheme}>
|
<div class="affine-edgeless-viewport" data-theme=${edgelessTheme}>
|
||||||
${new BlockStdScope({
|
${new BlockStdScope({
|
||||||
store: syncedDoc,
|
store: syncedDoc,
|
||||||
extensions: this._buildPreviewSpec('preview:edgeless'),
|
extensions: this._buildPreviewSpec('preview-edgeless'),
|
||||||
}).render()}
|
}).render()}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Peekable } from '@blocksuite/affine-components/peek';
|
import { Peekable } from '@blocksuite/affine-components/peek';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import {
|
import {
|
||||||
type DocLinkClickedEvent,
|
type DocLinkClickedEvent,
|
||||||
RefNodeSlotsProvider,
|
RefNodeSlotsProvider,
|
||||||
@@ -20,10 +21,7 @@ import {
|
|||||||
ThemeExtensionIdentifier,
|
ThemeExtensionIdentifier,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import {
|
import { cloneReferenceInfo } from '@blocksuite/affine-shared/utils';
|
||||||
cloneReferenceInfo,
|
|
||||||
SpecProvider,
|
|
||||||
} from '@blocksuite/affine-shared/utils';
|
|
||||||
import { Bound, getCommonBound } from '@blocksuite/global/gfx';
|
import { Bound, getCommonBound } from '@blocksuite/global/gfx';
|
||||||
import {
|
import {
|
||||||
BlockSelection,
|
BlockSelection,
|
||||||
@@ -113,9 +111,10 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
protected _buildPreviewSpec = (name: 'preview:page' | 'preview:edgeless') => {
|
protected _buildPreviewSpec = (name: 'preview-page' | 'preview-edgeless') => {
|
||||||
const nextDepth = this.depth + 1;
|
const nextDepth = this.depth + 1;
|
||||||
const previewSpecBuilder = SpecProvider._.getSpec(name);
|
const viewExtensionManager = this.std.get(ViewExtensionManagerIdentifier);
|
||||||
|
const previewSpec = viewExtensionManager.get(name);
|
||||||
const currentDisposables = this.disposables;
|
const currentDisposables = this.disposables;
|
||||||
const editorSetting = this.std.getOptional(EditorSettingProvider) ?? {
|
const editorSetting = this.std.getOptional(EditorSettingProvider) ?? {
|
||||||
setting$: signal(GeneralSettingSchema.parse({})),
|
setting$: signal(GeneralSettingSchema.parse({})),
|
||||||
@@ -157,13 +156,11 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previewSpecBuilder.extend([
|
return previewSpec.concat([
|
||||||
EmbedSyncedDocWatcher,
|
EmbedSyncedDocWatcher,
|
||||||
GfxViewportInitializer,
|
GfxViewportInitializer,
|
||||||
EditorSettingExtension(editorSetting),
|
EditorSettingExtension(editorSetting),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return previewSpecBuilder.value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected _renderSyncedView = () => {
|
protected _renderSyncedView = () => {
|
||||||
@@ -204,7 +201,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
<div class="affine-page-viewport" data-theme=${appTheme}>
|
<div class="affine-page-viewport" data-theme=${appTheme}>
|
||||||
${new BlockStdScope({
|
${new BlockStdScope({
|
||||||
store: syncedDoc,
|
store: syncedDoc,
|
||||||
extensions: this._buildPreviewSpec('preview:page'),
|
extensions: this._buildPreviewSpec('preview-page'),
|
||||||
}).render()}
|
}).render()}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@@ -215,7 +212,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
<div class="affine-edgeless-viewport" data-theme=${edgelessTheme}>
|
<div class="affine-edgeless-viewport" data-theme=${edgelessTheme}>
|
||||||
${new BlockStdScope({
|
${new BlockStdScope({
|
||||||
store: syncedDoc,
|
store: syncedDoc,
|
||||||
extensions: this._buildPreviewSpec('preview:edgeless'),
|
extensions: this._buildPreviewSpec('preview-edgeless'),
|
||||||
}).render()}
|
}).render()}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"@blocksuite/affine-block-frame": "workspace:*",
|
"@blocksuite/affine-block-frame": "workspace:*",
|
||||||
"@blocksuite/affine-block-surface": "workspace:*",
|
"@blocksuite/affine-block-surface": "workspace:*",
|
||||||
"@blocksuite/affine-components": "workspace:*",
|
"@blocksuite/affine-components": "workspace:*",
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*",
|
||||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||||
"@blocksuite/affine-model": "workspace:*",
|
"@blocksuite/affine-model": "workspace:*",
|
||||||
"@blocksuite/affine-shared": "workspace:*",
|
"@blocksuite/affine-shared": "workspace:*",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { CanvasRenderer } from '@blocksuite/affine-block-surface';
|
import type { CanvasRenderer } from '@blocksuite/affine-block-surface';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import type { NoteBlockModel } from '@blocksuite/affine-model';
|
import type { NoteBlockModel } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
@@ -10,7 +11,6 @@ import {
|
|||||||
EDGELESS_BLOCK_CHILD_PADDING,
|
EDGELESS_BLOCK_CHILD_PADDING,
|
||||||
} from '@blocksuite/affine-shared/consts';
|
} from '@blocksuite/affine-shared/consts';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
|
||||||
import { deserializeXYWH } from '@blocksuite/global/gfx';
|
import { deserializeXYWH } from '@blocksuite/global/gfx';
|
||||||
import { WithDisposable } from '@blocksuite/global/lit';
|
import { WithDisposable } from '@blocksuite/global/lit';
|
||||||
import {
|
import {
|
||||||
@@ -122,10 +122,12 @@ export class SurfaceRefNotePortal extends WithDisposable(ShadowlessElement) {
|
|||||||
query: this.query,
|
query: this.query,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
const previewSpec = SpecProvider._.getSpec('preview:page');
|
const previewSpec = this.host.std
|
||||||
|
.get(ViewExtensionManagerIdentifier)
|
||||||
|
.get('preview-page');
|
||||||
return new BlockStdScope({
|
return new BlockStdScope({
|
||||||
store: doc,
|
store: doc,
|
||||||
extensions: previewSpec.value.slice(),
|
extensions: previewSpec,
|
||||||
}).render();
|
}).render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
import type { BlockCaptionEditor } from '@blocksuite/affine-components/caption';
|
import type { BlockCaptionEditor } from '@blocksuite/affine-components/caption';
|
||||||
import { whenHover } from '@blocksuite/affine-components/hover';
|
import { whenHover } from '@blocksuite/affine-components/hover';
|
||||||
import { Peekable } from '@blocksuite/affine-components/peek';
|
import { Peekable } from '@blocksuite/affine-components/peek';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-inline-reference';
|
import { RefNodeSlotsProvider } from '@blocksuite/affine-inline-reference';
|
||||||
import {
|
import {
|
||||||
FrameBlockModel,
|
FrameBlockModel,
|
||||||
@@ -20,10 +21,7 @@ import {
|
|||||||
ViewportElementExtension,
|
ViewportElementExtension,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||||
import {
|
import { requestConnectedFrame } from '@blocksuite/affine-shared/utils';
|
||||||
requestConnectedFrame,
|
|
||||||
SpecProvider,
|
|
||||||
} from '@blocksuite/affine-shared/utils';
|
|
||||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import {
|
import {
|
||||||
@@ -46,7 +44,7 @@ import {
|
|||||||
type GfxModel,
|
type GfxModel,
|
||||||
GfxPrimitiveElementModel,
|
GfxPrimitiveElementModel,
|
||||||
} from '@blocksuite/std/gfx';
|
} from '@blocksuite/std/gfx';
|
||||||
import type { BaseSelection, Store } from '@blocksuite/store';
|
import type { BaseSelection, ExtensionType, Store } from '@blocksuite/store';
|
||||||
import { effect, signal } from '@preact/signals-core';
|
import { effect, signal } from '@preact/signals-core';
|
||||||
import { css, html, nothing } from 'lit';
|
import { css, html, nothing } from 'lit';
|
||||||
import { query } from 'lit/decorators.js';
|
import { query } from 'lit/decorators.js';
|
||||||
@@ -114,9 +112,18 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
|
|
||||||
private _previewDoc: Store | null = null;
|
private _previewDoc: Store | null = null;
|
||||||
|
|
||||||
private readonly _previewSpec = SpecProvider._.getSpec(
|
private _runtimePreviewExt: ExtensionType[] = [];
|
||||||
'preview:edgeless'
|
|
||||||
).extend([ViewportElementExtension('.ref-viewport')]);
|
private get _viewExtensionManager() {
|
||||||
|
return this.std.get(ViewExtensionManagerIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _previewSpec() {
|
||||||
|
return [
|
||||||
|
...this._viewExtensionManager.get('preview-edgeless'),
|
||||||
|
ViewportElementExtension('.ref-viewport'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private _referencedModel: GfxModel | null = null;
|
private _referencedModel: GfxModel | null = null;
|
||||||
|
|
||||||
@@ -338,7 +345,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._previewSpec.extend([SurfaceRefViewportWatcher]);
|
this._runtimePreviewExt = [SurfaceRefViewportWatcher];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _initHover() {
|
private _initHover() {
|
||||||
@@ -366,7 +373,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
|
|
||||||
private _renderRefContent(referencedModel: GfxModel) {
|
private _renderRefContent(referencedModel: GfxModel) {
|
||||||
const [, , w, h] = deserializeXYWH(referencedModel.xywh);
|
const [, , w, h] = deserializeXYWH(referencedModel.xywh);
|
||||||
const _previewSpec = this._previewSpec.value;
|
const _previewSpec = this._previewSpec.concat(this._runtimePreviewExt);
|
||||||
|
|
||||||
return html`<div class="ref-content">
|
return html`<div class="ref-content">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
{ "path": "../frame" },
|
{ "path": "../frame" },
|
||||||
{ "path": "../surface" },
|
{ "path": "../surface" },
|
||||||
{ "path": "../../components" },
|
{ "path": "../../components" },
|
||||||
|
{ "path": "../../ext-loader" },
|
||||||
{ "path": "../../inlines/reference" },
|
{ "path": "../../inlines/reference" },
|
||||||
{ "path": "../../model" },
|
{ "path": "../../model" },
|
||||||
{ "path": "../../shared" },
|
{ "path": "../../shared" },
|
||||||
|
|||||||
@@ -54,14 +54,17 @@ describe('multiple scopes', () => {
|
|||||||
class ViewExt1 extends ViewExtensionProvider {
|
class ViewExt1 extends ViewExtensionProvider {
|
||||||
override name = 'ViewExt1';
|
override name = 'ViewExt1';
|
||||||
|
|
||||||
override setup(context: ViewExtensionContext) {
|
constructor() {
|
||||||
super.setup(context);
|
super();
|
||||||
|
setup1();
|
||||||
|
}
|
||||||
|
|
||||||
|
override setup(context: ViewExtensionContext, option?: { foo: number }) {
|
||||||
|
super.setup(context, option);
|
||||||
if (context.scope === 'page') {
|
if (context.scope === 'page') {
|
||||||
setup1();
|
|
||||||
context.register(Ext2);
|
context.register(Ext2);
|
||||||
}
|
}
|
||||||
if (context.scope === 'edgeless') {
|
if (context.scope === 'edgeless') {
|
||||||
setup2();
|
|
||||||
context.register(Ext3);
|
context.register(Ext3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,6 +72,11 @@ describe('multiple scopes', () => {
|
|||||||
class ViewExt2 extends ViewExtensionProvider {
|
class ViewExt2 extends ViewExtensionProvider {
|
||||||
override name = 'ViewExt2';
|
override name = 'ViewExt2';
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
setup2();
|
||||||
|
}
|
||||||
|
|
||||||
override setup(context: ViewExtensionContext) {
|
override setup(context: ViewExtensionContext) {
|
||||||
super.setup(context);
|
super.setup(context);
|
||||||
if (context.scope === 'page') {
|
if (context.scope === 'page') {
|
||||||
@@ -87,7 +95,7 @@ describe('multiple scopes', () => {
|
|||||||
expect(edgelessExtensions).toEqual([Ext3, Ext5]);
|
expect(edgelessExtensions).toEqual([Ext3, Ext5]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setup be cached', () => {
|
it('should cache provider instances', () => {
|
||||||
manager.get('page');
|
manager.get('page');
|
||||||
manager.get('edgeless');
|
manager.get('edgeless');
|
||||||
expect(setup1).toHaveBeenCalledTimes(1);
|
expect(setup1).toHaveBeenCalledTimes(1);
|
||||||
|
|||||||
@@ -84,16 +84,17 @@ export class ExtensionManager<Scope extends string> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all extensions registered for a specific scope.
|
* Retrieves all extensions registered for a specific scope.
|
||||||
* If the scope hasn't been built yet, it triggers the build process.
|
* It triggers the build process.
|
||||||
*
|
*
|
||||||
* @param scope - The scope to retrieve extensions for
|
* @param scope - The scope to retrieve extensions for
|
||||||
* @returns An array of extensions registered for the specified scope
|
* @returns An array of extensions registered for the specified scope
|
||||||
* @throws {BlockSuiteError} If the scope is not found
|
* @throws {BlockSuiteError} If the scope is not found
|
||||||
*/
|
*/
|
||||||
get(scope: Scope) {
|
get(scope: Scope) {
|
||||||
if (!this._extensions.has(scope)) {
|
if (this._extensions.has(scope)) {
|
||||||
this._build(scope);
|
this._extensions.delete(scope);
|
||||||
}
|
}
|
||||||
|
this._build(scope);
|
||||||
const extensionSet = this._extensions.get(scope);
|
const extensionSet = this._extensions.get(scope);
|
||||||
if (!extensionSet) {
|
if (!extensionSet) {
|
||||||
throw new BlockSuiteError(
|
throw new BlockSuiteError(
|
||||||
@@ -117,14 +118,19 @@ export class ExtensionManager<Scope extends string> {
|
|||||||
provider: typeof BaseExtensionProvider<Scope, T>,
|
provider: typeof BaseExtensionProvider<Scope, T>,
|
||||||
options: ((prev: T | undefined) => T | undefined) | T | undefined
|
options: ((prev: T | undefined) => T | undefined) | T | undefined
|
||||||
) {
|
) {
|
||||||
|
const prev = this._providerOptions.get(provider);
|
||||||
|
|
||||||
let config: T | undefined;
|
let config: T | undefined;
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
const prev = this._providerOptions.get(provider);
|
|
||||||
config = (options as (prev: unknown) => T)(prev);
|
config = (options as (prev: unknown) => T)(prev);
|
||||||
} else {
|
} else {
|
||||||
config = options;
|
config = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prev === config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (config === undefined) {
|
if (config === undefined) {
|
||||||
this._providerOptions.delete(provider);
|
this._providerOptions.delete(provider);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"@blocksuite/affine-block-frame": "workspace:*",
|
"@blocksuite/affine-block-frame": "workspace:*",
|
||||||
"@blocksuite/affine-block-surface": "workspace:*",
|
"@blocksuite/affine-block-surface": "workspace:*",
|
||||||
"@blocksuite/affine-components": "workspace:*",
|
"@blocksuite/affine-components": "workspace:*",
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*",
|
||||||
"@blocksuite/affine-model": "workspace:*",
|
"@blocksuite/affine-model": "workspace:*",
|
||||||
"@blocksuite/affine-rich-text": "workspace:*",
|
"@blocksuite/affine-rich-text": "workspace:*",
|
||||||
"@blocksuite/affine-shared": "workspace:*",
|
"@blocksuite/affine-shared": "workspace:*",
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
DocModeExtension,
|
DocModeExtension,
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
ViewportElementExtension,
|
ViewportElementExtension,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
|
||||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||||
import { Bound, deserializeXYWH } from '@blocksuite/global/gfx';
|
import { Bound, deserializeXYWH } from '@blocksuite/global/gfx';
|
||||||
import { WithDisposable } from '@blocksuite/global/lit';
|
import { WithDisposable } from '@blocksuite/global/lit';
|
||||||
@@ -15,13 +15,12 @@ import {
|
|||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
} from '@blocksuite/std';
|
} from '@blocksuite/std';
|
||||||
import { GfxControllerIdentifier } from '@blocksuite/std/gfx';
|
import { GfxControllerIdentifier } from '@blocksuite/std/gfx';
|
||||||
import { type Query, type Store } from '@blocksuite/store';
|
import { type ExtensionType, type Query, type Store } from '@blocksuite/store';
|
||||||
import { css, html, nothing, type PropertyValues } from 'lit';
|
import { css, html, nothing, type PropertyValues } from 'lit';
|
||||||
import { property, query, state } from 'lit/decorators.js';
|
import { property, query, state } from 'lit/decorators.js';
|
||||||
import { guard } from 'lit/directives/guard.js';
|
import { guard } from 'lit/directives/guard.js';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
|
|
||||||
const DEFAULT_PREVIEW_CONTAINER_WIDTH = 280;
|
const DEFAULT_PREVIEW_CONTAINER_WIDTH = 280;
|
||||||
const DEFAULT_PREVIEW_CONTAINER_HEIGHT = 166;
|
const DEFAULT_PREVIEW_CONTAINER_HEIGHT = 166;
|
||||||
|
|
||||||
@@ -86,7 +85,15 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
private _previewDoc: Store | null = null;
|
private _previewDoc: Store | null = null;
|
||||||
|
|
||||||
private readonly _previewSpec = SpecProvider._.getSpec('preview:edgeless');
|
private _runtimePreviewExt: ExtensionType[] = [];
|
||||||
|
|
||||||
|
private get _viewExtensionManager() {
|
||||||
|
return this.std.get(ViewExtensionManagerIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _previewSpec() {
|
||||||
|
return this._viewExtensionManager.get('preview-edgeless');
|
||||||
|
}
|
||||||
|
|
||||||
private readonly _updateFrameViewportWH = () => {
|
private readonly _updateFrameViewportWH = () => {
|
||||||
const [, , w, h] = deserializeXYWH(this.frame.xywh);
|
const [, , w, h] = deserializeXYWH(this.frame.xywh);
|
||||||
@@ -143,11 +150,11 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const docModeService = this.std.get(DocModeProvider);
|
const docModeService = this.std.get(DocModeProvider);
|
||||||
this._previewSpec.extend([
|
this._runtimePreviewExt = [
|
||||||
ViewportElementExtension('.frame-preview-viewport'),
|
ViewportElementExtension('.frame-preview-viewport'),
|
||||||
FramePreviewWatcher,
|
FramePreviewWatcher,
|
||||||
DocModeExtension(docModeService),
|
DocModeExtension(docModeService),
|
||||||
]);
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _refreshViewport() {
|
private _refreshViewport() {
|
||||||
@@ -163,7 +170,7 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
|||||||
private _renderSurfaceContent() {
|
private _renderSurfaceContent() {
|
||||||
const { width, height } = this.frameViewportWH;
|
const { width, height } = this.frameViewportWH;
|
||||||
|
|
||||||
const _previewSpec = this._previewSpec.value;
|
const _previewSpec = this._previewSpec.concat(this._runtimePreviewExt);
|
||||||
return html`<div
|
return html`<div
|
||||||
class="frame-preview-surface-container"
|
class="frame-preview-surface-container"
|
||||||
style=${styleMap({
|
style=${styleMap({
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
{ "path": "../../blocks/frame" },
|
{ "path": "../../blocks/frame" },
|
||||||
{ "path": "../../blocks/surface" },
|
{ "path": "../../blocks/surface" },
|
||||||
{ "path": "../../components" },
|
{ "path": "../../components" },
|
||||||
|
{ "path": "../../ext-loader" },
|
||||||
{ "path": "../../model" },
|
{ "path": "../../model" },
|
||||||
{ "path": "../../rich-text" },
|
{ "path": "../../rich-text" },
|
||||||
{ "path": "../../shared" },
|
{ "path": "../../shared" },
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export function EditorSettingExtension(
|
|||||||
): ExtensionType {
|
): ExtensionType {
|
||||||
return {
|
return {
|
||||||
setup: di => {
|
setup: di => {
|
||||||
di.addImpl(EditorSettingProvider, () => service);
|
di.override(EditorSettingProvider, () => service);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"@blocksuite/affine-block-paragraph": "workspace:*",
|
"@blocksuite/affine-block-paragraph": "workspace:*",
|
||||||
"@blocksuite/affine-block-surface": "workspace:*",
|
"@blocksuite/affine-block-surface": "workspace:*",
|
||||||
"@blocksuite/affine-components": "workspace:*",
|
"@blocksuite/affine-components": "workspace:*",
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*",
|
||||||
"@blocksuite/affine-model": "workspace:*",
|
"@blocksuite/affine-model": "workspace:*",
|
||||||
"@blocksuite/affine-shared": "workspace:*",
|
"@blocksuite/affine-shared": "workspace:*",
|
||||||
"@blocksuite/global": "workspace:*",
|
"@blocksuite/global": "workspace:*",
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
||||||
import {
|
import {
|
||||||
DocModeExtension,
|
DocModeExtension,
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
EditorSettingExtension,
|
EditorSettingExtension,
|
||||||
EditorSettingProvider,
|
EditorSettingProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
|
||||||
import { BlockStdScope, BlockViewIdentifier } from '@blocksuite/std';
|
import { BlockStdScope, BlockViewIdentifier } from '@blocksuite/std';
|
||||||
import type {
|
import type {
|
||||||
BlockModel,
|
BlockModel,
|
||||||
@@ -69,7 +69,9 @@ export class PreviewHelper {
|
|||||||
const editorSetting = std.get(EditorSettingProvider);
|
const editorSetting = std.get(EditorSettingProvider);
|
||||||
const query = this._calculateQuery(blockIds as string[]);
|
const query = this._calculateQuery(blockIds as string[]);
|
||||||
const store = widget.doc.doc.getStore({ query });
|
const store = widget.doc.doc.getStore({ query });
|
||||||
const previewSpec = SpecProvider._.getSpec('preview:page');
|
let previewSpec = widget.std
|
||||||
|
.get(ViewExtensionManagerIdentifier)
|
||||||
|
.get('preview-page');
|
||||||
const settingSignal = signal({ ...editorSetting.setting$.peek() });
|
const settingSignal = signal({ ...editorSetting.setting$.peek() });
|
||||||
const extensions = [
|
const extensions = [
|
||||||
DocModeExtension(docModeService),
|
DocModeExtension(docModeService),
|
||||||
@@ -99,7 +101,7 @@ export class PreviewHelper {
|
|||||||
} as ExtensionType,
|
} as ExtensionType,
|
||||||
];
|
];
|
||||||
|
|
||||||
previewSpec.extend(extensions);
|
previewSpec = previewSpec.concat(extensions);
|
||||||
|
|
||||||
settingSignal.value = {
|
settingSignal.value = {
|
||||||
...settingSignal.value,
|
...settingSignal.value,
|
||||||
@@ -108,7 +110,7 @@ export class PreviewHelper {
|
|||||||
|
|
||||||
const previewStd = new BlockStdScope({
|
const previewStd = new BlockStdScope({
|
||||||
store,
|
store,
|
||||||
extensions: previewSpec.value,
|
extensions: previewSpec,
|
||||||
});
|
});
|
||||||
|
|
||||||
let width: number = 500;
|
let width: number = 500;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
{ "path": "../../blocks/paragraph" },
|
{ "path": "../../blocks/paragraph" },
|
||||||
{ "path": "../../blocks/surface" },
|
{ "path": "../../blocks/surface" },
|
||||||
{ "path": "../../components" },
|
{ "path": "../../components" },
|
||||||
|
{ "path": "../../ext-loader" },
|
||||||
{ "path": "../../model" },
|
{ "path": "../../model" },
|
||||||
{ "path": "../../shared" },
|
{ "path": "../../shared" },
|
||||||
{ "path": "../../../framework/global" },
|
{ "path": "../../../framework/global" },
|
||||||
|
|||||||
@@ -28,7 +28,9 @@
|
|||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
"./effects": "./src/effects.ts"
|
"./effects": "./src/effects.ts",
|
||||||
|
"./store": "./src/store.ts",
|
||||||
|
"./view": "./src/view.ts"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
import '@toeverything/theme/style.css';
|
import '@toeverything/theme/style.css';
|
||||||
import '@toeverything/theme/fonts.css';
|
import '@toeverything/theme/fonts.css';
|
||||||
|
|
||||||
import { effects as blocksEffects } from '@blocksuite/affine/effects';
|
import { registerStoreSpecs } from '@blocksuite/affine/extensions';
|
||||||
import {
|
|
||||||
EdgelessEditorBlockSpecs,
|
|
||||||
PageEditorBlockSpecs,
|
|
||||||
registerStoreSpecs,
|
|
||||||
StoreExtensions,
|
|
||||||
} from '@blocksuite/affine/extensions';
|
|
||||||
import type { DocMode } from '@blocksuite/affine/model';
|
import type { DocMode } from '@blocksuite/affine/model';
|
||||||
import { AffineSchemas } from '@blocksuite/affine/schemas';
|
import { AffineSchemas } from '@blocksuite/affine/schemas';
|
||||||
import {
|
import {
|
||||||
@@ -27,11 +21,17 @@ import {
|
|||||||
|
|
||||||
import { effects } from '../../effects.js';
|
import { effects } from '../../effects.js';
|
||||||
import { TestAffineEditorContainer } from '../../index.js';
|
import { TestAffineEditorContainer } from '../../index.js';
|
||||||
|
import { getTestStoreManager } from '../../store.js';
|
||||||
|
import { getTestViewManager } from '../../view.js';
|
||||||
|
|
||||||
|
// FIXME: used for test import/export
|
||||||
registerStoreSpecs();
|
registerStoreSpecs();
|
||||||
blocksEffects();
|
const storeManager = getTestStoreManager();
|
||||||
|
const viewManager = getTestViewManager();
|
||||||
effects();
|
effects();
|
||||||
|
|
||||||
|
const storeExtensions = storeManager.get('store');
|
||||||
|
|
||||||
export function getRenderer() {
|
export function getRenderer() {
|
||||||
return editor.std.get(
|
return editor.std.get(
|
||||||
ViewportTurboRendererIdentifier
|
ViewportTurboRendererIdentifier
|
||||||
@@ -85,12 +85,12 @@ async function createEditor(
|
|||||||
editor.doc = doc;
|
editor.doc = doc;
|
||||||
editor.mode = mode;
|
editor.mode = mode;
|
||||||
editor.pageSpecs = [
|
editor.pageSpecs = [
|
||||||
...PageEditorBlockSpecs,
|
...viewManager.get('page'),
|
||||||
FontConfigExtension(CommunityCanvasTextFonts),
|
FontConfigExtension(CommunityCanvasTextFonts),
|
||||||
...extensions,
|
...extensions,
|
||||||
];
|
];
|
||||||
editor.edgelessSpecs = [
|
editor.edgelessSpecs = [
|
||||||
...EdgelessEditorBlockSpecs,
|
...viewManager.get('edgeless'),
|
||||||
FontConfigExtension(CommunityCanvasTextFonts),
|
FontConfigExtension(CommunityCanvasTextFonts),
|
||||||
...extensions,
|
...extensions,
|
||||||
];
|
];
|
||||||
@@ -123,7 +123,7 @@ export async function setupEditor(
|
|||||||
extensions: ExtensionType[] = []
|
extensions: ExtensionType[] = []
|
||||||
) {
|
) {
|
||||||
const collection = new TestWorkspace(createCollectionOptions());
|
const collection = new TestWorkspace(createCollectionOptions());
|
||||||
collection.storeExtensions = StoreExtensions;
|
collection.storeExtensions = storeExtensions;
|
||||||
collection.meta.initialize();
|
collection.meta.initialize();
|
||||||
|
|
||||||
window.collection = collection;
|
window.collection = collection;
|
||||||
|
|||||||
7
blocksuite/integration-test/src/store.ts
Normal file
7
blocksuite/integration-test/src/store.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { StoreExtensionManager } from '@blocksuite/affine/ext-loader';
|
||||||
|
import { MigratingStoreExtension } from '@blocksuite/affine/extensions/store';
|
||||||
|
|
||||||
|
export function getTestStoreManager() {
|
||||||
|
const manager = new StoreExtensionManager([MigratingStoreExtension]);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
7
blocksuite/integration-test/src/view.ts
Normal file
7
blocksuite/integration-test/src/view.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { ViewExtensionManager } from '@blocksuite/affine/ext-loader';
|
||||||
|
import { MigratingViewExtension } from '@blocksuite/affine/extensions/view';
|
||||||
|
|
||||||
|
export function getTestViewManager() {
|
||||||
|
const manager = new ViewExtensionManager([MigratingViewExtension]);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ import '../../style.css';
|
|||||||
|
|
||||||
import * as databaseBlocks from '@blocksuite/affine/blocks/database';
|
import * as databaseBlocks from '@blocksuite/affine/blocks/database';
|
||||||
import * as noteBlocks from '@blocksuite/affine/blocks/note';
|
import * as noteBlocks from '@blocksuite/affine/blocks/note';
|
||||||
import { effects as blocksEffects } from '@blocksuite/affine/effects';
|
|
||||||
import { registerStoreSpecs } from '@blocksuite/affine/extensions';
|
import { registerStoreSpecs } from '@blocksuite/affine/extensions';
|
||||||
import * as globalUtils from '@blocksuite/affine/global/utils';
|
import * as globalUtils from '@blocksuite/affine/global/utils';
|
||||||
import * as services from '@blocksuite/affine/shared/services';
|
import * as services from '@blocksuite/affine/shared/services';
|
||||||
@@ -10,7 +9,8 @@ import * as blockStd from '@blocksuite/affine/std';
|
|||||||
import * as store from '@blocksuite/affine/store';
|
import * as store from '@blocksuite/affine/store';
|
||||||
import * as affineModel from '@blocksuite/affine-model';
|
import * as affineModel from '@blocksuite/affine-model';
|
||||||
import * as editor from '@blocksuite/integration-test';
|
import * as editor from '@blocksuite/integration-test';
|
||||||
import { effects as presetsEffects } from '@blocksuite/integration-test/effects';
|
import { effects as itEffects } from '@blocksuite/integration-test/effects';
|
||||||
|
import { getTestStoreManager } from '@blocksuite/integration-test/store';
|
||||||
|
|
||||||
import { setupEdgelessTemplate } from '../_common/setup.js';
|
import { setupEdgelessTemplate } from '../_common/setup.js';
|
||||||
import { effects as commentEffects } from '../comment/effects.js';
|
import { effects as commentEffects } from '../comment/effects.js';
|
||||||
@@ -22,8 +22,8 @@ import { mountDefaultDocEditor } from './utils/setup-playground';
|
|||||||
import { prepareTestApp } from './utils/test';
|
import { prepareTestApp } from './utils/test';
|
||||||
|
|
||||||
registerStoreSpecs();
|
registerStoreSpecs();
|
||||||
blocksEffects();
|
itEffects();
|
||||||
presetsEffects();
|
const storeManager = getTestStoreManager();
|
||||||
commentEffects();
|
commentEffects();
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
@@ -34,7 +34,7 @@ async function main() {
|
|||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const room = params.get('room') ?? Math.random().toString(16).slice(2, 8);
|
const room = params.get('room') ?? Math.random().toString(16).slice(2, 8);
|
||||||
const isE2E = room.startsWith('playwright');
|
const isE2E = room.startsWith('playwright');
|
||||||
const collection = createStarterDocCollection();
|
const collection = createStarterDocCollection(storeManager);
|
||||||
|
|
||||||
if (isE2E) {
|
if (isE2E) {
|
||||||
Object.defineProperty(window, '$blocksuite', {
|
Object.defineProperty(window, '$blocksuite', {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import type { StoreExtensionManager } from '@blocksuite/affine/ext-loader';
|
||||||
import { AffineSchemas } from '@blocksuite/affine/schemas';
|
import { AffineSchemas } from '@blocksuite/affine/schemas';
|
||||||
import { SpecProvider } from '@blocksuite/affine/shared/utils';
|
|
||||||
import { nanoid, Schema, Transformer } from '@blocksuite/affine/store';
|
import { nanoid, Schema, Transformer } from '@blocksuite/affine/store';
|
||||||
import {
|
import {
|
||||||
createAutoIncrementIdGenerator,
|
createAutoIncrementIdGenerator,
|
||||||
@@ -23,7 +23,9 @@ const room = params.get('room');
|
|||||||
const isE2E = room?.startsWith('playwright');
|
const isE2E = room?.startsWith('playwright');
|
||||||
const blobSourceArgs = (params.get('blobSource') ?? '').split(',');
|
const blobSourceArgs = (params.get('blobSource') ?? '').split(',');
|
||||||
|
|
||||||
export function createStarterDocCollection() {
|
export function createStarterDocCollection(
|
||||||
|
storeExtensionManager: StoreExtensionManager
|
||||||
|
) {
|
||||||
const collectionId = room ?? 'starter';
|
const collectionId = room ?? 'starter';
|
||||||
const schema = new Schema();
|
const schema = new Schema();
|
||||||
schema.register(AffineSchemas);
|
schema.register(AffineSchemas);
|
||||||
@@ -56,7 +58,7 @@ export function createStarterDocCollection() {
|
|||||||
blobSources,
|
blobSources,
|
||||||
};
|
};
|
||||||
const collection = new TestWorkspace(options);
|
const collection = new TestWorkspace(options);
|
||||||
collection.storeExtensions = SpecProvider._.getSpec('store').value;
|
collection.storeExtensions = storeExtensionManager.get('store');
|
||||||
collection.start();
|
collection.start();
|
||||||
|
|
||||||
// debug info
|
// debug info
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
import {
|
|
||||||
EdgelessEditorBlockSpecs,
|
|
||||||
PageEditorBlockSpecs,
|
|
||||||
} from '@blocksuite/affine/extensions';
|
|
||||||
import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference';
|
import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference';
|
||||||
import {
|
import {
|
||||||
CommunityCanvasTextFonts,
|
CommunityCanvasTextFonts,
|
||||||
@@ -13,6 +9,7 @@ import {
|
|||||||
} from '@blocksuite/affine/shared/services';
|
} from '@blocksuite/affine/shared/services';
|
||||||
import type { ExtensionType, Store, Workspace } from '@blocksuite/affine/store';
|
import type { ExtensionType, Store, Workspace } from '@blocksuite/affine/store';
|
||||||
import { type TestAffineEditorContainer } from '@blocksuite/integration-test';
|
import { type TestAffineEditorContainer } from '@blocksuite/integration-test';
|
||||||
|
import { getTestViewManager } from '@blocksuite/integration-test/view';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
mockDocModeService,
|
mockDocModeService,
|
||||||
@@ -20,6 +17,8 @@ import {
|
|||||||
mockParseDocUrlService,
|
mockParseDocUrlService,
|
||||||
} from '../../_common/mock-services';
|
} from '../../_common/mock-services';
|
||||||
|
|
||||||
|
const viewManager = getTestViewManager();
|
||||||
|
|
||||||
export function getTestCommonExtensions(
|
export function getTestCommonExtensions(
|
||||||
editor: TestAffineEditorContainer
|
editor: TestAffineEditorContainer
|
||||||
): ExtensionType[] {
|
): ExtensionType[] {
|
||||||
@@ -48,8 +47,8 @@ export function createTestEditor(store: Store, workspace: Workspace) {
|
|||||||
editor.doc = store;
|
editor.doc = store;
|
||||||
|
|
||||||
const defaultExtensions = getTestCommonExtensions(editor);
|
const defaultExtensions = getTestCommonExtensions(editor);
|
||||||
editor.pageSpecs = [...PageEditorBlockSpecs, ...defaultExtensions];
|
editor.pageSpecs = [...viewManager.get('page'), ...defaultExtensions];
|
||||||
editor.edgelessSpecs = [...EdgelessEditorBlockSpecs, ...defaultExtensions];
|
editor.edgelessSpecs = [...viewManager.get('edgeless'), ...defaultExtensions];
|
||||||
|
|
||||||
editor.std
|
editor.std
|
||||||
.get(RefNodeSlotsProvider)
|
.get(RefNodeSlotsProvider)
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ import {
|
|||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
FeatureFlagService,
|
FeatureFlagService,
|
||||||
} from '@blocksuite/affine/shared/services';
|
} from '@blocksuite/affine/shared/services';
|
||||||
import { type SpecBuilder } from '@blocksuite/affine/shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { ShadowlessElement } from '@blocksuite/affine/std';
|
import { ShadowlessElement } from '@blocksuite/affine/std';
|
||||||
import type { BaseSelection } from '@blocksuite/affine/store';
|
import type { BaseSelection, ExtensionType } from '@blocksuite/affine/store';
|
||||||
import { ArrowDownBigIcon as ArrowDownIcon } from '@blocksuite/icons/lit';
|
import { ArrowDownBigIcon as ArrowDownIcon } from '@blocksuite/icons/lit';
|
||||||
import { css, html, nothing, type PropertyValues } from 'lit';
|
import { css, html, nothing, type PropertyValues } from 'lit';
|
||||||
import { property, query, state } from 'lit/decorators.js';
|
import { property, query, state } from 'lit/decorators.js';
|
||||||
@@ -157,7 +156,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
|
|||||||
accessor updateContext!: (context: Partial<ChatContextValue>) => void;
|
accessor updateContext!: (context: Partial<ChatContextValue>) => void;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor previewSpecBuilder!: SpecBuilder;
|
accessor extensions!: ExtensionType[];
|
||||||
|
|
||||||
@query('.chat-panel-messages-container')
|
@query('.chat-panel-messages-container')
|
||||||
accessor messagesContainer: HTMLDivElement | null = null;
|
accessor messagesContainer: HTMLDivElement | null = null;
|
||||||
@@ -271,7 +270,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
|
|||||||
.isLast=${isLast}
|
.isLast=${isLast}
|
||||||
.status=${isLast ? status : 'idle'}
|
.status=${isLast ? status : 'idle'}
|
||||||
.error=${isLast ? error : null}
|
.error=${isLast ? error : null}
|
||||||
.previewSpecBuilder=${this.previewSpecBuilder}
|
.extensions=${this.extensions}
|
||||||
.getSessionId=${this.getSessionId}
|
.getSessionId=${this.getSessionId}
|
||||||
.retry=${() => this.retry()}
|
.retry=${() => this.retry()}
|
||||||
></chat-message-assistant>`;
|
></chat-message-assistant>`;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WithDisposable } from '@blocksuite/affine/global/lit';
|
import { WithDisposable } from '@blocksuite/affine/global/lit';
|
||||||
import type { SpecBuilder } from '@blocksuite/affine/shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { ShadowlessElement } from '@blocksuite/affine/std';
|
import { ShadowlessElement } from '@blocksuite/affine/std';
|
||||||
|
import type { ExtensionType } from '@blocksuite/affine/store';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
|
|
||||||
@@ -18,13 +18,13 @@ export class ChatContentRichText extends WithDisposable(ShadowlessElement) {
|
|||||||
accessor state: 'finished' | 'generating' = 'finished';
|
accessor state: 'finished' | 'generating' = 'finished';
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor previewSpecBuilder!: SpecBuilder;
|
accessor extensions!: ExtensionType[];
|
||||||
|
|
||||||
protected override render() {
|
protected override render() {
|
||||||
const { text, host } = this;
|
const { text, host } = this;
|
||||||
return html`${createTextRenderer(host, {
|
return html`${createTextRenderer(host, {
|
||||||
customHeading: true,
|
customHeading: true,
|
||||||
extensions: this.previewSpecBuilder.value,
|
extensions: this.extensions,
|
||||||
})(text, this.state)}`;
|
})(text, this.state)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ import './chat-panel-messages';
|
|||||||
|
|
||||||
import type { ContextEmbedStatus } from '@affine/graphql';
|
import type { ContextEmbedStatus } from '@affine/graphql';
|
||||||
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
|
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/lit';
|
||||||
import type { SpecBuilder } from '@blocksuite/affine/shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { ShadowlessElement } from '@blocksuite/affine/std';
|
import { ShadowlessElement } from '@blocksuite/affine/std';
|
||||||
import type { Store } from '@blocksuite/affine/store';
|
import type { ExtensionType, Store } from '@blocksuite/affine/store';
|
||||||
import { HelpIcon } from '@blocksuite/icons/lit';
|
import { HelpIcon } from '@blocksuite/icons/lit';
|
||||||
import { type Signal, signal } from '@preact/signals-core';
|
import { type Signal, signal } from '@preact/signals-core';
|
||||||
import { css, html, type PropertyValues } from 'lit';
|
import { css, html, type PropertyValues } from 'lit';
|
||||||
@@ -208,7 +207,7 @@ export class ChatPanel extends SignalWatcher(
|
|||||||
accessor docDisplayConfig!: DocDisplayConfig;
|
accessor docDisplayConfig!: DocDisplayConfig;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor previewSpecBuilder!: SpecBuilder;
|
accessor extensions!: ExtensionType[];
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
accessor isLoading = false;
|
accessor isLoading = false;
|
||||||
@@ -401,7 +400,7 @@ export class ChatPanel extends SignalWatcher(
|
|||||||
.updateContext=${this.updateContext}
|
.updateContext=${this.updateContext}
|
||||||
.host=${this.host}
|
.host=${this.host}
|
||||||
.isLoading=${this.isLoading}
|
.isLoading=${this.isLoading}
|
||||||
.previewSpecBuilder=${this.previewSpecBuilder}
|
.extensions=${this.extensions}
|
||||||
></chat-panel-messages>
|
></chat-panel-messages>
|
||||||
<ai-chat-composer
|
<ai-chat-composer
|
||||||
.host=${this.host}
|
.host=${this.host}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { WithDisposable } from '@blocksuite/affine/global/lit';
|
|||||||
import { isInsidePageEditor } from '@blocksuite/affine/shared/utils';
|
import { isInsidePageEditor } from '@blocksuite/affine/shared/utils';
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { ShadowlessElement } from '@blocksuite/affine/std';
|
import { ShadowlessElement } from '@blocksuite/affine/std';
|
||||||
|
import type { ExtensionType } from '@blocksuite/affine/store';
|
||||||
import { css, html, nothing } from 'lit';
|
import { css, html, nothing } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) {
|
|||||||
accessor error: AIError | null = null;
|
accessor error: AIError | null = null;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor previewSpecBuilder: any;
|
accessor extensions!: ExtensionType[];
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor getSessionId!: () => Promise<string | undefined>;
|
accessor getSessionId!: () => Promise<string | undefined>;
|
||||||
@@ -90,7 +91,7 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) {
|
|||||||
.host=${host}
|
.host=${host}
|
||||||
.text=${item.content}
|
.text=${item.content}
|
||||||
.state=${state}
|
.state=${state}
|
||||||
.previewSpecBuilder=${this.previewSpecBuilder}
|
.extensions=${this.extensions}
|
||||||
></chat-content-rich-text>
|
></chat-content-rich-text>
|
||||||
${shouldRenderError ? AIChatErrorRenderer(host, error) : nothing}
|
${shouldRenderError ? AIChatErrorRenderer(host, error) : nothing}
|
||||||
${this.renderEditorActions()}
|
${this.renderEditorActions()}
|
||||||
|
|||||||
@@ -43,6 +43,18 @@ import type {
|
|||||||
AffineAIPanelWidgetConfig,
|
AffineAIPanelWidgetConfig,
|
||||||
} from '../widgets/ai-panel/type';
|
} from '../widgets/ai-panel/type';
|
||||||
|
|
||||||
|
export const CustomPageEditorBlockSpecs: ExtensionType[] = [
|
||||||
|
...PageEditorBlockSpecs,
|
||||||
|
{
|
||||||
|
setup: di => {
|
||||||
|
di.override(
|
||||||
|
BlockViewIdentifier('affine:page'),
|
||||||
|
() => literal`affine-page-root`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const customHeadingStyles = css`
|
const customHeadingStyles = css`
|
||||||
.custom-heading {
|
.custom-heading {
|
||||||
.h1 {
|
.h1 {
|
||||||
@@ -91,18 +103,6 @@ export type TextRendererOptions = {
|
|||||||
testId?: string;
|
testId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CustomPageEditorBlockSpecs: ExtensionType[] = [
|
|
||||||
...PageEditorBlockSpecs,
|
|
||||||
{
|
|
||||||
setup: di => {
|
|
||||||
di.override(
|
|
||||||
BlockViewIdentifier('affine:page'),
|
|
||||||
() => literal`affine-page-root`
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// todo: refactor it for more general purpose usage instead of AI only?
|
// todo: refactor it for more general purpose usage instead of AI only?
|
||||||
export class TextRenderer extends WithDisposable(ShadowlessElement) {
|
export class TextRenderer extends WithDisposable(ShadowlessElement) {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { ExtensionType } from '@blocksuite/affine/store';
|
|||||||
|
|
||||||
import { setupCodeToolbarAIEntry } from '../entries/code-toolbar/setup-code-toolbar';
|
import { setupCodeToolbarAIEntry } from '../entries/code-toolbar/setup-code-toolbar';
|
||||||
|
|
||||||
class AICodeBlockWatcher extends LifeCycleWatcher {
|
export class AICodeBlockWatcher extends LifeCycleWatcher {
|
||||||
static override key = 'ai-code-block-watcher';
|
static override key = 'ai-code-block-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function createAIEdgelessRootBlockSpec(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAIEdgelessRootWatcher(framework: FrameworkProvider) {
|
export function getAIEdgelessRootWatcher(framework: FrameworkProvider) {
|
||||||
class AIEdgelessRootWatcher extends LifeCycleWatcher {
|
class AIEdgelessRootWatcher extends LifeCycleWatcher {
|
||||||
static override key = 'ai-edgeless-root-watcher';
|
static override key = 'ai-edgeless-root-watcher';
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
} from '../widgets/ai-panel/ai-panel';
|
} from '../widgets/ai-panel/ai-panel';
|
||||||
import { AiSlashMenuConfigExtension } from './ai-slash-menu';
|
import { AiSlashMenuConfigExtension } from './ai-slash-menu';
|
||||||
|
|
||||||
function getAIPageRootWatcher(framework: FrameworkProvider) {
|
export function getAIPageRootWatcher(framework: FrameworkProvider) {
|
||||||
class AIPageRootWatcher extends LifeCycleWatcher {
|
class AIPageRootWatcher extends LifeCycleWatcher {
|
||||||
static override key = 'ai-page-root-watcher';
|
static override key = 'ai-page-root-watcher';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { WorkspaceImpl } from '@affine/core/modules/workspace/impls/workspace';
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impls/workspace';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine/ext-loader';
|
||||||
import { WithDisposable } from '@blocksuite/affine/global/lit';
|
import { WithDisposable } from '@blocksuite/affine/global/lit';
|
||||||
import { SpecProvider } from '@blocksuite/affine/shared/utils';
|
|
||||||
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/std';
|
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/std';
|
||||||
import type { Store } from '@blocksuite/affine/store';
|
import type { Store } from '@blocksuite/affine/store';
|
||||||
import { css, html, LitElement, nothing } from 'lit';
|
import { css, html, LitElement, nothing } from 'lit';
|
||||||
@@ -91,6 +91,12 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _getExtensions() {
|
||||||
|
return this.host.std
|
||||||
|
.get(ViewExtensionManagerIdentifier)
|
||||||
|
.get('preview-edgeless');
|
||||||
|
}
|
||||||
|
|
||||||
protected override render() {
|
protected override render() {
|
||||||
return html`<style>
|
return html`<style>
|
||||||
.slides-container {
|
.slides-container {
|
||||||
@@ -205,7 +211,7 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
|
|||||||
>
|
>
|
||||||
${new BlockStdScope({
|
${new BlockStdScope({
|
||||||
store: this._doc,
|
store: this._doc,
|
||||||
extensions: SpecProvider._.getSpec('preview:edgeless').value,
|
extensions: this._getExtensions(),
|
||||||
}).render()}
|
}).render()}
|
||||||
</div>
|
</div>
|
||||||
<div class="mask"></div>
|
<div class="mask"></div>
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import {
|
|||||||
EdgelessCRUDIdentifier,
|
EdgelessCRUDIdentifier,
|
||||||
getSurfaceBlock,
|
getSurfaceBlock,
|
||||||
} from '@blocksuite/affine/blocks/surface';
|
} from '@blocksuite/affine/blocks/surface';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine/ext-loader';
|
||||||
import { ConnectorMode } from '@blocksuite/affine/model';
|
import { ConnectorMode } from '@blocksuite/affine/model';
|
||||||
import {
|
import {
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
TelemetryProvider,
|
TelemetryProvider,
|
||||||
} from '@blocksuite/affine/shared/services';
|
} from '@blocksuite/affine/shared/services';
|
||||||
import type { Signal, SpecBuilder } from '@blocksuite/affine/shared/utils';
|
import type { Signal } from '@blocksuite/affine/shared/utils';
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { signal } from '@preact/signals-core';
|
import { signal } from '@preact/signals-core';
|
||||||
import { html, LitElement, nothing } from 'lit';
|
import { html, LitElement, nothing } from 'lit';
|
||||||
@@ -437,9 +438,11 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
|
|
||||||
override connectedCallback() {
|
override connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this._textRendererOptions = {
|
const extensions = this.host.std
|
||||||
extensions: this.previewSpecBuilder.value,
|
.get(ViewExtensionManagerIdentifier)
|
||||||
};
|
.get('preview-page');
|
||||||
|
|
||||||
|
this._textRendererOptions = { extensions };
|
||||||
this._historyMessages = this._deserializeHistoryChatMessages(
|
this._historyMessages = this._deserializeHistoryChatMessages(
|
||||||
this.historyMessagesString
|
this.historyMessagesString
|
||||||
);
|
);
|
||||||
@@ -529,9 +532,6 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor host!: EditorHost;
|
accessor host!: EditorHost;
|
||||||
|
|
||||||
@property({ attribute: false })
|
|
||||||
accessor previewSpecBuilder!: SpecBuilder;
|
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor networkSearchConfig!: AINetworkSearchConfig;
|
accessor networkSearchConfig!: AINetworkSearchConfig;
|
||||||
|
|
||||||
@@ -566,7 +566,6 @@ declare global {
|
|||||||
export const AIChatBlockPeekViewTemplate = (
|
export const AIChatBlockPeekViewTemplate = (
|
||||||
blockModel: AIChatBlockModel,
|
blockModel: AIChatBlockModel,
|
||||||
host: EditorHost,
|
host: EditorHost,
|
||||||
previewSpecBuilder: SpecBuilder,
|
|
||||||
docDisplayConfig: DocDisplayConfig,
|
docDisplayConfig: DocDisplayConfig,
|
||||||
searchMenuConfig: SearchMenuConfig,
|
searchMenuConfig: SearchMenuConfig,
|
||||||
networkSearchConfig: AINetworkSearchConfig
|
networkSearchConfig: AINetworkSearchConfig
|
||||||
@@ -574,7 +573,6 @@ export const AIChatBlockPeekViewTemplate = (
|
|||||||
return html`<ai-chat-block-peek-view
|
return html`<ai-chat-block-peek-view
|
||||||
.blockModel=${blockModel}
|
.blockModel=${blockModel}
|
||||||
.host=${host}
|
.host=${host}
|
||||||
.previewSpecBuilder=${previewSpecBuilder}
|
|
||||||
.networkSearchConfig=${networkSearchConfig}
|
.networkSearchConfig=${networkSearchConfig}
|
||||||
.docDisplayConfig=${docDisplayConfig}
|
.docDisplayConfig=${docDisplayConfig}
|
||||||
.searchMenuConfig=${searchMenuConfig}
|
.searchMenuConfig=${searchMenuConfig}
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ import {
|
|||||||
AffineSharedPageReference,
|
AffineSharedPageReference,
|
||||||
} from '../../components/affine/reference-link';
|
} from '../../components/affine/reference-link';
|
||||||
import { LitTextRenderer } from '../ai/components/text-renderer';
|
import { LitTextRenderer } from '../ai/components/text-renderer';
|
||||||
import { enableEditorExtension } from '../extensions/entry/enable-editor';
|
|
||||||
import {
|
import {
|
||||||
patchReferenceRenderer,
|
patchReferenceRenderer,
|
||||||
type ReferenceReactRenderer,
|
type ReferenceReactRenderer,
|
||||||
} from '../extensions/reference-renderer';
|
} from '../extensions/reference-renderer';
|
||||||
|
import { getViewManager } from '../manager/migrating-view';
|
||||||
import * as styles from './bi-directional-link-panel.css';
|
import * as styles from './bi-directional-link-panel.css';
|
||||||
|
|
||||||
const PREFIX = 'bi-directional-link-panel-collapse:';
|
const PREFIX = 'bi-directional-link-panel-collapse:';
|
||||||
@@ -163,9 +163,9 @@ const usePreviewExtensions = () => {
|
|||||||
const enableAI = useEnableAI();
|
const enableAI = useEnableAI();
|
||||||
|
|
||||||
const extensions = useMemo(() => {
|
const extensions = useMemo(() => {
|
||||||
const specs = enableEditorExtension(framework, 'page', enableAI);
|
const manager = getViewManager(framework, enableAI);
|
||||||
specs.extend([patchReferenceRenderer(reactToLit, referenceRenderer)]);
|
const specs = manager.get('preview-page');
|
||||||
return specs.value;
|
return [...specs, patchReferenceRenderer(reactToLit, referenceRenderer)];
|
||||||
}, [reactToLit, referenceRenderer, framework, enableAI]);
|
}, [reactToLit, referenceRenderer, framework, enableAI]);
|
||||||
|
|
||||||
return [extensions, portals] as const;
|
return [extensions, portals] as const;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { registerAIEffects } from '@affine/core/blocksuite/ai/effects';
|
import { registerAIEffects } from '@affine/core/blocksuite/ai/effects';
|
||||||
import { editorEffects } from '@affine/core/blocksuite/editors';
|
import { editorEffects } from '@affine/core/blocksuite/editors';
|
||||||
import { effects as bsEffects } from '@blocksuite/affine/effects';
|
import type * as EffectType from '@blocksuite/affine/effects';
|
||||||
|
|
||||||
|
declare type _GLOBAL_ = typeof EffectType;
|
||||||
|
|
||||||
import { registerTemplates } from './register-templates';
|
import { registerTemplates } from './register-templates';
|
||||||
|
|
||||||
bsEffects();
|
|
||||||
editorEffects();
|
editorEffects();
|
||||||
registerAIEffects();
|
registerAIEffects();
|
||||||
registerTemplates();
|
registerTemplates();
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ import { EdgelessClipboardAIChatConfig } from '../extensions/edgeless-clipboard'
|
|||||||
import { patchForClipboardInElectron } from '../extensions/electron-clipboard';
|
import { patchForClipboardInElectron } from '../extensions/electron-clipboard';
|
||||||
import { enableEditorExtension } from '../extensions/entry/enable-editor';
|
import { enableEditorExtension } from '../extensions/entry/enable-editor';
|
||||||
import { enableMobileExtension } from '../extensions/entry/enable-mobile';
|
import { enableMobileExtension } from '../extensions/entry/enable-mobile';
|
||||||
import { enablePreviewExtension } from '../extensions/entry/enable-preview';
|
|
||||||
import { patchForEdgelessNoteConfig } from '../extensions/note-config';
|
import { patchForEdgelessNoteConfig } from '../extensions/note-config';
|
||||||
import { patchNotificationService } from '../extensions/notification-service';
|
import { patchNotificationService } from '../extensions/notification-service';
|
||||||
import { patchOpenDocExtension } from '../extensions/open-doc';
|
import { patchOpenDocExtension } from '../extensions/open-doc';
|
||||||
@@ -140,10 +139,6 @@ const usePatchSpecs = (mode: DocMode) => {
|
|||||||
};
|
};
|
||||||
}, [workspaceService]);
|
}, [workspaceService]);
|
||||||
|
|
||||||
useMemo(() => {
|
|
||||||
enablePreviewExtension(framework);
|
|
||||||
}, [framework]);
|
|
||||||
|
|
||||||
const confirmModal = useConfirmModal();
|
const confirmModal = useConfirmModal();
|
||||||
|
|
||||||
const enableAI = useEnableAI();
|
const enableAI = useEnableAI();
|
||||||
@@ -161,9 +156,9 @@ const usePatchSpecs = (mode: DocMode) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const patchedSpecs = useMemo(() => {
|
const patchedSpecs = useMemo(() => {
|
||||||
const builder = enableEditorExtension(framework, mode, enableAI);
|
let extensions = enableEditorExtension(framework, mode, enableAI);
|
||||||
|
|
||||||
builder.extend(
|
extensions = extensions.concat(
|
||||||
[
|
[
|
||||||
patchReferenceRenderer(reactToLit, referenceRenderer),
|
patchReferenceRenderer(reactToLit, referenceRenderer),
|
||||||
patchForEdgelessNoteConfig(framework, reactToLit, insidePeekView),
|
patchForEdgelessNoteConfig(framework, reactToLit, insidePeekView),
|
||||||
@@ -190,17 +185,20 @@ const usePatchSpecs = (mode: DocMode) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (enablePDFEmbedPreview) {
|
if (enablePDFEmbedPreview) {
|
||||||
builder.extend([patchForPDFEmbedView(reactToLit)]);
|
extensions = extensions.concat([patchForPDFEmbedView(reactToLit)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BUILD_CONFIG.isMobileEdition) {
|
if (BUILD_CONFIG.isMobileEdition) {
|
||||||
enableMobileExtension(builder, framework);
|
extensions = enableMobileExtension(extensions, framework);
|
||||||
}
|
|
||||||
if (BUILD_CONFIG.isElectron) {
|
|
||||||
builder.extend([patchForClipboardInElectron(framework)].flat());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.value;
|
if (BUILD_CONFIG.isElectron) {
|
||||||
|
extensions = extensions.concat(
|
||||||
|
[patchForClipboardInElectron(framework)].flat()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extensions;
|
||||||
}, [
|
}, [
|
||||||
framework,
|
framework,
|
||||||
mode,
|
mode,
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
import { enableAIExtension } from '@affine/core/blocksuite/ai';
|
import type { ExtensionType } from '@blocksuite/affine/store';
|
||||||
import { enableAffineExtension } from '@affine/core/blocksuite/extensions';
|
|
||||||
import {
|
|
||||||
type SpecBuilder,
|
|
||||||
SpecProvider,
|
|
||||||
} from '@blocksuite/affine/shared/utils';
|
|
||||||
import { type FrameworkProvider } from '@toeverything/infra';
|
import { type FrameworkProvider } from '@toeverything/infra';
|
||||||
|
|
||||||
|
import { getViewManager } from '../../manager/migrating-view';
|
||||||
|
|
||||||
export function enableEditorExtension(
|
export function enableEditorExtension(
|
||||||
framework: FrameworkProvider,
|
framework: FrameworkProvider,
|
||||||
mode: 'edgeless' | 'page',
|
mode: 'edgeless' | 'page',
|
||||||
enableAI: boolean
|
enableAI: boolean
|
||||||
): SpecBuilder {
|
): ExtensionType[] {
|
||||||
const spec = SpecProvider._.getSpec(mode);
|
const manager = getViewManager(framework, enableAI);
|
||||||
enableAffineExtension(spec, framework);
|
return manager.get(mode);
|
||||||
enableAIExtension(spec, framework, enableAI);
|
|
||||||
|
|
||||||
return spec;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
VirtualKeyboardProvider as BSVirtualKeyboardProvider,
|
VirtualKeyboardProvider as BSVirtualKeyboardProvider,
|
||||||
type VirtualKeyboardProviderWithAction,
|
type VirtualKeyboardProviderWithAction,
|
||||||
} from '@blocksuite/affine/shared/services';
|
} from '@blocksuite/affine/shared/services';
|
||||||
import type { SpecBuilder } from '@blocksuite/affine/shared/utils';
|
|
||||||
import { type BlockStdScope, LifeCycleWatcher } from '@blocksuite/affine/std';
|
import { type BlockStdScope, LifeCycleWatcher } from '@blocksuite/affine/std';
|
||||||
import type { ExtensionType } from '@blocksuite/affine/store';
|
import type { ExtensionType } from '@blocksuite/affine/store';
|
||||||
import { SlashMenuExtension } from '@blocksuite/affine/widgets/slash-menu';
|
import { SlashMenuExtension } from '@blocksuite/affine/widgets/slash-menu';
|
||||||
@@ -112,16 +111,26 @@ function KeyboardToolbarExtension(framework: FrameworkProvider): ExtensionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function enableMobileExtension(
|
export function enableMobileExtension(
|
||||||
specBuilder: SpecBuilder,
|
extensions: ExtensionType[],
|
||||||
framework: FrameworkProvider
|
framework: FrameworkProvider
|
||||||
): void {
|
): ExtensionType[] {
|
||||||
specBuilder.omit(codeToolbarWidget);
|
const next = extensions.filter(extension => {
|
||||||
specBuilder.omit(toolbarWidget);
|
if (extension === codeToolbarWidget) {
|
||||||
specBuilder.omit(SlashMenuExtension);
|
return false;
|
||||||
specBuilder.extend([
|
}
|
||||||
|
if (extension === toolbarWidget) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (extension === SlashMenuExtension) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
next.push(
|
||||||
MobileSpecsPatches,
|
MobileSpecsPatches,
|
||||||
KeyboardToolbarExtension(framework),
|
KeyboardToolbarExtension(framework),
|
||||||
mobileParagraphConfig,
|
mobileParagraphConfig,
|
||||||
mobileCodeConfig,
|
mobileCodeConfig
|
||||||
]);
|
);
|
||||||
|
return next;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { getFontConfigExtension } from '../font-config';
|
|||||||
import { patchPeekViewService } from '../peek-view-service';
|
import { patchPeekViewService } from '../peek-view-service';
|
||||||
import { getThemeExtension } from '../theme';
|
import { getThemeExtension } from '../theme';
|
||||||
|
|
||||||
function getPagePreviewThemeExtension(framework: FrameworkProvider) {
|
export function getPagePreviewThemeExtension(framework: FrameworkProvider) {
|
||||||
class AffinePagePreviewThemeExtension
|
class AffinePagePreviewThemeExtension
|
||||||
extends LifeCycleWatcher
|
extends LifeCycleWatcher
|
||||||
implements ThemeExtension
|
implements ThemeExtension
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
type StoreExtensionContext,
|
||||||
|
StoreExtensionManager,
|
||||||
|
StoreExtensionProvider,
|
||||||
|
} from '@blocksuite/affine/ext-loader';
|
||||||
|
import { MigratingStoreExtension } from '@blocksuite/affine/extensions/store';
|
||||||
|
|
||||||
|
import { AIChatBlockSchemaExtension } from '../ai/blocks/ai-chat-block/model';
|
||||||
|
|
||||||
|
class MigratingAffineStoreExtension extends StoreExtensionProvider {
|
||||||
|
override name = 'affine-store-extensions';
|
||||||
|
|
||||||
|
override setup(context: StoreExtensionContext) {
|
||||||
|
super.setup(context);
|
||||||
|
context.register(AIChatBlockSchemaExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const manager = new StoreExtensionManager([
|
||||||
|
MigratingAffineStoreExtension,
|
||||||
|
MigratingStoreExtension,
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function getStoreManager() {
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
144
packages/frontend/core/src/blocksuite/manager/migrating-view.ts
Normal file
144
packages/frontend/core/src/blocksuite/manager/migrating-view.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { PeekViewService } from '@affine/core/modules/peek-view';
|
||||||
|
import { ParagraphBlockConfigExtension } from '@blocksuite/affine/blocks/paragraph';
|
||||||
|
import {
|
||||||
|
type ViewExtensionContext,
|
||||||
|
ViewExtensionManager,
|
||||||
|
ViewExtensionProvider,
|
||||||
|
} from '@blocksuite/affine/ext-loader';
|
||||||
|
import { MigratingViewExtension } from '@blocksuite/affine/extensions/view';
|
||||||
|
import { ToolbarModuleExtension } from '@blocksuite/affine/shared/services';
|
||||||
|
import { BlockFlavourIdentifier } from '@blocksuite/affine/std';
|
||||||
|
import { FrameworkProvider } from '@toeverything/infra';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { toolbarAIEntryConfig } from '../ai';
|
||||||
|
import { AIChatBlockSpec } from '../ai/blocks';
|
||||||
|
import { AITranscriptionBlockSpec } from '../ai/blocks/ai-chat-block/ai-transcription-block';
|
||||||
|
import { edgelessToolbarAIEntryConfig } from '../ai/entries/edgeless';
|
||||||
|
import { imageToolbarAIEntryConfig } from '../ai/entries/image-toolbar/setup-image-toolbar';
|
||||||
|
import { AICodeBlockWatcher } from '../ai/extensions/ai-code';
|
||||||
|
import { getAIEdgelessRootWatcher } from '../ai/extensions/ai-edgeless-root';
|
||||||
|
import { getAIPageRootWatcher } from '../ai/extensions/ai-page-root';
|
||||||
|
import { AiSlashMenuConfigExtension } from '../ai/extensions/ai-slash-menu';
|
||||||
|
import { CopilotTool } from '../ai/tool/copilot-tool';
|
||||||
|
import { aiPanelWidget } from '../ai/widgets/ai-panel/ai-panel';
|
||||||
|
import { edgelessCopilotWidget } from '../ai/widgets/edgeless-copilot';
|
||||||
|
import { buildDocDisplayMetaExtension } from '../extensions/display-meta';
|
||||||
|
import { getEditorConfigExtension } from '../extensions/editor-config';
|
||||||
|
import { getPagePreviewThemeExtension } from '../extensions/entry/enable-preview';
|
||||||
|
import { getFontConfigExtension } from '../extensions/font-config';
|
||||||
|
import { patchPeekViewService } from '../extensions/peek-view-service';
|
||||||
|
import { getTelemetryExtension } from '../extensions/telemetry';
|
||||||
|
import { getThemeExtension } from '../extensions/theme';
|
||||||
|
|
||||||
|
const optionsSchema = z.object({
|
||||||
|
enableAI: z.boolean().optional(),
|
||||||
|
framework: z.instanceof(FrameworkProvider),
|
||||||
|
});
|
||||||
|
|
||||||
|
class MigratingAffineViewExtension extends ViewExtensionProvider<
|
||||||
|
z.infer<typeof optionsSchema>
|
||||||
|
> {
|
||||||
|
override name = 'affine-view-extensions';
|
||||||
|
|
||||||
|
override schema = optionsSchema;
|
||||||
|
|
||||||
|
override setup(
|
||||||
|
context: ViewExtensionContext,
|
||||||
|
options?: z.infer<typeof optionsSchema>
|
||||||
|
) {
|
||||||
|
super.setup(context);
|
||||||
|
const { framework, enableAI } = options || {};
|
||||||
|
if (framework) {
|
||||||
|
context.register([
|
||||||
|
getThemeExtension(framework),
|
||||||
|
getFontConfigExtension(),
|
||||||
|
buildDocDisplayMetaExtension(framework),
|
||||||
|
]);
|
||||||
|
if (context.scope === 'page' || context.scope === 'edgeless') {
|
||||||
|
context.register(getTelemetryExtension());
|
||||||
|
context.register(getEditorConfigExtension(framework));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
context.scope === 'preview-page' ||
|
||||||
|
context.scope === 'preview-edgeless'
|
||||||
|
) {
|
||||||
|
context.register(getPagePreviewThemeExtension(framework));
|
||||||
|
context.register(patchPeekViewService(framework.get(PeekViewService)));
|
||||||
|
}
|
||||||
|
if (enableAI) {
|
||||||
|
context.register(AIChatBlockSpec);
|
||||||
|
context.register(AITranscriptionBlockSpec);
|
||||||
|
context.register(
|
||||||
|
[
|
||||||
|
AICodeBlockWatcher,
|
||||||
|
ToolbarModuleExtension({
|
||||||
|
id: BlockFlavourIdentifier('custom:affine:image'),
|
||||||
|
config: imageToolbarAIEntryConfig(),
|
||||||
|
}),
|
||||||
|
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(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const manager = new ViewExtensionManager([
|
||||||
|
MigratingViewExtension,
|
||||||
|
MigratingAffineViewExtension,
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function getViewManager(
|
||||||
|
framework: FrameworkProvider,
|
||||||
|
enableAI: boolean
|
||||||
|
) {
|
||||||
|
manager.configure(MigratingAffineViewExtension, {
|
||||||
|
framework,
|
||||||
|
enableAI,
|
||||||
|
});
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Skeleton } from '@affine/component';
|
import { Skeleton } from '@affine/component';
|
||||||
|
import { getViewManager } from '@affine/core/blocksuite/manager/migrating-view';
|
||||||
import type { EditorSettingSchema } from '@affine/core/modules/editor-setting';
|
import type { EditorSettingSchema } from '@affine/core/modules/editor-setting';
|
||||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine/blocks/surface';
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine/blocks/surface';
|
||||||
import { Bound } from '@blocksuite/affine/global/gfx';
|
import { Bound } from '@blocksuite/affine/global/gfx';
|
||||||
import { ViewportElementExtension } from '@blocksuite/affine/shared/services';
|
import { ViewportElementExtension } from '@blocksuite/affine/shared/services';
|
||||||
import { SpecProvider } from '@blocksuite/affine/shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { BlockStdScope } from '@blocksuite/affine/std';
|
import { BlockStdScope } from '@blocksuite/affine/std';
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
import type { Block, Store } from '@blocksuite/affine/store';
|
import type { Block, Store } from '@blocksuite/affine/store';
|
||||||
import { useFramework } from '@toeverything/infra';
|
import { useFramework } from '@toeverything/infra';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import { map, pairwise } from 'rxjs';
|
import { map, pairwise } from 'rxjs';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -55,6 +55,13 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
const framework = useFramework();
|
const framework = useFramework();
|
||||||
const { editorSetting } = framework.get(EditorSettingService);
|
const { editorSetting } = framework.get(EditorSettingService);
|
||||||
|
|
||||||
|
const extensions = useMemo(() => {
|
||||||
|
const manager = getViewManager(framework, false);
|
||||||
|
return manager
|
||||||
|
.get('preview-edgeless')
|
||||||
|
.concat([ViewportElementExtension('.ref-viewport')]);
|
||||||
|
}, [framework]);
|
||||||
|
|
||||||
const updateElements = useCallback(() => {
|
const updateElements = useCallback(() => {
|
||||||
const editorHost = editorHostRef.current;
|
const editorHost = editorHostRef.current;
|
||||||
const doc = docRef.current;
|
const doc = docRef.current;
|
||||||
@@ -76,9 +83,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
|
|
||||||
const editorHost = new BlockStdScope({
|
const editorHost = new BlockStdScope({
|
||||||
store: doc,
|
store: doc,
|
||||||
extensions: SpecProvider._.getSpec('preview:edgeless').extend([
|
extensions,
|
||||||
ViewportElementExtension('.ref-viewport'),
|
|
||||||
]).value,
|
|
||||||
}).render();
|
}).render();
|
||||||
docRef.current = doc;
|
docRef.current = doc;
|
||||||
editorHostRef.current?.remove();
|
editorHostRef.current?.remove();
|
||||||
@@ -115,7 +120,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
|
|
||||||
// append to dom node
|
// append to dom node
|
||||||
wrapperRef.current.append(editorHost);
|
wrapperRef.current.append(editorHost);
|
||||||
}, [docName, firstUpdate, updateElements]);
|
}, [docName, extensions, firstUpdate, updateElements]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import { ChatPanel } from '@affine/core/blocksuite/ai';
|
|||||||
import type { AffineEditorContainer } from '@affine/core/blocksuite/block-suite-editor';
|
import type { AffineEditorContainer } from '@affine/core/blocksuite/block-suite-editor';
|
||||||
import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config';
|
import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
|
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine/ext-loader';
|
||||||
import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference';
|
import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference';
|
||||||
import { DocModeProvider } from '@blocksuite/affine/shared/services';
|
import { DocModeProvider } from '@blocksuite/affine/shared/services';
|
||||||
import {
|
import { createSignalFromObservable } from '@blocksuite/affine/shared/utils';
|
||||||
createSignalFromObservable,
|
|
||||||
SpecProvider,
|
|
||||||
} from '@blocksuite/affine/shared/utils';
|
|
||||||
import { useFramework } from '@toeverything/infra';
|
import { useFramework } from '@toeverything/infra';
|
||||||
import { forwardRef, useEffect, useRef } from 'react';
|
import { forwardRef, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
@@ -69,8 +67,9 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel(
|
|||||||
chatPanelRef.current.docDisplayConfig = docDisplayConfig;
|
chatPanelRef.current.docDisplayConfig = docDisplayConfig;
|
||||||
chatPanelRef.current.searchMenuConfig = searchMenuConfig;
|
chatPanelRef.current.searchMenuConfig = searchMenuConfig;
|
||||||
chatPanelRef.current.networkSearchConfig = networkSearchConfig;
|
chatPanelRef.current.networkSearchConfig = networkSearchConfig;
|
||||||
chatPanelRef.current.previewSpecBuilder =
|
chatPanelRef.current.extensions = editor.host.std
|
||||||
SpecProvider._.getSpec('preview:page');
|
.get(ViewExtensionManagerIdentifier)
|
||||||
|
.get('preview-page');
|
||||||
|
|
||||||
containerRef.current?.append(chatPanelRef.current);
|
containerRef.current?.append(chatPanelRef.current);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { toReactNode } from '@affine/component';
|
|||||||
import { AIChatBlockPeekViewTemplate } from '@affine/core/blocksuite/ai';
|
import { AIChatBlockPeekViewTemplate } from '@affine/core/blocksuite/ai';
|
||||||
import type { AIChatBlockModel } from '@affine/core/blocksuite/ai/blocks/ai-chat-block/model/ai-chat-model';
|
import type { AIChatBlockModel } from '@affine/core/blocksuite/ai/blocks/ai-chat-block/model/ai-chat-model';
|
||||||
import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config';
|
import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config';
|
||||||
import { SpecProvider } from '@blocksuite/affine/shared/utils';
|
|
||||||
import type { EditorHost } from '@blocksuite/affine/std';
|
import type { EditorHost } from '@blocksuite/affine/std';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
@@ -18,11 +17,9 @@ export const AIChatBlockPeekView = ({
|
|||||||
const { docDisplayConfig, searchMenuConfig, networkSearchConfig } =
|
const { docDisplayConfig, searchMenuConfig, networkSearchConfig } =
|
||||||
useAIChatConfig();
|
useAIChatConfig();
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const previewSpecBuilder = SpecProvider._.getSpec('preview:page');
|
|
||||||
const template = AIChatBlockPeekViewTemplate(
|
const template = AIChatBlockPeekViewTemplate(
|
||||||
model,
|
model,
|
||||||
host,
|
host,
|
||||||
previewSpecBuilder,
|
|
||||||
docDisplayConfig,
|
docDisplayConfig,
|
||||||
searchMenuConfig,
|
searchMenuConfig,
|
||||||
networkSearchConfig
|
networkSearchConfig
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SpecProvider } from '@blocksuite/affine/shared/utils';
|
import { getStoreManager } from '@affine/core/blocksuite/manager/migrating-store';
|
||||||
import {
|
import {
|
||||||
AwarenessStore,
|
AwarenessStore,
|
||||||
type Doc,
|
type Doc,
|
||||||
@@ -294,11 +294,9 @@ export class DocImpl implements Doc {
|
|||||||
return this._storeMap.get(key) as Store;
|
return this._storeMap.get(key) as Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeExtensions = SpecProvider._.getSpec('store');
|
const storeExtensions = getStoreManager().get('store');
|
||||||
const extensionSet = new Set(
|
const extensionSet = new Set(
|
||||||
storeExtensions.value
|
storeExtensions.concat(extensions ?? []).concat(this.storeExtensions)
|
||||||
.concat(extensions ?? [])
|
|
||||||
.concat(this.storeExtensions)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const doc = new Store({
|
const doc = new Store({
|
||||||
|
|||||||
@@ -388,6 +388,7 @@ export const PackageList = [
|
|||||||
'blocksuite/affine/blocks/frame',
|
'blocksuite/affine/blocks/frame',
|
||||||
'blocksuite/affine/blocks/surface',
|
'blocksuite/affine/blocks/surface',
|
||||||
'blocksuite/affine/components',
|
'blocksuite/affine/components',
|
||||||
|
'blocksuite/affine/ext-loader',
|
||||||
'blocksuite/affine/inlines/reference',
|
'blocksuite/affine/inlines/reference',
|
||||||
'blocksuite/affine/model',
|
'blocksuite/affine/model',
|
||||||
'blocksuite/affine/shared',
|
'blocksuite/affine/shared',
|
||||||
@@ -465,6 +466,7 @@ export const PackageList = [
|
|||||||
'blocksuite/affine/blocks/frame',
|
'blocksuite/affine/blocks/frame',
|
||||||
'blocksuite/affine/blocks/surface',
|
'blocksuite/affine/blocks/surface',
|
||||||
'blocksuite/affine/components',
|
'blocksuite/affine/components',
|
||||||
|
'blocksuite/affine/ext-loader',
|
||||||
'blocksuite/affine/model',
|
'blocksuite/affine/model',
|
||||||
'blocksuite/affine/rich-text',
|
'blocksuite/affine/rich-text',
|
||||||
'blocksuite/affine/shared',
|
'blocksuite/affine/shared',
|
||||||
@@ -754,6 +756,7 @@ export const PackageList = [
|
|||||||
'blocksuite/affine/blocks/paragraph',
|
'blocksuite/affine/blocks/paragraph',
|
||||||
'blocksuite/affine/blocks/surface',
|
'blocksuite/affine/blocks/surface',
|
||||||
'blocksuite/affine/components',
|
'blocksuite/affine/components',
|
||||||
|
'blocksuite/affine/ext-loader',
|
||||||
'blocksuite/affine/model',
|
'blocksuite/affine/model',
|
||||||
'blocksuite/affine/shared',
|
'blocksuite/affine/shared',
|
||||||
'blocksuite/framework/global',
|
'blocksuite/framework/global',
|
||||||
|
|||||||
@@ -2875,6 +2875,7 @@ __metadata:
|
|||||||
"@blocksuite/affine-block-frame": "workspace:*"
|
"@blocksuite/affine-block-frame": "workspace:*"
|
||||||
"@blocksuite/affine-block-surface": "workspace:*"
|
"@blocksuite/affine-block-surface": "workspace:*"
|
||||||
"@blocksuite/affine-components": "workspace:*"
|
"@blocksuite/affine-components": "workspace:*"
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*"
|
||||||
"@blocksuite/affine-inline-reference": "workspace:*"
|
"@blocksuite/affine-inline-reference": "workspace:*"
|
||||||
"@blocksuite/affine-model": "workspace:*"
|
"@blocksuite/affine-model": "workspace:*"
|
||||||
"@blocksuite/affine-shared": "workspace:*"
|
"@blocksuite/affine-shared": "workspace:*"
|
||||||
@@ -3027,6 +3028,7 @@ __metadata:
|
|||||||
"@blocksuite/affine-block-frame": "workspace:*"
|
"@blocksuite/affine-block-frame": "workspace:*"
|
||||||
"@blocksuite/affine-block-surface": "workspace:*"
|
"@blocksuite/affine-block-surface": "workspace:*"
|
||||||
"@blocksuite/affine-components": "workspace:*"
|
"@blocksuite/affine-components": "workspace:*"
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*"
|
||||||
"@blocksuite/affine-model": "workspace:*"
|
"@blocksuite/affine-model": "workspace:*"
|
||||||
"@blocksuite/affine-rich-text": "workspace:*"
|
"@blocksuite/affine-rich-text": "workspace:*"
|
||||||
"@blocksuite/affine-shared": "workspace:*"
|
"@blocksuite/affine-shared": "workspace:*"
|
||||||
@@ -3598,6 +3600,7 @@ __metadata:
|
|||||||
"@blocksuite/affine-block-paragraph": "workspace:*"
|
"@blocksuite/affine-block-paragraph": "workspace:*"
|
||||||
"@blocksuite/affine-block-surface": "workspace:*"
|
"@blocksuite/affine-block-surface": "workspace:*"
|
||||||
"@blocksuite/affine-components": "workspace:*"
|
"@blocksuite/affine-components": "workspace:*"
|
||||||
|
"@blocksuite/affine-ext-loader": "workspace:*"
|
||||||
"@blocksuite/affine-model": "workspace:*"
|
"@blocksuite/affine-model": "workspace:*"
|
||||||
"@blocksuite/affine-shared": "workspace:*"
|
"@blocksuite/affine-shared": "workspace:*"
|
||||||
"@blocksuite/global": "workspace:*"
|
"@blocksuite/global": "workspace:*"
|
||||||
|
|||||||
Reference in New Issue
Block a user