mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
fix: drag block issue (#9902)
### Changed - Added support for changing the preview offset during dragging. - Fixed the preview rendering for embed block and surface-ref block - Resolved an issue where the host element might be reused in certain cases, which could cause unexpected behavior - Moved viewport-related constants and methods to a more appropriate location
This commit is contained in:
@@ -47,7 +47,6 @@ import { EdgelessPageKeyboardManager } from './edgeless-keyboard.js';
|
||||
import type { EdgelessRootService } from './edgeless-root-service.js';
|
||||
import { getBackgroundGrid, isCanvasElement } from './utils/query.js';
|
||||
import { mountShapeTextEditor } from './utils/text.js';
|
||||
import { fitToScreen } from './utils/viewport.js';
|
||||
|
||||
export class EdgelessRootBlockComponent extends BlockComponent<
|
||||
RootBlockModel,
|
||||
@@ -341,9 +340,7 @@ export class EdgelessRootBlockComponent extends BlockComponent<
|
||||
const storedViewport = std.get(EditPropsStore).getStorage('viewport');
|
||||
|
||||
if (!storedViewport) {
|
||||
fitToScreen(this.gfx.gfxElements, gfx.viewport, {
|
||||
smooth: false,
|
||||
});
|
||||
this.gfx.fitToScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import { query, state } from 'lit/decorators.js';
|
||||
import type { EdgelessRootBlockWidgetName } from '../types.js';
|
||||
import type { EdgelessRootService } from './edgeless-root-service.js';
|
||||
import { getBackgroundGrid, isCanvasElement } from './utils/query.js';
|
||||
import { fitToScreen } from './utils/viewport.js';
|
||||
|
||||
export class EdgelessRootPreviewBlockComponent
|
||||
extends BlockComponent<
|
||||
@@ -178,14 +177,6 @@ export class EdgelessRootPreviewBlockComponent
|
||||
);
|
||||
}
|
||||
|
||||
private _initViewport() {
|
||||
const gfx = this.service.gfx;
|
||||
|
||||
fitToScreen(gfx.gfxElements, gfx.viewport, {
|
||||
smooth: false,
|
||||
});
|
||||
}
|
||||
|
||||
private get _disableScheduleUpdate() {
|
||||
const editorSetting = this.std.getOptional(EditorSettingProvider);
|
||||
|
||||
@@ -195,7 +186,6 @@ export class EdgelessRootPreviewBlockComponent
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this._initViewport();
|
||||
this.handleEvent('selectionChange', () => {
|
||||
const surface = this.host.selection.value.find(
|
||||
(sel): sel is SurfaceSelection => sel.is(SurfaceSelection)
|
||||
|
||||
@@ -27,6 +27,9 @@ import {
|
||||
GfxControllerIdentifier,
|
||||
GfxExtensionIdentifier,
|
||||
isGfxGroupCompatibleModel,
|
||||
ZOOM_MAX,
|
||||
ZOOM_MIN,
|
||||
ZOOM_STEP,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||
import { Bound, getCommonBound } from '@blocksuite/global/utils';
|
||||
@@ -41,15 +44,7 @@ import {
|
||||
createStickerMiddleware,
|
||||
replaceIdMiddleware,
|
||||
} from './services/template-middlewares.js';
|
||||
import { FIT_TO_SCREEN_PADDING } from './utils/consts.js';
|
||||
import { getCursorMode } from './utils/query.js';
|
||||
import {
|
||||
ZOOM_INITIAL,
|
||||
ZOOM_MAX,
|
||||
ZOOM_MIN,
|
||||
ZOOM_STEP,
|
||||
type ZoomAction,
|
||||
} from './utils/zoom.js';
|
||||
|
||||
export class EdgelessRootService extends RootService implements SurfaceContext {
|
||||
static override readonly flavour = RootBlockSchema.model.flavour;
|
||||
@@ -288,34 +283,6 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
||||
return this.surface.getConnectors(id) as ConnectorElementModel[];
|
||||
}
|
||||
|
||||
getFitToScreenData(
|
||||
padding: [number, number, number, number] = [0, 0, 0, 0],
|
||||
inputBounds?: Bound[]
|
||||
) {
|
||||
let bounds = [];
|
||||
if (inputBounds && inputBounds.length) {
|
||||
bounds = inputBounds;
|
||||
} else {
|
||||
this.blocks.forEach(block => {
|
||||
bounds.push(Bound.deserialize(block.xywh));
|
||||
});
|
||||
|
||||
const surfaceElementsBound = getCommonBound(this.elements);
|
||||
if (surfaceElementsBound) {
|
||||
bounds.push(surfaceElementsBound);
|
||||
}
|
||||
}
|
||||
|
||||
const bound = getCommonBound(bounds);
|
||||
|
||||
return this.viewport.getFitToScreenData(
|
||||
bound,
|
||||
padding,
|
||||
ZOOM_INITIAL,
|
||||
FIT_TO_SCREEN_PADDING
|
||||
);
|
||||
}
|
||||
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
this._initSlotEffects();
|
||||
@@ -372,12 +339,12 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
||||
}
|
||||
}
|
||||
|
||||
setZoomByAction(action: ZoomAction) {
|
||||
setZoomByAction(action: 'fit' | 'out' | 'reset' | 'in') {
|
||||
if (this.locked) return;
|
||||
|
||||
switch (action) {
|
||||
case 'fit':
|
||||
this.zoomToFit();
|
||||
this.gfx.fitToScreen();
|
||||
break;
|
||||
case 'reset':
|
||||
this.viewport.smoothZoom(1.0);
|
||||
@@ -439,9 +406,4 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
||||
this.selectionManager.set([]);
|
||||
this.disposables.dispose();
|
||||
}
|
||||
|
||||
zoomToFit() {
|
||||
const { centerX, centerY, zoom } = this.getFitToScreenData();
|
||||
this.viewport.setViewport(zoom, [centerX, centerY], true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ import {
|
||||
mountShapeTextEditor,
|
||||
mountTextElementEditor,
|
||||
} from '../utils/text.js';
|
||||
import { fitToScreen } from '../utils/viewport.js';
|
||||
import { CanvasElementEventExt } from './default-tool-ext/event-ext.js';
|
||||
import type { DefaultToolExt } from './default-tool-ext/ext.js';
|
||||
import { DefaultModeDragType } from './default-tool-ext/ext.js';
|
||||
@@ -766,11 +765,7 @@ export class DefaultTool extends BaseTool {
|
||||
if (this.doc.readonly) {
|
||||
const viewport = this.gfx.viewport;
|
||||
if (viewport.zoom === 1) {
|
||||
// Fit to Screen
|
||||
fitToScreen(
|
||||
[...this.gfx.layer.blocks, ...this.gfx.layer.canvasElements],
|
||||
this.gfx.viewport
|
||||
);
|
||||
this.gfx.fitToScreen();
|
||||
} else {
|
||||
// Zoom to 100% and Center
|
||||
const [x, y] = viewport.toModelCoord(e.x, e.y);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { GfxModel, Viewport } from '@blocksuite/block-std/gfx';
|
||||
import { Bound, getCommonBound } from '@blocksuite/global/utils';
|
||||
|
||||
import { FIT_TO_SCREEN_PADDING } from './consts.js';
|
||||
import { ZOOM_INITIAL } from './zoom.js';
|
||||
|
||||
export function fitToScreen(
|
||||
elements: GfxModel[],
|
||||
viewport: Viewport,
|
||||
options: {
|
||||
padding?: [number, number, number, number];
|
||||
smooth?: boolean;
|
||||
} = {
|
||||
padding: [0, 0, 0, 0],
|
||||
smooth: true,
|
||||
}
|
||||
) {
|
||||
const elemBounds = elements.map(element => Bound.deserialize(element.xywh));
|
||||
const commonBound = getCommonBound(elemBounds);
|
||||
const { zoom, centerX, centerY } = viewport.getFitToScreenData(
|
||||
commonBound,
|
||||
options.padding,
|
||||
ZOOM_INITIAL,
|
||||
FIT_TO_SCREEN_PADDING
|
||||
);
|
||||
|
||||
viewport.setViewport(zoom, [centerX, centerY], options.smooth);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export type ZoomAction = 'fit' | 'out' | 'reset' | 'in';
|
||||
export const ZOOM_MAX = 6.0;
|
||||
export const ZOOM_MIN = 0.1;
|
||||
export const ZOOM_STEP = 0.25;
|
||||
export const ZOOM_INITIAL = 1.0;
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
ViewBarIcon,
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import { stopPropagation } from '@blocksuite/affine-shared/utils';
|
||||
import { ZOOM_STEP } from '@blocksuite/block-std/gfx';
|
||||
import { WithDisposable } from '@blocksuite/global/utils';
|
||||
import { effect } from '@preact/signals-core';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
@@ -11,7 +12,6 @@ import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
|
||||
import { ZOOM_STEP } from '../../edgeless/utils/zoom.js';
|
||||
|
||||
export class EdgelessZoomToolbar extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
@@ -87,6 +87,10 @@ export class EdgelessZoomToolbar extends WithDisposable(LitElement) {
|
||||
return this.edgeless.service;
|
||||
}
|
||||
|
||||
get gfx() {
|
||||
return this.edgeless.gfx;
|
||||
}
|
||||
|
||||
get edgelessTool() {
|
||||
return this.edgeless.gfx.tool.currentToolOption$.peek();
|
||||
}
|
||||
@@ -162,7 +166,7 @@ export class EdgelessZoomToolbar extends WithDisposable(LitElement) {
|
||||
.tooltip=${'Fit to screen'}
|
||||
.tipPosition=${this._isVerticalBar() ? 'right' : 'top-end'}
|
||||
.arrow=${!this._isVerticalBar()}
|
||||
@click=${() => this.edgelessService.zoomToFit()}
|
||||
@click=${() => this.gfx.fitToScreen()}
|
||||
.iconContainerPadding=${4}
|
||||
.disabled=${locked}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user