mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-22 20:41:50 +08:00
refactor(editor): reduce getService (#10100)
This commit is contained in:
@@ -76,10 +76,6 @@ export class BlockRenderer
|
|||||||
return this.host?.doc.getBlock(this.rowId)?.model;
|
return this.host?.doc.getBlock(this.rowId)?.model;
|
||||||
}
|
}
|
||||||
|
|
||||||
get service() {
|
|
||||||
return this.host.std.getService('affine:database');
|
|
||||||
}
|
|
||||||
|
|
||||||
override connectedCallback() {
|
override connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
if (this.model && this.model.text) {
|
if (this.model && this.model.text) {
|
||||||
|
|||||||
@@ -123,10 +123,6 @@ abstract class BaseTextCell extends BaseCellRenderer<Text> {
|
|||||||
return this.host?.std.get(DefaultInlineManagerExtension.identifier);
|
return this.host?.std.get(DefaultInlineManagerExtension.identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
get service() {
|
|
||||||
return this.host?.std.getService('affine:database');
|
|
||||||
}
|
|
||||||
|
|
||||||
get topContenteditableElement() {
|
get topContenteditableElement() {
|
||||||
const databaseBlock =
|
const databaseBlock =
|
||||||
this.closest<DatabaseBlockComponent>('affine-database');
|
this.closest<DatabaseBlockComponent>('affine-database');
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ export function toEdgelessEmbedBlock<
|
|||||||
return Bound.deserialize(this.model.xywh);
|
return Bound.deserialize(this.model.xywh);
|
||||||
}
|
}
|
||||||
|
|
||||||
get rootService() {
|
|
||||||
return this.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleClick(_: MouseEvent): void {
|
_handleClick(_: MouseEvent): void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
-10
@@ -36,12 +36,6 @@ export class EmbedEdgelessLinkedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
bound.w = EMBED_CARD_WIDTH[style];
|
bound.w = EMBED_CARD_WIDTH[style];
|
||||||
bound.h = EMBED_CARD_HEIGHT[style];
|
bound.h = EMBED_CARD_HEIGHT[style];
|
||||||
|
|
||||||
const edgelessService = this.rootService;
|
|
||||||
|
|
||||||
if (!edgelessService) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { addBlock } = this.std.get(EdgelessCRUDIdentifier);
|
const { addBlock } = this.std.get(EdgelessCRUDIdentifier);
|
||||||
const surface = this.gfx.surface ?? undefined;
|
const surface = this.gfx.surface ?? undefined;
|
||||||
const newId = addBlock(
|
const newId = addBlock(
|
||||||
@@ -67,10 +61,6 @@ export class EmbedEdgelessLinkedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
doc.deleteBlock(this.model);
|
doc.deleteBlock(this.model);
|
||||||
};
|
};
|
||||||
|
|
||||||
get rootService() {
|
|
||||||
return this.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override _handleClick(evt: MouseEvent): void {
|
protected override _handleClick(evt: MouseEvent): void {
|
||||||
if (isNewTabTrigger(evt)) {
|
if (isNewTabTrigger(evt)) {
|
||||||
this.open({ openMode: 'open-in-new-tab', event: evt });
|
this.open({ openMode: 'open-in-new-tab', event: evt });
|
||||||
|
|||||||
-9
@@ -123,16 +123,11 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
override convertToCard = (aliasInfo?: AliasInfo) => {
|
override convertToCard = (aliasInfo?: AliasInfo) => {
|
||||||
const { id, doc, caption, xywh } = this.model;
|
const { id, doc, caption, xywh } = this.model;
|
||||||
|
|
||||||
const edgelessService = this.rootService;
|
|
||||||
const style = 'vertical';
|
const style = 'vertical';
|
||||||
const bound = Bound.deserialize(xywh);
|
const bound = Bound.deserialize(xywh);
|
||||||
bound.w = EMBED_CARD_WIDTH[style];
|
bound.w = EMBED_CARD_WIDTH[style];
|
||||||
bound.h = EMBED_CARD_HEIGHT[style];
|
bound.h = EMBED_CARD_HEIGHT[style];
|
||||||
|
|
||||||
if (!edgelessService) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { addBlock } = this.std.get(EdgelessCRUDIdentifier);
|
const { addBlock } = this.std.get(EdgelessCRUDIdentifier);
|
||||||
const surface = this.gfx.surface ?? undefined;
|
const surface = this.gfx.surface ?? undefined;
|
||||||
const newId = addBlock(
|
const newId = addBlock(
|
||||||
@@ -159,10 +154,6 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
doc.deleteBlock(this.model);
|
doc.deleteBlock(this.model);
|
||||||
};
|
};
|
||||||
|
|
||||||
get rootService() {
|
|
||||||
return this.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
override renderGfxBlock() {
|
override renderGfxBlock() {
|
||||||
const { style, xywh } = this.model;
|
const { style, xywh } = this.model;
|
||||||
const bound = Bound.deserialize(xywh);
|
const bound = Bound.deserialize(xywh);
|
||||||
|
|||||||
@@ -351,10 +351,6 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
.title(pageId, { params, referenced: true });
|
.title(pageId, { params, referenced: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
private get _rootService() {
|
|
||||||
return this.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
get blockState() {
|
get blockState() {
|
||||||
return {
|
return {
|
||||||
isLoading: this._loading,
|
isLoading: this._loading,
|
||||||
@@ -504,8 +500,8 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this._rootService && !this.linkedMode) {
|
if (!this.linkedMode) {
|
||||||
const docMode = this._rootService.std.get(DocModeProvider);
|
const docMode = this.std.get(DocModeProvider);
|
||||||
this.syncedDocMode = docMode.getPrimaryMode(this.model.pageId);
|
this.syncedDocMode = docMode.getPrimaryMode(this.model.pageId);
|
||||||
this._isEmptySyncedDoc = isEmptyDoc(this.syncedDoc, this.editorMode);
|
this._isEmptySyncedDoc = isEmptyDoc(this.syncedDoc, this.editorMode);
|
||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
|||||||
return this.gfx.viewport.zoom;
|
return this.gfx.viewport.zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
get rootService() {
|
|
||||||
return this.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
private _collapsedContent() {
|
private _collapsedContent() {
|
||||||
if (!this._isShowCollapsedContent) {
|
if (!this._isShowCollapsedContent) {
|
||||||
return nothing;
|
return nothing;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import type { Command } from '@blocksuite/block-std';
|
import type { Command } from '@blocksuite/block-std';
|
||||||
|
|
||||||
|
import { SurfaceBlockService } from '../surface-service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-associate bindings for block that have been converted.
|
* Re-associate bindings for block that have been converted.
|
||||||
*
|
*
|
||||||
@@ -11,7 +13,7 @@ export const reassociateConnectorsCommand: Command<{
|
|||||||
newId: string;
|
newId: string;
|
||||||
}> = (ctx, next) => {
|
}> = (ctx, next) => {
|
||||||
const { oldId, newId } = ctx;
|
const { oldId, newId } = ctx;
|
||||||
const service = ctx.std.getService('affine:surface');
|
const service = ctx.std.get(SurfaceBlockService);
|
||||||
if (!oldId || !newId || !service) {
|
if (!oldId || !newId || !service) {
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import type { SurfaceElementModelMap } from '@blocksuite/affine-model';
|
|||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
||||||
import { type BlockStdScope, StdIdentifier } from '@blocksuite/block-std';
|
import { type BlockStdScope, StdIdentifier } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
|
GfxBlockElementModel,
|
||||||
GfxControllerIdentifier,
|
GfxControllerIdentifier,
|
||||||
type GfxModel,
|
type GfxModel,
|
||||||
|
isGfxGroupCompatibleModel,
|
||||||
} from '@blocksuite/block-std/gfx';
|
} from '@blocksuite/block-std/gfx';
|
||||||
import { type Container, createIdentifier } from '@blocksuite/global/di';
|
import { type Container, createIdentifier } from '@blocksuite/global/di';
|
||||||
import { type BlockModel, Extension } from '@blocksuite/store';
|
import { type BlockModel, Extension } from '@blocksuite/store';
|
||||||
@@ -155,4 +157,25 @@ export class EdgelessCRUDExtension extends Extension {
|
|||||||
}
|
}
|
||||||
return this._surface.getElementsByType(type);
|
return this._surface.getElementsByType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeElement(id: string | GfxModel) {
|
||||||
|
id = typeof id === 'string' ? id : id.id;
|
||||||
|
|
||||||
|
const el = this.getElementById(id);
|
||||||
|
if (isGfxGroupCompatibleModel(el)) {
|
||||||
|
el.childIds.forEach(childId => {
|
||||||
|
this.removeElement(childId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el instanceof GfxBlockElementModel) {
|
||||||
|
this.std.store.deleteBlock(el);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._surface?.hasElementById(id)) {
|
||||||
|
this._surface.deleteElement(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import { query } from 'lit/decorators.js';
|
|||||||
|
|
||||||
import { ConnectorElementModel } from './element-model/index.js';
|
import { ConnectorElementModel } from './element-model/index.js';
|
||||||
import { CanvasRenderer } from './renderer/canvas-renderer.js';
|
import { CanvasRenderer } from './renderer/canvas-renderer.js';
|
||||||
import type { ElementRenderer } from './renderer/elements/index.js';
|
import {
|
||||||
|
type ElementRenderer,
|
||||||
|
elementRenderers,
|
||||||
|
} from './renderer/elements/index.js';
|
||||||
import { OverlayIdentifier } from './renderer/overlay.js';
|
import { OverlayIdentifier } from './renderer/overlay.js';
|
||||||
import type { SurfaceBlockModel } from './surface-model.js';
|
import type { SurfaceBlockModel } from './surface-model.js';
|
||||||
import type { SurfaceBlockService } from './surface-service.js';
|
import type { SurfaceBlockService } from './surface-service.js';
|
||||||
@@ -126,10 +129,6 @@ export class SurfaceBlockComponent extends BlockComponent<
|
|||||||
this._renderer?.refresh();
|
this._renderer?.refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
private get _edgelessService() {
|
|
||||||
return this.std.getService('affine:page') as unknown as SurfaceContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _gfx() {
|
private get _gfx() {
|
||||||
return this.std.get(GfxControllerIdentifier);
|
return this.std.get(GfxControllerIdentifier);
|
||||||
}
|
}
|
||||||
@@ -179,12 +178,12 @@ export class SurfaceBlockComponent extends BlockComponent<
|
|||||||
property,
|
property,
|
||||||
themeService.edgelessTheme
|
themeService.edgelessTheme
|
||||||
),
|
),
|
||||||
selectedElements: () => this._edgelessService.selection.selectedIds,
|
selectedElements: () => gfx.selection.selectedIds,
|
||||||
},
|
},
|
||||||
onStackingCanvasCreated(canvas) {
|
onStackingCanvasCreated(canvas) {
|
||||||
canvas.className = 'indexable-canvas';
|
canvas.className = 'indexable-canvas';
|
||||||
},
|
},
|
||||||
elementRenderers: this._edgelessService.elementRenderers,
|
elementRenderers,
|
||||||
surfaceModel: this.model,
|
surfaceModel: this.model,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -205,7 +204,7 @@ export class SurfaceBlockComponent extends BlockComponent<
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
this._edgelessService.selection.slots.updated.on(() => {
|
gfx.selection.slots.updated.on(() => {
|
||||||
this._renderer.refresh();
|
this._renderer.refresh();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { CodeBlockConfig } from '@blocksuite/affine-block-code';
|
import type { CodeBlockConfig } from '@blocksuite/affine-block-code';
|
||||||
|
import { ParagraphBlockService } from '@blocksuite/affine-block-paragraph';
|
||||||
import {
|
import {
|
||||||
type ReferenceNodeConfig,
|
type ReferenceNodeConfig,
|
||||||
ReferenceNodeConfigIdentifier,
|
ReferenceNodeConfigIdentifier,
|
||||||
@@ -100,7 +101,7 @@ export class MobileSpecsPatches extends LifeCycleWatcher {
|
|||||||
override mounted() {
|
override mounted() {
|
||||||
// remove slash placeholder for mobile: `type / ...`
|
// remove slash placeholder for mobile: `type / ...`
|
||||||
{
|
{
|
||||||
const paragraphService = this.std.getService('affine:paragraph');
|
const paragraphService = this.std.get(ParagraphBlockService);
|
||||||
if (!paragraphService) return;
|
if (!paragraphService) return;
|
||||||
|
|
||||||
paragraphService.placeholderGenerator = model => {
|
paragraphService.placeholderGenerator = model => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
type EditorHost,
|
type EditorHost,
|
||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
Bound,
|
Bound,
|
||||||
debounce,
|
debounce,
|
||||||
@@ -19,7 +20,6 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|||||||
|
|
||||||
import { SpecProvider } from '../../../../_specs/index.js';
|
import { SpecProvider } from '../../../../_specs/index.js';
|
||||||
import type { EdgelessRootPreviewBlockComponent } from '../../edgeless-root-preview-block.js';
|
import type { EdgelessRootPreviewBlockComponent } from '../../edgeless-root-preview-block.js';
|
||||||
import type { EdgelessRootService } from '../../edgeless-root-service.js';
|
|
||||||
|
|
||||||
const DEFAULT_PREVIEW_CONTAINER_WIDTH = 280;
|
const DEFAULT_PREVIEW_CONTAINER_WIDTH = 280;
|
||||||
const DEFAULT_PREVIEW_CONTAINER_HEIGHT = 166;
|
const DEFAULT_PREVIEW_CONTAINER_HEIGHT = 166;
|
||||||
@@ -144,12 +144,9 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
if (!previewEditorHost) return;
|
if (!previewEditorHost) return;
|
||||||
|
|
||||||
const edgelessService = previewEditorHost.std.getService(
|
const { viewport } = previewEditorHost.std.get(GfxControllerIdentifier);
|
||||||
'affine:page'
|
|
||||||
) as EdgelessRootService;
|
|
||||||
|
|
||||||
const frameBound = Bound.deserialize(this.frame.xywh);
|
const frameBound = Bound.deserialize(this.frame.xywh);
|
||||||
edgelessService.viewport.setViewportByBound(frameBound);
|
viewport.setViewportByBound(frameBound);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderSurfaceContent() {
|
private _renderSurfaceContent() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { AIError } from '@blocksuite/affine-components/ai-item';
|
import type { AIError } from '@blocksuite/affine-components/ai-item';
|
||||||
import {
|
import {
|
||||||
|
DocModeProvider,
|
||||||
NotificationProvider,
|
NotificationProvider,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
stopPropagation,
|
stopPropagation,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import { WidgetComponent } from '@blocksuite/block-std';
|
import { WidgetComponent } from '@blocksuite/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import type { BaseSelection } from '@blocksuite/store';
|
import type { BaseSelection } from '@blocksuite/store';
|
||||||
import {
|
import {
|
||||||
@@ -24,8 +26,6 @@ import { css, html, nothing, type PropertyValues } from 'lit';
|
|||||||
import { property, query } from 'lit/decorators.js';
|
import { property, query } from 'lit/decorators.js';
|
||||||
import { choose } from 'lit/directives/choose.js';
|
import { choose } from 'lit/directives/choose.js';
|
||||||
|
|
||||||
import type { EdgelessRootService } from '../../edgeless/edgeless-root-service.js';
|
|
||||||
import { PageRootService } from '../../page/page-root-service.js';
|
|
||||||
import { AFFINE_FORMAT_BAR_WIDGET } from '../format-bar/format-bar.js';
|
import { AFFINE_FORMAT_BAR_WIDGET } from '../format-bar/format-bar.js';
|
||||||
import {
|
import {
|
||||||
AFFINE_VIEWPORT_OVERLAY_WIDGET,
|
AFFINE_VIEWPORT_OVERLAY_WIDGET,
|
||||||
@@ -363,12 +363,13 @@ export class AffineAIPanelWidget extends WidgetComponent {
|
|||||||
): Partial<ComputePositionConfig> {
|
): Partial<ComputePositionConfig> {
|
||||||
let rootBoundary: Rect | undefined;
|
let rootBoundary: Rect | undefined;
|
||||||
{
|
{
|
||||||
const rootService = this.host.std.getService('affine:page');
|
const docModeProvider = this.host.std.get(DocModeProvider);
|
||||||
if (rootService instanceof PageRootService) {
|
if (docModeProvider.getEditorMode() === 'page') {
|
||||||
rootBoundary = undefined;
|
rootBoundary = undefined;
|
||||||
} else {
|
} else {
|
||||||
|
const gfx = this.host.std.get(GfxControllerIdentifier);
|
||||||
// TODO circular dependency: instanceof EdgelessRootService
|
// TODO circular dependency: instanceof EdgelessRootService
|
||||||
const viewport = (rootService as EdgelessRootService).viewport;
|
const viewport = gfx.viewport;
|
||||||
rootBoundary = {
|
rootBoundary = {
|
||||||
x: viewport.left,
|
x: viewport.left,
|
||||||
y: viewport.top,
|
y: viewport.top,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import './left-side-panel.js';
|
|||||||
import { NotionHtmlAdapter } from '@blocksuite/affine-shared/adapters';
|
import { NotionHtmlAdapter } from '@blocksuite/affine-shared/adapters';
|
||||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
import { ShadowlessElement } from '@blocksuite/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
ColorScheme,
|
ColorScheme,
|
||||||
ColorVariables,
|
ColorVariables,
|
||||||
@@ -28,7 +29,6 @@ import {
|
|||||||
type DocMode,
|
type DocMode,
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
download,
|
download,
|
||||||
EdgelessRootService,
|
|
||||||
ExportManager,
|
ExportManager,
|
||||||
FontFamilyVariables,
|
FontFamilyVariables,
|
||||||
HtmlAdapterFactoryIdentifier,
|
HtmlAdapterFactoryIdentifier,
|
||||||
@@ -210,10 +210,6 @@ export class StarterDebugMenu extends ShadowlessElement {
|
|||||||
this.editor.mode = value;
|
this.editor.mode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get rootService() {
|
|
||||||
return this.editor.std?.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
private _addNote() {
|
private _addNote() {
|
||||||
const rootModel = this.doc.root;
|
const rootModel = this.doc.root;
|
||||||
if (!rootModel) return;
|
if (!rootModel) return;
|
||||||
@@ -544,18 +540,8 @@ export class StarterDebugMenu extends ShadowlessElement {
|
|||||||
|
|
||||||
private _present() {
|
private _present() {
|
||||||
if (!this.editor.std || !this.editor.host) return;
|
if (!this.editor.std || !this.editor.host) return;
|
||||||
const rootService = this.editor.std.getService('affine:page');
|
const gfx = this.editor.std.get(GfxControllerIdentifier);
|
||||||
if (!(rootService instanceof EdgelessRootService)) {
|
gfx.tool.setTool('frameNavigator', {
|
||||||
toast(
|
|
||||||
this.editor.host,
|
|
||||||
'The presentation mode is only available on edgeless mode.',
|
|
||||||
3000
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const edgelessRootService = rootService as EdgelessRootService;
|
|
||||||
edgelessRootService?.gfx.tool.setTool('frameNavigator', {
|
|
||||||
mode: 'fit',
|
mode: 'fit',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1016,7 +1016,7 @@ export async function deleteAllConnectors(page: Page) {
|
|||||||
const container = document.querySelector('affine-edgeless-root');
|
const container = document.querySelector('affine-edgeless-root');
|
||||||
if (!container) throw new Error('container not found');
|
if (!container) throw new Error('container not found');
|
||||||
container.service.crud.getElementsByType('connector').forEach(c => {
|
container.service.crud.getElementsByType('connector').forEach(c => {
|
||||||
container.service.removeElement(c.id);
|
container.service.crud.removeElement(c.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import { ChatHistoryOrder } from '@affine/graphql';
|
import { ChatHistoryOrder } from '@affine/graphql';
|
||||||
import {
|
import {
|
||||||
BlockSelection,
|
BlockSelection,
|
||||||
|
type BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
TextSelection,
|
TextSelection,
|
||||||
} from '@blocksuite/affine/block-std';
|
} from '@blocksuite/affine/block-std';
|
||||||
import type {
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
DocMode,
|
import type { DocMode, ImageSelection } from '@blocksuite/affine/blocks';
|
||||||
EdgelessRootService,
|
|
||||||
ImageSelection,
|
|
||||||
RootService,
|
|
||||||
} from '@blocksuite/affine/blocks';
|
|
||||||
import {
|
import {
|
||||||
BlocksUtils,
|
BlocksUtils,
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
EditPropsStore,
|
EditPropsStore,
|
||||||
getSelectedBlocksCommand,
|
getSelectedBlocksCommand,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
@@ -116,10 +114,10 @@ export async function constructRootChatBlockMessages(
|
|||||||
return constructUserInfoWithMessages(forkMessages, userInfo);
|
return constructUserInfoWithMessages(forkMessages, userInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getViewportCenter(mode: DocMode, rootService: RootService) {
|
function getViewportCenter(mode: DocMode, std: BlockStdScope) {
|
||||||
const center = { x: 400, y: 50 };
|
const center = { x: 400, y: 50 };
|
||||||
if (mode === 'page') {
|
if (mode === 'page') {
|
||||||
const viewport = rootService.std.get(EditPropsStore).getStorage('viewport');
|
const viewport = std.get(EditPropsStore).getStorage('viewport');
|
||||||
if (viewport) {
|
if (viewport) {
|
||||||
if ('xywh' in viewport) {
|
if ('xywh' in viewport) {
|
||||||
const bound = Bound.deserialize(viewport.xywh);
|
const bound = Bound.deserialize(viewport.xywh);
|
||||||
@@ -132,9 +130,9 @@ function getViewportCenter(mode: DocMode, rootService: RootService) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Else we should get latest viewport center from the edgeless root service
|
// Else we should get latest viewport center from the edgeless root service
|
||||||
const edgelessService = rootService as EdgelessRootService;
|
const viewport = std.get(GfxControllerIdentifier).viewport;
|
||||||
center.x = edgelessService.viewport.centerX;
|
center.x = viewport.centerX;
|
||||||
center.y = edgelessService.viewport.centerY;
|
center.y = viewport.centerY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return center;
|
return center;
|
||||||
@@ -310,18 +308,11 @@ const SAVE_CHAT_TO_BLOCK_ACTION: ChatAction = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootService = host.std.getService('affine:page');
|
|
||||||
const surfaceService = host.std.getService('affine:surface');
|
|
||||||
if (!rootService || !surfaceService) return false;
|
|
||||||
|
|
||||||
const notificationService = host.std.getOptional(NotificationProvider);
|
const notificationService = host.std.getOptional(NotificationProvider);
|
||||||
const docModeService = host.std.get(DocModeProvider);
|
const docModeService = host.std.get(DocModeProvider);
|
||||||
const { layer } = surfaceService;
|
const layer = host.std.get(GfxControllerIdentifier).layer;
|
||||||
const curMode = docModeService.getEditorMode() || 'page';
|
const curMode = docModeService.getEditorMode() || 'page';
|
||||||
const viewportCenter = getViewportCenter(
|
const viewportCenter = getViewportCenter(curMode, host.std);
|
||||||
curMode,
|
|
||||||
rootService as RootService
|
|
||||||
);
|
|
||||||
const newBlockIndex = layer.generateIndex();
|
const newBlockIndex = layer.generateIndex();
|
||||||
// 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') {
|
||||||
@@ -402,11 +393,9 @@ 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.std.getService<EdgelessRootService>('affine:page');
|
|
||||||
if (!service) return;
|
|
||||||
|
|
||||||
const elements = service.selection.selectedElements;
|
|
||||||
|
|
||||||
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
|
const elements = gfx.selection.selectedElements;
|
||||||
const props: { displayMode: NoteDisplayMode; xywh?: SerializedXYWH } = {
|
const props: { displayMode: NoteDisplayMode; xywh?: SerializedXYWH } = {
|
||||||
displayMode: NoteDisplayMode.EdgelessOnly,
|
displayMode: NoteDisplayMode.EdgelessOnly,
|
||||||
};
|
};
|
||||||
@@ -423,7 +412,7 @@ const ADD_TO_EDGELESS_AS_NOTE = {
|
|||||||
|
|
||||||
await insertFromMarkdown(host, content, doc, id, 0);
|
await insertFromMarkdown(host, content, doc, id, 0);
|
||||||
|
|
||||||
service.selection.set({
|
gfx.selection.set({
|
||||||
elements: [id],
|
elements: [id],
|
||||||
editing: false,
|
editing: false,
|
||||||
});
|
});
|
||||||
@@ -488,10 +477,6 @@ const CREATE_AS_LINKED_DOC = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const service = host.std.getService<EdgelessRootService>('affine:page');
|
|
||||||
if (!service) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const docModeService = host.std.get(DocModeProvider);
|
const docModeService = host.std.get(DocModeProvider);
|
||||||
const mode = docModeService.getEditorMode();
|
const mode = docModeService.getEditorMode();
|
||||||
if (mode !== 'edgeless') {
|
if (mode !== 'edgeless') {
|
||||||
@@ -506,8 +491,9 @@ const CREATE_AS_LINKED_DOC = {
|
|||||||
const noteId = newDoc.addBlock('affine:note', {}, rootId);
|
const noteId = newDoc.addBlock('affine:note', {}, rootId);
|
||||||
await insertFromMarkdown(host, content, newDoc, noteId, 0);
|
await insertFromMarkdown(host, content, newDoc, noteId, 0);
|
||||||
|
|
||||||
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
// Add a linked doc card to link to the new doc
|
// Add a linked doc card to link to the new doc
|
||||||
const elements = service.selection.selectedElements;
|
const elements = gfx.selection.selectedElements;
|
||||||
const width = 364;
|
const width = 364;
|
||||||
const height = 390;
|
const height = 390;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
@@ -523,12 +509,12 @@ const CREATE_AS_LINKED_DOC = {
|
|||||||
|
|
||||||
// If the selected elements are not in the viewport, center the linked doc card
|
// If the selected elements are not in the viewport, center the linked doc card
|
||||||
if (x === Number.POSITIVE_INFINITY || y === Number.POSITIVE_INFINITY) {
|
if (x === Number.POSITIVE_INFINITY || y === Number.POSITIVE_INFINITY) {
|
||||||
const viewportCenter = getViewportCenter(mode, service);
|
const viewportCenter = getViewportCenter(mode, host.std);
|
||||||
x = viewportCenter.x - width / 2;
|
x = viewportCenter.x - width / 2;
|
||||||
y = viewportCenter.y - height / 2;
|
y = viewportCenter.y - height / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
service.crud.addBlock(
|
host.std.get(EdgelessCRUDIdentifier).addBlock(
|
||||||
'affine:embed-linked-doc',
|
'affine:embed-linked-doc',
|
||||||
{
|
{
|
||||||
xywh: `[${x}, ${y}, ${width}, ${height}]`,
|
xywh: `[${x}, ${y}, ${width}, ${height}]`,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { type EditorHost } from '@blocksuite/affine/block-std';
|
|||||||
import {
|
import {
|
||||||
type AIItemGroupConfig,
|
type AIItemGroupConfig,
|
||||||
createLitPortal,
|
createLitPortal,
|
||||||
EdgelessRootService,
|
|
||||||
HoverController,
|
HoverController,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||||
@@ -14,7 +13,6 @@ import { property, query } from 'lit/decorators.js';
|
|||||||
import { ref } from 'lit/directives/ref.js';
|
import { ref } from 'lit/directives/ref.js';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import { getRootService } from '../../utils/selection-utils';
|
|
||||||
import type { ButtonSize } from './ask-ai-icon';
|
import type { ButtonSize } from './ask-ai-icon';
|
||||||
|
|
||||||
type toggleType = 'hover' | 'click';
|
type toggleType = 'hover' | 'click';
|
||||||
@@ -27,14 +25,6 @@ export type AskAIButtonOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class AskAIButton extends WithDisposable(LitElement) {
|
export class AskAIButton extends WithDisposable(LitElement) {
|
||||||
get _edgeless() {
|
|
||||||
const rootService = getRootService(this.host);
|
|
||||||
if (rootService instanceof EdgelessRootService) {
|
|
||||||
return rootService;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
.ask-ai-button {
|
.ask-ai-button {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
+4
-10
@@ -1,7 +1,7 @@
|
|||||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
type AIItemGroupConfig,
|
type AIItemGroupConfig,
|
||||||
EdgelessRootService,
|
DocModeProvider,
|
||||||
scrollbarStyle,
|
scrollbarStyle,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||||
@@ -9,8 +9,6 @@ import { css, html, LitElement } from 'lit';
|
|||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import { getRootService } from '../../utils/selection-utils';
|
|
||||||
|
|
||||||
export class AskAIPanel extends WithDisposable(LitElement) {
|
export class AskAIPanel extends WithDisposable(LitElement) {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
:host {
|
:host {
|
||||||
@@ -50,12 +48,8 @@ export class AskAIPanel extends WithDisposable(LitElement) {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
accessor minWidth = 330;
|
accessor minWidth = 330;
|
||||||
|
|
||||||
get _edgeless() {
|
get _isEdgelessMode() {
|
||||||
const rootService = getRootService(this.host);
|
return this.host.std.get(DocModeProvider).getEditorMode() === 'edgeless';
|
||||||
if (rootService instanceof EdgelessRootService) {
|
|
||||||
return rootService;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get _actionGroups() {
|
get _actionGroups() {
|
||||||
@@ -66,7 +60,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._isEdgelessMode ? 'edgeless' : 'page',
|
||||||
this.host
|
this.host
|
||||||
)
|
)
|
||||||
: true
|
: true
|
||||||
|
|||||||
@@ -74,10 +74,6 @@ export class ChatCopyMore extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private get _rootService() {
|
|
||||||
return this.host.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _selectionValue() {
|
private get _selectionValue() {
|
||||||
return this.host.selection.value;
|
return this.host.selection.value;
|
||||||
}
|
}
|
||||||
@@ -130,7 +126,6 @@ export class ChatCopyMore extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly _notifySuccess = (title: string) => {
|
private readonly _notifySuccess = (title: string) => {
|
||||||
if (!this._rootService) return;
|
|
||||||
const notificationService = this.host.std.getOptional(NotificationProvider);
|
const notificationService = this.host.std.getOptional(NotificationProvider);
|
||||||
notificationService?.notify({
|
notificationService?.notify({
|
||||||
title: title,
|
title: title,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
import type {
|
import type {
|
||||||
AffineAIPanelWidget,
|
AffineAIPanelWidget,
|
||||||
AIItemConfig,
|
AIItemConfig,
|
||||||
EdgelessCopilotWidget,
|
EdgelessCopilotWidget,
|
||||||
EdgelessElementToolbarWidget,
|
EdgelessElementToolbarWidget,
|
||||||
EdgelessRootService,
|
|
||||||
MindmapElementModel,
|
MindmapElementModel,
|
||||||
ShapeElementModel,
|
ShapeElementModel,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
@@ -35,17 +35,12 @@ import { AIProvider } from '../provider';
|
|||||||
import { reportResponse } from '../utils/action-reporter';
|
import { reportResponse } from '../utils/action-reporter';
|
||||||
import { getAIPanelWidget } from '../utils/ai-widgets';
|
import { getAIPanelWidget } from '../utils/ai-widgets';
|
||||||
import type { AIContext } from '../utils/context';
|
import type { AIContext } from '../utils/context';
|
||||||
import {
|
import { getEdgelessCopilotWidget, isMindMapRoot } from '../utils/edgeless';
|
||||||
getEdgelessCopilotWidget,
|
|
||||||
getService,
|
|
||||||
isMindMapRoot,
|
|
||||||
} from '../utils/edgeless';
|
|
||||||
import { preprocessHtml } from '../utils/html';
|
import { preprocessHtml } from '../utils/html';
|
||||||
import { fetchImageToFile } from '../utils/image';
|
import { fetchImageToFile } from '../utils/image';
|
||||||
import {
|
import {
|
||||||
getCopilotSelectedElems,
|
getCopilotSelectedElems,
|
||||||
getEdgelessRootFromEditor,
|
getEdgelessRootFromEditor,
|
||||||
getEdgelessService,
|
|
||||||
getSurfaceElementFromEditor,
|
getSurfaceElementFromEditor,
|
||||||
} from '../utils/selection-utils';
|
} from '../utils/selection-utils';
|
||||||
import { createTemplateJob } from '../utils/template-job';
|
import { createTemplateJob } from '../utils/template-job';
|
||||||
@@ -222,9 +217,9 @@ function insertBelow(
|
|||||||
) {
|
) {
|
||||||
insertFromMarkdown(host, markdown, host.doc, parentId, index)
|
insertFromMarkdown(host, markdown, host.doc, parentId, index)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const service = getService(host);
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
|
|
||||||
service.selection.set({
|
gfx.selection.set({
|
||||||
elements: [parentId],
|
elements: [parentId],
|
||||||
editing: false,
|
editing: false,
|
||||||
});
|
});
|
||||||
@@ -398,9 +393,8 @@ export function responseToExpandMindmap(host: EditorHost, ctx: AIContext) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const edgelessService = getEdgelessService(host);
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
|
gfx.selection.set({
|
||||||
edgelessService.selection.set({
|
|
||||||
elements: [subtree.element.id],
|
elements: [subtree.element.id],
|
||||||
editing: false,
|
editing: false,
|
||||||
});
|
});
|
||||||
@@ -410,7 +404,7 @@ export function responseToExpandMindmap(host: EditorHost, ctx: AIContext) {
|
|||||||
|
|
||||||
function responseToBrainstormMindmap(host: EditorHost, ctx: AIContext) {
|
function responseToBrainstormMindmap(host: EditorHost, ctx: AIContext) {
|
||||||
const aiPanel = getAIPanelWidget(host);
|
const aiPanel = getAIPanelWidget(host);
|
||||||
const edgelessService = getEdgelessService(host);
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
const edgelessCopilot = getEdgelessCopilotWidget(host);
|
const edgelessCopilot = getEdgelessCopilotWidget(host);
|
||||||
const selectionRect = edgelessCopilot.selectionModelRect;
|
const selectionRect = edgelessCopilot.selectionModelRect;
|
||||||
const surface = getSurfaceBlock(host.doc);
|
const surface = getSurfaceBlock(host.doc);
|
||||||
@@ -456,13 +450,13 @@ function responseToBrainstormMindmap(host: EditorHost, ctx: AIContext) {
|
|||||||
|
|
||||||
// This is a workaround to make sure mindmap and other microtask are done
|
// This is a workaround to make sure mindmap and other microtask are done
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
edgelessService.viewport.setViewportByBound(
|
gfx.viewport.setViewportByBound(
|
||||||
mindmap.elementBound,
|
mindmap.elementBound,
|
||||||
[20, 20, 20, 20],
|
[20, 20, 20, 20],
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
edgelessService.selection.set({
|
gfx.selection.set({
|
||||||
elements: [mindmap.tree.element.id],
|
elements: [mindmap.tree.element.id],
|
||||||
editing: false,
|
editing: false,
|
||||||
});
|
});
|
||||||
@@ -508,9 +502,6 @@ async function responseToCreateSlides(host: EditorHost, ctx: AIContext) {
|
|||||||
const { contents = [], images = [] } = data;
|
const { contents = [], images = [] } = data;
|
||||||
if (contents.length === 0) return;
|
if (contents.length === 0) return;
|
||||||
|
|
||||||
const service = host.std.getService<EdgelessRootService>('affine:page');
|
|
||||||
if (!service) return;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < contents.length; i++) {
|
for (let i = 0; i < contents.length; i++) {
|
||||||
const image = images[i] || [];
|
const image = images[i] || [];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AINetworkSearchService } from '@affine/core/modules/ai-button/services/network-search';
|
import { AINetworkSearchService } from '@affine/core/modules/ai-button/services/network-search';
|
||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
type AffineAIPanelWidget,
|
type AffineAIPanelWidget,
|
||||||
type AffineAIPanelWidgetConfig,
|
type AffineAIPanelWidgetConfig,
|
||||||
@@ -38,7 +39,7 @@ import { AIProvider } from './provider';
|
|||||||
import { reportResponse } from './utils/action-reporter';
|
import { reportResponse } from './utils/action-reporter';
|
||||||
import { getAIPanelWidget } from './utils/ai-widgets';
|
import { getAIPanelWidget } from './utils/ai-widgets';
|
||||||
import { AIContext } from './utils/context';
|
import { AIContext } from './utils/context';
|
||||||
import { findNoteBlockModel, getService } from './utils/edgeless';
|
import { findNoteBlockModel } from './utils/edgeless';
|
||||||
import { copyTextAnswer } from './utils/editor-actions';
|
import { copyTextAnswer } from './utils/editor-actions';
|
||||||
import { getSelections } from './utils/selection-utils';
|
import { getSelections } from './utils/selection-utils';
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ function createNewNote(host: EditorHost): AIItemConfig {
|
|||||||
const newBound = new Bound(bound.x - bound.w - 20, bound.y, bound.w, 72);
|
const newBound = new Bound(bound.x - bound.w - 20, bound.y, bound.w, 72);
|
||||||
const doc = host.doc;
|
const doc = host.doc;
|
||||||
const panel = getAIPanelWidget(host);
|
const panel = getAIPanelWidget(host);
|
||||||
const service = getService(host);
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
doc.transact(() => {
|
doc.transact(() => {
|
||||||
assertExists(doc.root);
|
assertExists(doc.root);
|
||||||
const noteBlockId = doc.addBlock(
|
const noteBlockId = doc.addBlock(
|
||||||
@@ -101,7 +102,7 @@ function createNewNote(host: EditorHost): AIItemConfig {
|
|||||||
{
|
{
|
||||||
xywh: newBound.serialize(),
|
xywh: newBound.serialize(),
|
||||||
displayMode: NoteDisplayMode.EdgelessOnly,
|
displayMode: NoteDisplayMode.EdgelessOnly,
|
||||||
index: service.generateIndex(),
|
index: gfx.layer.generateIndex(),
|
||||||
},
|
},
|
||||||
doc.root.id
|
doc.root.id
|
||||||
);
|
);
|
||||||
@@ -109,7 +110,7 @@ function createNewNote(host: EditorHost): AIItemConfig {
|
|||||||
assertExists(panel.answer);
|
assertExists(panel.answer);
|
||||||
insertFromMarkdown(host, panel.answer, doc, noteBlockId)
|
insertFromMarkdown(host, panel.answer, doc, noteBlockId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
service.selection.set({
|
gfx.selection.set({
|
||||||
elements: [noteBlockId],
|
elements: [noteBlockId],
|
||||||
editing: false,
|
editing: false,
|
||||||
});
|
});
|
||||||
@@ -119,7 +120,7 @@ function createNewNote(host: EditorHost): AIItemConfig {
|
|||||||
if (!newNote || !matchModels(newNote, [NoteBlockModel])) return;
|
if (!newNote || !matchModels(newNote, [NoteBlockModel])) return;
|
||||||
const newNoteBound = Bound.deserialize(newNote.xywh);
|
const newNoteBound = Bound.deserialize(newNote.xywh);
|
||||||
const bounds = [bound, newNoteBound];
|
const bounds = [bound, newNoteBound];
|
||||||
service.gfx.fitToScreen({
|
gfx.fitToScreen({
|
||||||
bounds,
|
bounds,
|
||||||
padding: [20, 20, 20, 20],
|
padding: [20, 20, 20, 20],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import type { Bound } from '@blocksuite/affine/global/utils';
|
|||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { query } from 'lit/decorators.js';
|
import { query } from 'lit/decorators.js';
|
||||||
|
|
||||||
import type { MindmapService } from './mindmap-service.js';
|
import { MindmapService } from './mindmap-service.js';
|
||||||
|
|
||||||
export class MindmapSurfaceBlock extends BlockComponent<SurfaceBlockModel> {
|
export class MindmapSurfaceBlock extends BlockComponent<SurfaceBlockModel> {
|
||||||
renderer?: CanvasRenderer;
|
renderer?: CanvasRenderer;
|
||||||
@@ -30,7 +30,7 @@ export class MindmapSurfaceBlock extends BlockComponent<SurfaceBlockModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get mindmapService() {
|
get mindmapService() {
|
||||||
return this.std.getService('affine:page') as unknown as MindmapService;
|
return this.std.get(MindmapService);
|
||||||
}
|
}
|
||||||
|
|
||||||
get viewport() {
|
get viewport() {
|
||||||
|
|||||||
+13
-17
@@ -4,7 +4,8 @@ import {
|
|||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
ConnectorMode,
|
ConnectorMode,
|
||||||
DocModeProvider,
|
DocModeProvider,
|
||||||
type EdgelessRootService,
|
EdgelessCRUDIdentifier,
|
||||||
|
getSurfaceBlock,
|
||||||
NotificationProvider,
|
NotificationProvider,
|
||||||
TelemetryProvider,
|
TelemetryProvider,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
@@ -33,10 +34,6 @@ import { calcChildBound } from './utils';
|
|||||||
export class AIChatBlockPeekView extends LitElement {
|
export class AIChatBlockPeekView extends LitElement {
|
||||||
static override styles = PeekViewStyles;
|
static override styles = PeekViewStyles;
|
||||||
|
|
||||||
private get _rootService() {
|
|
||||||
return this.host.std.getService('affine:page');
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _modeService() {
|
private get _modeService() {
|
||||||
return this.host.std.get(DocModeProvider);
|
return this.host.std.get(DocModeProvider);
|
||||||
}
|
}
|
||||||
@@ -172,9 +169,10 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const edgelessService = this._rootService as EdgelessRootService;
|
const bound = calcChildBound(this.parentModel, this.host.std);
|
||||||
const bound = calcChildBound(this.parentModel, edgelessService);
|
|
||||||
const aiChatBlockId = edgelessService.crud.addBlock(
|
const crud = this.host.std.get(EdgelessCRUDIdentifier);
|
||||||
|
const aiChatBlockId = crud.addBlock(
|
||||||
'affine:embed-ai-chat',
|
'affine:embed-ai-chat',
|
||||||
{
|
{
|
||||||
xywh: bound.serialize(),
|
xywh: bound.serialize(),
|
||||||
@@ -193,7 +191,7 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
this.updateContext({ currentChatBlockId: aiChatBlockId });
|
this.updateContext({ currentChatBlockId: aiChatBlockId });
|
||||||
|
|
||||||
// Connect the parent chat block to the AI chat block
|
// Connect the parent chat block to the AI chat block
|
||||||
edgelessService.crud.addElement(CanvasElementType.CONNECTOR, {
|
crud.addElement(CanvasElementType.CONNECTOR, {
|
||||||
mode: ConnectorMode.Curve,
|
mode: ConnectorMode.Curve,
|
||||||
controllers: [],
|
controllers: [],
|
||||||
source: { id: this.parentChatBlockId },
|
source: { id: this.parentChatBlockId },
|
||||||
@@ -249,7 +247,6 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
* Clean current chat messages and delete the newly created AI chat block
|
* Clean current chat messages and delete the newly created AI chat block
|
||||||
*/
|
*/
|
||||||
cleanCurrentChatHistories = async () => {
|
cleanCurrentChatHistories = async () => {
|
||||||
if (!this._rootService) return;
|
|
||||||
const notificationService = this.host.std.getOptional(NotificationProvider);
|
const notificationService = this.host.std.getOptional(NotificationProvider);
|
||||||
if (!notificationService) return;
|
if (!notificationService) return;
|
||||||
|
|
||||||
@@ -275,18 +272,17 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentChatBlockId) {
|
if (currentChatBlockId) {
|
||||||
const edgelessService = this._rootService as EdgelessRootService;
|
const surface = getSurfaceBlock(doc);
|
||||||
|
const crud = this.host.std.get(EdgelessCRUDIdentifier);
|
||||||
const chatBlock = doc.getBlock(currentChatBlockId)?.model;
|
const chatBlock = doc.getBlock(currentChatBlockId)?.model;
|
||||||
if (chatBlock) {
|
if (chatBlock) {
|
||||||
const connectors = edgelessService.getConnectors(
|
const connectors = surface?.getConnectors(chatBlock.id);
|
||||||
chatBlock as AIChatBlockModel
|
|
||||||
);
|
|
||||||
doc.transact(() => {
|
doc.transact(() => {
|
||||||
// Delete the AI chat block
|
// Delete the AI chat block
|
||||||
edgelessService.removeElement(currentChatBlockId);
|
crud.removeElement(currentChatBlockId);
|
||||||
// Delete the connectors
|
// Delete the connectors
|
||||||
connectors.forEach(connector => {
|
connectors?.forEach(connector => {
|
||||||
edgelessService.removeElement(connector.id);
|
crud.removeElement(connector.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import type { EdgelessRootService } from '@blocksuite/affine/blocks';
|
import type { BlockStdScope } from '@blocksuite/affine/block-std';
|
||||||
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
getSurfaceBlock,
|
||||||
|
} from '@blocksuite/affine/blocks';
|
||||||
import { Bound } from '@blocksuite/affine/global/utils';
|
import { Bound } from '@blocksuite/affine/global/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -19,18 +23,19 @@ import {
|
|||||||
*/
|
*/
|
||||||
export function calcChildBound(
|
export function calcChildBound(
|
||||||
parentModel: AIChatBlockModel,
|
parentModel: AIChatBlockModel,
|
||||||
service: EdgelessRootService
|
std: BlockStdScope
|
||||||
) {
|
) {
|
||||||
|
const surface = getSurfaceBlock(std.store);
|
||||||
|
const crud = std.get(EdgelessCRUDIdentifier);
|
||||||
const parentXYWH = Bound.deserialize(parentModel.xywh);
|
const parentXYWH = Bound.deserialize(parentModel.xywh);
|
||||||
const { x: parentX, y: parentY, w: parentWidth } = parentXYWH;
|
const { x: parentX, y: parentY, w: parentWidth } = parentXYWH;
|
||||||
|
|
||||||
const connectors = service.getConnectors(parentModel.id);
|
const connectors = surface?.getConnectors(parentModel.id);
|
||||||
const gapX = CHAT_BLOCK_WIDTH;
|
const gapX = CHAT_BLOCK_WIDTH;
|
||||||
const gapY = 60;
|
const gapY = 60;
|
||||||
const defaultX = parentX + parentWidth + gapX;
|
const defaultX = parentX + parentWidth + gapX;
|
||||||
const defaultY = parentY;
|
const defaultY = parentY;
|
||||||
|
if (!connectors?.length) {
|
||||||
if (!connectors.length) {
|
|
||||||
return new Bound(defaultX, defaultY, CHAT_BLOCK_WIDTH, CHAT_BLOCK_HEIGHT);
|
return new Bound(defaultX, defaultY, CHAT_BLOCK_WIDTH, CHAT_BLOCK_HEIGHT);
|
||||||
} else {
|
} else {
|
||||||
// Filter out the connectors which source is the parent block
|
// Filter out the connectors which source is the parent block
|
||||||
@@ -41,7 +46,7 @@ export function calcChildBound(
|
|||||||
const targetBlocks = childConnectors
|
const targetBlocks = childConnectors
|
||||||
.map(connector => connector.target.id)
|
.map(connector => connector.target.id)
|
||||||
.filter(id => id !== undefined)
|
.filter(id => id !== undefined)
|
||||||
.map(id => service.crud.getElementById(id))
|
.map(id => crud.getElementById(id))
|
||||||
.filter(block => !!block);
|
.filter(block => !!block);
|
||||||
|
|
||||||
if (targetBlocks.length) {
|
if (targetBlocks.length) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import type { EdgelessRootService } from '@blocksuite/affine/blocks';
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
import type { BlockSnapshot } from '@blocksuite/affine/store';
|
import type { BlockSnapshot } from '@blocksuite/affine/store';
|
||||||
|
|
||||||
import { markdownToSnapshot } from '../../_common';
|
import { markdownToSnapshot } from '../../_common';
|
||||||
@@ -13,11 +13,10 @@ import {
|
|||||||
} from './template';
|
} from './template';
|
||||||
|
|
||||||
export const PPTBuilder = (host: EditorHost) => {
|
export const PPTBuilder = (host: EditorHost) => {
|
||||||
const service = host.std.getService<EdgelessRootService>('affine:page');
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
const docs: PPTDoc[] = [];
|
const docs: PPTDoc[] = [];
|
||||||
const contents: unknown[] = [];
|
const contents: unknown[] = [];
|
||||||
const allImages: TemplateImage[][] = [];
|
const allImages: TemplateImage[][] = [];
|
||||||
if (!service) return;
|
|
||||||
|
|
||||||
const addDoc = async (block: BlockSnapshot) => {
|
const addDoc = async (block: BlockSnapshot) => {
|
||||||
const sections = block.children.map(v => {
|
const sections = block.children.map(v => {
|
||||||
@@ -62,7 +61,7 @@ export const PPTBuilder = (host: EditorHost) => {
|
|||||||
const block = snapshot.snapshot.content[0];
|
const block = snapshot.snapshot.content[0];
|
||||||
for (const child of block.children) {
|
for (const child of block.children) {
|
||||||
await addDoc(child);
|
await addDoc(child);
|
||||||
service.gfx.fitToScreen();
|
gfx.fitToScreen();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { GfxModel } from '@blocksuite/affine/block-std/gfx';
|
|||||||
import {
|
import {
|
||||||
AFFINE_EDGELESS_COPILOT_WIDGET,
|
AFFINE_EDGELESS_COPILOT_WIDGET,
|
||||||
type EdgelessCopilotWidget,
|
type EdgelessCopilotWidget,
|
||||||
type EdgelessRootService,
|
|
||||||
matchModels,
|
matchModels,
|
||||||
MindmapElementModel,
|
MindmapElementModel,
|
||||||
NoteBlockModel,
|
NoteBlockModel,
|
||||||
@@ -43,14 +42,6 @@ export function isMindmapChild(ele: GfxModel) {
|
|||||||
return ele?.group instanceof MindmapElementModel && !isMindMapRoot(ele);
|
return ele?.group instanceof MindmapElementModel && !isMindMapRoot(ele);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getService(host: EditorHost) {
|
|
||||||
const edgelessService = host.std.getService(
|
|
||||||
'affine:page'
|
|
||||||
) as EdgelessRootService;
|
|
||||||
|
|
||||||
return edgelessService;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getEdgelessCopilotWidget(
|
export function getEdgelessCopilotWidget(
|
||||||
host: EditorHost
|
host: EditorHost
|
||||||
): EdgelessCopilotWidget {
|
): EdgelessCopilotWidget {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { type EditorHost, TextSelection } from '@blocksuite/affine/block-std';
|
import { type EditorHost, TextSelection } from '@blocksuite/affine/block-std';
|
||||||
import type { GfxModel } from '@blocksuite/affine/block-std/gfx';
|
import {
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
type GfxModel,
|
||||||
|
} from '@blocksuite/affine/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
BlocksUtils,
|
BlocksUtils,
|
||||||
type CopilotTool,
|
type CopilotTool,
|
||||||
DatabaseBlockModel,
|
DatabaseBlockModel,
|
||||||
EdgelessRootService,
|
|
||||||
type FrameBlockModel,
|
type FrameBlockModel,
|
||||||
getBlockSelectionsCommand,
|
getBlockSelectionsCommand,
|
||||||
getImageSelectionsCommand,
|
getImageSelectionsCommand,
|
||||||
@@ -22,11 +24,7 @@ import {
|
|||||||
} from '@blocksuite/affine/store';
|
} from '@blocksuite/affine/store';
|
||||||
|
|
||||||
import { getContentFromSlice } from '../../_common';
|
import { getContentFromSlice } from '../../_common';
|
||||||
import { getEdgelessCopilotWidget, getService } from './edgeless';
|
import { getEdgelessCopilotWidget } from './edgeless';
|
||||||
|
|
||||||
export const getRootService = (host: EditorHost) => {
|
|
||||||
return host.std.getService('affine:page');
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getEdgelessRootFromEditor(editor: EditorHost) {
|
export function getEdgelessRootFromEditor(editor: EditorHost) {
|
||||||
const edgelessRoot = editor.getElementsByTagName('affine-edgeless-root')[0];
|
const edgelessRoot = editor.getElementsByTagName('affine-edgeless-root')[0];
|
||||||
@@ -36,14 +34,6 @@ export function getEdgelessRootFromEditor(editor: EditorHost) {
|
|||||||
}
|
}
|
||||||
return edgelessRoot;
|
return edgelessRoot;
|
||||||
}
|
}
|
||||||
export function getEdgelessService(editor: EditorHost) {
|
|
||||||
const rootService = editor.std.getService('affine:page');
|
|
||||||
if (rootService instanceof EdgelessRootService) {
|
|
||||||
return rootService;
|
|
||||||
}
|
|
||||||
alert('Please switch to edgeless mode');
|
|
||||||
throw new Error('Please open switch to edgeless mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function selectedToCanvas(host: EditorHost) {
|
export async function selectedToCanvas(host: EditorHost) {
|
||||||
const edgelessRoot = getEdgelessRootFromEditor(host);
|
const edgelessRoot = getEdgelessRootFromEditor(host);
|
||||||
@@ -287,15 +277,15 @@ export const getSelectedNoteAnchor = (host: EditorHost, id: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getCopilotSelectedElems(host: EditorHost): GfxModel[] {
|
export function getCopilotSelectedElems(host: EditorHost): GfxModel[] {
|
||||||
const service = getService(host);
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
const copilotWidget = getEdgelessCopilotWidget(host);
|
const copilotWidget = getEdgelessCopilotWidget(host);
|
||||||
|
|
||||||
if (copilotWidget.visible) {
|
if (copilotWidget.visible) {
|
||||||
const currentTool = service.gfx.tool.currentTool$.peek() as CopilotTool;
|
const currentTool = gfx.tool.currentTool$.peek() as CopilotTool;
|
||||||
return currentTool?.selectedElements ?? [];
|
return currentTool?.selectedElements ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return service.selection.selectedElements;
|
return gfx.selection.selectedElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const imageCustomInput = async (host: EditorHost) => {
|
export const imageCustomInput = async (host: EditorHost) => {
|
||||||
|
|||||||
+16
-20
@@ -9,14 +9,12 @@ import { I18n } from '@affine/i18n';
|
|||||||
import type { BlockStdScope } from '@blocksuite/affine/block-std';
|
import type { BlockStdScope } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
type GfxBlockElementModel,
|
type GfxBlockElementModel,
|
||||||
|
GfxControllerIdentifier,
|
||||||
type GfxModel,
|
type GfxModel,
|
||||||
GfxPrimitiveElementModel,
|
GfxPrimitiveElementModel,
|
||||||
isGfxGroupCompatibleModel,
|
isGfxGroupCompatibleModel,
|
||||||
} from '@blocksuite/affine/block-std/gfx';
|
} from '@blocksuite/affine/block-std/gfx';
|
||||||
import type {
|
import type { MenuContext } from '@blocksuite/affine/blocks';
|
||||||
EdgelessRootService,
|
|
||||||
MenuContext,
|
|
||||||
} from '@blocksuite/affine/blocks';
|
|
||||||
import { Bound, getCommonBound } from '@blocksuite/affine/global/utils';
|
import { Bound, getCommonBound } from '@blocksuite/affine/global/utils';
|
||||||
import { CopyAsImgaeIcon } from '@blocksuite/icons/lit';
|
import { CopyAsImgaeIcon } from '@blocksuite/icons/lit';
|
||||||
import type { FrameworkProvider } from '@toeverything/infra';
|
import type { FrameworkProvider } from '@toeverything/infra';
|
||||||
@@ -135,11 +133,9 @@ export function createCopyAsPngMenuItem(framework: FrameworkProvider) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const service =
|
const gfx = ctx.host.std.get(GfxControllerIdentifier);
|
||||||
ctx.host.std.getService<EdgelessRootService>('affine:page');
|
|
||||||
if (!service) return;
|
|
||||||
|
|
||||||
let selected = service.selection.selectedElements;
|
let selected = gfx.selection.selectedElements;
|
||||||
// select mindmap if root node selected
|
// select mindmap if root node selected
|
||||||
const maybeMindmap = selected[0];
|
const maybeMindmap = selected[0];
|
||||||
const mindmapId = maybeMindmap.group?.id;
|
const mindmapId = maybeMindmap.group?.id;
|
||||||
@@ -148,31 +144,31 @@ export function createCopyAsPngMenuItem(framework: FrameworkProvider) {
|
|||||||
mindmapId &&
|
mindmapId &&
|
||||||
(isMindMapRoot(maybeMindmap) || isMindmapChild(maybeMindmap))
|
(isMindMapRoot(maybeMindmap) || isMindmapChild(maybeMindmap))
|
||||||
) {
|
) {
|
||||||
service.gfx.selection.set({ elements: [mindmapId] });
|
gfx.selection.set({ elements: [mindmapId] });
|
||||||
}
|
}
|
||||||
|
|
||||||
// select bound
|
// select bound
|
||||||
selected = service.selection.selectedElements;
|
selected = gfx.selection.selectedElements;
|
||||||
const elements = withDescendantElements(selected);
|
const elements = withDescendantElements(selected);
|
||||||
const bounds = elements.map(element => Bound.deserialize(element.xywh));
|
const bounds = elements.map(element => Bound.deserialize(element.xywh));
|
||||||
const bound = getCommonBound(bounds);
|
const bound = getCommonBound(bounds);
|
||||||
if (!bound) return;
|
if (!bound) return;
|
||||||
const { zoom } = service.viewport;
|
const { zoom } = gfx.viewport;
|
||||||
const exBound = expandBound(bound, MARGIN * zoom);
|
const exBound = expandBound(bound, MARGIN * zoom);
|
||||||
|
|
||||||
// fit to screen
|
// fit to screen
|
||||||
if (
|
if (
|
||||||
!isInside(service.viewport.viewportBounds, exBound) ||
|
!isInside(gfx.viewport.viewportBounds, exBound) ||
|
||||||
service.viewport.zoom < 1
|
gfx.viewport.zoom < 1
|
||||||
) {
|
) {
|
||||||
service.viewport.setViewportByBound(bound, [20, 20, 20, 20], false);
|
gfx.viewport.setViewportByBound(bound, [20, 20, 20, 20], false);
|
||||||
if (service.viewport.zoom > 1) {
|
if (gfx.viewport.zoom > 1) {
|
||||||
service.viewport.setZoom(1);
|
gfx.viewport.setZoom(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide unselected overlap elements
|
// hide unselected overlap elements
|
||||||
const overlapElements = service.gfx.gfxElements.filter(ele => {
|
const overlapElements = gfx.gfxElements.filter(ele => {
|
||||||
const eleBound = Bound.deserialize(ele.xywh);
|
const eleBound = Bound.deserialize(ele.xywh);
|
||||||
const exEleBound = expandBound(eleBound, MARGIN * zoom);
|
const exEleBound = expandBound(eleBound, MARGIN * zoom);
|
||||||
const isSelected = elements.includes(ele);
|
const isSelected = elements.includes(ele);
|
||||||
@@ -190,14 +186,14 @@ export function createCopyAsPngMenuItem(framework: FrameworkProvider) {
|
|||||||
if (!apis) return;
|
if (!apis) return;
|
||||||
try {
|
try {
|
||||||
const domRect = getSelectedRect();
|
const domRect = getSelectedRect();
|
||||||
const { zoom } = service.viewport;
|
const { zoom } = gfx.viewport;
|
||||||
const isFrameSelected =
|
const isFrameSelected =
|
||||||
selected.length === 1 &&
|
selected.length === 1 &&
|
||||||
(selected[0] as GfxBlockElementModel).flavour === 'affine:frame';
|
(selected[0] as GfxBlockElementModel).flavour === 'affine:frame';
|
||||||
const margin = isFrameSelected ? -2 : MARGIN * zoom;
|
const margin = isFrameSelected ? -2 : MARGIN * zoom;
|
||||||
|
|
||||||
service.selection.clear();
|
gfx.selection.clear();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
apis.ui
|
apis.ui
|
||||||
.captureArea({
|
.captureArea({
|
||||||
x: domRect.left - margin,
|
x: domRect.left - margin,
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import { copyTextToClipboard } from '@affine/core/utils/clipboard';
|
|||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import { GfxBlockElementModel } from '@blocksuite/affine/block-std/gfx';
|
import {
|
||||||
|
GfxBlockElementModel,
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
} from '@blocksuite/affine/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
type DocMode,
|
type DocMode,
|
||||||
type EdgelessRootService,
|
|
||||||
getBlockSelectionsCommand,
|
getBlockSelectionsCommand,
|
||||||
getImageSelectionsCommand,
|
getImageSelectionsCommand,
|
||||||
getSelectedModelsCommand,
|
getSelectedModelsCommand,
|
||||||
@@ -87,10 +89,9 @@ export const getSelectedNodes = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode === 'edgeless') {
|
if (mode === 'edgeless') {
|
||||||
const service = std.getService<EdgelessRootService>('affine:page');
|
const { selection } = std.get(GfxControllerIdentifier);
|
||||||
if (!service) return result;
|
|
||||||
|
|
||||||
for (const element of service.selection.selectedElements) {
|
for (const element of selection.selectedElements) {
|
||||||
if (element instanceof GfxBlockElementModel) {
|
if (element instanceof GfxBlockElementModel) {
|
||||||
blockIds.push(element.id);
|
blockIds.push(element.id);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+4
-9
@@ -9,13 +9,10 @@ import { SettingRow } from '@affine/component/setting-components';
|
|||||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import type {
|
import type { ShapeElementModel, ShapeName } from '@blocksuite/affine/blocks';
|
||||||
EdgelessRootService,
|
|
||||||
ShapeElementModel,
|
|
||||||
ShapeName,
|
|
||||||
} from '@blocksuite/affine/blocks';
|
|
||||||
import {
|
import {
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
FontFamily,
|
FontFamily,
|
||||||
FontFamilyMap,
|
FontFamilyMap,
|
||||||
FontStyle,
|
FontStyle,
|
||||||
@@ -354,18 +351,16 @@ export const ShapeSettings = () => {
|
|||||||
|
|
||||||
const firstUpdate = useCallback(
|
const firstUpdate = useCallback(
|
||||||
(doc: Store, editorHost: EditorHost) => {
|
(doc: Store, editorHost: EditorHost) => {
|
||||||
const edgelessService = editorHost.std.getService(
|
|
||||||
'affine:page'
|
|
||||||
) as EdgelessRootService;
|
|
||||||
const surface = getSurfaceBlock(doc);
|
const surface = getSurfaceBlock(doc);
|
||||||
if (!surface) return;
|
if (!surface) return;
|
||||||
|
const crud = editorHost.std.get(EdgelessCRUDIdentifier);
|
||||||
doc.readonly = false;
|
doc.readonly = false;
|
||||||
surface.getElementsByType('shape').forEach(node => {
|
surface.getElementsByType('shape').forEach(node => {
|
||||||
const shape = node as ShapeElementModel;
|
const shape = node as ShapeElementModel;
|
||||||
const { shapeType, radius } = shape;
|
const { shapeType, radius } = shape;
|
||||||
const shapeName = getShapeName(shapeType, radius);
|
const shapeName = getShapeName(shapeType, radius);
|
||||||
const props = editorSetting.get(`shape:${shapeName}`);
|
const props = editorSetting.get(`shape:${shapeName}`);
|
||||||
edgelessService.crud.updateElement(shape.id, props);
|
crud.updateElement(shape.id, props);
|
||||||
});
|
});
|
||||||
doc.readonly = true;
|
doc.readonly = true;
|
||||||
},
|
},
|
||||||
|
|||||||
+14
-13
@@ -4,18 +4,20 @@ import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
|||||||
import { AppThemeService } from '@affine/core/modules/theme';
|
import { AppThemeService } from '@affine/core/modules/theme';
|
||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
|
BlockServiceIdentifier,
|
||||||
BlockStdScope,
|
BlockStdScope,
|
||||||
LifeCycleWatcher,
|
LifeCycleWatcher,
|
||||||
StdIdentifier,
|
StdIdentifier,
|
||||||
} from '@blocksuite/affine/block-std';
|
} from '@blocksuite/affine/block-std';
|
||||||
import type { GfxPrimitiveElementModel } from '@blocksuite/affine/block-std/gfx';
|
import {
|
||||||
import type {
|
GfxControllerIdentifier,
|
||||||
EdgelessRootService,
|
type GfxPrimitiveElementModel,
|
||||||
ThemeExtension,
|
} from '@blocksuite/affine/block-std/gfx';
|
||||||
} from '@blocksuite/affine/blocks';
|
import type { ThemeExtension } from '@blocksuite/affine/blocks';
|
||||||
import {
|
import {
|
||||||
ColorScheme,
|
ColorScheme,
|
||||||
createSignalFromObservable,
|
createSignalFromObservable,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
SpecProvider,
|
SpecProvider,
|
||||||
ThemeExtensionIdentifier,
|
ThemeExtensionIdentifier,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
@@ -72,14 +74,12 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
const editorHost = editorHostRef.current;
|
const editorHost = editorHostRef.current;
|
||||||
const doc = docRef.current;
|
const doc = docRef.current;
|
||||||
if (!editorHost || !doc) return;
|
if (!editorHost || !doc) return;
|
||||||
const edgelessService = editorHost.std.getService(
|
const crud = editorHost.std.get(EdgelessCRUDIdentifier);
|
||||||
'affine:page'
|
|
||||||
) as EdgelessRootService;
|
|
||||||
const elements = getElements(doc);
|
const elements = getElements(doc);
|
||||||
const props = editorSetting.get(keyName) as any;
|
const props = editorSetting.get(keyName) as any;
|
||||||
doc.readonly = false;
|
doc.readonly = false;
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
edgelessService.crud.updateElement(element.id, props);
|
crud.updateElement(element.id, props);
|
||||||
});
|
});
|
||||||
doc.readonly = true;
|
doc.readonly = true;
|
||||||
}, [editorSetting, getElements, keyName]);
|
}, [editorSetting, getElements, keyName]);
|
||||||
@@ -107,9 +107,10 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// refresh viewport
|
// refresh viewport
|
||||||
const edgelessService = editorHost.std.getService(
|
const edgelessService = editorHost.std.get(
|
||||||
'affine:page'
|
BlockServiceIdentifier('affine:page')
|
||||||
) as EdgelessRootService;
|
);
|
||||||
|
const gfx = editorHost.std.get(GfxControllerIdentifier);
|
||||||
edgelessService.specSlots.viewConnected.once(({ component }) => {
|
edgelessService.specSlots.viewConnected.once(({ component }) => {
|
||||||
const edgelessBlock = component as any;
|
const edgelessBlock = component as any;
|
||||||
doc.readonly = false;
|
doc.readonly = false;
|
||||||
@@ -121,7 +122,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
doc.deleteBlock(frame);
|
doc.deleteBlock(frame);
|
||||||
}
|
}
|
||||||
const bound = boundMap.get(docName);
|
const bound = boundMap.get(docName);
|
||||||
bound && edgelessService.viewport.setViewportByBound(bound);
|
bound && gfx.viewport.setViewportByBound(bound);
|
||||||
doc.readonly = true;
|
doc.readonly = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { DefaultOpenProperty } from '@affine/core/components/doc-properties';
|
import type { DefaultOpenProperty } from '@affine/core/components/doc-properties';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
type DocMode,
|
type DocMode,
|
||||||
EdgelessRootService,
|
|
||||||
FeatureFlagService as BSFeatureFlagService,
|
FeatureFlagService as BSFeatureFlagService,
|
||||||
HighlightSelection,
|
HighlightSelection,
|
||||||
type ReferenceParams,
|
type ReferenceParams,
|
||||||
@@ -73,13 +73,11 @@ export class Editor extends Entity {
|
|||||||
isPresenting$ = new LiveData<boolean>(false);
|
isPresenting$ = new LiveData<boolean>(false);
|
||||||
|
|
||||||
togglePresentation() {
|
togglePresentation() {
|
||||||
const edgelessRootService =
|
const gfx = this.editorContainer$.value?.host?.std.get(
|
||||||
this.editorContainer$.value?.host?.std.getService(
|
GfxControllerIdentifier
|
||||||
'affine:page'
|
);
|
||||||
) as EdgelessRootService;
|
if (!gfx) return;
|
||||||
if (!edgelessRootService) return;
|
gfx.tool.setTool({
|
||||||
|
|
||||||
edgelessRootService.gfx.tool.setTool({
|
|
||||||
type: !this.isPresenting$.value ? 'frameNavigator' : 'default',
|
type: !this.isPresenting$.value ? 'frameNavigator' : 'default',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -200,7 +198,7 @@ export class Editor extends Entity {
|
|||||||
this.editorContainer$.next(editorContainer);
|
this.editorContainer$.next(editorContainer);
|
||||||
const unsubs: (() => void)[] = [];
|
const unsubs: (() => void)[] = [];
|
||||||
|
|
||||||
const rootService = editorContainer.host?.std.getService('affine:page');
|
const gfx = editorContainer.host?.std.get(GfxControllerIdentifier);
|
||||||
|
|
||||||
// ----- Scroll Position and Selection -----
|
// ----- Scroll Position and Selection -----
|
||||||
// if we have default scroll position, we should restore it
|
// if we have default scroll position, we should restore it
|
||||||
@@ -209,9 +207,9 @@ export class Editor extends Entity {
|
|||||||
} else if (
|
} else if (
|
||||||
this.mode$.value === 'edgeless' &&
|
this.mode$.value === 'edgeless' &&
|
||||||
this.scrollPosition.edgeless &&
|
this.scrollPosition.edgeless &&
|
||||||
rootService instanceof EdgelessRootService
|
gfx
|
||||||
) {
|
) {
|
||||||
rootService.viewport.setViewport(this.scrollPosition.edgeless.zoom, [
|
gfx.viewport.setViewport(this.scrollPosition.edgeless.zoom, [
|
||||||
this.scrollPosition.edgeless.centerX,
|
this.scrollPosition.edgeless.centerX,
|
||||||
this.scrollPosition.edgeless.centerY,
|
this.scrollPosition.edgeless.centerY,
|
||||||
]);
|
]);
|
||||||
@@ -253,14 +251,11 @@ export class Editor extends Entity {
|
|||||||
if (this.mode$.value === 'page' && scrollViewport) {
|
if (this.mode$.value === 'page' && scrollViewport) {
|
||||||
this.scrollPosition.page = scrollViewport.scrollTop;
|
this.scrollPosition.page = scrollViewport.scrollTop;
|
||||||
this.workbenchView?.setScrollPosition(scrollViewport.scrollTop);
|
this.workbenchView?.setScrollPosition(scrollViewport.scrollTop);
|
||||||
} else if (
|
} else if (this.mode$.value === 'edgeless' && gfx) {
|
||||||
this.mode$.value === 'edgeless' &&
|
|
||||||
rootService instanceof EdgelessRootService
|
|
||||||
) {
|
|
||||||
const pos = {
|
const pos = {
|
||||||
centerX: rootService.viewport.centerX,
|
centerX: gfx.viewport.centerX,
|
||||||
centerY: rootService.viewport.centerY,
|
centerY: gfx.viewport.centerY,
|
||||||
zoom: rootService.viewport.zoom,
|
zoom: gfx.viewport.zoom,
|
||||||
};
|
};
|
||||||
this.scrollPosition.edgeless = pos;
|
this.scrollPosition.edgeless = pos;
|
||||||
this.workbenchView?.setScrollPosition(pos);
|
this.workbenchView?.setScrollPosition(pos);
|
||||||
@@ -270,10 +265,8 @@ export class Editor extends Entity {
|
|||||||
unsubs.push(() => {
|
unsubs.push(() => {
|
||||||
scrollViewport?.removeEventListener('scroll', saveScrollPosition);
|
scrollViewport?.removeEventListener('scroll', saveScrollPosition);
|
||||||
});
|
});
|
||||||
if (rootService instanceof EdgelessRootService) {
|
if (gfx) {
|
||||||
unsubs.push(
|
unsubs.push(gfx.viewport.viewportUpdated.on(saveScrollPosition).dispose);
|
||||||
rootService.viewport.viewportUpdated.on(saveScrollPosition).dispose
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update selection when focusAt$ changed
|
// update selection when focusAt$ changed
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ import { EditorOutlineViewer } from '@affine/core/components/blocksuite/outline-
|
|||||||
import { PageNotFound } from '@affine/core/desktop/pages/404';
|
import { PageNotFound } from '@affine/core/desktop/pages/404';
|
||||||
import { EditorService } from '@affine/core/modules/editor';
|
import { EditorService } from '@affine/core/modules/editor';
|
||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import {
|
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||||
type EdgelessRootService,
|
import { RefNodeSlotsProvider } from '@blocksuite/affine/blocks';
|
||||||
RefNodeSlotsProvider,
|
|
||||||
} from '@blocksuite/affine/blocks';
|
|
||||||
import {
|
import {
|
||||||
Bound,
|
Bound,
|
||||||
type Disposable,
|
type Disposable,
|
||||||
@@ -46,25 +44,22 @@ function fitViewport(
|
|||||||
throw new Error('editor host is not ready');
|
throw new Error('editor host is not ready');
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootService =
|
const gfx = editor.host.std.get(GfxControllerIdentifier);
|
||||||
editor.host.std.getService<EdgelessRootService>('affine:page');
|
const viewport = gfx.viewport;
|
||||||
if (!rootService) {
|
viewport.onResize();
|
||||||
return;
|
|
||||||
}
|
|
||||||
rootService.viewport.onResize();
|
|
||||||
|
|
||||||
if (xywh) {
|
if (xywh) {
|
||||||
const viewport = {
|
const newViewport = {
|
||||||
xywh: xywh,
|
xywh: xywh,
|
||||||
padding: [60, 20, 20, 20] as [number, number, number, number],
|
padding: [60, 20, 20, 20] as [number, number, number, number],
|
||||||
};
|
};
|
||||||
rootService.viewport.setViewportByBound(
|
viewport.setViewportByBound(
|
||||||
Bound.deserialize(viewport.xywh),
|
Bound.deserialize(newViewport.xywh),
|
||||||
viewport.padding,
|
newViewport.padding,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
rootService.gfx.fitToScreen({
|
gfx.fitToScreen({
|
||||||
smooth: false,
|
smooth: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user