chore: bump bs with new extension api (#8042)

This commit is contained in:
Saul-Mirone
2024-09-02 10:32:22 +00:00
parent 61e37d8873
commit 56f4634c1f
90 changed files with 1300 additions and 988 deletions

View File

@@ -3,8 +3,8 @@
"private": true, "private": true,
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@blocksuite/global": "0.17.0-canary-202408191538-1511d04", "@blocksuite/global": "0.0.0-canary-20240902070217",
"@blocksuite/store": "0.17.0-canary-202408191538-1511d04", "@blocksuite/store": "0.0.0-canary-20240902070217",
"react": "18.3.1", "react": "18.3.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"vitest": "1.6.0" "vitest": "1.6.0"

View File

@@ -14,10 +14,10 @@
"@affine/debug": "workspace:*", "@affine/debug": "workspace:*",
"@affine/env": "workspace:*", "@affine/env": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@blocksuite/blocks": "0.17.0-canary-202408191538-1511d04", "@blocksuite/blocks": "0.0.0-canary-20240902070217",
"@blocksuite/global": "0.17.0-canary-202408191538-1511d04", "@blocksuite/global": "0.0.0-canary-20240902070217",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@blocksuite/store": "0.17.0-canary-202408191538-1511d04", "@blocksuite/store": "0.0.0-canary-20240902070217",
"@datastructures-js/binary-search-tree": "^5.3.2", "@datastructures-js/binary-search-tree": "^5.3.2",
"foxact": "^0.2.33", "foxact": "^0.2.33",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
@@ -34,8 +34,8 @@
"devDependencies": { "devDependencies": {
"@affine-test/fixtures": "workspace:*", "@affine-test/fixtures": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@blocksuite/block-std": "0.17.0-canary-202408191538-1511d04", "@blocksuite/block-std": "0.0.0-canary-20240902070217",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@testing-library/react": "^16.0.0", "@testing-library/react": "^16.0.0",
"async-call-rpc": "^6.4.0", "async-call-rpc": "^6.4.0",
"fake-indexeddb": "^6.0.0", "fake-indexeddb": "^6.0.0",

View File

@@ -1,10 +1,9 @@
import type { RootBlockModel } from '@blocksuite/blocks'; import type { DocMode, RootBlockModel } from '@blocksuite/blocks';
import { Entity } from '../../../framework'; import { Entity } from '../../../framework';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
import type { DocScope } from '../scopes/doc'; import type { DocScope } from '../scopes/doc';
import type { DocsStore } from '../stores/docs'; import type { DocsStore } from '../stores/docs';
import type { DocMode } from './record';
export class Doc extends Entity { export class Doc extends Entity {
constructor( constructor(
@@ -44,7 +43,7 @@ export class Doc extends Entity {
togglePrimaryMode() { togglePrimaryMode() {
this.setPrimaryMode( this.setPrimaryMode(
this.getPrimaryMode() === 'edgeless' ? 'page' : 'edgeless' (this.getPrimaryMode() === 'edgeless' ? 'page' : 'edgeless') as DocMode
); );
} }

View File

@@ -1,9 +1,10 @@
import type { DocMode } from '@blocksuite/blocks';
import { map } from 'rxjs'; import { map } from 'rxjs';
import { Entity } from '../../../framework'; import { Entity } from '../../../framework';
import { LiveData } from '../../../livedata'; import { LiveData } from '../../../livedata';
import type { DocsStore } from '../stores/docs'; import type { DocsStore } from '../stores/docs';
import { type DocMode, DocRecord } from './record'; import { DocRecord } from './record';
export class DocRecordList extends Entity { export class DocRecordList extends Entity {
constructor(private readonly store: DocsStore) { constructor(private readonly store: DocsStore) {
@@ -64,7 +65,9 @@ export class DocRecordList extends Entity {
} }
public togglePrimaryMode(id: string) { public togglePrimaryMode(id: string) {
const mode = this.getPrimaryMode(id) === 'edgeless' ? 'page' : 'edgeless'; const mode = (
this.getPrimaryMode(id) === 'edgeless' ? 'page' : 'edgeless'
) as DocMode;
this.setPrimaryMode(id, mode); this.setPrimaryMode(id, mode);
return this.getPrimaryMode(id); return this.getPrimaryMode(id);
} }

View File

@@ -1,11 +1,10 @@
import type { DocMode } from '@blocksuite/blocks';
import type { DocMeta } from '@blocksuite/store'; import type { DocMeta } from '@blocksuite/store';
import { Entity } from '../../../framework'; import { Entity } from '../../../framework';
import { LiveData } from '../../../livedata'; import { LiveData } from '../../../livedata';
import type { DocsStore } from '../stores/docs'; import type { DocsStore } from '../stores/docs';
export type DocMode = 'edgeless' | 'page';
/** /**
* # DocRecord * # DocRecord
* *
@@ -28,8 +27,8 @@ export class DocRecord extends Entity<{ id: string }> {
primaryMode$: LiveData<DocMode> = LiveData.from( primaryMode$: LiveData<DocMode> = LiveData.from(
this.docsStore.watchDocPrimaryModeSetting(this.id), this.docsStore.watchDocPrimaryModeSetting(this.id),
'page' 'page' as DocMode
).map(mode => (mode === 'edgeless' ? 'edgeless' : 'page')); ).map(mode => (mode === 'edgeless' ? 'edgeless' : 'page') as DocMode);
setPrimaryMode(mode: DocMode) { setPrimaryMode(mode: DocMode) {
return this.docsStore.setDocPrimaryModeSetting(this.id, mode); return this.docsStore.setDocPrimaryModeSetting(this.id, mode);

View File

@@ -1,5 +1,4 @@
export { Doc } from './entities/doc'; export { Doc } from './entities/doc';
export type { DocMode } from './entities/record';
export { DocRecord } from './entities/record'; export { DocRecord } from './entities/record';
export { DocRecordList } from './entities/record-list'; export { DocRecordList } from './entities/record-list';
export { DocScope } from './scopes/doc'; export { DocScope } from './scopes/doc';

View File

@@ -1,10 +1,10 @@
import { Unreachable } from '@affine/env/constant'; import { Unreachable } from '@affine/env/constant';
import type { DocMode } from '@blocksuite/blocks';
import { Service } from '../../../framework'; import { Service } from '../../../framework';
import { initEmptyPage } from '../../../initialization'; import { initEmptyPage } from '../../../initialization';
import { ObjectPool } from '../../../utils'; import { ObjectPool } from '../../../utils';
import type { Doc } from '../entities/doc'; import type { Doc } from '../entities/doc';
import type { DocMode } from '../entities/record';
import { DocRecordList } from '../entities/record-list'; import { DocRecordList } from '../entities/record-list';
import { DocScope } from '../scopes/doc'; import { DocScope } from '../scopes/doc';
import type { DocsStore } from '../stores/docs'; import type { DocsStore } from '../stores/docs';

View File

@@ -1,10 +1,10 @@
import type { DocMode } from '@blocksuite/blocks';
import { type DocMeta } from '@blocksuite/store'; import { type DocMeta } from '@blocksuite/store';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { distinctUntilChanged, Observable } from 'rxjs'; import { distinctUntilChanged, Observable } from 'rxjs';
import { Store } from '../../../framework'; import { Store } from '../../../framework';
import type { WorkspaceLocalState, WorkspaceService } from '../../workspace'; import type { WorkspaceLocalState, WorkspaceService } from '../../workspace';
import type { DocMode } from '../entities/record';
export class DocsStore extends Store { export class DocsStore extends Store {
constructor( constructor(

View File

@@ -12,13 +12,6 @@ export const AFFINE_FLAGS = {
description: 'Allows adding notes to database attachments.', description: 'Allows adding notes to database attachments.',
configurable: isNotStableBuild, configurable: isNotStableBuild,
}, },
enable_database_statistics: {
category: 'blocksuite',
bsFlag: 'enable_database_statistics',
displayName: 'Database Block Statistics',
description: 'Shows statistics for database blocks.',
configurable: isNotStableBuild,
},
enable_block_query: { enable_block_query: {
category: 'blocksuite', category: 'blocksuite',
bsFlag: 'enable_block_query', bsFlag: 'enable_block_query',

View File

@@ -1,7 +1,8 @@
import type { DocMode } from '@blocksuite/blocks';
import { Entity } from '../../../framework'; import { Entity } from '../../../framework';
import { LiveData } from '../../../livedata'; import { LiveData } from '../../../livedata';
import { MemoryMemento } from '../../../storage'; import { MemoryMemento } from '../../../storage';
import type { DocMode } from '../../doc';
export class GlobalContext extends Entity { export class GlobalContext extends Entity {
memento = new MemoryMemento(); memento = new MemoryMemento();

View File

@@ -81,12 +81,12 @@
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
"devDependencies": { "devDependencies": {
"@blocksuite/block-std": "0.17.0-canary-202408191538-1511d04", "@blocksuite/block-std": "0.0.0-canary-20240902070217",
"@blocksuite/blocks": "0.17.0-canary-202408191538-1511d04", "@blocksuite/blocks": "0.0.0-canary-20240902070217",
"@blocksuite/global": "0.17.0-canary-202408191538-1511d04", "@blocksuite/global": "0.0.0-canary-20240902070217",
"@blocksuite/icons": "2.1.66", "@blocksuite/icons": "2.1.66",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@blocksuite/store": "0.17.0-canary-202408191538-1511d04", "@blocksuite/store": "0.0.0-canary-20240902070217",
"@chromatic-com/storybook": "^1", "@chromatic-com/storybook": "^1",
"@storybook/addon-actions": "^8.2.9", "@storybook/addon-actions": "^8.2.9",
"@storybook/addon-essentials": "^8.2.9", "@storybook/addon-essentials": "^8.2.9",

View File

@@ -15,13 +15,13 @@
"@affine/graphql": "workspace:*", "@affine/graphql": "workspace:*",
"@affine/i18n": "workspace:*", "@affine/i18n": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@blocksuite/block-std": "0.17.0-canary-202408191538-1511d04", "@blocksuite/block-std": "0.0.0-canary-20240902070217",
"@blocksuite/blocks": "0.17.0-canary-202408191538-1511d04", "@blocksuite/blocks": "0.0.0-canary-20240902070217",
"@blocksuite/global": "0.17.0-canary-202408191538-1511d04", "@blocksuite/global": "0.0.0-canary-20240902070217",
"@blocksuite/icons": "2.1.66", "@blocksuite/icons": "2.1.66",
"@blocksuite/inline": "0.17.0-canary-202408191538-1511d04", "@blocksuite/inline": "0.0.0-canary-20240902070217",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@blocksuite/store": "0.17.0-canary-202408191538-1511d04", "@blocksuite/store": "0.0.0-canary-20240902070217",
"@dnd-kit/core": "^6.1.0", "@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0", "@dnd-kit/sortable": "^8.0.0",

View File

@@ -4,11 +4,12 @@ import type {
EditorHost, EditorHost,
TextSelection, TextSelection,
} from '@blocksuite/block-std'; } from '@blocksuite/block-std';
import type { import {
DocMode, type DocMode,
EdgelessRootService, DocModeProvider,
ImageSelection, type EdgelessRootService,
PageRootService, type ImageSelection,
type PageRootService,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { BlocksUtils, NoteDisplayMode } from '@blocksuite/blocks'; import { BlocksUtils, NoteDisplayMode } from '@blocksuite/blocks';
import { import {
@@ -176,8 +177,7 @@ function addAIChatBlock(
} }
export function promptDocTitle(host: EditorHost, autofill?: string) { export function promptDocTitle(host: EditorHost, autofill?: string) {
const notification = const notification = host.std.getService('affine:page').notificationService;
host.std.spec.getService('affine:page').notificationService;
if (!notification) return Promise.resolve(undefined); if (!notification) return Promise.resolve(undefined);
return notification.prompt({ return notification.prompt({
@@ -297,11 +297,12 @@ const SAVE_CHAT_TO_BLOCK_ACTION: ChatAction = {
return false; return false;
} }
const rootService = host.spec.getService('affine:page'); const rootService = host.std.getService('affine:page');
const surfaceService = host.spec.getService('affine:surface'); const surfaceService = host.std.getService('affine:surface');
if (!rootService || !surfaceService) return false; if (!rootService || !surfaceService) return false;
const { docModeService, notificationService } = rootService; const { notificationService } = rootService;
const docModeService = host.std.get(DocModeProvider);
const { layer } = surfaceService; const { layer } = surfaceService;
const curMode = docModeService.getMode(); const curMode = docModeService.getMode();
const viewportCenter = getViewportCenter( const viewportCenter = getViewportCenter(
@@ -312,7 +313,7 @@ const SAVE_CHAT_TO_BLOCK_ACTION: ChatAction = {
// If current mode is not edgeless, switch to edgeless mode first // If current mode is not edgeless, switch to edgeless mode first
if (curMode !== 'edgeless') { if (curMode !== 'edgeless') {
// Set mode to edgeless // Set mode to edgeless
docModeService.setMode('edgeless'); docModeService.setMode('edgeless' as DocMode);
// Notify user to switch to edgeless mode // Notify user to switch to edgeless mode
notificationService?.notify({ notificationService?.notify({
title: 'Save chat to a block', title: 'Save chat to a block',
@@ -382,7 +383,7 @@ const ADD_TO_EDGELESS_AS_NOTE = {
handler: async (host: EditorHost, content: string) => { handler: async (host: EditorHost, content: string) => {
reportResponse('result:add-note'); reportResponse('result:add-note');
const { doc } = host; const { doc } = host;
const service = host.spec.getService<EdgelessRootService>('affine:page'); const service = host.std.getService<EdgelessRootService>('affine:page');
const elements = service.selection.selectedElements; const elements = service.selection.selectedElements;
const props: { displayMode: NoteDisplayMode; xywh?: SerializedXYWH } = { const props: { displayMode: NoteDisplayMode; xywh?: SerializedXYWH } = {
@@ -423,8 +424,8 @@ const CREATE_AS_DOC = {
newDoc.addBlock('affine:surface', {}, rootId); newDoc.addBlock('affine:surface', {}, rootId);
const noteId = newDoc.addBlock('affine:note', {}, rootId); const noteId = newDoc.addBlock('affine:note', {}, rootId);
host.spec.getService('affine:page').slots.docLinkClicked.emit({ host.std.getService('affine:page').slots.docLinkClicked.emit({
docId: newDoc.id, pageId: newDoc.id,
}); });
let complete = false; let complete = false;
(function addContent() { (function addContent() {
@@ -460,8 +461,9 @@ const CREATE_AS_LINKED_DOC = {
return false; return false;
} }
const service = host.spec.getService<EdgelessRootService>('affine:page'); const service = host.std.getService<EdgelessRootService>('affine:page');
const mode = service.docModeService.getMode(); const docModeService = host.std.get(DocModeProvider);
const mode = docModeService.getMode();
if (mode !== 'edgeless') { if (mode !== 'edgeless') {
return false; return false;
} }

View File

@@ -1,6 +1,7 @@
import { type EditorHost, WithDisposable } from '@blocksuite/block-std'; import { type EditorHost, WithDisposable } from '@blocksuite/block-std';
import { import {
type AIItemGroupConfig, type AIItemGroupConfig,
DocMode,
EdgelessRootService, EdgelessRootService,
scrollbarStyle, scrollbarStyle,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
@@ -63,7 +64,7 @@ export class AskAIPanel extends WithDisposable(LitElement) {
item.showWhen item.showWhen
? item.showWhen( ? item.showWhen(
this.host.command.chain(), this.host.command.chain(),
this._edgeless ? 'edgeless' : 'page', this._edgeless ? DocMode.Edgeless : DocMode.Page,
this.host this.host
) )
: true : true

View File

@@ -60,7 +60,7 @@ export class ChatActionList extends LitElement {
} }
private get _rootService() { private get _rootService() {
return this.host.spec.getService('affine:page'); return this.host.std.getService('affine:page');
} }
private get _currentTextSelection(): TextSelection | undefined { private get _currentTextSelection(): TextSelection | undefined {

View File

@@ -73,7 +73,7 @@ export class ChatCopyMore extends WithDisposable(LitElement) {
`; `;
private get _rootService() { private get _rootService() {
return this.host.spec.getService('affine:page'); return this.host.std.getService('affine:page');
} }
private get _selectionValue() { private get _selectionValue() {

View File

@@ -12,7 +12,7 @@ import { Slice } from '@blocksuite/store';
import { getMarkdownFromSlice } from './markdown-utils'; import { getMarkdownFromSlice } from './markdown-utils';
export const getRootService = (host: EditorHost) => { export const getRootService = (host: EditorHost) => {
return host.std.spec.getService('affine:page'); return host.std.getService('affine:page');
}; };
export function getEdgelessRootFromEditor(editor: EditorHost) { export function getEdgelessRootFromEditor(editor: EditorHost) {
@@ -24,7 +24,7 @@ export function getEdgelessRootFromEditor(editor: EditorHost) {
return edgelessRoot; return edgelessRoot;
} }
export function getEdgelessService(editor: EditorHost) { export function getEdgelessService(editor: EditorHost) {
const rootService = editor.std.spec.getService('affine:page'); const rootService = editor.std.getService('affine:page');
if (rootService instanceof EdgelessRootService) { if (rootService instanceof EdgelessRootService) {
return rootService; return rootService;
} }

View File

@@ -507,7 +507,7 @@ export const responses: {
const contents = data.contents as unknown[]; const contents = data.contents as unknown[];
if (!contents) return; if (!contents) return;
const images = data.images as { url: string; id: string }[][]; const images = data.images as { url: string; id: string }[][];
const service = host.spec.getService<EdgelessRootService>('affine:page'); const service = host.std.getService<EdgelessRootService>('affine:page');
(async function () { (async function () {
for (let i = 0; i < contents.length - 1; i++) { for (let i = 0; i < contents.length - 1; i++) {

View File

@@ -1,4 +1,8 @@
import type { BlockSpec } from '@blocksuite/block-std'; import {
BlockServiceWatcher,
type ExtensionType,
WidgetViewMapIdentifier,
} from '@blocksuite/block-std';
import { import {
AFFINE_AI_PANEL_WIDGET, AFFINE_AI_PANEL_WIDGET,
AFFINE_EDGELESS_COPILOT_WIDGET, AFFINE_EDGELESS_COPILOT_WIDGET,
@@ -11,8 +15,10 @@ import {
EdgelessCopilotWidget, EdgelessCopilotWidget,
EdgelessElementToolbarWidget, EdgelessElementToolbarWidget,
EdgelessRootBlockSpec, EdgelessRootBlockSpec,
edgelessRootWigetViewMap,
ImageBlockSpec, ImageBlockSpec,
PageRootBlockSpec, PageRootBlockSpec,
pageRootWidgetViewMap,
ParagraphBlockService, ParagraphBlockService,
ParagraphBlockSpec, ParagraphBlockSpec,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
@@ -30,56 +36,52 @@ import { setupImageToolbarEntry } from './entries/image-toolbar/setup-image-tool
import { setupSlashMenuEntry } from './entries/slash-menu/setup-slash-menu'; import { setupSlashMenuEntry } from './entries/slash-menu/setup-slash-menu';
import { setupSpaceEntry } from './entries/space/setup-space'; import { setupSpaceEntry } from './entries/space/setup-space';
export const AIPageRootBlockSpec: BlockSpec = { class AIPageRootWatcher extends BlockServiceWatcher {
static override readonly flavour = 'affine:page';
override mounted() {
super.mounted();
this.blockService.specSlots.widgetConnected.on(view => {
if (view.component instanceof AffineAIPanelWidget) {
view.component.style.width = '630px';
view.component.config = buildAIPanelConfig(view.component);
setupSpaceEntry(view.component);
}
if (view.component instanceof AffineFormatBarWidget) {
setupFormatBarEntry(view.component);
}
if (view.component instanceof AffineSlashMenuWidget) {
setupSlashMenuEntry(view.component);
}
});
}
}
export const AIPageRootBlockSpec: ExtensionType[] = [
...PageRootBlockSpec, ...PageRootBlockSpec,
view: { AIPageRootWatcher,
...PageRootBlockSpec.view, {
widgets: { setup: di => {
...PageRootBlockSpec.view.widgets, di.override(WidgetViewMapIdentifier('affine:page'), () => {
[AFFINE_AI_PANEL_WIDGET]: literal`${unsafeStatic( return {
AFFINE_AI_PANEL_WIDGET ...pageRootWidgetViewMap,
)}`, [AFFINE_AI_PANEL_WIDGET]: literal`${unsafeStatic(
AFFINE_AI_PANEL_WIDGET
)}`,
};
});
}, },
}, },
setup: (slots, disposableGroup) => { ];
PageRootBlockSpec.setup?.(slots, disposableGroup);
disposableGroup.add(
slots.widgetConnected.on(view => {
if (view.component instanceof AffineAIPanelWidget) {
view.component.style.width = '630px';
view.component.config = buildAIPanelConfig(view.component);
setupSpaceEntry(view.component);
}
if (view.component instanceof AffineFormatBarWidget) { class AIEdgelessRootWatcher extends BlockServiceWatcher {
setupFormatBarEntry(view.component); static override readonly flavour = 'affine:page';
}
if (view.component instanceof AffineSlashMenuWidget) { override mounted() {
setupSlashMenuEntry(view.component); super.mounted();
} this.blockService.specSlots.widgetConnected.on(view => {
})
);
},
};
export const AIEdgelessRootBlockSpec: BlockSpec = {
...EdgelessRootBlockSpec,
view: {
...EdgelessRootBlockSpec.view,
widgets: {
...EdgelessRootBlockSpec.view.widgets,
[AFFINE_EDGELESS_COPILOT_WIDGET]: literal`${unsafeStatic(
AFFINE_EDGELESS_COPILOT_WIDGET
)}`,
[AFFINE_AI_PANEL_WIDGET]: literal`${unsafeStatic(
AFFINE_AI_PANEL_WIDGET
)}`,
},
},
setup(slots, disposableGroup) {
EdgelessRootBlockSpec.setup?.(slots, disposableGroup);
slots.widgetConnected.on(view => {
if (view.component instanceof AffineAIPanelWidget) { if (view.component instanceof AffineAIPanelWidget) {
view.component.style.width = '430px'; view.component.style.width = '430px';
view.component.config = buildAIPanelConfig(view.component); view.component.config = buildAIPanelConfig(view.component);
@@ -102,55 +104,93 @@ export const AIEdgelessRootBlockSpec: BlockSpec = {
setupSlashMenuEntry(view.component); setupSlashMenuEntry(view.component);
} }
}); });
}, }
}; }
export const AIParagraphBlockSpec: BlockSpec = { export const AIEdgelessRootBlockSpec: ExtensionType[] = [
...ParagraphBlockSpec, ...EdgelessRootBlockSpec,
setup(slots, disposableGroup) { AIEdgelessRootWatcher,
ParagraphBlockSpec.setup?.(slots, disposableGroup); {
slots.mounted.on(({ service }) => { setup: di => {
assertInstanceOf(service, ParagraphBlockService); di.override(WidgetViewMapIdentifier('affine:page'), () => {
service.placeholderGenerator = model => { return {
if (model.type === 'text') { ...edgelessRootWigetViewMap,
return "Type '/' for commands, 'space' for AI"; [AFFINE_EDGELESS_COPILOT_WIDGET]: literal`${unsafeStatic(
} AFFINE_EDGELESS_COPILOT_WIDGET
)}`,
const placeholders = { [AFFINE_AI_PANEL_WIDGET]: literal`${unsafeStatic(
h1: 'Heading 1', AFFINE_AI_PANEL_WIDGET
h2: 'Heading 2', )}`,
h3: 'Heading 3',
h4: 'Heading 4',
h5: 'Heading 5',
h6: 'Heading 6',
quote: '',
}; };
return placeholders[model.type]; });
}; },
});
}, },
}; ];
export const AICodeBlockSpec: BlockSpec = { class AIParagraphBlockWatcher extends BlockServiceWatcher {
...CodeBlockSpec, static override readonly flavour = 'affine:paragraph';
setup(slots, disposableGroup) {
CodeBlockSpec.setup?.(slots, disposableGroup); override mounted() {
slots.widgetConnected.on(view => { super.mounted();
const service = this.blockService;
assertInstanceOf(service, ParagraphBlockService);
service.placeholderGenerator = model => {
if (model.type === 'text') {
return "Type '/' for commands, 'space' for AI";
}
const placeholders = {
h1: 'Heading 1',
h2: 'Heading 2',
h3: 'Heading 3',
h4: 'Heading 4',
h5: 'Heading 5',
h6: 'Heading 6',
quote: '',
};
return placeholders[model.type];
};
}
}
export const AIParagraphBlockSpec: ExtensionType[] = [
...ParagraphBlockSpec,
AIParagraphBlockWatcher,
];
class AICodeBlockWatcher extends BlockServiceWatcher {
static override readonly flavour = 'affine:code';
override mounted() {
super.mounted();
const service = this.blockService;
service.specSlots.widgetConnected.on(view => {
if (view.component instanceof AffineCodeToolbarWidget) { if (view.component instanceof AffineCodeToolbarWidget) {
setupCodeToolbarEntry(view.component); setupCodeToolbarEntry(view.component);
} }
}); });
}, }
}; }
export const AIImageBlockSpec: BlockSpec = { export const AICodeBlockSpec: ExtensionType[] = [
...ImageBlockSpec, ...CodeBlockSpec,
setup(slots, disposableGroup) { AICodeBlockWatcher,
ImageBlockSpec.setup?.(slots, disposableGroup); ];
slots.widgetConnected.on(view => {
class AIImageBlockWatcher extends BlockServiceWatcher {
static override readonly flavour = 'affine:image';
override mounted() {
super.mounted();
this.blockService.specSlots.widgetConnected.on(view => {
if (view.component instanceof AffineImageToolbarWidget) { if (view.component instanceof AffineImageToolbarWidget) {
setupImageToolbarEntry(view.component); setupImageToolbarEntry(view.component);
} }
}); });
}, }
}; }
export const AIImageBlockSpec: ExtensionType[] = [
...ImageBlockSpec,
AIImageBlockWatcher,
];

View File

@@ -17,6 +17,7 @@ import type { BaseSelection, EditorHost } from '@blocksuite/block-std';
import { ShadowlessElement, WithDisposable } from '@blocksuite/block-std'; import { ShadowlessElement, WithDisposable } from '@blocksuite/block-std';
import { import {
type AIError, type AIError,
DocModeProvider,
isInsidePageEditor, isInsidePageEditor,
PaymentRequiredError, PaymentRequiredError,
UnauthorizedError, UnauthorizedError,
@@ -161,7 +162,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
this._selectionValue = this.host.selection.value; this._selectionValue = this.host.selection.value;
}) })
); );
const { docModeService } = this.host.spec.getService('affine:page'); const docModeService = this.host.std.get(DocModeProvider);
disposables.add(docModeService.onModeChange(() => this.requestUpdate())); disposables.add(docModeService.onModeChange(() => this.requestUpdate()));
} }
} }

View File

@@ -160,7 +160,7 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) {
private readonly _cleanupHistories = async () => { private readonly _cleanupHistories = async () => {
const notification = const notification =
this.host.std.spec.getService('affine:page').notificationService; this.host.std.getService('affine:page').notificationService;
if (!notification) return; if (!notification) return;
if ( if (

View File

@@ -1,9 +1,6 @@
import '../../_common/components/ask-ai-button'; import '../../_common/components/ask-ai-button';
import type { import type { AffineCodeToolbarWidget } from '@blocksuite/blocks';
AffineCodeToolbarWidget,
CodeBlockComponent,
} from '@blocksuite/blocks';
import { html } from 'lit'; import { html } from 'lit';
const AICodeItemGroups = buildAICodeItemGroups(); const AICodeItemGroups = buildAICodeItemGroups();
@@ -14,42 +11,34 @@ const buttonOptions: AskAIButtonOptions = {
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button'; import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
import { buildAICodeItemGroups } from '../../_common/config'; import { buildAICodeItemGroups } from '../../_common/config';
import { AIStarIcon } from '../../_common/icons';
export function setupCodeToolbarEntry(codeToolbar: AffineCodeToolbarWidget) { export function setupCodeToolbarEntry(codeToolbar: AffineCodeToolbarWidget) {
const onAskAIClick = () => { codeToolbar.addPrimaryItems([
const { host } = codeToolbar; {
const { selection } = host; type: 'ask-ai',
const codeBlock = codeToolbar.block; when: ({ doc }) => !doc.readonly,
selection.setGroup('note', [ generate: ({ host, blockComponent }) => {
selection.create('block', { blockId: codeBlock.blockId }), return {
]); action: () => {
}; const { selection } = host;
codeToolbar.setupDefaultConfig(); selection.setGroup('note', [
codeToolbar.addItems( selection.create('block', { blockId: blockComponent.blockId }),
[ ]);
{ },
type: 'custom', render: item =>
name: 'Ask AI', html`<ask-ai-button
tooltip: 'Ask AI', class="code-toolbar-button ask-ai"
icon: AIStarIcon, .host=${host}
showWhen: CodeBlockComponent => !CodeBlockComponent.doc.readonly, .actionGroups=${AICodeItemGroups}
render(codeBlock: CodeBlockComponent, onClick?: () => void) { .toggleType=${'click'}
return html`<ask-ai-button .options=${buttonOptions}
class="code-toolbar-button ask-ai" @click=${(e: MouseEvent) => {
.host=${codeBlock.host} e.stopPropagation();
.actionGroups=${AICodeItemGroups} item.action();
.toggleType=${'click'} }}
.options=${buttonOptions} ></ask-ai-button>`,
@click=${(e: MouseEvent) => { };
e.stopPropagation();
onAskAIClick();
onClick?.();
}}
></ask-ai-button>`;
},
}, },
], },
0 ]);
);
} }

View File

@@ -1,5 +1,6 @@
import type { import type {
AIItemGroupConfig, AIItemGroupConfig,
DocMode,
EdgelessCopilotWidget, EdgelessCopilotWidget,
EdgelessElementToolbarWidget, EdgelessElementToolbarWidget,
EdgelessRootBlockComponent, EdgelessRootBlockComponent,
@@ -27,7 +28,7 @@ export function setupEdgelessElementToolbarEntry(
const chain = edgeless.service.std.command.chain(); const chain = edgeless.service.std.command.chain();
const filteredGroups = edgelessActionGroups.reduce((pre, group) => { const filteredGroups = edgelessActionGroups.reduce((pre, group) => {
const filtered = group.items.filter(item => const filtered = group.items.filter(item =>
item.showWhen?.(chain, 'edgeless', edgeless.host) item.showWhen?.(chain, 'edgeless' as DocMode, edgeless.host)
); );
if (filtered.length > 0) pre.push({ ...group, items: filtered }); if (filtered.length > 0) pre.push({ ...group, items: filtered });

View File

@@ -1,9 +1,6 @@
import '../../_common/components/ask-ai-button'; import '../../_common/components/ask-ai-button';
import type { import type { AffineImageToolbarWidget } from '@blocksuite/blocks';
AffineImageToolbarWidget,
ImageBlockComponent,
} from '@blocksuite/blocks';
import { html } from 'lit'; import { html } from 'lit';
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button'; import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
@@ -17,34 +14,33 @@ const buttonOptions: AskAIButtonOptions = {
}; };
export function setupImageToolbarEntry(imageToolbar: AffineImageToolbarWidget) { export function setupImageToolbarEntry(imageToolbar: AffineImageToolbarWidget) {
const onAskAIClick = () => { imageToolbar.addPrimaryItems(
const { host } = imageToolbar;
const { selection } = host;
const imageBlock = imageToolbar.block;
selection.setGroup('note', [
selection.create('image', { blockId: imageBlock.blockId }),
]);
};
imageToolbar.buildDefaultConfig();
imageToolbar.addConfigItems(
[ [
{ {
type: 'custom', type: 'ask-ai',
render(imageBlock: ImageBlockComponent, onClick?: () => void) { when: ({ doc }) => !doc.readonly,
return html`<ask-ai-button generate: ({ host, blockComponent }) => {
class="image-toolbar-button ask-ai" return {
.host=${imageBlock.host} action: () => {
.actionGroups=${AIImageItemGroups} const { selection } = host;
.toggleType=${'click'} selection.setGroup('note', [
.options=${buttonOptions} selection.create('image', { blockId: blockComponent.blockId }),
@click=${(e: MouseEvent) => { ]);
e.stopPropagation(); },
onAskAIClick(); render: item =>
onClick?.(); html`<ask-ai-button
}} class="image-toolbar-button ask-ai"
></ask-ai-button>`; .host=${host}
.actionGroups=${AIImageItemGroups}
.toggleType=${'click'}
.options=${buttonOptions}
@click=${(e: MouseEvent) => {
e.stopPropagation();
item.action();
}}
></ask-ai-button>`,
};
}, },
showWhen: imageBlockComponent => !imageBlockComponent.doc.readonly,
}, },
], ],
0 0

View File

@@ -1,10 +1,11 @@
import type { import {
AffineAIPanelWidget, type AffineAIPanelWidget,
AffineSlashMenuActionItem, type AffineSlashMenuActionItem,
AffineSlashMenuContext, type AffineSlashMenuContext,
AffineSlashMenuItem, type AffineSlashMenuItem,
AffineSlashSubMenu, type AffineSlashSubMenu,
AIItemConfig, type AIItemConfig,
DocModeProvider,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { import {
AFFINE_AI_PANEL_WIDGET, AFFINE_AI_PANEL_WIDGET,
@@ -38,9 +39,8 @@ export function setupSlashMenuEntry(slashMenu: AffineSlashMenuWidget) {
if (affineAIPanelWidget === null) return false; if (affineAIPanelWidget === null) return false;
const chain = rootComponent.host.command.chain(); const chain = rootComponent.host.command.chain();
const editorMode = rootComponent.service.docModeService.getMode( const docModeService = rootComponent.std.get(DocModeProvider);
rootComponent.doc.id const editorMode = docModeService.getMode(rootComponent.doc.id);
);
return item?.showWhen?.(chain, editorMode, rootComponent.host) ?? true; return item?.showWhen?.(chain, editorMode, rootComponent.host) ?? true;
}; };

View File

@@ -1,4 +1,4 @@
import type { EditorHost } from '@blocksuite/block-std'; import { BlockStdScope, type EditorHost } from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/block-std'; import { WithDisposable } from '@blocksuite/block-std';
import { import {
type AffineAIPanelWidgetConfig, type AffineAIPanelWidgetConfig,
@@ -207,7 +207,10 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
class="edgeless-container affine-edgeless-viewport" class="edgeless-container affine-edgeless-viewport"
${ref(this._editorContainer)} ${ref(this._editorContainer)}
> >
${this.host.renderSpecPortal(this._doc, EdgelessEditorBlockSpecs)} ${new BlockStdScope({
doc: this._doc,
extensions: EdgelessEditorBlockSpecs,
}).render()}
</div> </div>
<div class="mask"></div> <div class="mask"></div>
</div>`; </div>`;

View File

@@ -1,7 +1,11 @@
import { type EditorHost, WithDisposable } from '@blocksuite/block-std'; import {
import type { BlockStdScope,
AffineAIPanelState, type EditorHost,
AffineAIPanelWidgetConfig, WithDisposable,
} from '@blocksuite/block-std';
import {
type AffineAIPanelState,
type AffineAIPanelWidgetConfig,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { import {
CodeBlockComponent, CodeBlockComponent,
@@ -271,7 +275,10 @@ export class AIAnswerText extends WithDisposable(LitElement) {
${keyed( ${keyed(
this._doc, this._doc,
html`<div class="ai-answer-text-editor affine-page-viewport"> html`<div class="ai-answer-text-editor affine-page-viewport">
${this.host.renderSpecPortal(this._doc, CustomPageEditorBlockSpecs)} ${new BlockStdScope({
doc: this._doc,
extensions: CustomPageEditorBlockSpecs,
}).render()}
</div>` </div>`
)} )}
</div> </div>

View File

@@ -8,6 +8,7 @@ import {
type AIError, type AIError,
CanvasElementType, CanvasElementType,
ConnectorMode, ConnectorMode,
DocModeProvider,
type EdgelessRootService, type EdgelessRootService,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { import {
@@ -37,11 +38,11 @@ export class AIChatBlockPeekView extends LitElement {
static override styles = PeekViewStyles; static override styles = PeekViewStyles;
private get _rootService() { private get _rootService() {
return this.host.spec.getService('affine:page'); return this.host.std.getService('affine:page');
} }
private get _modeService() { private get _modeService() {
return this._rootService.docModeService; return this.host.std.get(DocModeProvider);
} }
private get parentSessionId() { private get parentSessionId() {

View File

@@ -12,7 +12,7 @@ import {
} from './template'; } from './template';
export const PPTBuilder = (host: EditorHost) => { export const PPTBuilder = (host: EditorHost) => {
const service = host.spec.getService<EdgelessRootService>('affine:page'); const service = host.std.getService<EdgelessRootService>('affine:page');
const docs: PPTDoc[] = []; const docs: PPTDoc[] = [];
const contents: unknown[] = []; const contents: unknown[] = [];
const allImages: TemplateImage[][] = []; const allImages: TemplateImage[][] = [];

View File

@@ -1,3 +1,10 @@
import {
BlockFlavourIdentifier,
BlockServiceIdentifier,
BlockViewIdentifier,
type ExtensionType,
StdIdentifier,
} from '@blocksuite/block-std';
import { PageEditorBlockSpecs, PageRootService } from '@blocksuite/blocks'; import { PageEditorBlockSpecs, PageRootService } from '@blocksuite/blocks';
import { literal } from 'lit/static-html.js'; import { literal } from 'lit/static-html.js';
@@ -8,15 +15,19 @@ class CustomPageRootService extends PageRootService {
override loadFonts() {} override loadFonts() {}
} }
export const CustomPageEditorBlockSpecs = PageEditorBlockSpecs.map(spec => { export const CustomPageEditorBlockSpecs: ExtensionType[] = [
if (spec.schema.model.flavour === 'affine:page') { ...PageEditorBlockSpecs,
return { {
...spec, setup: di => {
service: CustomPageRootService, di.override(
view: { BlockServiceIdentifier('affine:page'),
component: literal`affine-page-root`, CustomPageRootService,
}, [StdIdentifier, BlockFlavourIdentifier('affine:page')]
}; );
} di.override(
return spec; BlockViewIdentifier('affine:page'),
}); () => literal`affine-page-root`
);
},
},
];

View File

@@ -40,7 +40,7 @@ export function isMindmapChild(ele: BlockSuite.EdgelessModel) {
} }
export function getService(host: EditorHost) { export function getService(host: EditorHost) {
const edgelessService = host.spec.getService( const edgelessService = host.std.getService(
'affine:page' 'affine:page'
) as EdgelessRootService; ) as EdgelessRootService;

View File

@@ -18,7 +18,7 @@ import { getEdgelessCopilotWidget, getService } from './edgeless';
import { getContentFromSlice } from './markdown-utils'; import { getContentFromSlice } from './markdown-utils';
export const getRootService = (host: EditorHost) => { export const getRootService = (host: EditorHost) => {
return host.std.spec.getService('affine:page'); return host.std.getService('affine:page');
}; };
export function getEdgelessRootFromEditor(editor: EditorHost) { export function getEdgelessRootFromEditor(editor: EditorHost) {
@@ -30,7 +30,7 @@ export function getEdgelessRootFromEditor(editor: EditorHost) {
return edgelessRoot; return edgelessRoot;
} }
export function getEdgelessService(editor: EditorHost) { export function getEdgelessService(editor: EditorHost) {
const rootService = editor.std.spec.getService('affine:page'); const rootService = editor.std.getService('affine:page');
if (rootService instanceof EdgelessRootService) { if (rootService instanceof EdgelessRootService) {
return rootService; return rootService;
} }

View File

@@ -2,7 +2,7 @@ import { DebugLogger } from '@affine/debug';
import { DEFAULT_WORKSPACE_NAME } from '@affine/env/constant'; import { DEFAULT_WORKSPACE_NAME } from '@affine/env/constant';
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import onboardingUrl from '@affine/templates/onboarding.zip'; import onboardingUrl from '@affine/templates/onboarding.zip';
import { ZipTransformer } from '@blocksuite/blocks'; import { DocMode, ZipTransformer } from '@blocksuite/blocks';
import type { WorkspacesService } from '@toeverything/infra'; import type { WorkspacesService } from '@toeverything/infra';
import { DocsService, initEmptyPage } from '@toeverything/infra'; import { DocsService, initEmptyPage } from '@toeverything/infra';
@@ -31,7 +31,7 @@ export async function buildShowcaseWorkspace(
); );
if (defaultDoc) { if (defaultDoc) {
defaultDoc.setPrimaryMode('edgeless'); defaultDoc.setPrimaryMode(DocMode.Edgeless);
} }
dispose(); dispose();

View File

@@ -1,4 +1,5 @@
import type { useI18n } from '@affine/i18n'; import type { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { ImportIcon, PlusIcon } from '@blocksuite/icons/rc'; import { ImportIcon, PlusIcon } from '@blocksuite/icons/rc';
import type { usePageHelper } from '../components/blocksuite/block-suite-page-list/utils'; import type { usePageHelper } from '../components/blocksuite/block-suite-page-list/utils';
@@ -31,7 +32,7 @@ export function registerAffineCreationCommands({
run() { run() {
track.$.cmdk.creation.createDoc({ mode: 'page' }); track.$.cmdk.creation.createDoc({ mode: 'page' });
pageHelper.createPage('page'); pageHelper.createPage('page' as DocMode);
}, },
}) })
); );

View File

@@ -9,16 +9,12 @@ import { EditorService } from '@affine/core/modules/editor';
import { WorkspacePermissionService } from '@affine/core/modules/permissions'; import { WorkspacePermissionService } from '@affine/core/modules/permissions';
import { WorkspaceQuotaService } from '@affine/core/modules/quota'; import { WorkspaceQuotaService } from '@affine/core/modules/quota';
import { i18nTime, Trans, useI18n } from '@affine/i18n'; import { i18nTime, Trans, useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons/rc'; import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons/rc';
import type { Doc as BlockSuiteDoc, DocCollection } from '@blocksuite/store'; import type { Doc as BlockSuiteDoc, DocCollection } from '@blocksuite/store';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import type { DialogContentProps } from '@radix-ui/react-dialog'; import type { DialogContentProps } from '@radix-ui/react-dialog';
import { import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
type DocMode,
useLiveData,
useService,
WorkspaceService,
} from '@toeverything/infra';
import { atom, useAtom, useSetAtom } from 'jotai'; import { atom, useAtom, useSetAtom } from 'jotai';
import type { PropsWithChildren } from 'react'; import type { PropsWithChildren } from 'react';
import { import {

View File

@@ -6,23 +6,27 @@ import {
} from '@affine/core/modules/peek-view'; } from '@affine/core/modules/peek-view';
import { WorkbenchLink } from '@affine/core/modules/workbench'; import { WorkbenchLink } from '@affine/core/modules/workbench';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { BlockStdScope } from '@blocksuite/block-std';
import { DocMode } from '@blocksuite/blocks';
import { import {
BlockLinkIcon,
DeleteIcon, DeleteIcon,
LinkedEdgelessIcon, LinkedEdgelessIcon,
LinkedPageIcon, LinkedPageIcon,
TodayIcon, TodayIcon,
} from '@blocksuite/icons/rc'; } from '@blocksuite/icons/rc';
import type { DocCollection } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { useService } from '@toeverything/infra';
import { import {
type DocMode, type PropsWithChildren,
DocsService, useCallback,
LiveData, useEffect,
useLiveData, useRef,
useService, useState,
} from '@toeverything/infra'; } from 'react';
import { type PropsWithChildren, useCallback, useRef } from 'react';
import * as styles from './styles.css'; import * as styles from './styles.css';
import { scrollAnchoring } from './utils';
export interface PageReferenceRendererOptions { export interface PageReferenceRendererOptions {
docMode: DocMode | null; docMode: DocMode | null;
@@ -31,6 +35,9 @@ export interface PageReferenceRendererOptions {
pageMetaHelper: ReturnType<typeof useDocMetaHelper>; pageMetaHelper: ReturnType<typeof useDocMetaHelper>;
journalHelper: ReturnType<typeof useJournalHelper>; journalHelper: ReturnType<typeof useJournalHelper>;
t: ReturnType<typeof useI18n>; t: ReturnType<typeof useI18n>;
// linking doc with block or element
blockIds?: string[];
elementIds?: string[];
} }
// use a function to be rendered in the lit renderer // use a function to be rendered in the lit renderer
export function pageReferenceRenderer({ export function pageReferenceRenderer({
@@ -39,30 +46,37 @@ export function pageReferenceRenderer({
pageMetaHelper, pageMetaHelper,
journalHelper, journalHelper,
t, t,
blockIds,
elementIds,
}: PageReferenceRendererOptions) { }: PageReferenceRendererOptions) {
const { isPageJournal, getLocalizedJournalDateString } = journalHelper; const { isPageJournal, getLocalizedJournalDateString } = journalHelper;
const referencedPage = pageMetaHelper.getDocMeta(pageId); const referencedPage = pageMetaHelper.getDocMeta(pageId);
let title = let title =
referencedPage?.title ?? t['com.affine.editor.reference-not-found'](); referencedPage?.title ?? t['com.affine.editor.reference-not-found']();
let icon = !referencedPage ? ( let Icon = DeleteIcon;
<DeleteIcon className={styles.pageReferenceIcon} />
) : docMode === 'page' || docMode === null ? ( if (referencedPage) {
<LinkedPageIcon className={styles.pageReferenceIcon} /> if (docMode === DocMode.Edgeless) {
) : ( Icon = LinkedEdgelessIcon;
<LinkedEdgelessIcon className={styles.pageReferenceIcon} /> } else {
); Icon = LinkedPageIcon;
}
if (blockIds?.length || elementIds?.length) {
Icon = BlockLinkIcon;
}
}
const isJournal = isPageJournal(pageId); const isJournal = isPageJournal(pageId);
const localizedJournalDate = getLocalizedJournalDateString(pageId); const localizedJournalDate = getLocalizedJournalDateString(pageId);
if (isJournal && localizedJournalDate) { if (isJournal && localizedJournalDate) {
title = localizedJournalDate; title = localizedJournalDate;
icon = <TodayIcon className={styles.pageReferenceIcon} />; Icon = TodayIcon;
} }
return ( return (
<> <>
{icon} <Icon className={styles.pageReferenceIcon} />
<span className="affine-reference-title"> <span className="affine-reference-title">
{title ? title : t['Untitled']()} {title ? title : t['Untitled']()}
</span> </span>
@@ -74,32 +88,42 @@ export function AffinePageReference({
pageId, pageId,
docCollection, docCollection,
wrapper: Wrapper, wrapper: Wrapper,
mode = DocMode.Page,
params = {},
isSameDoc = false,
std,
}: { }: {
docCollection: DocCollection; docCollection: DocCollection;
pageId: string; pageId: string;
wrapper?: React.ComponentType<PropsWithChildren>; wrapper?: React.ComponentType<PropsWithChildren>;
mode?: DocMode;
params?: {
mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
};
isSameDoc?: boolean;
std?: BlockStdScope;
}) { }) {
const pageMetaHelper = useDocMetaHelper(docCollection); const pageMetaHelper = useDocMetaHelper(docCollection);
const journalHelper = useJournalHelper(docCollection); const journalHelper = useJournalHelper(docCollection);
const t = useI18n(); const t = useI18n();
const [anchor, setAnchor] = useState<{
mode: DocMode;
id: string;
} | null>(null);
const { mode: linkedWithMode, blockIds, elementIds } = params;
const docsService = useService(DocsService);
const docPrimaryMode = useLiveData(
LiveData.computed(get => {
const primaryMode$ = get(docsService.list.doc$(pageId))?.primaryMode$;
if (!primaryMode$) {
return null;
}
return get(primaryMode$);
})
);
const el = pageReferenceRenderer({ const el = pageReferenceRenderer({
docMode: docPrimaryMode, docMode: linkedWithMode ?? mode,
pageId, pageId,
pageMetaHelper, pageMetaHelper,
journalHelper, journalHelper,
docCollection, docCollection,
t, t,
blockIds,
elementIds,
}); });
const ref = useRef<HTMLAnchorElement>(null); const ref = useRef<HTMLAnchorElement>(null);
@@ -107,6 +131,18 @@ export function AffinePageReference({
const peekView = useService(PeekViewService).peekView; const peekView = useService(PeekViewService).peekView;
const isInPeekView = useInsidePeekView(); const isInPeekView = useInsidePeekView();
useEffect(() => {
if (isSameDoc) {
if (mode === DocMode.Edgeless && elementIds?.length) {
setAnchor({ mode, id: elementIds[0] });
} else if (blockIds?.length) {
setAnchor({ mode, id: blockIds[0] });
}
} else {
setAnchor(null);
}
}, [std, isSameDoc, mode, blockIds, elementIds]);
const onClick = useCallback( const onClick = useCallback(
(e: React.MouseEvent) => { (e: React.MouseEvent) => {
if (e.shiftKey && ref.current) { if (e.shiftKey && ref.current) {
@@ -114,18 +150,39 @@ export function AffinePageReference({
e.stopPropagation(); e.stopPropagation();
peekView.open(ref.current).catch(console.error); peekView.open(ref.current).catch(console.error);
} }
if (isInPeekView) {
if (std && anchor) {
e.preventDefault();
e.stopPropagation();
const { mode, id } = anchor;
scrollAnchoring(std, mode, id);
} else if (isInPeekView) {
peekView.close(); peekView.close();
} }
return; return;
}, },
[isInPeekView, peekView] [isInPeekView, peekView, anchor, std]
); );
// A block/element reference link
const search = new URLSearchParams();
if (linkedWithMode) {
search.set('mode', linkedWithMode);
}
if (blockIds?.length) {
search.set('blockIds', blockIds.join(','));
}
if (elementIds?.length) {
search.set('elementIds', elementIds.join(','));
}
const query = search.size > 0 ? `?${search.toString()}` : '';
return ( return (
<WorkbenchLink <WorkbenchLink
ref={ref} ref={ref}
to={`/${pageId}`} to={`/${pageId}${query}`}
onClick={onClick} onClick={onClick}
className={styles.pageReferenceLink} className={styles.pageReferenceLink}
> >

View File

@@ -0,0 +1,108 @@
import type { BlockStdScope } from '@blocksuite/block-std';
import {
DocMode,
type EdgelessRootService,
type PageRootService,
} from '@blocksuite/blocks';
import { Bound, deserializeXYWH } from '@blocksuite/global/utils';
function scrollAnchoringInEdgelessMode(
service: EdgelessRootService,
id: string
) {
requestAnimationFrame(() => {
let isNotInNote = true;
let bounds: Bound | null = null;
const blockComponent = service.std.view.getBlock(id);
const parentComponent = blockComponent?.parentComponent;
if (parentComponent && parentComponent.flavour === 'affine:note') {
isNotInNote = false;
const selection = parentComponent.std.selection;
if (!selection) return;
selection.set([
selection.create('block', {
blockId: id,
}),
]);
const { left: x, width: w } = parentComponent.getBoundingClientRect();
const { top: y, height: h } = blockComponent.getBoundingClientRect();
const coord = service.viewport.toModelCoordFromClientCoord([x, y]);
bounds = new Bound(
coord[0],
coord[1],
w / service.viewport.zoom,
h / service.viewport.zoom
);
} else {
const model = service.getElementById(id);
if (!model) return;
bounds = Bound.fromXYWH(deserializeXYWH(model.xywh));
}
if (!bounds) return;
if (isNotInNote) {
service.selection.set({
elements: [id],
editing: false,
});
}
const { zoom, centerX, centerY } = service.getFitToScreenData(
[20, 20, 20, 20],
[bounds]
);
service.viewport.setViewport(zoom, [centerX, centerY]);
// const surfaceComponent = service.std.view.getBlock(service.surface.id);
// if (!surfaceComponent) return;
// (surfaceComponent as SurfaceBlockComponent).refresh();
// TODO(@fundon): toolbar should be hidden
});
}
function scrollAnchoringInPageMode(service: PageRootService, id: string) {
const blockComponent = service.std.view.getBlock(id);
if (!blockComponent || !blockComponent.path.length) return;
blockComponent.scrollIntoView({
behavior: 'instant',
block: 'center',
});
const selection = service.std.selection;
if (!selection) return;
selection.set([
selection.create('block', {
blockId: id,
}),
]);
// TODO(@fundon): toolbar should be hidden
}
// TODO(@fundon): it should be a command
export function scrollAnchoring(std: BlockStdScope, mode: DocMode, id: string) {
if (mode === DocMode.Edgeless) {
const service = std.getService<EdgelessRootService>('affine:page');
if (!service) return;
scrollAnchoringInEdgelessMode(service, id);
return;
}
const service = std.getService<PageRootService>('affine:page');
if (!service) return;
scrollAnchoringInPageMode(service, id);
}

View File

@@ -23,8 +23,9 @@ import {
SystemFontFamilyService, SystemFontFamilyService,
} from '@affine/core/modules/system-font-family'; } from '@affine/core/modules/system-font-family';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { DoneIcon, SearchIcon } from '@blocksuite/icons/rc'; import { DoneIcon, SearchIcon } from '@blocksuite/icons/rc';
import { type DocMode, useLiveData, useServices } from '@toeverything/infra'; import { useLiveData, useServices } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import { import {
type ChangeEvent, type ChangeEvent,

View File

@@ -12,6 +12,7 @@ import { ShareInfoService } from '@affine/core/modules/share-doc';
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { PublicPageMode } from '@affine/graphql'; import { PublicPageMode } from '@affine/graphql';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { import {
BlockIcon, BlockIcon,
CollaborationIcon, CollaborationIcon,
@@ -158,10 +159,10 @@ export const AFFiNESharePage = (props: ShareMenuProps) => {
}); });
const onCopyPageLink = useCallback(() => { const onCopyPageLink = useCallback(() => {
onClickCopyLink('page'); onClickCopyLink('page' as DocMode);
}, [onClickCopyLink]); }, [onClickCopyLink]);
const onCopyEdgelessLink = useCallback(() => { const onCopyEdgelessLink = useCallback(() => {
onClickCopyLink('edgeless'); onClickCopyLink('edgeless' as DocMode);
}, [onClickCopyLink]); }, [onClickCopyLink]);
const onCopyBlockLink = useCallback(() => { const onCopyBlockLink = useCallback(() => {
// TODO(@JimmFly): handle frame // TODO(@JimmFly): handle frame

View File

@@ -1,15 +1,13 @@
import type { BlockComponent } from '@blocksuite/block-std'; import type { ReferenceInfo } from '@blocksuite/affine-model';
import { DocMode } from '@blocksuite/blocks';
import type { import type {
AffineEditorContainer, AffineEditorContainer,
EdgelessEditor, EdgelessEditor,
PageEditor, PageEditor,
} from '@blocksuite/presets'; } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store'; import { type Doc, Slot } from '@blocksuite/store';
import { Slot } from '@blocksuite/store';
import { type DocMode } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import type React from 'react'; import type React from 'react';
import type { RefObject } from 'react';
import { import {
forwardRef, forwardRef,
useEffect, useEffect,
@@ -19,6 +17,7 @@ import {
useState, useState,
} from 'react'; } from 'react';
import { scrollAnchoring } from '../../affine/reference-link/utils';
import { BlocksuiteDocEditor, BlocksuiteEdgelessEditor } from './lit-adaper'; import { BlocksuiteDocEditor, BlocksuiteEdgelessEditor } from './lit-adaper';
import * as styles from './styles.css'; import * as styles from './styles.css';
@@ -43,7 +42,8 @@ interface BlocksuiteEditorContainerProps {
shared?: boolean; shared?: boolean;
className?: string; className?: string;
style?: React.CSSProperties; style?: React.CSSProperties;
defaultSelectedBlockId?: string; blockIds?: string[];
elementIds?: string[];
} }
// mimic the interface of the webcomponent and expose slots & host // mimic the interface of the webcomponent and expose slots & host
@@ -53,68 +53,36 @@ type BlocksuiteEditorContainerRef = Pick<
> & > &
HTMLDivElement; HTMLDivElement;
function findBlockElementById(container: HTMLElement, blockId: string) {
const element = container.querySelector(
`[data-block-id="${blockId}"]`
) as BlockComponent | null;
return element;
}
// a workaround for returning the webcomponent for the given block id
// by iterating over the children of the rendered dom tree
const useBlockElementById = (
containerRef: RefObject<HTMLElement | null>,
blockId: string | undefined,
timeout = 1000
) => {
const [blockElement, setBlockElement] = useState<BlockComponent | null>(null);
useEffect(() => {
if (!blockId) {
return;
}
let canceled = false;
const start = Date.now();
function run() {
if (canceled || !containerRef.current || !blockId) {
return;
}
const element = findBlockElementById(containerRef.current, blockId);
if (element) {
setBlockElement(element);
} else if (Date.now() - start < timeout) {
setTimeout(run, 100);
}
}
run();
return () => {
canceled = true;
};
}, [blockId, containerRef, timeout]);
return blockElement;
};
export const BlocksuiteEditorContainer = forwardRef< export const BlocksuiteEditorContainer = forwardRef<
AffineEditorContainer, AffineEditorContainer,
BlocksuiteEditorContainerProps BlocksuiteEditorContainerProps
>(function AffineEditorContainer( >(function AffineEditorContainer(
{ page, mode, className, style, defaultSelectedBlockId, shared }, { page, mode, className, style, shared, blockIds, elementIds },
ref ref
) { ) {
const scrolledRef = useRef(false); const scrolledRef = useRef(false);
const hashChangedRef = useRef(false);
const rootRef = useRef<HTMLDivElement>(null); const rootRef = useRef<HTMLDivElement>(null);
const docRef = useRef<PageEditor>(null); const docRef = useRef<PageEditor>(null);
const edgelessRef = useRef<EdgelessEditor>(null); const edgelessRef = useRef<EdgelessEditor>(null);
const [anchor, setAnchor] = useState<string | null>(null);
const slots: BlocksuiteEditorContainerRef['slots'] = useMemo(() => { const slots: BlocksuiteEditorContainerRef['slots'] = useMemo(() => {
return { return {
docLinkClicked: new Slot(), docLinkClicked: new Slot<ReferenceInfo>(),
editorModeSwitched: new Slot(), editorModeSwitched: new Slot(),
docUpdated: new Slot(), docUpdated: new Slot(),
tagClicked: new Slot(), tagClicked: new Slot(),
}; };
}, []); }, []);
useEffect(() => {
if (mode === DocMode.Edgeless && elementIds?.length) {
setAnchor(elementIds[0]);
} else if (blockIds?.length) {
setAnchor(blockIds[0]);
}
}, [blockIds, elementIds, mode]);
// forward the slot to the webcomponent // forward the slot to the webcomponent
useLayoutEffect(() => { useLayoutEffect(() => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
@@ -209,36 +177,22 @@ export const BlocksuiteEditorContainer = forwardRef<
} }
}, [affineEditorContainerProxy, ref]); }, [affineEditorContainerProxy, ref]);
const blockElement = useBlockElementById(rootRef, defaultSelectedBlockId); // `scrolledRef` should be updated if blockElement is changed
useEffect(() => {
scrolledRef.current = false;
}, [anchor]);
useEffect(() => { useEffect(() => {
if (!anchor) return;
let canceled = false; let canceled = false;
const handleScrollToBlock = (blockElement: BlockComponent) => {
if (!mode || !blockElement) {
return;
}
blockElement.scrollIntoView({
behavior: 'instant',
block: 'center',
});
const selectManager = affineEditorContainerProxy.host?.selection;
if (!blockElement.path.length || !selectManager) {
return;
}
const newSelection = selectManager.create('block', {
blockId: blockElement.blockId,
});
selectManager.set([newSelection]);
};
affineEditorContainerProxy.updateComplete affineEditorContainerProxy.updateComplete
.then(() => { .then(() => {
if ( if (!scrolledRef.current && !canceled) {
blockElement && const std = affineEditorContainerProxy.host?.std;
!scrolledRef.current && if (std) {
!canceled && scrollAnchoring(std, mode, anchor);
!hashChangedRef.current }
) {
handleScrollToBlock(blockElement);
scrolledRef.current = true; scrolledRef.current = true;
} }
}) })
@@ -246,7 +200,7 @@ export const BlocksuiteEditorContainer = forwardRef<
return () => { return () => {
canceled = true; canceled = true;
}; };
}, [blockElement, affineEditorContainerProxy, mode]); }, [anchor, affineEditorContainerProxy, mode]);
return ( return (
<div <div

View File

@@ -1,4 +1,5 @@
import { EditorLoading } from '@affine/component/page-detail-skeleton'; import { EditorLoading } from '@affine/component/page-detail-skeleton';
import type { DocMode } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
@@ -22,13 +23,14 @@ export type ErrorBoundaryProps = {
export type EditorProps = { export type EditorProps = {
page: Doc; page: Doc;
mode: 'page' | 'edgeless'; mode: DocMode;
shared?: boolean; shared?: boolean;
defaultSelectedBlockId?: string;
// on Editor instance instantiated // on Editor instance instantiated
onLoadEditor?: (editor: AffineEditorContainer) => () => void; onLoadEditor?: (editor: AffineEditorContainer) => () => void;
style?: CSSProperties; style?: CSSProperties;
className?: string; className?: string;
blockIds?: string[];
elementIds?: string[];
}; };
function usePageRoot(page: Doc) { function usePageRoot(page: Doc) {
@@ -59,10 +61,11 @@ const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>(
mode, mode,
page, page,
className, className,
defaultSelectedBlockId,
onLoadEditor, onLoadEditor,
shared, shared,
style, style,
blockIds,
elementIds,
}, },
ref ref
) { ) {
@@ -113,7 +116,8 @@ const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>(
ref={onRefChange} ref={onRefChange}
className={className} className={className}
style={style} style={style}
defaultSelectedBlockId={defaultSelectedBlockId} blockIds={blockIds}
elementIds={elementIds}
/> />
); );
} }

View File

@@ -7,7 +7,7 @@ import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import { EditorSettingService } from '@affine/core/modules/editor-settting'; import { EditorSettingService } from '@affine/core/modules/editor-settting';
import { PeekViewService } from '@affine/core/modules/peek-view'; import { PeekViewService } from '@affine/core/modules/peek-view';
import { WorkbenchService } from '@affine/core/modules/workbench'; import { WorkbenchService } from '@affine/core/modules/workbench';
import type { DocMode } from '@blocksuite/blocks'; import { DocMode } from '@blocksuite/blocks';
import { DocTitle, EdgelessEditor, PageEditor } from '@blocksuite/presets'; import { DocTitle, EdgelessEditor, PageEditor } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import { import {
@@ -73,13 +73,26 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
const framework = useFramework(); const framework = useFramework();
const referenceRenderer: ReferenceReactRenderer = useMemo(() => { const referenceRenderer: ReferenceReactRenderer = useMemo(() => {
return function customReference(reference) { return function customReference(reference) {
const pageId = reference.delta.attributes?.reference?.pageId; const data = reference.delta.attributes?.reference;
if (!data) return <span />;
const pageId = data.pageId;
if (!pageId) return <span />; if (!pageId) return <span />;
const isSameDoc = pageId === page.id;
return ( return (
<AffinePageReference docCollection={page.collection} pageId={pageId} /> <AffinePageReference
docCollection={page.collection}
pageId={pageId}
mode={mode}
params={data.params}
std={reference.std}
isSameDoc={isSameDoc}
/>
); );
}; };
}, [page.collection]); }, [mode, page.collection, page.id]);
const specs = useMemo(() => { const specs = useMemo(() => {
return mode === 'edgeless' return mode === 'edgeless'
@@ -89,20 +102,19 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
const confirmModal = useConfirmModal(); const confirmModal = useConfirmModal();
const patchedSpecs = useMemo(() => { const patchedSpecs = useMemo(() => {
let patched = patchReferenceRenderer(specs, reactToLit, referenceRenderer); let patched = specs.concat(
patched = patchNotificationService( patchReferenceRenderer(reactToLit, referenceRenderer)
patchReferenceRenderer(patched, reactToLit, referenceRenderer),
confirmModal
); );
patched = patchPeekViewService(patched, peekViewService); patched = patched.concat(patchNotificationService(confirmModal));
patched = patchEdgelessClipboard(patched); patched = patched.concat(patchPeekViewService(peekViewService));
patched = patched.concat(patchEdgelessClipboard());
if (!page.readonly) { if (!page.readonly) {
patched = patchQuickSearchService(patched, framework); patched = patched.concat(patchQuickSearchService(framework));
} }
if (shared) { if (shared) {
patched = patchForSharedPage(patched); patched = patched.concat(patchForSharedPage());
} }
patched = patchDocModeService(patched, docService, docsService); patched = patched.concat(patchDocModeService(docService, docsService));
return patched; return patched;
}, [ }, [
confirmModal, confirmModal,
@@ -179,7 +191,7 @@ export const BlocksuiteDocEditor = forwardRef<
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const [specs, portals] = usePatchSpecs(page, !!shared, 'page'); const [specs, portals] = usePatchSpecs(page, !!shared, DocMode.Page);
const settings = useLiveData(editorSettingService.editorSetting.settings$); const settings = useLiveData(editorSettingService.editorSetting.settings$);
@@ -219,7 +231,7 @@ export const BlocksuiteEdgelessEditor = forwardRef<
EdgelessEditor, EdgelessEditor,
BlocksuiteEditorProps BlocksuiteEditorProps
>(function BlocksuiteEdgelessEditor({ page, shared }, ref) { >(function BlocksuiteEdgelessEditor({ page, shared }, ref) {
const [specs, portals] = usePatchSpecs(page, !!shared, 'edgeless'); const [specs, portals] = usePatchSpecs(page, !!shared, DocMode.Edgeless);
const editorRef = useRef<EdgelessEditor | null>(null); const editorRef = useRef<EdgelessEditor | null>(null);
const onDocRef = useCallback( const onDocRef = useCallback(

View File

@@ -3,7 +3,7 @@ import {
AIImageBlockSpec, AIImageBlockSpec,
AIParagraphBlockSpec, AIParagraphBlockSpec,
} from '@affine/core/blocksuite/presets/ai'; } from '@affine/core/blocksuite/presets/ai';
import type { BlockSpec } from '@blocksuite/block-std'; import type { ExtensionType } from '@blocksuite/block-std';
import { import {
BookmarkBlockSpec, BookmarkBlockSpec,
DatabaseBlockSpec, DatabaseBlockSpec,
@@ -17,15 +17,12 @@ import {
EmbedSyncedDocBlockSpec, EmbedSyncedDocBlockSpec,
EmbedYoutubeBlockSpec, EmbedYoutubeBlockSpec,
ListBlockSpec, ListBlockSpec,
NoteBlockSpec,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { AIChatBlockSpec, EdgelessAIChatBlockSpec } from '@blocksuite/presets';
import { CustomAttachmentBlockSpec } from './custom/attachment-block'; import { CustomAttachmentBlockSpec } from './custom/attachment-block';
export const CommonBlockSpecs: BlockSpec[] = [ export const CommonBlockSpecs: ExtensionType[] = [
ListBlockSpec, ListBlockSpec,
NoteBlockSpec,
DatabaseBlockSpec, DatabaseBlockSpec,
DataViewBlockSpec, DataViewBlockSpec,
DividerBlockSpec, DividerBlockSpec,
@@ -42,6 +39,4 @@ export const CommonBlockSpecs: BlockSpec[] = [
AICodeBlockSpec, AICodeBlockSpec,
AIImageBlockSpec, AIImageBlockSpec,
AIParagraphBlockSpec, AIParagraphBlockSpec,
AIChatBlockSpec, ].flat();
EdgelessAIChatBlockSpec,
];

View File

@@ -1,4 +1,9 @@
import type { BlockSpec } from '@blocksuite/block-std'; import {
BlockFlavourIdentifier,
BlockServiceIdentifier,
type ExtensionType,
StdIdentifier,
} from '@blocksuite/block-std';
import { import {
AttachmentBlockService, AttachmentBlockService,
AttachmentBlockSpec, AttachmentBlockSpec,
@@ -14,7 +19,15 @@ class CustomAttachmentBlockService extends AttachmentBlockService {
} }
} }
export const CustomAttachmentBlockSpec: BlockSpec = { export const CustomAttachmentBlockSpec: ExtensionType[] = [
...AttachmentBlockSpec, ...AttachmentBlockSpec,
service: CustomAttachmentBlockService, {
}; setup: di => {
di.override(
BlockServiceIdentifier('affine:attachment'),
CustomAttachmentBlockService,
[StdIdentifier, BlockFlavourIdentifier('affine:attachment')]
);
},
},
];

View File

@@ -3,12 +3,14 @@ import {
AIPageRootBlockSpec, AIPageRootBlockSpec,
} from '@affine/core/blocksuite/presets/ai'; } from '@affine/core/blocksuite/presets/ai';
import { mixpanel } from '@affine/core/mixpanel'; import { mixpanel } from '@affine/core/mixpanel';
import type { import {
EdgelessRootBlockSpecType, BlockFlavourIdentifier,
PageRootBlockSpecType, BlockServiceIdentifier,
RootService, ConfigExtension,
TelemetryEventMap, type ExtensionType,
} from '@blocksuite/blocks'; StdIdentifier,
} from '@blocksuite/block-std';
import type { RootService, TelemetryEventMap } from '@blocksuite/blocks';
import { import {
AffineCanvasTextFonts, AffineCanvasTextFonts,
EdgelessRootService, EdgelessRootService,
@@ -31,6 +33,7 @@ function customLoadFonts(service: RootService): void {
} }
} }
// TODO: make load fonts and telemetry service as BS extension
function withAffineRootService(Service: typeof PageRootService) { function withAffineRootService(Service: typeof PageRootService) {
return class extends Service { return class extends Service {
override loadFonts(): void { override loadFonts(): void {
@@ -50,24 +53,40 @@ function withAffineRootService(Service: typeof PageRootService) {
export function createPageRootBlockSpec( export function createPageRootBlockSpec(
framework: FrameworkProvider framework: FrameworkProvider
): PageRootBlockSpecType { ): ExtensionType[] {
return { return [
...AIPageRootBlockSpec, ...AIPageRootBlockSpec,
service: withAffineRootService(PageRootService), {
config: { setup: di => {
linkedWidget: createLinkedWidgetConfig(framework), di.override(
BlockServiceIdentifier('affine:page'),
withAffineRootService(PageRootService),
[StdIdentifier, BlockFlavourIdentifier('affine:page')]
);
},
}, },
}; ConfigExtension('affine:page', {
linkedWidget: createLinkedWidgetConfig(framework),
}),
];
} }
export function createEdgelessRootBlockSpec( export function createEdgelessRootBlockSpec(
framework: FrameworkProvider framework: FrameworkProvider
): EdgelessRootBlockSpecType { ): ExtensionType[] {
return { return [
...AIEdgelessRootBlockSpec, ...AIEdgelessRootBlockSpec,
service: withAffineRootService(EdgelessRootService as never), {
config: { setup: di => {
linkedWidget: createLinkedWidgetConfig(framework), di.override(
BlockServiceIdentifier('affine:page'),
withAffineRootService(EdgelessRootService as never),
[StdIdentifier, BlockFlavourIdentifier('affine:page')]
);
},
}, },
}; ConfigExtension('affine:page', {
linkedWidget: createLinkedWidgetConfig(framework),
}),
];
} }

View File

@@ -20,20 +20,31 @@ import {
RecentDocsQuickSearchSession, RecentDocsQuickSearchSession,
} from '@affine/core/modules/quicksearch'; } from '@affine/core/modules/quicksearch';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import type { BlockSpec, WidgetComponent } from '@blocksuite/block-std';
import { import {
type AffineReference, type BlockService,
BlockViewIdentifier,
type ExtensionType,
type WidgetComponent,
} from '@blocksuite/block-std';
import { BlockServiceWatcher } from '@blocksuite/block-std';
import type {
AffineReference,
DatabaseBlockService,
ListBlockService,
ParagraphBlockService,
RootService,
} from '@blocksuite/blocks';
import {
AffineSlashMenuWidget, AffineSlashMenuWidget,
DocMode,
DocModeProvider,
EdgelessRootBlockComponent, EdgelessRootBlockComponent,
EmbedLinkedDocBlockComponent, EmbedLinkedDocBlockComponent,
type ParagraphBlockService,
type RootService,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { LinkIcon } from '@blocksuite/icons/rc'; import { LinkIcon } from '@blocksuite/icons/rc';
import { AIChatBlockSchema } from '@blocksuite/presets'; import { AIChatBlockSchema } from '@blocksuite/presets';
import type { BlockSnapshot } from '@blocksuite/store'; import type { BlockSnapshot } from '@blocksuite/store';
import { import {
type DocMode,
type DocService, type DocService,
DocsService, DocsService,
type FrameworkProvider, type FrameworkProvider,
@@ -48,84 +59,62 @@ export type ReferenceReactRenderer = (
const logger = new DebugLogger('affine::spec-patchers'); const logger = new DebugLogger('affine::spec-patchers');
function patchSpecService<Spec extends BlockSpec>( function patchSpecService<Service extends BlockService = BlockService>(
spec: Spec, flavour: string,
onMounted: ( onMounted: (service: Service) => (() => void) | void,
service: Spec extends BlockSpec<any, infer BlockService>
? BlockService
: never
) => (() => void) | void,
onWidgetConnected?: (component: WidgetComponent) => void onWidgetConnected?: (component: WidgetComponent) => void
) { ) {
const oldSetup = spec.setup; class TempServiceWatcher extends BlockServiceWatcher {
spec.setup = (slots, disposableGroup) => { static override readonly flavour = flavour;
oldSetup?.(slots, disposableGroup); override mounted() {
disposableGroup.add( super.mounted();
slots.mounted.on(({ service }) => { const disposable = onMounted(this.blockService as any);
const disposable = onMounted(service as any); const disposableGroup = this.blockService.disposables;
if (disposable) { if (disposable) {
disposableGroup.add(disposable); disposableGroup.add(disposable);
} }
})
);
onWidgetConnected && if (onWidgetConnected) {
disposableGroup.add( disposableGroup.add(
slots.widgetConnected.on(({ component }) => { this.blockService.specSlots.widgetConnected.on(({ component }) => {
onWidgetConnected(component); onWidgetConnected(component);
}) })
); );
}; }
return spec; }
}
return TempServiceWatcher;
} }
/** /**
* Patch the block specs with custom renderers. * Patch the block specs with custom renderers.
*/ */
export function patchReferenceRenderer( export function patchReferenceRenderer(
specs: BlockSpec[],
reactToLit: (element: ElementOrFactory) => TemplateResult, reactToLit: (element: ElementOrFactory) => TemplateResult,
reactRenderer: ReferenceReactRenderer reactRenderer: ReferenceReactRenderer
) { ): ExtensionType[] {
const litRenderer = (reference: AffineReference) => { const litRenderer = (reference: AffineReference) => {
const node = reactRenderer(reference); const node = reactRenderer(reference);
return reactToLit(node); return reactToLit(node);
}; };
return specs.map(spec => { return ['affine:paragraph', 'affine:list', 'affine:database'].map(flavour => {
if ( return patchSpecService<
['affine:paragraph', 'affine:list', 'affine:database'].includes( ParagraphBlockService | ListBlockService | DatabaseBlockService
spec.schema.model.flavour >(flavour, service => {
) service.referenceNodeConfig.setCustomContent(litRenderer);
) { return () => {
spec = patchSpecService( service.referenceNodeConfig.setCustomContent(null);
spec as BlockSpec<string, ParagraphBlockService>, };
service => { });
service.referenceNodeConfig.setCustomContent(litRenderer);
return () => {
service.referenceNodeConfig.setCustomContent(null);
};
}
);
}
return spec;
}); });
} }
export function patchNotificationService( export function patchNotificationService({
specs: BlockSpec[], closeConfirmModal,
{ closeConfirmModal, openConfirmModal }: ReturnType<typeof useConfirmModal> openConfirmModal,
) { }: ReturnType<typeof useConfirmModal>) {
const rootSpec = specs.find( return patchSpecService<RootService>('affine:page', service => {
spec => spec.schema.model.flavour === 'affine:page'
) as BlockSpec<string, RootService>;
if (!rootSpec) {
return specs;
}
patchSpecService(rootSpec, service => {
service.notificationService = { service.notificationService = {
confirm: async ({ title, message, confirmText, cancelText, abort }) => { confirm: async ({ title, message, confirmText, cancelText, abort }) => {
return new Promise<boolean>(resolve => { return new Promise<boolean>(resolve => {
@@ -234,22 +223,10 @@ export function patchNotificationService(
}, },
}; };
}); });
return specs;
} }
export function patchPeekViewService( export function patchPeekViewService(service: PeekViewService) {
specs: BlockSpec[], return patchSpecService<RootService>('affine:page', pageService => {
service: PeekViewService
) {
const rootSpec = specs.find(
spec => spec.schema.model.flavour === 'affine:page'
) as BlockSpec<string, RootService>;
if (!rootSpec) {
return specs;
}
patchSpecService(rootSpec, pageService => {
pageService.peekViewService = { pageService.peekViewService = {
peek: (target: ActivePeekView['target'], template?: TemplateResult) => { peek: (target: ActivePeekView['target'], template?: TemplateResult) => {
logger.debug('center peek', target, template); logger.debug('center peek', target, template);
@@ -257,75 +234,55 @@ export function patchPeekViewService(
}, },
}; };
}); });
return specs;
} }
export function patchDocModeService( export function patchDocModeService(
specs: BlockSpec[],
docService: DocService, docService: DocService,
docsService: DocsService docsService: DocsService
) { ): ExtensionType {
const rootSpec = specs.find( const DEFAULT_MODE = 'page';
spec => spec.schema.model.flavour === 'affine:page' class AffineDocModeService implements DocModeProvider {
) as BlockSpec<string, RootService>; setMode = (mode: DocMode, id?: string) => {
if (id) {
if (!rootSpec) { docsService.list.setPrimaryMode(id, mode);
return specs; } else {
docService.doc.setPrimaryMode(mode);
}
};
getMode = (id?: string) => {
const mode = id
? docsService.list.getPrimaryMode(id)
: docService.doc.getPrimaryMode();
return (mode || DEFAULT_MODE) as DocMode;
};
toggleMode = (id?: string) => {
const mode = id
? docsService.list.togglePrimaryMode(id)
: docService.doc.togglePrimaryMode();
return (mode || DEFAULT_MODE) as DocMode;
};
onModeChange = (handler: (mode: DocMode) => void, id?: string) => {
// eslint-disable-next-line rxjs/finnish
const mode$ = id
? docsService.list.primaryMode$(id)
: docService.doc.primaryMode$;
const sub = mode$.subscribe(m => handler((m || DEFAULT_MODE) as DocMode));
return {
dispose: sub.unsubscribe,
};
};
} }
patchSpecService(rootSpec, pageService => { const docModeExtension: ExtensionType = {
const DEFAULT_MODE = 'page'; setup: di => [di.override(DocModeProvider, AffineDocModeService)],
pageService.docModeService = { };
setMode: (mode: DocMode, id?: string) => {
if (id) {
docsService.list.setPrimaryMode(id, mode);
} else {
docService.doc.setPrimaryMode(mode);
}
},
getMode: (id?: string) => {
const mode = id
? docsService.list.getPrimaryMode(id)
: docService.doc.getPrimaryMode();
return mode || DEFAULT_MODE;
},
toggleMode: (id?: string) => {
const mode = id
? docsService.list.togglePrimaryMode(id)
: docService.doc.togglePrimaryMode();
return mode || DEFAULT_MODE;
},
onModeChange: (handler: (mode: DocMode) => void, id?: string) => {
// eslint-disable-next-line rxjs/finnish
const mode$ = id
? docsService.list.primaryMode$(id)
: docService.doc.primaryMode$;
const sub = mode$.subscribe(m => handler(m || DEFAULT_MODE));
return {
dispose: sub.unsubscribe,
};
},
};
});
return specs; return docModeExtension;
} }
export function patchQuickSearchService( export function patchQuickSearchService(framework: FrameworkProvider) {
specs: BlockSpec[], return patchSpecService<RootService>(
framework: FrameworkProvider 'affine:page',
) {
const rootSpec = specs.find(
spec => spec.schema.model.flavour === 'affine:page'
) as BlockSpec<string, RootService>;
if (!rootSpec) {
return specs;
}
patchSpecService(
rootSpec,
pageService => { pageService => {
pageService.quickSearchService = { pageService.quickSearchService = {
async searchDoc(options) { async searchDoc(options) {
@@ -409,8 +366,8 @@ export function patchQuickSearchService(
const docsService = framework.get(DocsService); const docsService = framework.get(DocsService);
const mode = const mode =
result.id === 'creation:create-edgeless' result.id === 'creation:create-edgeless'
? 'edgeless' ? DocMode.Edgeless
: 'page'; : DocMode.Page;
const newDoc = docsService.createDoc({ const newDoc = docsService.createDoc({
primaryMode: mode, primaryMode: mode,
title: result.payload.title, title: result.payload.title,
@@ -490,63 +447,56 @@ export function patchQuickSearchService(
} }
} }
); );
return specs;
} }
export function patchEdgelessClipboard(specs: BlockSpec[]) { export function patchEdgelessClipboard() {
const rootSpec = specs.find( class EdgelessClipboardWatcher extends BlockServiceWatcher {
spec => spec.schema.model.flavour === 'affine:page' static override readonly flavour = 'affine:page';
) as BlockSpec<string, RootService>;
if (!rootSpec) { override mounted() {
return specs; super.mounted();
} this.blockService.disposables.add(
this.blockService.specSlots.viewConnected.on(view => {
const oldSetup = rootSpec.setup; const { component } = view;
rootSpec.setup = (slots, disposableGroup) => { if (component instanceof EdgelessRootBlockComponent) {
oldSetup?.(slots, disposableGroup); const AIChatBlockFlavour = AIChatBlockSchema.model.flavour;
disposableGroup.add( const createFunc = (blocks: BlockSnapshot[]) => {
slots.viewConnected.on(view => { const blockIds = blocks.map(({ props }) => {
const component = view.component; const {
if (component instanceof EdgelessRootBlockComponent) {
const AIChatBlockFlavour = AIChatBlockSchema.model.flavour;
const createFunc = (blocks: BlockSnapshot[]) => {
const blockIds = blocks.map(({ props }) => {
const {
xywh,
scale,
messages,
sessionId,
rootDocId,
rootWorkspaceId,
} = props;
const blockId = component.service.addBlock(
AIChatBlockFlavour,
{
xywh, xywh,
scale, scale,
messages, messages,
sessionId, sessionId,
rootDocId, rootDocId,
rootWorkspaceId, rootWorkspaceId,
}, } = props;
component.surface.model.id const blockId = component.service.addBlock(
); AIChatBlockFlavour,
return blockId; {
}); xywh,
return blockIds; scale,
}; messages,
component.clipboardController.registerBlock( sessionId,
AIChatBlockFlavour, rootDocId,
createFunc rootWorkspaceId,
); },
} component.surface.model.id
}) );
); return blockId;
}; });
return blockIds;
};
component.clipboardController.registerBlock(
AIChatBlockFlavour,
createFunc
);
}
})
);
}
}
return specs; return EdgelessClipboardWatcher;
} }
@customElement('affine-linked-doc-ref-block') @customElement('affine-linked-doc-ref-block')
@@ -557,22 +507,18 @@ export class LinkedDocBlockComponent extends EmbedLinkedDocBlockComponent {
} }
} }
export function patchForSharedPage(specs: BlockSpec[]) { export function patchForSharedPage() {
return specs.map(spec => { const extension: ExtensionType = {
const linkedDocNames = [ setup: di => {
'affine:embed-linked-doc', di.override(
'affine:embed-synced-doc', BlockViewIdentifier('affine:embed-linked-doc'),
]; () => literal`affine-linked-doc-ref-block`
);
if (linkedDocNames.includes(spec.schema.model.flavour)) { di.override(
spec = { BlockViewIdentifier('affine:embed-synced-doc'),
...spec, () => literal`affine-linked-doc-ref-block`
view: { );
component: literal`affine-linked-doc-ref-block`, },
widgets: {}, };
}, return extension;
};
}
return spec;
});
} }

View File

@@ -1,4 +1,4 @@
import type { BlockSpec } from '@blocksuite/block-std'; import type { ExtensionType } from '@blocksuite/block-std';
import { import {
EdgelessNoteBlockSpec, EdgelessNoteBlockSpec,
EdgelessSurfaceBlockSpec, EdgelessSurfaceBlockSpec,
@@ -6,6 +6,7 @@ import {
EdgelessTextBlockSpec, EdgelessTextBlockSpec,
FrameBlockSpec, FrameBlockSpec,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { EdgelessAIChatBlockSpec } from '@blocksuite/presets';
import type { FrameworkProvider } from '@toeverything/infra'; import type { FrameworkProvider } from '@toeverything/infra';
import { CommonBlockSpecs } from './common'; import { CommonBlockSpecs } from './common';
@@ -13,7 +14,7 @@ import { createEdgelessRootBlockSpec } from './custom/root-block';
export function createEdgelessModeSpecs( export function createEdgelessModeSpecs(
framework: FrameworkProvider framework: FrameworkProvider
): BlockSpec[] { ): ExtensionType[] {
return [ return [
...CommonBlockSpecs, ...CommonBlockSpecs,
EdgelessSurfaceBlockSpec, EdgelessSurfaceBlockSpec,
@@ -21,7 +22,8 @@ export function createEdgelessModeSpecs(
FrameBlockSpec, FrameBlockSpec,
EdgelessTextBlockSpec, EdgelessTextBlockSpec,
EdgelessNoteBlockSpec, EdgelessNoteBlockSpec,
EdgelessAIChatBlockSpec,
// special // special
createEdgelessRootBlockSpec(framework), createEdgelessRootBlockSpec(framework),
]; ].flat();
} }

View File

@@ -1,19 +1,25 @@
import type { BlockSpec } from '@blocksuite/block-std'; import type { ExtensionType } from '@blocksuite/block-std';
import { import {
NoteBlockSpec,
PageSurfaceBlockSpec, PageSurfaceBlockSpec,
PageSurfaceRefBlockSpec, PageSurfaceRefBlockSpec,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { AIChatBlockSpec } from '@blocksuite/presets';
import { type FrameworkProvider } from '@toeverything/infra'; import { type FrameworkProvider } from '@toeverything/infra';
import { CommonBlockSpecs } from './common'; import { CommonBlockSpecs } from './common';
import { createPageRootBlockSpec } from './custom/root-block'; import { createPageRootBlockSpec } from './custom/root-block';
export function createPageModeSpecs(framework: FrameworkProvider): BlockSpec[] { export function createPageModeSpecs(
framework: FrameworkProvider
): ExtensionType[] {
return [ return [
...CommonBlockSpecs, ...CommonBlockSpecs,
PageSurfaceBlockSpec, PageSurfaceBlockSpec,
PageSurfaceRefBlockSpec, PageSurfaceRefBlockSpec,
NoteBlockSpec,
AIChatBlockSpec,
// special // special
createPageRootBlockSpec(framework), createPageRootBlockSpec(framework),
]; ].flat();
} }

View File

@@ -1,10 +1,10 @@
import type { BlockSpec } from '@blocksuite/block-std'; import type { ExtensionType } from '@blocksuite/block-std';
import { SpecProvider } from '@blocksuite/blocks'; import { SpecProvider } from '@blocksuite/blocks';
import { AIChatBlockSpec, EdgelessAIChatBlockSpec } from '@blocksuite/presets'; import { EdgelessAIChatBlockSpec } from '@blocksuite/presets';
const CustomSpecs: BlockSpec[] = [AIChatBlockSpec, EdgelessAIChatBlockSpec]; const CustomSpecs: ExtensionType[] = [EdgelessAIChatBlockSpec].flat();
function patchPreviewSpec(id: string, specs: BlockSpec[]) { function patchPreviewSpec(id: string, specs: ExtensionType[]) {
const specProvider = SpecProvider.getInstance(); const specProvider = SpecProvider.getInstance();
specProvider.extendSpec(id, specs); specProvider.extendSpec(id, specs);
} }

View File

@@ -14,7 +14,7 @@ export const usePresent = () => {
// TODO(@catsjuice): use surfaceService subAtom // TODO(@catsjuice): use surfaceService subAtom
const enterOrLeavePresentationMode = () => { const enterOrLeavePresentationMode = () => {
const edgelessRootService = editorHost.spec.getService( const edgelessRootService = editorHost.std.getService(
'affine:page' 'affine:page'
) as EdgelessRootService; ) as EdgelessRootService;

View File

@@ -3,8 +3,9 @@ import { registerAffineCommand } from '@affine/core/commands';
import { track } from '@affine/core/mixpanel'; import { track } from '@affine/core/mixpanel';
import { EditorService } from '@affine/core/modules/editor'; import { EditorService } from '@affine/core/modules/editor';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { DocMode } from '@blocksuite/blocks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc';
import { type DocMode, useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useService } from '@toeverything/infra';
import { useCallback, useEffect, useMemo } from 'react'; import { useCallback, useEffect, useMemo } from 'react';
import { switchItem } from './style.css'; import { switchItem } from './style.css';
@@ -38,16 +39,16 @@ export const EditorModeSwitch = () => {
const togglePage = useCallback(() => { const togglePage = useCallback(() => {
if (currentMode === 'page' || isSharedMode || trash) return; if (currentMode === 'page' || isSharedMode || trash) return;
editor.setMode('page'); editor.setMode(DocMode.Page);
editor.doc.setPrimaryMode('page'); editor.doc.setPrimaryMode(DocMode.Page);
toast(t['com.affine.toastMessage.pageMode']()); toast(t['com.affine.toastMessage.pageMode']());
track.$.header.actions.switchPageMode({ mode: 'page' }); track.$.header.actions.switchPageMode({ mode: 'page' });
}, [currentMode, editor, isSharedMode, t, trash]); }, [currentMode, editor, isSharedMode, t, trash]);
const toggleEdgeless = useCallback(() => { const toggleEdgeless = useCallback(() => {
if (currentMode === 'edgeless' || isSharedMode || trash) return; if (currentMode === 'edgeless' || isSharedMode || trash) return;
editor.setMode('edgeless'); editor.setMode(DocMode.Edgeless);
editor.doc.setPrimaryMode('edgeless'); editor.doc.setPrimaryMode(DocMode.Edgeless);
toast(t['com.affine.toastMessage.edgelessMode']()); toast(t['com.affine.toastMessage.edgelessMode']());
track.$.header.actions.switchPageMode({ mode: 'edgeless' }); track.$.header.actions.switchPageMode({ mode: 'edgeless' });
}, [currentMode, editor, isSharedMode, t, trash]); }, [currentMode, editor, isSharedMode, t, trash]);
@@ -78,7 +79,10 @@ export const EditorModeSwitch = () => {
binding: 'Alt+KeyS', binding: 'Alt+KeyS',
capture: true, capture: true,
}, },
run: () => onModeChange(currentMode === 'edgeless' ? 'page' : 'edgeless'), run: () =>
onModeChange(
currentMode === 'edgeless' ? DocMode.Page : DocMode.Edgeless
),
}); });
}, [currentMode, isSharedMode, onModeChange, t, trash]); }, [currentMode, isSharedMode, onModeChange, t, trash]);
@@ -93,8 +97,8 @@ export const EditorModeSwitch = () => {
<PureEditorModeSwitch <PureEditorModeSwitch
mode={currentMode} mode={currentMode}
setMode={onModeChange} setMode={onModeChange}
hidePage={shouldHide('page')} hidePage={shouldHide(DocMode.Page)}
hideEdgeless={shouldHide('edgeless')} hideEdgeless={shouldHide(DocMode.Edgeless)}
/> />
</div> </div>
</Tooltip> </Tooltip>

View File

@@ -2,8 +2,8 @@ import { toast } from '@affine/component';
import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper'; import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
import { EditorSettingService } from '@affine/core/modules/editor-settting'; import { EditorSettingService } from '@affine/core/modules/editor-settting';
import { WorkbenchService } from '@affine/core/modules/workbench'; import { WorkbenchService } from '@affine/core/modules/workbench';
import type { DocMode } from '@blocksuite/blocks';
import { import {
type DocMode,
DocsService, DocsService,
initEmptyPage, initEmptyPage,
useLiveData, useLiveData,
@@ -29,7 +29,7 @@ export const usePageHelper = (docCollection: DocCollection) => {
const page = createDoc(); const page = createDoc();
initEmptyPage(page); initEmptyPage(page);
const primaryMode = mode || settings.newDocDefaultMode; const primaryMode = mode || settings.newDocDefaultMode;
docRecordList.doc$(page.id).value?.setPrimaryMode(primaryMode); docRecordList.doc$(page.id).value?.setPrimaryMode(primaryMode as DocMode);
if (open !== false) if (open !== false)
workbench.openDoc(page.id, { workbench.openDoc(page.id, {
at: open === 'new-tab' ? 'new-tab' : 'active', at: open === 'new-tab' ? 'new-tab' : 'active',
@@ -41,7 +41,7 @@ export const usePageHelper = (docCollection: DocCollection) => {
const createEdgelessAndOpen = useCallback( const createEdgelessAndOpen = useCallback(
(open?: boolean | 'new-tab') => { (open?: boolean | 'new-tab') => {
return createPageAndOpen('edgeless', open); return createPageAndOpen('edgeless' as DocMode, open);
}, },
[createPageAndOpen] [createPageAndOpen]
); );

View File

@@ -1,5 +1,6 @@
import { AuthService } from '@affine/core/modules/cloud'; import { AuthService } from '@affine/core/modules/cloud';
import { type DocMode, useLiveData, useService } from '@toeverything/infra'; import type { DocMode } from '@blocksuite/blocks';
import { useLiveData, useService } from '@toeverything/infra';
import { PresentButton } from './present'; import { PresentButton } from './present';
import { SignIn } from './sign-in'; import { SignIn } from './sign-in';

View File

@@ -1,15 +1,20 @@
import './page-detail-editor.css'; import './page-detail-editor.css';
import { useDocCollectionPage } from '@affine/core/hooks/use-block-suite-workspace-page'; import { useDocCollectionPage } from '@affine/core/hooks/use-block-suite-workspace-page';
import { ViewService } from '@affine/core/modules/workbench/services/view';
import type { DocMode } from '@blocksuite/blocks';
import { DisposableGroup } from '@blocksuite/global/utils'; import { DisposableGroup } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Doc as BlockSuiteDoc, DocCollection } from '@blocksuite/store'; import type { Doc as BlockSuiteDoc, DocCollection } from '@blocksuite/store';
import { type DocMode, useLiveData, useService } from '@toeverything/infra'; import {
useLiveData,
useService,
useServiceOptional,
} from '@toeverything/infra';
import { cssVar } from '@toeverything/theme'; import { cssVar } from '@toeverything/theme';
import clsx from 'clsx'; import clsx from 'clsx';
import type { CSSProperties } from 'react'; import type { CSSProperties } from 'react';
import { memo, Suspense, useCallback, useMemo } from 'react'; import { memo, Suspense, useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { EditorService } from '../modules/editor'; import { EditorService } from '../modules/editor';
import { import {
@@ -37,14 +42,27 @@ export interface PageDetailEditorProps {
onLoad?: OnLoadEditor; onLoad?: OnLoadEditor;
} }
function useRouterHash() {
return useLocation().hash.substring(1);
}
const PageDetailEditorMain = memo(function PageDetailEditorMain({ const PageDetailEditorMain = memo(function PageDetailEditorMain({
page, page,
onLoad, onLoad,
}: PageDetailEditorProps & { page: BlockSuiteDoc }) { }: PageDetailEditorProps & { page: BlockSuiteDoc }) {
const viewService = useServiceOptional(ViewService);
const params = useLiveData(
viewService?.view.queryString$<{
mode?: string;
blockIds?: string[];
elementIds?: string[];
}>({
// Cannot handle single id situation correctly: `blockIds=xxx`
arrayFormat: 'none',
types: {
mode: 'string',
blockIds: value => (value.length ? value.split(',') : []),
elementIds: value => (value.length ? value.split(',') : []),
},
})
);
const editor = useService(EditorService).editor; const editor = useService(EditorService).editor;
const mode = useLiveData(editor.mode$); const mode = useLiveData(editor.mode$);
@@ -66,8 +84,6 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({
: fontStyle.value; : fontStyle.value;
}, [settings.customFontFamily, settings.fontFamily]); }, [settings.customFontFamily, settings.fontFamily]);
const blockId = useRouterHash();
const onLoadEditor = useCallback( const onLoadEditor = useCallback(
(editor: AffineEditorContainer) => { (editor: AffineEditorContainer) => {
// debug current detail editor // debug current detail editor
@@ -106,7 +122,8 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({
mode={mode} mode={mode}
page={page} page={page}
shared={isSharedMode} shared={isSharedMode}
defaultSelectedBlockId={blockId} blockIds={params?.blockIds}
elementIds={params?.elementIds}
onLoadEditor={onLoadEditor} onLoadEditor={onLoadEditor}
/> />
); );

View File

@@ -13,6 +13,7 @@ import { TagService } from '@affine/core/modules/tag';
import { isNewTabTrigger } from '@affine/core/utils'; import { isNewTabTrigger } from '@affine/core/utils';
import type { Collection } from '@affine/env/filter'; import type { Collection } from '@affine/env/filter';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { import {
ArrowDownSmallIcon, ArrowDownSmallIcon,
SearchIcon, SearchIcon,
@@ -79,7 +80,7 @@ export const PageListHeader = () => {
createEdgeless(isNewTabTrigger(e) ? 'new-tab' : true) createEdgeless(isNewTabTrigger(e) ? 'new-tab' : true)
} }
onCreatePage={e => onCreatePage={e =>
createPage('page', isNewTabTrigger(e) ? 'new-tab' : true) createPage('page' as DocMode, isNewTabTrigger(e) ? 'new-tab' : true)
} }
onCreateDoc={e => onCreateDoc={e =>
createPage(undefined, isNewTabTrigger(e) ? 'new-tab' : true) createPage(undefined, isNewTabTrigger(e) ? 'new-tab' : true)
@@ -144,7 +145,10 @@ export const CollectionPageListHeader = ({
[openConfirmModal, t, createAndAddDocument] [openConfirmModal, t, createAndAddDocument]
); );
const createPageModeDoc = useCallback(() => createPage('page'), [createPage]); const createPageModeDoc = useCallback(
() => createPage('page' as DocMode),
[createPage]
);
const onCreateEdgeless = useCallback( const onCreateEdgeless = useCallback(
() => onConfirmAddDocument(createEdgeless), () => onConfirmAddDocument(createEdgeless),

View File

@@ -13,6 +13,7 @@ import { CMDKQuickSearchService } from '@affine/core/modules/quicksearch/service
import { isNewTabTrigger } from '@affine/core/utils'; import { isNewTabTrigger } from '@affine/core/utils';
import { events } from '@affine/electron-api'; import { events } from '@affine/electron-api';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { import {
AllDocsIcon, AllDocsIcon,
GithubIcon, GithubIcon,
@@ -110,7 +111,7 @@ export const RootAppSidebar = (): ReactElement => {
const onClickNewPage = useAsyncCallback( const onClickNewPage = useAsyncCallback(
async (e?: MouseEvent) => { async (e?: MouseEvent) => {
const page = pageHelper.createPage( const page = pageHelper.createPage(
settings.newDocDefaultMode, settings.newDocDefaultMode as DocMode,
isNewTabTrigger(e) ? 'new-tab' : true isNewTabTrigger(e) ? 'new-tab' : true
); );
page.load(); page.load();

View File

@@ -2,6 +2,7 @@ import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper'; import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
import { CollectionService } from '@affine/core/modules/collection'; import { CollectionService } from '@affine/core/modules/collection';
import type { DocMode } from '@blocksuite/blocks';
import { DocsService, useService } from '@toeverything/infra'; import { DocsService, useService } from '@toeverything/infra';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { applyUpdate, encodeStateAsUpdate } from 'yjs'; import { applyUpdate, encodeStateAsUpdate } from 'yjs';
@@ -102,7 +103,7 @@ export function useBlockSuiteMetaHelper(docCollection: DocCollection) {
pageRecordList pageRecordList
.doc$(newPage.id) .doc$(newPage.id)
.value?.setPrimaryMode(currentPagePrimaryMode || 'page'); .value?.setPrimaryMode(currentPagePrimaryMode || ('page' as DocMode));
setDocTitle(newPage.id, newPageTitle); setDocTitle(newPage.id, newPageTitle);
openPageAfterDuplication && openPage(docCollection.id, newPage.id); openPageAfterDuplication && openPage(docCollection.id, newPage.id);
}, },

View File

@@ -36,7 +36,7 @@ async function exportHandler({
const editorRoot = document.querySelector('editor-host'); const editorRoot = document.querySelector('editor-host');
let pageService: PageRootService | null = null; let pageService: PageRootService | null = null;
if (editorRoot) { if (editorRoot) {
pageService = editorRoot.spec.getService<PageRootService>('affine:page'); pageService = editorRoot.std.getService<PageRootService>('affine:page');
} }
track.$.sharePanel.$.export({ track.$.sharePanel.$.export({
type, type,

View File

@@ -7,8 +7,9 @@ import {
revokePublicPageMutation, revokePublicPageMutation,
} from '@affine/graphql'; } from '@affine/graphql';
import { type I18nKeys, useI18n } from '@affine/i18n'; import { type I18nKeys, useI18n } from '@affine/i18n';
import { DocMode } from '@blocksuite/blocks';
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc'; import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc';
import type { DocMode, Workspace } from '@toeverything/infra'; import { type Workspace } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme'; import { cssVar } from '@toeverything/theme';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
@@ -85,7 +86,9 @@ export function useIsSharedPage(
const isPageShared = !!publicPage; const isPageShared = !!publicPage;
const currentShareMode: DocMode = const currentShareMode: DocMode =
publicPage?.mode === PublicPageMode.Edgeless ? 'edgeless' : 'page'; publicPage?.mode === PublicPageMode.Edgeless
? DocMode.Edgeless
: DocMode.Page;
return [isPageShared, currentShareMode]; return [isPageShared, currentShareMode];
}, [data?.workspace.publicPages, pageId]); }, [data?.workspace.publicPages, pageId]);
@@ -210,7 +213,8 @@ export function usePublicPages(workspace: Workspace) {
() => () =>
maybeData?.workspace.publicPages.map(i => ({ maybeData?.workspace.publicPages.map(i => ({
id: i.id, id: i.id,
mode: i.mode === PublicPageMode.Edgeless ? 'edgeless' : 'page', mode:
i.mode === PublicPageMode.Edgeless ? DocMode.Edgeless : DocMode.Page,
})) ?? [], })) ?? [],
[maybeData?.workspace.publicPages] [maybeData?.workspace.publicPages]
); );

View File

@@ -3,7 +3,7 @@ import { track } from '@affine/core/mixpanel';
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch'; import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { BaseSelection } from '@blocksuite/block-std'; import type { BaseSelection } from '@blocksuite/block-std';
import { type DocMode } from '@toeverything/infra'; import type { DocMode } from '@blocksuite/blocks';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useActiveBlocksuiteEditor } from '../use-block-suite-editor'; import { useActiveBlocksuiteEditor } from '../use-block-suite-editor';
@@ -34,19 +34,18 @@ const generateUrl = ({
try { try {
const url = new URL(`${baseUrl}/workspace/${workspaceId}/${pageId}`); const url = new URL(`${baseUrl}/workspace/${workspaceId}/${pageId}`);
const search = url.searchParams;
if (shareMode) { if (shareMode) {
url.searchParams.append('mode', shareMode); search.append('mode', shareMode);
} }
// TODO(@JimmFly): use query string to handle blockIds
if (blockIds && blockIds.length > 0) { if (blockIds && blockIds.length > 0) {
// hash is used to store blockIds search.append('blockIds', blockIds.join(','));
url.hash = blockIds.join(',');
} }
if (elementIds && elementIds.length > 0) { if (elementIds && elementIds.length > 0) {
url.searchParams.append('element', elementIds.join(',')); search.append('elementIds', elementIds.join(','));
} }
if (xywh) { if (xywh) {
url.searchParams.append('xywh', xywh); search.append('xywh', xywh);
} }
return url.toString(); return url.toString();
} catch { } catch {

View File

@@ -1,4 +1,5 @@
import type { WorkspaceSubPath } from '@affine/core/shared'; import type { WorkspaceSubPath } from '@affine/core/shared';
import type { DocMode } from '@blocksuite/blocks';
import { createContext, useCallback, useContext, useMemo } from 'react'; import { createContext, useCallback, useContext, useMemo } from 'react';
import type { NavigateFunction, NavigateOptions } from 'react-router-dom'; import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
@@ -40,10 +41,17 @@ export function useNavigateHelper() {
( (
workspaceId: string, workspaceId: string,
pageId: string, pageId: string,
blockId: string, mode?: DocMode,
blockIds?: string[],
elementIds?: string[],
logic: RouteLogic = RouteLogic.PUSH logic: RouteLogic = RouteLogic.PUSH
) => { ) => {
return navigate(`/workspace/${workspaceId}/${pageId}#${blockId}`, { const search = new URLSearchParams();
if (mode) search.append('mode', mode);
if (blockIds?.length) search.append('blockIds', blockIds.join(','));
if (elementIds?.length) search.append('elementIds', elementIds.join(','));
const query = search.size > 0 ? `?${search.toString()}` : '';
return navigate(`/workspace/${workspaceId}/${pageId}${query}`, {
replace: logic === RouteLogic.REPLACE, replace: logic === RouteLogic.REPLACE,
}); });
}, },

View File

@@ -4,9 +4,8 @@ import {
resolveGlobalLoadingEventAtom, resolveGlobalLoadingEventAtom,
} from '@affine/component/global-loading'; } from '@affine/component/global-loading';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { ZipTransformer } from '@blocksuite/blocks'; import { type DocMode, ZipTransformer } from '@blocksuite/blocks';
import { import {
type DocMode,
DocsService, DocsService,
effect, effect,
fromPromise, fromPromise,

View File

@@ -1,4 +1,4 @@
import type { DocMode } from '@blocksuite/blocks'; import { DocMode } from '@blocksuite/blocks';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { DocService, WorkspaceService } from '@toeverything/infra'; import type { DocService, WorkspaceService } from '@toeverything/infra';
import { Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
@@ -18,7 +18,9 @@ export class Editor extends Entity<{ defaultMode: DocMode }> {
readonly editorContainer$ = new LiveData<AffineEditorContainer | null>(null); readonly editorContainer$ = new LiveData<AffineEditorContainer | null>(null);
toggleMode() { toggleMode() {
this.mode$.next(this.mode$.value === 'edgeless' ? 'page' : 'edgeless'); this.mode$.next(
this.mode$.value === 'edgeless' ? DocMode.Page : DocMode.Edgeless
);
} }
setMode(mode: DocMode) { setMode(mode: DocMode) {

View File

@@ -25,19 +25,19 @@ afterEach(() => {
const testCases: [string, ReturnType<typeof resolveLinkToDoc>][] = [ const testCases: [string, ReturnType<typeof resolveLinkToDoc>][] = [
['http://example.com/', null], ['http://example.com/', null],
[ [
'/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j#xxxx', '/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j?blockIds=xxxx',
{ {
workspaceId: '48__RTCSwASvWZxyAk3Jw', workspaceId: '48__RTCSwASvWZxyAk3Jw',
docId: '-Uge-K6SYcAbcNYfQ5U-j', docId: '-Uge-K6SYcAbcNYfQ5U-j',
blockId: 'xxxx', blockIds: ['xxxx'],
}, },
], ],
[ [
'http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j#xxxx', 'http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j?blockIds=xxxx',
{ {
workspaceId: '48__RTCSwASvWZxyAk3Jw', workspaceId: '48__RTCSwASvWZxyAk3Jw',
docId: '-Uge-K6SYcAbcNYfQ5U-j', docId: '-Uge-K6SYcAbcNYfQ5U-j',
blockId: 'xxxx', blockIds: ['xxxx'],
}, },
], ],
['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/all', null], ['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/all', null],
@@ -45,19 +45,19 @@ const testCases: [string, ReturnType<typeof resolveLinkToDoc>][] = [
['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/tag', null], ['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/tag', null],
['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/trash', null], ['http://affine.pro/workspace/48__RTCSwASvWZxyAk3Jw/trash', null],
[ [
'file//./workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j#xxxx', 'file//./workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j?blockIds=xxxx',
{ {
workspaceId: '48__RTCSwASvWZxyAk3Jw', workspaceId: '48__RTCSwASvWZxyAk3Jw',
docId: '-Uge-K6SYcAbcNYfQ5U-j', docId: '-Uge-K6SYcAbcNYfQ5U-j',
blockId: 'xxxx', blockIds: ['xxxx'],
}, },
], ],
[ [
'http//localhost:8000/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j#xxxx', 'http//localhost:8000/workspace/48__RTCSwASvWZxyAk3Jw/-Uge-K6SYcAbcNYfQ5U-j?blockIds=xxxx',
{ {
workspaceId: '48__RTCSwASvWZxyAk3Jw', workspaceId: '48__RTCSwASvWZxyAk3Jw',
docId: '-Uge-K6SYcAbcNYfQ5U-j', docId: '-Uge-K6SYcAbcNYfQ5U-j',
blockId: 'xxxx', blockIds: ['xxxx'],
}, },
], ],
]; ];

View File

@@ -1,3 +1,6 @@
import type { DocMode } from '@blocksuite/blocks';
import queryString from 'query-string';
function maybeAffineOrigin(origin: string) { function maybeAffineOrigin(origin: string) {
return ( return (
origin.startsWith('file://') || origin.startsWith('file://') ||
@@ -73,9 +76,23 @@ const isRouteModulePath = (
export const resolveLinkToDoc = (href: string) => { export const resolveLinkToDoc = (href: string) => {
const meta = resolveRouteLinkMeta(href); const meta = resolveRouteLinkMeta(href);
if (!meta || meta.moduleName !== 'doc') return null; if (!meta || meta.moduleName !== 'doc') return null;
const params: {
mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
} = queryString.parse(meta.location.search, {
arrayFormat: 'none',
types: {
mode: value => (value === 'edgeless' ? 'edgeless' : 'page') as DocMode,
blockIds: value => value.split(','),
elementIds: value => value.split(','),
},
});
return { return {
workspaceId: meta.workspaceId, workspaceId: meta.workspaceId,
docId: meta.docId, docId: meta.docId,
blockId: meta.blockId, ...params,
}; };
}; };

View File

@@ -1,6 +1,7 @@
import type { BlockComponent, EditorHost } from '@blocksuite/block-std'; import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
import { import {
AffineReference, AffineReference,
type DocMode,
type EmbedLinkedDocModel, type EmbedLinkedDocModel,
type EmbedSyncedDocModel, type EmbedSyncedDocModel,
type ImageBlockModel, type ImageBlockModel,
@@ -9,7 +10,7 @@ import {
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import type { AIChatBlockModel } from '@blocksuite/presets'; import type { AIChatBlockModel } from '@blocksuite/presets';
import type { BlockModel } from '@blocksuite/store'; import type { BlockModel } from '@blocksuite/store';
import { type DocMode, Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
import type { TemplateResult } from 'lit'; import type { TemplateResult } from 'lit';
import { firstValueFrom, map, race } from 'rxjs'; import { firstValueFrom, map, race } from 'rxjs';
@@ -21,20 +22,21 @@ export type PeekViewTarget =
| BlockComponent | BlockComponent
| AffineReference | AffineReference
| HTMLAnchorElement | HTMLAnchorElement
| { docId: string; blockId?: string }; | { docId: string; blockIds?: string[] };
export interface DocPeekViewInfo { export interface DocPeekViewInfo {
type: 'doc'; type: 'doc';
docId: string; docId: string;
blockId?: string;
mode?: DocMode; mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
xywh?: `[${number},${number},${number},${number}]`; xywh?: `[${number},${number},${number},${number}]`;
} }
export type ImagePeekViewInfo = { export type ImagePeekViewInfo = {
type: 'image'; type: 'image';
docId: string; docId: string;
blockId: string; blockIds: [string];
}; };
export type AIChatBlockPeekViewInfo = { export type AIChatBlockPeekViewInfo = {
@@ -58,15 +60,16 @@ export type ActivePeekView = {
| AIChatBlockPeekViewInfo; | AIChatBlockPeekViewInfo;
}; };
const EMBED_DOC_FLAVOURS = [ const isEmbedLinkedDocModel = (
'affine:embed-linked-doc',
'affine:embed-synced-doc',
];
const isEmbedDocModel = (
blockModel: BlockModel blockModel: BlockModel
): blockModel is EmbedSyncedDocModel | EmbedLinkedDocModel => { ): blockModel is EmbedLinkedDocModel => {
return EMBED_DOC_FLAVOURS.includes(blockModel.flavour); return blockModel.flavour === 'affine:embed-linked-doc';
};
const isEmbedSyncedDocModel = (
blockModel: BlockModel
): blockModel is EmbedSyncedDocModel => {
return blockModel.flavour === 'affine:embed-synced-doc';
}; };
const isImageBlockModel = ( const isImageBlockModel = (
@@ -99,15 +102,26 @@ function resolvePeekInfoFromPeekTarget(
} }
if (peekTarget instanceof AffineReference) { if (peekTarget instanceof AffineReference) {
if (peekTarget.refMeta) { const referenceInfo = peekTarget.referenceInfo;
return { if (referenceInfo) {
const { pageId: docId } = referenceInfo;
const info: DocPeekViewInfo = {
type: 'doc', type: 'doc',
docId: peekTarget.refMeta.id, docId,
}; };
Object.assign(info, referenceInfo.params);
return info;
} }
} else if ('model' in peekTarget) { } else if ('model' in peekTarget) {
const blockModel = peekTarget.model; const blockModel = peekTarget.model;
if (isEmbedDocModel(blockModel)) { if (isEmbedLinkedDocModel(blockModel)) {
const info: DocPeekViewInfo = {
type: 'doc',
docId: blockModel.pageId,
};
Object.assign(info, blockModel.params);
return info;
} else if (isEmbedSyncedDocModel(blockModel)) {
return { return {
type: 'doc', type: 'doc',
docId: blockModel.pageId, docId: blockModel.pageId,
@@ -121,7 +135,7 @@ function resolvePeekInfoFromPeekTarget(
return { return {
type: 'doc', type: 'doc',
docId, docId,
mode: 'edgeless', mode: 'edgeless' as DocMode,
xywh: refModel.xywh, xywh: refModel.xywh,
}; };
} }
@@ -129,7 +143,7 @@ function resolvePeekInfoFromPeekTarget(
return { return {
type: 'image', type: 'image',
docId: blockModel.doc.id, docId: blockModel.doc.id,
blockId: blockModel.id, blockIds: [blockModel.id],
}; };
} else if (isAIChatBlockModel(blockModel)) { } else if (isAIChatBlockModel(blockModel)) {
return { return {
@@ -142,17 +156,28 @@ function resolvePeekInfoFromPeekTarget(
} else if (peekTarget instanceof HTMLAnchorElement) { } else if (peekTarget instanceof HTMLAnchorElement) {
const maybeDoc = resolveLinkToDoc(peekTarget.href); const maybeDoc = resolveLinkToDoc(peekTarget.href);
if (maybeDoc) { if (maybeDoc) {
return { const info: DocPeekViewInfo = {
type: 'doc', type: 'doc',
docId: maybeDoc.docId, docId: maybeDoc.docId,
blockId: maybeDoc.blockId,
}; };
if (maybeDoc.mode) {
info.mode = maybeDoc.mode;
}
if (maybeDoc.blockIds?.length) {
info.blockIds = maybeDoc.blockIds;
}
if (maybeDoc.elementIds?.length) {
info.elementIds = maybeDoc.elementIds;
}
return info;
} }
} else if ('docId' in peekTarget) { } else if ('docId' in peekTarget) {
return { return {
type: 'doc', type: 'doc',
docId: peekTarget.docId, docId: peekTarget.docId,
blockId: peekTarget.blockId, blockIds: peekTarget.blockIds,
}; };
} }
return; return;

View File

@@ -7,10 +7,9 @@ import { EditorOutlineViewer } from '@affine/core/components/blocksuite/outline-
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper'; import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import { PageNotFound } from '@affine/core/pages/404'; import { PageNotFound } from '@affine/core/pages/404';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import { type EdgelessRootService } from '@blocksuite/blocks'; import { DocMode, type EdgelessRootService } from '@blocksuite/blocks';
import { Bound, DisposableGroup } from '@blocksuite/global/utils'; import { Bound, DisposableGroup } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { DocMode } from '@toeverything/infra';
import { DocsService, FrameworkScope, useService } from '@toeverything/infra'; import { DocsService, FrameworkScope, useService } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
@@ -32,7 +31,7 @@ function fitViewport(
} }
const rootService = const rootService =
editor.host.std.spec.getService<EdgelessRootService>('affine:page'); editor.host.std.getService<EdgelessRootService>('affine:page');
rootService.viewport.onResize(); rootService.viewport.onResize();
if (xywh) { if (xywh) {
@@ -60,12 +59,14 @@ function fitViewport(
export function DocPeekPreview({ export function DocPeekPreview({
docId, docId,
blockId, blockIds,
elementIds,
mode, mode,
xywh, xywh,
}: { }: {
docId: string; docId: string;
blockId?: string; blockIds?: string[];
elementIds?: string[];
mode?: DocMode; mode?: DocMode;
xywh?: `[${number},${number},${number},${number}]`; xywh?: `[${number},${number},${number},${number}]`;
}) { }) {
@@ -97,7 +98,7 @@ export function DocPeekPreview({
useEffect(() => { useEffect(() => {
if (!mode || !resolvedMode) { if (!mode || !resolvedMode) {
setResolvedMode( setResolvedMode(
docs.list.doc$(docId).value?.primaryMode$.value || 'page' docs.list.doc$(docId).value?.primaryMode$.value || DocMode.Page
); );
} }
}, [docId, docs.list, resolvedMode, mode]); }, [docId, docs.list, resolvedMode, mode]);
@@ -125,12 +126,17 @@ export function DocPeekPreview({
return; return;
} }
const rootService = const rootService = editorElement.host.std.getService('affine:page');
editorElement.host.std.spec.getService('affine:page');
// doc change event inside peek view should be handled by peek view // doc change event inside peek view should be handled by peek view
disposableGroup.add( disposableGroup.add(
rootService.slots.docLinkClicked.on(({ docId, blockId }) => { rootService.slots.docLinkClicked.on(options => {
peekView.open({ docId, blockId }).catch(console.error); peekView
.open({
type: 'doc',
docId: options.pageId,
...options.params,
})
.catch(console.error);
}) })
); );
// TODO(@Peng): no tag peek view yet // TODO(@Peng): no tag peek view yet
@@ -175,7 +181,8 @@ export function DocPeekPreview({
ref={onRef} ref={onRef}
className={styles.editor} className={styles.editor}
mode={resolvedMode} mode={resolvedMode}
defaultSelectedBlockId={blockId} blockIds={blockIds}
elementIds={elementIds}
page={doc.blockSuiteDoc} page={doc.blockSuiteDoc}
/> />
</FrameworkScope> </FrameworkScope>

View File

@@ -1,12 +1,13 @@
import { IconButton } from '@affine/component'; import { IconButton } from '@affine/component';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { import {
CloseIcon, CloseIcon,
ExpandFullIcon, ExpandFullIcon,
OpenInNewIcon, OpenInNewIcon,
SplitViewIcon, SplitViewIcon,
} from '@blocksuite/icons/rc'; } from '@blocksuite/icons/rc';
import { type DocMode, useService } from '@toeverything/infra'; import { useService } from '@toeverything/infra';
import { clsx } from 'clsx'; import { clsx } from 'clsx';
import { import {
type HTMLAttributes, type HTMLAttributes,

View File

@@ -27,13 +27,16 @@ function renderPeekView({ info }: ActivePeekView) {
mode={info.mode} mode={info.mode}
xywh={info.xywh} xywh={info.xywh}
docId={info.docId} docId={info.docId}
blockId={info.blockId} blockIds={info.blockIds}
elementIds={info.elementIds}
/> />
); );
} }
if (info.type === 'image') { if (info.type === 'image') {
return <ImagePreviewPeekView docId={info.docId} blockId={info.blockId} />; return (
<ImagePreviewPeekView docId={info.docId} blockId={info.blockIds[0]} />
);
} }
if (info.type === 'ai-chat-block') { if (info.type === 'ai-chat-block') {

View File

@@ -1,4 +1,5 @@
import type { Doc, DocMode } from '@toeverything/infra'; import type { DocMode } from '@blocksuite/blocks';
import type { Doc } from '@toeverything/infra';
import { import {
DocsService, DocsService,
useLiveData, useLiveData,

View File

@@ -4,7 +4,8 @@ import {
type CommandCategory, type CommandCategory,
PreconditionStrategy, PreconditionStrategy,
} from '@affine/core/commands'; } from '@affine/core/commands';
import type { DocMode, GlobalContextService } from '@toeverything/infra'; import type { DocMode } from '@blocksuite/blocks';
import type { GlobalContextService } from '@toeverything/infra';
import { Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';

View File

@@ -1,5 +1,6 @@
import type { DocMode } from '@blocksuite/blocks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc';
import { type DocMode, Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
import type { QuickSearchSession } from '../providers/quick-search-provider'; import type { QuickSearchSession } from '../providers/quick-search-provider';
import type { QuickSearchGroup } from '../types/group'; import type { QuickSearchGroup } from '../types/group';

View File

@@ -66,7 +66,7 @@ export class DocsQuickSearchSession
{ {
docId: resolvedDoc.docId, docId: resolvedDoc.docId,
score: 100, score: 100,
blockId: resolvedDoc.blockId, blockId: resolvedDoc.blockIds?.[0],
blockContent: '', blockContent: '',
}, },
...docs, ...docs,

View File

@@ -1,4 +1,5 @@
import { track } from '@affine/core/mixpanel'; import { track } from '@affine/core/mixpanel';
import { DocMode } from '@blocksuite/blocks';
import type { DocsService } from '@toeverything/infra'; import type { DocsService } from '@toeverything/infra';
import { Service } from '@toeverything/infra'; import { Service } from '@toeverything/infra';
@@ -67,13 +68,13 @@ export class CMDKQuickSearchService extends Service {
} else if (result.source === 'creation') { } else if (result.source === 'creation') {
if (result.id === 'creation:create-page') { if (result.id === 'creation:create-page') {
const newDoc = this.docsService.createDoc({ const newDoc = this.docsService.createDoc({
primaryMode: 'page', primaryMode: DocMode.Page,
title: result.payload.title, title: result.payload.title,
}); });
this.workbenchService.workbench.openDoc(newDoc.id); this.workbenchService.workbench.openDoc(newDoc.id);
} else if (result.id === 'creation:create-edgeless') { } else if (result.id === 'creation:create-edgeless') {
const newDoc = this.docsService.createDoc({ const newDoc = this.docsService.createDoc({
primaryMode: 'edgeless', primaryMode: DocMode.Edgeless,
title: result.payload.title, title: result.payload.title,
}); });
this.workbenchService.workbench.openDoc(newDoc.id); this.workbenchService.workbench.openDoc(newDoc.id);

View File

@@ -1,6 +1,6 @@
import { UserFriendlyError } from '@affine/graphql'; import { UserFriendlyError } from '@affine/graphql';
import type { DocMode } from '@blocksuite/blocks';
import { import {
type DocMode,
effect, effect,
Entity, Entity,
fromPromise, fromPromise,

View File

@@ -1,5 +1,6 @@
import { ErrorNames, UserFriendlyError } from '@affine/graphql'; import { ErrorNames, UserFriendlyError } from '@affine/graphql';
import { type DocMode, Store } from '@toeverything/infra'; import type { DocMode } from '@blocksuite/blocks';
import { Store } from '@toeverything/infra';
import { type FetchService, isBackendError } from '../../cloud'; import { type FetchService, isBackendError } from '../../cloud';

View File

@@ -1,6 +1,7 @@
import { Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
import type { Location, To } from 'history'; import type { Location, To } from 'history';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import type { ParseOptions } from 'query-string';
import queryString from 'query-string'; import queryString from 'query-string';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
@@ -79,15 +80,14 @@ export class View extends Entity<{
icon$ = new LiveData(this.props.icon ?? 'allDocs'); icon$ = new LiveData(this.props.icon ?? 'allDocs');
queryString$<T extends Record<string, unknown>>({ queryString$<T extends Record<string, unknown>>(
parseNumbers = true, options: ParseOptions = {
}: { parseNumbers?: boolean } = {}) { parseNumbers: true,
parseBooleans: true,
}
) {
return this.location$.map( return this.location$.map(
location => location => queryString.parse(location.search, options) as Partial<T>
queryString.parse(location.search, {
parseBooleans: true,
parseNumbers: parseNumbers,
}) as Partial<T>
); );
} }

View File

@@ -128,9 +128,15 @@ export class Workbench extends Entity {
const docId = typeof id === 'string' ? id : id.docId; const docId = typeof id === 'string' ? id : id.docId;
const blockId = typeof id === 'string' ? undefined : id.blockId; const blockId = typeof id === 'string' ? undefined : id.blockId;
const mode = typeof id === 'string' ? undefined : id.mode; const mode = typeof id === 'string' ? undefined : id.mode;
const hash = blockId ? `#${blockId}` : ''; let query = '';
const query = mode ? `?mode=${mode}` : ''; if (mode || blockId) {
this.open(`/${docId}${query}${hash}`, options); const search = new URLSearchParams();
if (mode) search.set('mode', mode);
if (blockId) search.set('blockIds', blockId);
query = `?${search.toString()}`;
}
this.open(`/${docId}${query}`, options);
} }
openCollections(options?: WorkbenchOpenOptions) { openCollections(options?: WorkbenchOpenOptions) {

View File

@@ -10,6 +10,7 @@ import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { track } from '@affine/core/mixpanel'; import { track } from '@affine/core/mixpanel';
import { isNewTabTrigger } from '@affine/core/utils'; import { isNewTabTrigger } from '@affine/core/utils';
import type { Filter } from '@affine/env/filter'; import type { Filter } from '@affine/env/filter';
import { DocMode } from '@blocksuite/blocks';
import { PlusIcon } from '@blocksuite/icons/rc'; import { PlusIcon } from '@blocksuite/icons/rc';
import { useServices, WorkspaceService } from '@toeverything/infra'; import { useServices, WorkspaceService } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
@@ -67,7 +68,7 @@ export const AllPageHeader = ({
createEdgeless(isNewTabTrigger(e) ? 'new-tab' : true) createEdgeless(isNewTabTrigger(e) ? 'new-tab' : true)
} }
onCreatePage={e => onCreatePage={e =>
createPage('page', isNewTabTrigger(e) ? 'new-tab' : true) createPage(DocMode.Page, isNewTabTrigger(e) ? 'new-tab' : true)
} }
onCreateDoc={e => onCreateDoc={e =>
createPage(undefined, isNewTabTrigger(e) ? 'new-tab' : true) createPage(undefined, isNewTabTrigger(e) ? 'new-tab' : true)

View File

@@ -63,7 +63,9 @@ const useLoadDoc = (pageId: string) => {
} }
const editor = doc.scope const editor = doc.scope
.get(EditorsService) .get(EditorsService)
.createEditor(initialQueryStringMode || doc.getPrimaryMode() || 'page'); .createEditor(
initialQueryStringMode || doc.getPrimaryMode() || ('page' as DocMode)
);
setEditor(editor); setEditor(editor);
return () => { return () => {
editor.dispose(); editor.dispose();

View File

@@ -210,14 +210,23 @@ const DetailPageImpl = memo(function DetailPageImpl() {
// provide page mode and updated date to blocksuite // provide page mode and updated date to blocksuite
const pageService = const pageService =
editorHost?.std.spec.getService<PageRootService>('affine:page'); editorHost?.std.getService<PageRootService>('affine:page');
const disposable = new DisposableGroup(); const disposable = new DisposableGroup();
if (pageService) { if (pageService) {
disposable.add( disposable.add(
pageService.slots.docLinkClicked.on(({ docId, blockId }) => { pageService.slots.docLinkClicked.on(({ pageId, params }) => {
return blockId if (params) {
? jumpToPageBlock(docCollection.id, docId, blockId) const { mode, blockIds, elementIds } = params;
: openPage(docCollection.id, docId); return jumpToPageBlock(
docCollection.id,
pageId,
mode,
blockIds,
elementIds
);
}
return openPage(docCollection.id, pageId);
}) })
); );
disposable.add( disposable.add(

View File

@@ -1,4 +1,5 @@
import { ChatPanel } from '@affine/core/blocksuite/presets/ai'; import { ChatPanel } from '@affine/core/blocksuite/presets/ai';
import { DocModeProvider } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import { forwardRef, useCallback, useEffect, useRef } from 'react'; import { forwardRef, useCallback, useEffect, useRef } from 'react';
@@ -42,14 +43,16 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel(
useEffect(() => { useEffect(() => {
if (!editor) return; if (!editor) return;
const pageService = editor.host?.spec.getService('affine:page'); const pageService = editor.host?.std.getService('affine:page');
if (!pageService) return; if (!pageService) return;
const docModeService = editor.host?.std.get(DocModeProvider);
if (!docModeService) return;
const disposable = [ const disposable = [
pageService.slots.docLinkClicked.on(() => { pageService.slots.docLinkClicked.on(() => {
(chatPanelRef.current as ChatPanel).doc = editor.doc; (chatPanelRef.current as ChatPanel).doc = editor.doc;
}), }),
pageService.docModeService.onModeChange(() => { docModeService.onModeChange(() => {
if (!editor.host) return; if (!editor.host) return;
(chatPanelRef.current as ChatPanel).host = editor.host; (chatPanelRef.current as ChatPanel).host = editor.host;
}), }),

View File

@@ -2,8 +2,8 @@ import { BlocksuiteHeaderTitle } from '@affine/core/components/blocksuite/block-
import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch'; import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch';
import ShareHeaderRightItem from '@affine/core/components/cloud/share-header-right-item'; import ShareHeaderRightItem from '@affine/core/components/cloud/share-header-right-item';
import { AuthModal } from '@affine/core/providers/modal-provider'; import { AuthModal } from '@affine/core/providers/modal-provider';
import type { DocMode } from '@blocksuite/blocks';
import type { DocCollection } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { DocMode } from '@toeverything/infra';
import * as styles from './share-header.css'; import * as styles from './share-header.css';

View File

@@ -12,11 +12,12 @@ import { ShareReaderService } from '@affine/core/modules/share-doc';
import { CloudBlobStorage } from '@affine/core/modules/workspace-engine'; import { CloudBlobStorage } from '@affine/core/modules/workspace-engine';
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/blocks';
import { noop } from '@blocksuite/global/utils'; import { noop } from '@blocksuite/global/utils';
import { Logo1Icon } from '@blocksuite/icons/rc'; import { Logo1Icon } from '@blocksuite/icons/rc';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Doc as BlockSuiteDoc } from '@blocksuite/store'; import type { Doc as BlockSuiteDoc } from '@blocksuite/store';
import type { Doc, DocMode, Workspace } from '@toeverything/infra'; import type { Doc, Workspace } from '@toeverything/infra';
import { import {
DocsService, DocsService,
EmptyBlobStorage, EmptyBlobStorage,
@@ -96,7 +97,7 @@ const SharePageInner = ({
docId, docId,
workspaceBinary, workspaceBinary,
docBinary, docBinary,
publishMode = 'page', publishMode = 'page' as DocMode,
}: { }: {
workspaceId: string; workspaceId: string;
docId: string; docId: string;

View File

@@ -29,10 +29,10 @@
"@affine/env": "workspace:*", "@affine/env": "workspace:*",
"@affine/i18n": "workspace:*", "@affine/i18n": "workspace:*",
"@affine/native": "workspace:*", "@affine/native": "workspace:*",
"@blocksuite/block-std": "0.17.0-canary-202408191538-1511d04", "@blocksuite/block-std": "0.0.0-canary-20240902070217",
"@blocksuite/blocks": "0.17.0-canary-202408191538-1511d04", "@blocksuite/blocks": "0.0.0-canary-20240902070217",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@blocksuite/store": "0.17.0-canary-202408191538-1511d04", "@blocksuite/store": "0.0.0-canary-20240902070217",
"@electron-forge/cli": "^7.3.0", "@electron-forge/cli": "^7.3.0",
"@electron-forge/core": "^7.3.0", "@electron-forge/core": "^7.3.0",
"@electron-forge/core-utils": "^7.3.0", "@electron-forge/core-utils": "^7.3.0",

View File

@@ -130,14 +130,23 @@ const DetailPageImpl = () => {
// provide page mode and updated date to blocksuite // provide page mode and updated date to blocksuite
const pageService = const pageService =
editorHost?.std.spec.getService<PageRootService>('affine:page'); editorHost?.std.getService<PageRootService>('affine:page');
const disposable = new DisposableGroup(); const disposable = new DisposableGroup();
if (pageService) { if (pageService) {
disposable.add( disposable.add(
pageService.slots.docLinkClicked.on(({ docId, blockId }) => { pageService.slots.docLinkClicked.on(({ pageId, params }) => {
return blockId if (params) {
? jumpToPageBlock(docCollection.id, docId, blockId) const { mode, blockIds, elementIds } = params;
: openPage(docCollection.id, docId); return jumpToPageBlock(
docCollection.id,
pageId,
mode,
blockIds,
elementIds
);
}
return openPage(docCollection.id, pageId);
}) })
); );
disposable.add( disposable.add(

View File

@@ -24,25 +24,6 @@ vi.mock('@blocksuite/presets', () => ({
EdgelessAIChatBlockSpec: {}, EdgelessAIChatBlockSpec: {},
})); }));
vi.mock('@blocksuite/presets/ai', () => ({
AIProvider: {
slots: new Proxy(
{},
{
get: () => ({
on: vi.fn(),
}),
}
),
provide: vi.fn(),
},
AIEdgelessRootBlockSpec: {},
AICodeBlockSpec: {},
AIImageBlockSpec: {},
AIParagraphBlockSpec: {},
AIPageRootBlockSpec: {},
}));
if (typeof window !== 'undefined' && HTMLCanvasElement) { if (typeof window !== 'undefined' && HTMLCanvasElement) {
// @ts-expect-error // @ts-expect-error
HTMLCanvasElement.prototype.getContext = () => { HTMLCanvasElement.prototype.getContext = () => {

View File

@@ -481,17 +481,23 @@ test('can use @ to open quick search to search for doc and insert into canvas',
// press enter to insert the page to canvas // press enter to insert the page to canvas
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
await expect(page.locator('affine-embed-linked-doc-block')).toBeVisible(); await expect(
page.locator('affine-embed-edgeless-linked-doc-block')
).toBeVisible();
await expect( await expect(
page.locator('.affine-embed-linked-doc-content-title') page.locator('.affine-embed-linked-doc-content-title')
).toContainText('Write, Draw, Plan all at Once'); ).toContainText('Write, Draw, Plan all at Once');
// focus on the note block // focus on the note block
await page.waitForTimeout(500); await page.waitForTimeout(500);
await page.locator('affine-embed-linked-doc-block').click({ force: true }); await page
.locator('affine-embed-edgeless-linked-doc-block')
.click({ force: true });
await page.waitForTimeout(500); await page.waitForTimeout(500);
// double clock to show peek view // double clock to show peek view
await page.locator('affine-embed-linked-doc-block').dblclick({ force: true }); await page
.locator('affine-embed-edgeless-linked-doc-block')
.dblclick({ force: true });
await expect(page.getByTestId('peek-view-modal')).toBeVisible(); await expect(page.getByTestId('peek-view-modal')).toBeVisible();
}); });

View File

@@ -6,7 +6,7 @@
"@affine/env": "workspace:*", "@affine/env": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@aws-sdk/client-s3": "^3.620.0", "@aws-sdk/client-s3": "^3.620.0",
"@blocksuite/presets": "0.17.0-canary-202408191538-1511d04", "@blocksuite/presets": "0.0.0-canary-20240902070217",
"@clack/core": "^0.3.4", "@clack/core": "^0.3.4",
"@clack/prompts": "^0.7.0", "@clack/prompts": "^0.7.0",
"@magic-works/i18n-codegen": "^0.6.0", "@magic-works/i18n-codegen": "^0.6.0",

447
yarn.lock
View File

@@ -252,7 +252,7 @@ __metadata:
"@affine/env": "workspace:*" "@affine/env": "workspace:*"
"@affine/templates": "workspace:*" "@affine/templates": "workspace:*"
"@aws-sdk/client-s3": "npm:^3.620.0" "@aws-sdk/client-s3": "npm:^3.620.0"
"@blocksuite/presets": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/presets": "npm:0.0.0-canary-20240902070217"
"@clack/core": "npm:^0.3.4" "@clack/core": "npm:^0.3.4"
"@clack/prompts": "npm:^0.7.0" "@clack/prompts": "npm:^0.7.0"
"@magic-works/i18n-codegen": "npm:^0.6.0" "@magic-works/i18n-codegen": "npm:^0.6.0"
@@ -311,12 +311,12 @@ __metadata:
"@affine/i18n": "workspace:*" "@affine/i18n": "workspace:*"
"@atlaskit/pragmatic-drag-and-drop": "npm:^1.2.1" "@atlaskit/pragmatic-drag-and-drop": "npm:^1.2.1"
"@atlaskit/pragmatic-drag-and-drop-hitbox": "npm:^1.0.3" "@atlaskit/pragmatic-drag-and-drop-hitbox": "npm:^1.0.3"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/blocks": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/blocks": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/icons": "npm:2.1.66" "@blocksuite/icons": "npm:2.1.66"
"@blocksuite/presets": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/presets": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@chromatic-com/storybook": "npm:^1" "@chromatic-com/storybook": "npm:^1"
"@dnd-kit/core": "npm:^6.1.0" "@dnd-kit/core": "npm:^6.1.0"
"@dnd-kit/modifiers": "npm:^7.0.0" "@dnd-kit/modifiers": "npm:^7.0.0"
@@ -413,13 +413,13 @@ __metadata:
"@affine/graphql": "workspace:*" "@affine/graphql": "workspace:*"
"@affine/i18n": "workspace:*" "@affine/i18n": "workspace:*"
"@affine/templates": "workspace:*" "@affine/templates": "workspace:*"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/blocks": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/blocks": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/icons": "npm:2.1.66" "@blocksuite/icons": "npm:2.1.66"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/presets": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/presets": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@dnd-kit/core": "npm:^6.1.0" "@dnd-kit/core": "npm:^6.1.0"
"@dnd-kit/modifiers": "npm:^7.0.0" "@dnd-kit/modifiers": "npm:^7.0.0"
"@dnd-kit/sortable": "npm:^8.0.0" "@dnd-kit/sortable": "npm:^8.0.0"
@@ -552,10 +552,10 @@ __metadata:
"@affine/env": "workspace:*" "@affine/env": "workspace:*"
"@affine/i18n": "workspace:*" "@affine/i18n": "workspace:*"
"@affine/native": "workspace:*" "@affine/native": "workspace:*"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/blocks": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/blocks": "npm:0.0.0-canary-20240902070217"
"@blocksuite/presets": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/presets": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@electron-forge/cli": "npm:^7.3.0" "@electron-forge/cli": "npm:^7.3.0"
"@electron-forge/core": "npm:^7.3.0" "@electron-forge/core": "npm:^7.3.0"
"@electron-forge/core-utils": "npm:^7.3.0" "@electron-forge/core-utils": "npm:^7.3.0"
@@ -612,8 +612,8 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@affine/env@workspace:packages/common/env" resolution: "@affine/env@workspace:packages/common/env"
dependencies: dependencies:
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
lit: "npm:^3.1.2" lit: "npm:^3.1.2"
react: "npm:18.3.1" react: "npm:18.3.1"
react-dom: "npm:18.3.1" react-dom: "npm:18.3.1"
@@ -3475,139 +3475,165 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/affine-block-paragraph@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/affine-block-list@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/affine-block-paragraph@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/affine-block-list@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/affine-components": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-components": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-model": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-model": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-shared": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-shared": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@floating-ui/dom": "npm:^1.6.8" "@floating-ui/dom": "npm:^1.6.10"
"@lit-labs/preact-signals": "npm:^1.0.2" "@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2" "@lit/context": "npm:^1.1.2"
"@toeverything/theme": "npm:^1.0.2" "@toeverything/theme": "npm:^1.0.7"
lit: "npm:^3.1.4" lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1" minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
checksum: 10/691497f518f5b3cff09cda9ae206fdcf3652f355b2f0e711feac39bb4b5b7cde5444549ad96822427c697ae7eb746609781adca344519def3a2e73ec5578a23b checksum: 10/57694021c251d4d6c54d844b6991a819b7304e738328e5b2ddfc4ad11e4381625df7a2377eb89b44824a88d4ba752b96e5df026b5a4c446c5da94662ff52adbd
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/affine-components@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/affine-block-paragraph@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/affine-components@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/affine-block-paragraph@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/affine-model": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-components": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-shared": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-model": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-shared": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/icons": "npm:^2.1.62" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@floating-ui/dom": "npm:^1.6.8" "@floating-ui/dom": "npm:^1.6.10"
"@lit-labs/preact-signals": "npm:^1.0.2" "@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2" "@lit/context": "npm:^1.1.2"
"@toeverything/theme": "npm:^1.0.2" "@toeverything/theme": "npm:^1.0.7"
lit: "npm:^3.1.4" lit: "npm:^3.2.0"
zod: "npm:^3.23.8"
checksum: 10/2da75f271eb1f5e91c545f0ba571a22d0c72f7fea41c5215953c55a7981607477dbf81ebda96952a676bdafa052560e3ea85dfad793b88adf9eec56534649604
languageName: node
linkType: hard
"@blocksuite/affine-model@npm:0.17.0-canary-202408191538-1511d04":
version: 0.17.0-canary-202408191538-1511d04
resolution: "@blocksuite/affine-model@npm:0.17.0-canary-202408191538-1511d04"
dependencies:
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04"
zod: "npm:^3.23.8"
checksum: 10/28212de87f185151d8d81a3fb6bec08b81b681063ac4a7fd5333864ad91e3d583100ae455a8e92da5487d93074071d85e7b7d4816fd97aafacd230cf11ba1510
languageName: node
linkType: hard
"@blocksuite/affine-shared@npm:0.17.0-canary-202408191538-1511d04":
version: 0.17.0-canary-202408191538-1511d04
resolution: "@blocksuite/affine-shared@npm:0.17.0-canary-202408191538-1511d04"
dependencies:
"@blocksuite/affine-model": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04"
"@floating-ui/dom": "npm:^1.6.8"
"@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2"
"@toeverything/theme": "npm:^1.0.2"
lit: "npm:^3.1.4"
minimatch: "npm:^10.0.1" minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
checksum: 10/22d8656159b436f07c12a58f3fbc09d56ea54f72cd20f0175b1c980092f0f475eda6b5cc01371f5b640fa87d84753c200b626568edd6932410a515114ac1916f checksum: 10/8a4e98ddf5481804b47765e22a7f262600f0828b5545b1f57bb14cd31caa30fa34f9795f3ea170ea7f0fcc3c636c70ee4f6471d6fefec2701dcf1132a80d2d48
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/block-std@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/affine-components@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/block-std@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/affine-components@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-model": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-shared": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/icons": "npm:^2.1.66"
"@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@floating-ui/dom": "npm:^1.6.10"
"@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2"
"@lottiefiles/dotlottie-wc": "npm:^0.2.16"
"@toeverything/theme": "npm:^1.0.7"
katex: "npm:^0.16.11"
lit: "npm:^3.2.0"
shiki: "npm:^1.12.0"
zod: "npm:^3.23.8"
checksum: 10/030ce8d6c80c6733ec515161e61e3a7e11e6d7dece18715fc404cf3b32e533db7498095dca03d2cd6c3ed55954fe136e60f5cf7e4102c87ae2fe95878f0d3bdf
languageName: node
linkType: hard
"@blocksuite/affine-model@npm:0.0.0-canary-20240902070217":
version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/affine-model@npm:0.0.0-canary-20240902070217"
dependencies:
"@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.0.0-canary-20240902070217"
zod: "npm:^3.23.8"
checksum: 10/3817634c3effbc7cc6008844438326cc17e818f4b3cddcd32f46e9ac9d00cff9e92777278d87ee37d05b73bbeb840ecbaf8df8996740efac89795d4b1296e86e
languageName: node
linkType: hard
"@blocksuite/affine-shared@npm:0.0.0-canary-20240902070217":
version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/affine-shared@npm:0.0.0-canary-20240902070217"
dependencies:
"@blocksuite/affine-model": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@floating-ui/dom": "npm:^1.6.10"
"@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2"
"@toeverything/theme": "npm:^1.0.7"
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
zod: "npm:^3.23.8"
checksum: 10/51c64bc02e7aa82b55ecf419e44d9a58cb3519e305f447563152b64e9abd10a4cfc29fce6921e3523b2d59682362cf92daa45e96219ec1936c924758e4afd1c3
languageName: node
linkType: hard
"@blocksuite/block-std@npm:0.0.0-canary-20240902070217":
version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/block-std@npm:0.0.0-canary-20240902070217"
dependencies:
"@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@lit-labs/preact-signals": "npm:^1.0.2" "@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2" "@lit/context": "npm:^1.1.2"
"@types/hast": "npm:^3.0.4" "@types/hast": "npm:^3.0.4"
lib0: "npm:^0.2.95" lib0: "npm:^0.2.97"
lit: "npm:^3.1.4" lit: "npm:^3.2.0"
lz-string: "npm:^1.5.0" lz-string: "npm:^1.5.0"
rehype-parse: "npm:^9.0.0" rehype-parse: "npm:^9.0.0"
unified: "npm:^11.0.5" unified: "npm:^11.0.5"
w3c-keyname: "npm:^2.2.8" w3c-keyname: "npm:^2.2.8"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
peerDependencies: peerDependencies:
"@blocksuite/inline": 0.17.0-canary-202408191538-1511d04 "@blocksuite/inline": 0.0.0-canary-20240902070217
"@blocksuite/store": 0.17.0-canary-202408191538-1511d04 "@blocksuite/store": 0.0.0-canary-20240902070217
checksum: 10/03ea60144cfa2a23e9b92decb3f523503811c89c34e75fd9b966508ee6777aec501fd7021b73ccaf3871f88d53ee583064dded9fc477ecb8f9367f1941d53ece checksum: 10/37cd6a3ad4d43d3f962d64ed942cd2af692b4f90b1679ff6502d070fbb9617f8844dcc710b9435f522b00cab03556d3e088070dee122f09d26ec4fb730a5316d
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/blocks@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/blocks@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/blocks@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/blocks@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/affine-block-paragraph": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-block-list": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-components": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-block-paragraph": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-model": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-components": "npm:0.0.0-canary-20240902070217"
"@blocksuite/affine-shared": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-model": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-shared": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/icons": "npm:^2.1.62" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/icons": "npm:^2.1.66"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@dotlottie/player-component": "npm:^2.7.12" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@floating-ui/dom": "npm:^1.6.8" "@floating-ui/dom": "npm:^1.6.10"
"@lit-labs/preact-signals": "npm:^1.0.2" "@lit-labs/preact-signals": "npm:^1.0.2"
"@lit/context": "npm:^1.1.2" "@lit/context": "npm:^1.1.2"
"@toeverything/theme": "npm:^1.0.2" "@toeverything/theme": "npm:^1.0.7"
"@types/hast": "npm:^3.0.4" "@types/hast": "npm:^3.0.4"
"@types/mdast": "npm:^4.0.4" "@types/mdast": "npm:^4.0.4"
"@types/sortablejs": "npm:^1.15.8" "@types/sortablejs": "npm:^1.15.8"
collapse-white-space: "npm:^2.1.0" collapse-white-space: "npm:^2.1.0"
date-fns: "npm:^3.6.0" date-fns: "npm:^3.6.0"
dompurify: "npm:^3.1.6" dompurify: "npm:^3.1.6"
fflate: "npm:^0.8.2"
figma-squircle: "npm:^0.3.1" figma-squircle: "npm:^0.3.1"
file-type: "npm:^19.3.0" file-type: "npm:^19.4.1"
fractional-indexing: "npm:^3.2.0" fractional-indexing: "npm:^3.2.0"
html2canvas: "npm:^1.4.1" html2canvas: "npm:^1.4.1"
jszip: "npm:^3.10.1" lit: "npm:^3.2.0"
lit: "npm:^3.1.4" lodash.isplainobject: "npm:^4.0.6"
mdast-util-gfm-autolink-literal: "npm:^2.0.0" lodash.merge: "npm:^4.6.2"
mdast-util-gfm-autolink-literal: "npm:^2.0.1"
mdast-util-gfm-strikethrough: "npm:^2.0.0" mdast-util-gfm-strikethrough: "npm:^2.0.0"
mdast-util-gfm-table: "npm:^2.0.0" mdast-util-gfm-table: "npm:^2.0.0"
mdast-util-gfm-task-list-item: "npm:^2.0.0" mdast-util-gfm-task-list-item: "npm:^2.0.0"
merge: "npm:^2.1.1"
micromark-extension-gfm-autolink-literal: "npm:^2.1.0" micromark-extension-gfm-autolink-literal: "npm:^2.1.0"
micromark-extension-gfm-strikethrough: "npm:^2.1.0" micromark-extension-gfm-strikethrough: "npm:^2.1.0"
micromark-extension-gfm-table: "npm:^2.1.0" micromark-extension-gfm-table: "npm:^2.1.0"
@@ -3620,25 +3646,25 @@ __metadata:
rehype-stringify: "npm:^10.0.0" rehype-stringify: "npm:^10.0.0"
remark-parse: "npm:^11.0.0" remark-parse: "npm:^11.0.0"
remark-stringify: "npm:^11.0.0" remark-stringify: "npm:^11.0.0"
shiki: "npm:^1.12.0" shiki: "npm:^1.14.1"
sortablejs: "npm:^1.15.2" sortablejs: "npm:^1.15.2"
unified: "npm:^11.0.5" unified: "npm:^11.0.5"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
checksum: 10/ccbed0eda2a28b2d580b12fff4d58c78ce977bb853e20da9f6f114dedb3eddf3cafdf70bcb8e5b6b0236fd4a1e4f76b11741bc38fcc2b9a346a30b99a2d98275 checksum: 10/811a2ad0cdfc1d50e6151a15e4329393d7db148b60932124e2995e0f4fbd7303c4bf0d2ec8e186f2637c6baee6669841a6ab7cfe931900f589a619e06210f82b
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/global@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/global@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/global@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/global@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
lib0: "npm:^0.2.95" lib0: "npm:^0.2.97"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
checksum: 10/9e6f33646a964aab02384cd99472ad9b70dafce5d4778ea45142e719599bca2f4a94f992dcb647936428d9b14c73eb9ad1e631ea54482f7c34205ba9c8903c8a checksum: 10/c5828ac58fbed02ec477c700be3c8fb86a88bd64d0dcaa3c1b77fb766c2e5312b2fa5d26ed0afa60e64e14bf1c1f48537abe69f8ea5fb565c909b7aae3a37a25
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/icons@npm:2.1.66, @blocksuite/icons@npm:^2.1.62, @blocksuite/icons@npm:^2.1.66": "@blocksuite/icons@npm:2.1.66, @blocksuite/icons@npm:^2.1.66":
version: 2.1.66 version: 2.1.66
resolution: "@blocksuite/icons@npm:2.1.66" resolution: "@blocksuite/icons@npm:2.1.66"
peerDependencies: peerDependencies:
@@ -3654,76 +3680,74 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/inline@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/inline@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/inline@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/inline@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
peerDependencies: peerDependencies:
lit: ^3.1.1 lit: ^3.1.1
yjs: ^13.6.15 yjs: ^13.6.15
checksum: 10/283197e25f9a112e69f0ad6bf26cdf163eb639e577b0c0f0d0aa93df6f6790cb83fc2c4ce39d31c11e12d4e09497875da0fa0e0b593fcc2a574b80d3cc227607 checksum: 10/bd97ffef90c83c2641dc2479a6d2c49284393260dff5a41d3daddf3eb3b6e2d2ee520b219d5a3074991bc462babeea30dd8292654870fe5ee39687b389635be2
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/presets@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/presets@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/presets@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/presets@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/affine-shared": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/affine-shared": "npm:0.0.0-canary-20240902070217"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/blocks": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/blocks": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@dotlottie/player-component": "npm:^2.7.12" "@floating-ui/dom": "npm:^1.6.10"
"@fal-ai/serverless-client": "npm:^0.13.0"
"@floating-ui/dom": "npm:^1.6.8"
"@lit-labs/preact-signals": "npm:^1.0.2" "@lit-labs/preact-signals": "npm:^1.0.2"
"@toeverything/theme": "npm:^1.0.2" "@lottiefiles/dotlottie-wc": "npm:^0.2.16"
lit: "npm:^3.1.4" "@toeverything/theme": "npm:^1.0.7"
openai: "npm:^4.53.2" lit: "npm:^3.2.0"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
checksum: 10/2136ab81953f83f9544efdef42935bdda8bc015d1a5cd4a3d90916e091f529323c1a641fed9f9cf59ed4f113700bab455ad03b772a2e90de8521fee762ee5f09 checksum: 10/bbd1ea1b708ef058446350895f3d48377fc9c08af528521584b0950b02c2c1ea7f05a836fc88a8aacf9fed9f652be8ad124ac5fdce175322027edb539aa62c4b
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/store@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/store@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/store@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/store@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/inline": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/inline": "npm:0.0.0-canary-20240902070217"
"@blocksuite/sync": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/sync": "npm:0.0.0-canary-20240902070217"
"@preact/signals-core": "npm:^1.7.0" "@preact/signals-core": "npm:^1.8.0"
"@types/flexsearch": "npm:^0.7.6" "@types/flexsearch": "npm:^0.7.6"
"@types/lodash.ismatch": "npm:^4.4.9" "@types/lodash.ismatch": "npm:^4.4.9"
flexsearch: "npm:0.7.43" flexsearch: "npm:0.7.43"
lib0: "npm:^0.2.95" lib0: "npm:^0.2.97"
lodash.ismatch: "npm:^4.4.0" lodash.ismatch: "npm:^4.4.0"
merge: "npm:^2.1.1" lodash.merge: "npm:^4.6.2"
minimatch: "npm:^10.0.1" minimatch: "npm:^10.0.1"
nanoid: "npm:^5.0.7" nanoid: "npm:^5.0.7"
y-protocols: "npm:^1.0.6" y-protocols: "npm:^1.0.6"
zod: "npm:^3.23.8" zod: "npm:^3.23.8"
peerDependencies: peerDependencies:
yjs: ^13.6.15 yjs: ^13.6.15
checksum: 10/99ba97b28690079ed0ac9f3f9f52934e369bc4cd712aca24cb5298e80c6b98f668ca07bb0153e062497ea21b6d6ab8b6c569ff2324af969edb36b24d0db8c04b checksum: 10/6358b790fb190b5418719c35ef7acbff2ebc163b2098d88ec8f8c5f27a7581e799d92c752fb508e8d417d29dff89f4057ca41da8ed8613812e5f517353e7cd16
languageName: node languageName: node
linkType: hard linkType: hard
"@blocksuite/sync@npm:0.17.0-canary-202408191538-1511d04": "@blocksuite/sync@npm:0.0.0-canary-20240902070217":
version: 0.17.0-canary-202408191538-1511d04 version: 0.0.0-canary-20240902070217
resolution: "@blocksuite/sync@npm:0.17.0-canary-202408191538-1511d04" resolution: "@blocksuite/sync@npm:0.0.0-canary-20240902070217"
dependencies: dependencies:
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
idb: "npm:^8.0.0" idb: "npm:^8.0.0"
idb-keyval: "npm:^6.2.1" idb-keyval: "npm:^6.2.1"
y-protocols: "npm:^1.0.6" y-protocols: "npm:^1.0.6"
peerDependencies: peerDependencies:
yjs: ^13.6.15 yjs: ^13.6.15
checksum: 10/485d9e2e6536dc63492550a09a27804d161229130e7be9d44e2b52fdcba5ec953cf9283f794a27f264ad4a5c62722c9c730a9778bb149dbacf493dc1c59abf26 checksum: 10/b54f2acdf5c19337e3d24e5286ba9e57da79e182750a8c8624a90771b4a2d691fd516f1f7b736442472f49cfc0e37177f4f944f6622b048f6e1bf011bac3fcbc
languageName: node languageName: node
linkType: hard linkType: hard
@@ -5383,18 +5407,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@fal-ai/serverless-client@npm:^0.13.0":
version: 0.13.0
resolution: "@fal-ai/serverless-client@npm:0.13.0"
dependencies:
"@msgpack/msgpack": "npm:^3.0.0-beta2"
eventsource-parser: "npm:^1.1.2"
robot3: "npm:^0.4.1"
uuid-random: "npm:^1.3.2"
checksum: 10/b8256f4d7af0c612314d2af3f01b0825d22a3689cc2b1d252872027b822128295c83da91b0dd53d14272034e615253b9086ca282e26f6ead03601510c4da80e0
languageName: node
linkType: hard
"@fal-ai/serverless-client@npm:^0.14.0": "@fal-ai/serverless-client@npm:^0.14.0":
version: 0.14.2 version: 0.14.2
resolution: "@fal-ai/serverless-client@npm:0.14.2" resolution: "@fal-ai/serverless-client@npm:0.14.2"
@@ -5433,7 +5445,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@floating-ui/dom@npm:^1.0.0, @floating-ui/dom@npm:^1.6.5, @floating-ui/dom@npm:^1.6.8": "@floating-ui/dom@npm:^1.0.0, @floating-ui/dom@npm:^1.6.10, @floating-ui/dom@npm:^1.6.5":
version: 1.6.10 version: 1.6.10
resolution: "@floating-ui/dom@npm:1.6.10" resolution: "@floating-ui/dom@npm:1.6.10"
dependencies: dependencies:
@@ -6860,6 +6872,23 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@lottiefiles/dotlottie-wc@npm:^0.2.16":
version: 0.2.18
resolution: "@lottiefiles/dotlottie-wc@npm:0.2.18"
dependencies:
"@lottiefiles/dotlottie-web": "npm:0.31.1"
lit: "npm:^3.1.0"
checksum: 10/5fa5f98c6c736fa940fe8f65b53bfc67103ff1da6b26d3344c73ff850caacf20c0f506f202e9eec25acf0b202b6021d6e3681d4c315f9405c00bf77f57452d67
languageName: node
linkType: hard
"@lottiefiles/dotlottie-web@npm:0.31.1":
version: 0.31.1
resolution: "@lottiefiles/dotlottie-web@npm:0.31.1"
checksum: 10/c6b7bfb5e95561da8f227b14c0a77f4669800b418f802944609f4a29afb3978228649508221afc650c68987a2e4fd3f4c9f21f51535e631b33fba48fff5c90eb
languageName: node
linkType: hard
"@lukeed/csprng@npm:^1.0.0": "@lukeed/csprng@npm:^1.0.0":
version: 1.1.0 version: 1.1.0
resolution: "@lukeed/csprng@npm:1.1.0" resolution: "@lukeed/csprng@npm:1.1.0"
@@ -10057,10 +10086,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@preact/signals-core@npm:^1.2.3, @preact/signals-core@npm:^1.3.0, @preact/signals-core@npm:^1.7.0": "@preact/signals-core@npm:^1.2.3, @preact/signals-core@npm:^1.3.0, @preact/signals-core@npm:^1.8.0":
version: 1.7.0 version: 1.8.0
resolution: "@preact/signals-core@npm:1.7.0" resolution: "@preact/signals-core@npm:1.8.0"
checksum: 10/a23ae8ef97dd3f98f6212353c770e37548f9fb1ef9f098bbd9352185725b6979f1daa9309ef29d0cb272887392fdbe86b361121c645fdbb983a07f0661544e5e checksum: 10/480c1aaf1bce6f8bd5544eec9fd92a70ccdfffa24c23d99aa8e3c13783cc6b06ec0a3d90578c5fd368d06121cbe0f8fbe81368aa45ddba11d8a28af15410a9dc
languageName: node languageName: node
linkType: hard linkType: hard
@@ -12430,12 +12459,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@shikijs/core@npm:1.12.0": "@shikijs/core@npm:1.16.1":
version: 1.12.0 version: 1.16.1
resolution: "@shikijs/core@npm:1.12.0" resolution: "@shikijs/core@npm:1.16.1"
dependencies: dependencies:
"@shikijs/vscode-textmate": "npm:^9.2.0"
"@types/hast": "npm:^3.0.4" "@types/hast": "npm:^3.0.4"
checksum: 10/794d19b6f9840662021b8dd2a6921db09d1d2420ac1408a05767d850c54c4a57ec8a14beca2b710479719f15f86d2137c1b49bd1f5bdfcbcd563616ef2abc538 checksum: 10/5f5ef7d9d5e84e0c21c3f60fcab87fa8ff384081d0fbea8bd89ecdd98ff54eae5bd758b84aa6102fb5ac41f278f4c60144adc1d28be4c9e7c7cf0f88fff8d579
languageName: node
linkType: hard
"@shikijs/vscode-textmate@npm:^9.2.0":
version: 9.2.0
resolution: "@shikijs/vscode-textmate@npm:9.2.0"
checksum: 10/16e2521387bb60044919ec7a61359d75adc74daf7d03daefd074ccd4994b0fbd22923c3f258dcd3fd70d9a730920579462afeb3922a08b4e6549a4f43e059962
languageName: node languageName: node
linkType: hard linkType: hard
@@ -13928,11 +13965,11 @@ __metadata:
"@affine/debug": "workspace:*" "@affine/debug": "workspace:*"
"@affine/env": "workspace:*" "@affine/env": "workspace:*"
"@affine/templates": "workspace:*" "@affine/templates": "workspace:*"
"@blocksuite/block-std": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/block-std": "npm:0.0.0-canary-20240902070217"
"@blocksuite/blocks": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/blocks": "npm:0.0.0-canary-20240902070217"
"@blocksuite/global": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/global": "npm:0.0.0-canary-20240902070217"
"@blocksuite/presets": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/presets": "npm:0.0.0-canary-20240902070217"
"@blocksuite/store": "npm:0.17.0-canary-202408191538-1511d04" "@blocksuite/store": "npm:0.0.0-canary-20240902070217"
"@datastructures-js/binary-search-tree": "npm:^5.3.2" "@datastructures-js/binary-search-tree": "npm:^5.3.2"
"@testing-library/react": "npm:^16.0.0" "@testing-library/react": "npm:^16.0.0"
async-call-rpc: "npm:^6.4.0" async-call-rpc: "npm:^6.4.0"
@@ -13975,7 +14012,7 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@toeverything/theme@npm:^1.0.2, @toeverything/theme@npm:^1.0.7": "@toeverything/theme@npm:^1.0.7":
version: 1.0.7 version: 1.0.7
resolution: "@toeverything/theme@npm:1.0.7" resolution: "@toeverything/theme@npm:1.0.7"
checksum: 10/86b46af255450ab7ea0a20faf41c27793129852759d23736e914876a696c40e6daa15b25cde7353cd56c673c6191d04cabe6b77f6131ba0b0862bb8d482d7a01 checksum: 10/86b46af255450ab7ea0a20faf41c27793129852759d23736e914876a696c40e6daa15b25cde7353cd56c673c6191d04cabe6b77f6131ba0b0862bb8d482d7a01
@@ -21817,7 +21854,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"fflate@npm:^0.8.1": "fflate@npm:^0.8.1, fflate@npm:^0.8.2":
version: 0.8.2 version: 0.8.2
resolution: "fflate@npm:0.8.2" resolution: "fflate@npm:0.8.2"
checksum: 10/2bd26ba6d235d428de793c6a0cd1aaa96a06269ebd4e21b46c8fd1bd136abc631acf27e188d47c3936db090bf3e1ede11d15ce9eae9bffdc4bfe1b9dc66ca9cb checksum: 10/2bd26ba6d235d428de793c6a0cd1aaa96a06269ebd4e21b46c8fd1bd136abc631acf27e188d47c3936db090bf3e1ede11d15ce9eae9bffdc4bfe1b9dc66ca9cb
@@ -21858,7 +21895,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"file-type@npm:^19.1.0, file-type@npm:^19.3.0": "file-type@npm:^19.1.0, file-type@npm:^19.4.1":
version: 19.4.1 version: 19.4.1
resolution: "file-type@npm:19.4.1" resolution: "file-type@npm:19.4.1"
dependencies: dependencies:
@@ -25410,6 +25447,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"katex@npm:^0.16.11":
version: 0.16.11
resolution: "katex@npm:0.16.11"
dependencies:
commander: "npm:^8.3.0"
bin:
katex: cli.js
checksum: 10/adfb95a70168f732c26f44a443d27df393ca641a3533aa9321f37b1b69134cf4b15142d533c187ec9a0b02c0bbfebab5ab26f15bd0cc08a57114e1f767f0d7ae
languageName: node
linkType: hard
"keyv@npm:*, keyv@npm:^4.0.0, keyv@npm:^4.5.3, keyv@npm:^4.5.4": "keyv@npm:*, keyv@npm:^4.0.0, keyv@npm:^4.5.3, keyv@npm:^4.5.4":
version: 4.5.4 version: 4.5.4
resolution: "keyv@npm:4.5.4" resolution: "keyv@npm:4.5.4"
@@ -25481,7 +25529,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lib0@npm:^0.2.85, lib0@npm:^0.2.86, lib0@npm:^0.2.93, lib0@npm:^0.2.95": "lib0@npm:^0.2.85, lib0@npm:^0.2.86, lib0@npm:^0.2.93, lib0@npm:^0.2.95, lib0@npm:^0.2.97":
version: 0.2.97 version: 0.2.97
resolution: "lib0@npm:0.2.97" resolution: "lib0@npm:0.2.97"
dependencies: dependencies:
@@ -25681,7 +25729,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lit@npm:^3.1.2, lit@npm:^3.1.3, lit@npm:^3.1.4": "lit@npm:^3.1.0, lit@npm:^3.1.2, lit@npm:^3.1.3, lit@npm:^3.2.0":
version: 3.2.0 version: 3.2.0
resolution: "lit@npm:3.2.0" resolution: "lit@npm:3.2.0"
dependencies: dependencies:
@@ -26478,16 +26526,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mdast-util-gfm-autolink-literal@npm:^2.0.0": "mdast-util-gfm-autolink-literal@npm:^2.0.0, mdast-util-gfm-autolink-literal@npm:^2.0.1":
version: 2.0.0 version: 2.0.1
resolution: "mdast-util-gfm-autolink-literal@npm:2.0.0" resolution: "mdast-util-gfm-autolink-literal@npm:2.0.1"
dependencies: dependencies:
"@types/mdast": "npm:^4.0.0" "@types/mdast": "npm:^4.0.0"
ccount: "npm:^2.0.0" ccount: "npm:^2.0.0"
devlop: "npm:^1.0.0" devlop: "npm:^1.0.0"
mdast-util-find-and-replace: "npm:^3.0.0" mdast-util-find-and-replace: "npm:^3.0.0"
micromark-util-character: "npm:^2.0.0" micromark-util-character: "npm:^2.0.0"
checksum: 10/08656ea3a5b53376a3a09082c7017e4887c1dde00b2c21aee68440d47d9151485347745db49cc05138ce3b6b7760d9700362212685a3644a170344dc4330b696 checksum: 10/d933b42feb126bd094d4be4a4955326c4a9e727a5d0dbe3c824534a19d831996fcf16f67df3dd29550a7d2ac4ac568c80485bee380151ebb42c62848ab20dfa6
languageName: node languageName: node
linkType: hard linkType: hard
@@ -26713,13 +26761,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"merge@npm:^2.1.1":
version: 2.1.1
resolution: "merge@npm:2.1.1"
checksum: 10/1875521a8e429ba8d82c6d24bf3f229b4b64a348873c41a1245851b422c0caa7fbeb958118c24fbfcbb71e416a29924b3b1c4518911529db175f49eb5bcb5e62
languageName: node
linkType: hard
"meros@npm:^1.2.1": "meros@npm:^1.2.1":
version: 1.3.0 version: 1.3.0
resolution: "meros@npm:1.3.0" resolution: "meros@npm:1.3.0"
@@ -28541,7 +28582,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"openai@npm:^4.33.0, openai@npm:^4.53.2": "openai@npm:^4.33.0":
version: 4.56.0 version: 4.56.0
resolution: "openai@npm:4.56.0" resolution: "openai@npm:4.56.0"
dependencies: dependencies:
@@ -32343,13 +32384,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"shiki@npm:^1.12.0, shiki@npm:^1.9.1": "shiki@npm:^1.12.0, shiki@npm:^1.14.1, shiki@npm:^1.9.1":
version: 1.12.0 version: 1.16.1
resolution: "shiki@npm:1.12.0" resolution: "shiki@npm:1.16.1"
dependencies: dependencies:
"@shikijs/core": "npm:1.12.0" "@shikijs/core": "npm:1.16.1"
"@shikijs/vscode-textmate": "npm:^9.2.0"
"@types/hast": "npm:^3.0.4" "@types/hast": "npm:^3.0.4"
checksum: 10/17c9769e0b996433a9131debdc47246fded316fdf529d91fb1b5641a38c21b47fa4781c7bbc53a31cd927d9c9aaab028e105344d6a373dbb772f10b304e9434a checksum: 10/068359962e8812e238ed0e8bbc2e5c4c68875ca8098a36e8d641467027a4eb5539193659b08b2ad5277d73fc82ec1f4ee345066ac6bd11f51cb53b88bc8ee8b3
languageName: node languageName: node
linkType: hard linkType: hard
@@ -35107,13 +35149,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"uuid-random@npm:^1.3.2":
version: 1.3.2
resolution: "uuid-random@npm:1.3.2"
checksum: 10/9070c876651e1893f9255dddab2edc177ba34196660065be074050e4143405382b7f0f5fb922b666ebfd0794a6ef7b9f6acb627865df7b2978edb0da6b448f1d
languageName: node
linkType: hard
"uuid@npm:10.0.0, uuid@npm:^10.0.0": "uuid@npm:10.0.0, uuid@npm:^10.0.0":
version: 10.0.0 version: 10.0.0
resolution: "uuid@npm:10.0.0" resolution: "uuid@npm:10.0.0"