Skip to content

Commit

Permalink
feat: optimization of doc image (#2432)
Browse files Browse the repository at this point in the history
Co-authored-by: gggpound <gpoundLiu@gmail.com>
  • Loading branch information
Jocs and Gggpound authored Jul 11, 2024
1 parent 9867cc7 commit 3f98681
Show file tree
Hide file tree
Showing 78 changed files with 4,602 additions and 733 deletions.
314 changes: 173 additions & 141 deletions examples/src/data/docs/default-document-data-cn.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/src/sheets/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ univer.registerPlugin(UniverSheetsConditionalFormattingUIPlugin);

// drawing
univer.registerPlugin(UniverSheetsDrawingUIPlugin);
// univer.registerPlugin(UniverDocsDrawingUIPlugin);

// create univer sheet instance
if (!IS_E2E) {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/docs/data-model/text-x/text-x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export class TextX {
index += action.len;
}
}

return invertibleActions;
}

Expand Down
22 changes: 20 additions & 2 deletions packages/core/src/docs/data-model/text-x/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@

import { UpdateDocsAttributeType } from '../../../shared/command-enum';
import { Tools } from '../../../shared/tools';
import type { ICustomDecoration, IDocumentBody, IParagraph, ITextRun } from '../../../types/interfaces/i-document-data';
import type { ICustomBlock, ICustomDecoration, IDocumentBody, IParagraph, ITextRun } from '../../../types/interfaces/i-document-data';
import { DataStreamTreeTokenType } from '../types';
import type { IRetainAction } from './action-types';
import { coverTextRuns } from './apply-utils/update-apply';

// TODO: Support other properties like custom ranges, tables, etc.
// eslint-disable-next-line max-lines-per-function
export function getBodySlice(
body: IDocumentBody,
startOffset: number,
endOffset: number,
returnEmptyTextRun = false
): IDocumentBody {
const { dataStream, textRuns = [], paragraphs = [] } = body;
const { dataStream, textRuns = [], paragraphs = [], customBlocks = [] } = body;

const docBody: IDocumentBody = {
dataStream: dataStream.slice(startOffset, endOffset),
Expand Down Expand Up @@ -97,6 +98,23 @@ export function getBodySlice(
docBody.customDecorations = getCustomDecorationSlice(body, startOffset, endOffset);
const { customRanges } = getCustomRangeSlice(body, startOffset, endOffset);
docBody.customRanges = customRanges;

const newCustomBlocks: ICustomBlock[] = [];

for (const block of customBlocks) {
const { startIndex } = block;
if (startIndex >= startOffset && startIndex <= endOffset) {
newCustomBlocks.push(Tools.deepClone(block));
}
}

if (newCustomBlocks.length) {
docBody.customBlocks = newCustomBlocks.map((b) => ({
...b,
startIndex: b.startIndex - startOffset,
}));
}

return docBody;
}

Expand Down
11 changes: 7 additions & 4 deletions packages/core/src/services/snapshot/snapshot-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export async function generateTemporarySnap(
}> {
const blockMeta: { [key: string]: ISheetBlockMeta } = {};

// Deal with worksheets and their blocks.
// Deal with worksheets and their blocks.
const sheetMetas: { [key: string]: IWorksheetMeta } = {};
const blocksSaveSuccess = await Promise.all(
Object.entries(workbook.sheets).map(async ([sheetID, worksheet]) => {
Expand All @@ -61,7 +61,7 @@ export async function generateTemporarySnap(

sheetMetas[sheetID] = sheetMeta;

// Trigger RPC and store the result in sheetBlocks.
// Trigger RPC and store the result in sheetBlocks.
if (worksheet.cellData) {
const sheetBlocks = splitCellDataToBlocks(worksheet.cellData, worksheet.rowCount!);
const responses = await Promise.all(
Expand Down Expand Up @@ -300,9 +300,9 @@ export function transformSnapshotToDocumentData(snapshot: ISnapshot): IDocumentD
throw new Error('transformSnapshotToDocumentData(): snapshot.doc is undefined.');
}

const { unitID, rev, name, originalMeta } = documentMeta;
const { unitID, rev, name, originalMeta, resources = [] } = documentMeta;

const { body, documentStyle = {}, settings = {} } = decodeDocOriginalMeta(originalMeta);
const { body, documentStyle = {}, settings = {}, drawings = {}, drawingsOrder = [] } = decodeDocOriginalMeta(originalMeta);

const documentData: IDocumentData = {
id: unitID,
Expand All @@ -312,6 +312,9 @@ export function transformSnapshotToDocumentData(snapshot: ISnapshot): IDocumentD
body,
documentStyle,
settings,
drawings,
drawingsOrder,
resources,
};

return documentData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const DeleteDocDrawingsCommand: ICommand = {
return false;
}

const unitId = drawings[0].unitId;
const { unitId } = drawings[0];

const newDrawings = drawings.map((drawing) => {
const { unitId, subUnitId, drawingId, drawingType } = drawing as IDocDrawing;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,62 +14,119 @@
* limitations under the License.
*/

import type { ICommand } from '@univerjs/core';
import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core';
import {
CommandType,
ICommandService,
IUndoRedoService,
IUniverInstanceService,
JSONX,
TextX,
TextXActionType,
} from '@univerjs/core';

import { DocDrawingApplyType, IDocDrawingService, SetDocDrawingApplyMutation } from '@univerjs/docs-drawing';
import type { IAccessor } from '@wendellhu/redi';
import type { IDrawingJsonUndo1 } from '@univerjs/drawing';
import { ClearDocDrawingTransformerOperation } from '../operations/clear-drawing-transformer.operation';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import { getRetainAndDeleteFromReplace, getRichTextEditPath, RichTextEditingMutation, TextSelectionManagerService } from '@univerjs/docs';
import type { IInsertDrawingCommandParams } from './interfaces';

/**
* The command to insert new defined name
* The command to insert new drawings
*/
export const InsertDocDrawingCommand: ICommand = {
id: 'doc.command.insert-doc-image',

type: CommandType.COMMAND,

// eslint-disable-next-line max-lines-per-function
handler: (accessor: IAccessor, params?: IInsertDrawingCommandParams) => {
if (params == null) {
return false;
}

const commandService = accessor.get(ICommandService);
const undoRedoService = accessor.get(IUndoRedoService);
const docDrawingService = accessor.get(IDocDrawingService);
const textSelectionManagerService = accessor.get(TextSelectionManagerService);
const univerInstanceService = accessor.get(IUniverInstanceService);

const activeTextRange = textSelectionManagerService.getActiveRange();
const documentDataModel = univerInstanceService.getCurrentUniverDocInstance();
if (activeTextRange == null || documentDataModel == null) {
return false;
}

if (!params) return false;
const unitId = documentDataModel.getUnitId();
const { drawings } = params;
const { collapsed, startOffset, segmentId } = activeTextRange;
const body = documentDataModel.getSelfOrHeaderFooterModel(segmentId).getBody();

// const { drawingParam, imageParam } = params;
if (body == null) {
return false;
}

const drawings = params.drawings;
const textX = new TextX();
const jsonX = JSONX.getInstance();
const rawActions: JSONXActions = [];
const drawingOrderLength = documentDataModel.getSnapshot().drawingsOrder?.length ?? 0;

// const sheetDrawingParams = drawings.map((param) => param.sheetDrawingParam);
const unitIds: string[] = drawings.map((param) => param.unitId);
// Step 1: Insert placeholder `\b` in dataStream and add drawing to customBlocks.
if (collapsed) {
if (startOffset > 0) {
textX.push({
t: TextXActionType.RETAIN,
len: startOffset,
segmentId,
});
}
} else {
const { dos } = getRetainAndDeleteFromReplace(activeTextRange, segmentId, 0, body);
textX.push(...dos);
}

// execute do mutations and add undo mutations to undo stack if completed
const jsonOp = docDrawingService.getBatchAddOp(drawings) as IDrawingJsonUndo1;
textX.push({
t: TextXActionType.INSERT,
body: {
dataStream: '\b'.repeat(drawings.length),
customBlocks: drawings.map((drawing, i) => ({
startIndex: i,
blockId: drawing.drawingId,
})),
},
len: drawings.length,
line: 0,
segmentId,
});

const { unitId, subUnitId, undo, redo, objects } = jsonOp;
const path = getRichTextEditPath(documentDataModel, segmentId);
const placeHolderAction = jsonX.editOp(textX.serialize(), path);

const result = commandService.syncExecuteCommand(SetDocDrawingApplyMutation.id, { op: redo, unitId, subUnitId, objects, type: DocDrawingApplyType.INSERT });
rawActions.push(placeHolderAction!);

if (result) {
undoRedoService.pushUndoRedo({
unitID: unitId,
undoMutations: [
{ id: SetDocDrawingApplyMutation.id, params: { op: undo, unitId, subUnitId, objects, type: DocDrawingApplyType.REMOVE } },
{ id: ClearDocDrawingTransformerOperation.id, params: unitIds },
],
redoMutations: [
{ id: SetDocDrawingApplyMutation.id, params: { op: redo, unitId, subUnitId, objects, type: DocDrawingApplyType.INSERT } },
{ id: ClearDocDrawingTransformerOperation.id, params: unitIds },
],
});
// Step 2: add drawing to drawings and drawingsOrder fields.
for (const drawing of drawings) {
const { drawingId } = drawing;
const addDrawingAction = jsonX.insertOp(['drawings', drawingId], drawing);
const addDrawingOrderAction = jsonX.insertOp(['drawingsOrder', drawingOrderLength], drawingId);

return true;
rawActions.push(addDrawingAction!);
rawActions.push(addDrawingOrderAction!);
}

return false;
const doMutation: IMutationInfo<IRichTextEditingMutationParams> = {
id: RichTextEditingMutation.id,
params: {
unitId,
actions: [],
textRanges: [],
},
};

doMutation.params.actions = rawActions.reduce((acc, cur) => {
return JSONX.compose(acc, cur as JSONXActions);
}, null as JSONXActions);

const result = commandService.syncExecuteCommand<
IRichTextEditingMutationParams,
IRichTextEditingMutationParams
>(doMutation.id, doMutation.params);

return Boolean(result);
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,28 @@
*/

import type { ICommand } from '@univerjs/core';
import { CommandType, Direction, ICommandService } from '@univerjs/core';
import { CommandType, Direction, ICommandService, IUniverInstanceService, PositionedObjectLayoutType } from '@univerjs/core';
import type { IAccessor } from '@wendellhu/redi';

import type { IDocDrawing } from '@univerjs/docs-drawing';
import { IDocDrawingService } from '@univerjs/docs-drawing';
import { transformToDocDrawingPosition } from '@univerjs/docs-ui';
import { ClearDocDrawingTransformerOperation } from '../operations/clear-drawing-transformer.operation';
import type { ISetDrawingCommandParams } from './interfaces';
import { SetDocDrawingCommand } from './set-doc-drawing.command';
import { IRenderManagerService } from '@univerjs/engine-render';
import type { IDrawingDocTransform, IUpdateDrawingDocTransformParams } from './update-doc-drawing.command';
import { UpdateDrawingDocTransformCommand } from './update-doc-drawing.command';

export interface IMoveDrawingsCommandParams {
direction: Direction ;
direction: Direction;
}

export const MoveDocDrawingsCommand: ICommand = {

id: 'doc.command.move-drawing',

type: CommandType.COMMAND,
handler: (accessor: IAccessor, params: IMoveDrawingsCommandParams) => {
const commandService = accessor.get(ICommandService);
const docDrawingService = accessor.get(IDocDrawingService);
const univerInstanceService = accessor.get(IUniverInstanceService);
const renderManagerService = accessor.get(IRenderManagerService);

const { direction } = params;

Expand All @@ -46,42 +48,58 @@ export const MoveDocDrawingsCommand: ICommand = {

const unitId = drawings[0].unitId;

const renderObject = renderManagerService.getRenderById(unitId);
const scene = renderObject?.scene;
if (scene == null) {
return false;
}
const transformer = scene.getTransformerByCreate();

const documentDataModel = univerInstanceService.getUniverDocInstance(unitId);

const newDrawings = drawings.map((drawing) => {
const { transform } = drawing as IDocDrawing;
if (transform == null) {
const { drawingId } = drawing as IDocDrawing;
const drawingData = documentDataModel?.getSnapshot().drawings?.[drawingId];

// Inline drawing can not be moved by shortcut.
if (drawingData == null || drawingData.layoutType === PositionedObjectLayoutType.INLINE) {
return null;
}
const newTransform = { ...transform };

const { left = 0, top = 0 } = transform;
const { positionH, positionV } = drawingData.docTransform;

const newPositionH = { ...positionH };
const newPositionV = { ...positionV };

if (direction === Direction.UP) {
newTransform.top = top - 1;
newPositionV.posOffset = (newPositionV.posOffset ?? 0) - 2;
} else if (direction === Direction.DOWN) {
newTransform.top = top + 1;
newPositionV.posOffset = (newPositionV.posOffset ?? 0) + 2;
} else if (direction === Direction.LEFT) {
newTransform.left = left - 1;
newPositionH.posOffset = (newPositionH.posOffset ?? 0) - 2;
} else if (direction === Direction.RIGHT) {
newTransform.left = left + 1;
newPositionH.posOffset = (newPositionH.posOffset ?? 0) + 2;
}

return {
...drawing,
transform: newTransform,
docTransform: transformToDocDrawingPosition(newTransform),
} as IDocDrawing;
}).filter((drawing) => drawing != null) as IDocDrawing[];
drawingId,
key: direction === Direction.UP || direction === Direction.DOWN ? 'positionV' : 'positionH',
value: direction === Direction.UP || direction === Direction.DOWN ? newPositionV : newPositionH,
} as IDrawingDocTransform;
}).filter((drawing) => drawing != null) as IDrawingDocTransform[];

if (newDrawings.length === 0) {
return false;
}

const result = commandService.syncExecuteCommand<ISetDrawingCommandParams>(SetDocDrawingCommand.id, {
const result = commandService.syncExecuteCommand<IUpdateDrawingDocTransformParams>(UpdateDrawingDocTransformCommand.id, {
unitId,
subUnitId: unitId,
drawings: newDrawings,
});

if (result) {
commandService.syncExecuteCommand(ClearDocDrawingTransformerOperation.id, [unitId]);
return true;
}
transformer.refreshControls();

return false;
return Boolean(result);
},
};
Loading

0 comments on commit 3f98681

Please sign in to comment.