Skip to content

Commit

Permalink
feat(image): facade api (#4322)
Browse files Browse the repository at this point in the history
  • Loading branch information
DR-Univer authored Dec 18, 2024
1 parent ceff4eb commit b41e499
Show file tree
Hide file tree
Showing 18 changed files with 1,147 additions and 52 deletions.
1 change: 1 addition & 0 deletions examples/src/sheets/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import '@univerjs/sheets-hyper-link-ui/facade';

import '@univerjs/sheets-thread-comment/facade';
import '@univerjs/sheets-conditional-formatting/facade';
import '@univerjs/sheets-drawing-ui/facade';
import '../global.css';

/* eslint-disable-next-line node/prefer-global/process */
Expand Down
205 changes: 205 additions & 0 deletions packages/core/src/facade/f-blob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { Nullable } from '../shared';
import { Inject, Injector } from '@wendellhu/redi';
import { FBase } from './f-base';

export interface IFBlobSource {
/**
* Return the data inside this object as a blob.
*/
getBlob(): FBlob;

/**
* Return the data inside this object as a blob converted to the specified content type.
* @param contentType the content type refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types
*/
getAs(contentType: string): FBlob;
}

export class FBlob extends FBase {
constructor(
private _blob: Nullable<Blob>,
@Inject(Injector) protected readonly _injector: Injector
) {
super();
}

/**
* Returns a copy of this blob.
* @returns a new blob by copying the current blob
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.copyBlob();
* console.log(newBlob);
* ```
*/
copyBlob() {
return this._injector.createInstance(FBlob, this._blob);
}

/**
* Return the data inside this object as a blob converted to the specified content type.
* @param contentType the content type refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types
* @returns a new blob by converting the current blob to the specified content type
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.getBlob();
* ```
*/
getAs(contentType: string) {
const newBlob = this.copyBlob();
newBlob.setContentType(contentType);
return newBlob;
}

/**
* get the blob as a string
* @returns
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.getDataAsString();
* console.log(newBlob);
* ```
*/
getDataAsString(): Promise<string>;
/**
* get the blob as a string
* @param charset the charset
* @returns the blob content as a string
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.getDataAsString('iso-8859-1');
* console.log(newBlob);
* ```
*/
getDataAsString(charset?: string): Promise<string>;
getDataAsString(charset?: string): Promise<string> {
if (this._blob === null) {
return Promise.resolve('');
}

if (charset === undefined) {
return this._blob!.text();
}
return new Promise((resolve, reject) => {
this._blob!.arrayBuffer().then((arrayBuffer) => {
const text = new TextDecoder(charset).decode(arrayBuffer); // 解码为字符串
resolve(text);
}).catch((error) => {
reject(new Error(`Failed to read Blob as ArrayBuffer: ${error.message}`));
});
});
}

/**
* Gets the data stored in this blob.
* @returns the blob content as a byte array
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.getBytes();
* console.log(newBlob);
* ```
*/
getBytes(): Promise<Uint8Array> {
if (!this._blob) {
return Promise.reject(new Error('Blob is undefined or null.'));
}
return this._blob.arrayBuffer().then((buffer) => new Uint8Array(buffer));
}

/**
* Sets the data stored in this blob.
* @param bytes a byte array
* @returns the blob object
* @example
* ```ts
* const blob = UniverApi.newBlob();
* const bytes = new Uint8Array(10);
* blob.setBytes(bytes);
* ```
*/
setBytes(bytes: Uint8Array): FBlob {
this._blob = new Blob([bytes]);
return this;
}

/**
* Sets the data stored in this blob.
* @param data blob data string
* @returns the blob object
* @example
* ```ts
* const blob = UniverApi.newBlob();
* blob.setDataFromString('Hello, World!');
* ```
*/
setDataFromString(data: string): FBlob;
/**
* Sets the data stored in this blob.
* @param data a string
* @param contentType the content type refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types
* @returns the blob object
* @example
* ```ts
* const blob = UniverApi.newBlob();
* blob.setDataFromString('Hello, World!', 'text/plain');
* ```
*/
setDataFromString(data: string, contentType?: string): FBlob;
setDataFromString(data: string, contentType?: string): FBlob {
const contentTypeVal = contentType ?? 'text/plain';
const blob = new Blob([data], { type: contentTypeVal });
this._blob = blob;
return this;
}

/**
* Gets the content type of the data stored in this blob.
* @returns the content type
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.getContentType();
* console.log(newBlob);
* ```
*/
getContentType() {
return this._blob?.type;
}

/**
* Sets the content type of the data stored in this blob.
* @param contentType the content type refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types
* @returns the blob object
* @example
* ```ts
* const blob = UniverApi.newBlob(blob);
* const newBlob = blob.setContentType('text/plain');
* console.log(newBlob);
* ```
*/
setContentType(contentType: string): FBlob {
this._blob = this._blob?.slice(0, this._blob.size, contentType);
return this;
}
}
14 changes: 14 additions & 0 deletions packages/core/src/facade/f-univer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { LifecycleService } from '../services/lifecycle/lifecycle.service';
import { RedoCommand, UndoCommand } from '../services/undoredo/undoredo.service';
import { Univer } from '../univer';
import { FBase } from './f-base';
import { FBlob } from './f-blob';
import { FHooks } from './f-hooks';

export class FUniver extends FBase {
Expand Down Expand Up @@ -148,4 +149,17 @@ export class FUniver extends FBase {
getHooks(): FHooks {
return this._injector.createInstance(FHooks);
}

/**
* Create a new blob.
*
* @returns {FBlob} The new blob instance
* @example
* ```ts
* const blob = UniverApi.newBlob();
* ```
*/
newBlob(): FBlob {
return this._injector.createInstance(FBlob);
}
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export { mixinClass } from './common/mixin';
export { FBase } from './facade/f-base';
export { FUniver } from './facade/f-univer';
export { FHooks } from './facade/f-hooks';
export { FBlob, type IFBlobSource } from './facade/f-blob';
export { isNumeric, isSafeNumeric } from './common/number';
export { Registry, RegistryAsMap } from './common/registry';
export { requestImmediateMacroTask } from './common/request-immediate-macro-task';
Expand Down
75 changes: 42 additions & 33 deletions packages/sheets-drawing-ui/src/basics/transform-position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,65 @@
import type { ITransformState, Nullable } from '@univerjs/core';
import type { ISheetDrawingPosition } from '@univerjs/sheets-drawing';
import { precisionTo } from '@univerjs/engine-render';
import { attachRangeWithCoord, type ISheetSelectionRenderService, type SheetSkeletonManagerService } from '@univerjs/sheets-ui';
import { convertPositionSheetOverGridToAbsolute, type ISheetSelectionRenderService, type SheetSkeletonManagerService } from '@univerjs/sheets-ui';

export function drawingPositionToTransform(
position: ISheetDrawingPosition,
selectionRenderService: ISheetSelectionRenderService,
sheetSkeletonManagerService: SheetSkeletonManagerService): Nullable<ITransformState> {
const { from, to, flipY = false, flipX = false, angle = 0, skewX = 0, skewY = 0 } = position;
const { column: fromColumn, columnOffset: fromColumnOffset, row: fromRow, rowOffset: fromRowOffset } = from;
const { column: toColumn, columnOffset: toColumnOffset, row: toRow, rowOffset: toRowOffset } = to;
const skeletonParam = sheetSkeletonManagerService.getCurrent();
if (skeletonParam == null) {
return;
}

const absolutePosition = convertPositionSheetOverGridToAbsolute(
skeletonParam.unitId, skeletonParam.sheetId, { from, to }, sheetSkeletonManagerService
);

let { left, top, width, height } = absolutePosition;

const skeleton = sheetSkeletonManagerService.getCurrentSkeleton()!;

const startSelectionCell = attachRangeWithCoord(skeleton, {
startColumn: fromColumn,
endColumn: fromColumn,
startRow: fromRow,
endRow: fromRow,
});
// const startSelectionCell = attachRangeWithCoord(skeleton, {
// startColumn: fromColumn,
// endColumn: fromColumn,
// startRow: fromRow,
// endRow: fromRow,
// });

if (startSelectionCell == null) {
return;
}
// if (startSelectionCell == null) {
// return;
// }

const endSelectionCell = attachRangeWithCoord(skeleton, {
startColumn: toColumn,
endColumn: toColumn,
startRow: toRow,
endRow: toRow,
});
// const endSelectionCell = attachRangeWithCoord(skeleton, {
// startColumn: toColumn,
// endColumn: toColumn,
// startRow: toRow,
// endRow: toRow,
// });

if (endSelectionCell == null) {
return;
}
// if (endSelectionCell == null) {
// return;
// }

const { startX: startSelectionX, startY: startSelectionY } = startSelectionCell;
// const { startX: startSelectionX, startY: startSelectionY } = startSelectionCell;

const { startX: endSelectionX, startY: endSelectionY } = endSelectionCell;
// const { startX: endSelectionX, startY: endSelectionY } = endSelectionCell;

let left = precisionTo(startSelectionX + fromColumnOffset, 1);
let top = precisionTo(startSelectionY + fromRowOffset, 1);
// let left = precisionTo(startSelectionX + fromColumnOffset, 1);
// let top = precisionTo(startSelectionY + fromRowOffset, 1);

let width = precisionTo(endSelectionX + toColumnOffset - left, 1);
let height = precisionTo(endSelectionY + toRowOffset - top, 1);
// let width = precisionTo(endSelectionX + toColumnOffset - left, 1);
// let height = precisionTo(endSelectionY + toRowOffset - top, 1);

if (startSelectionCell.startX === endSelectionCell.endX) {
width = 0;
}
// if (startSelectionCell.startX === endSelectionCell.endX) {
// width = 0;
// }

if (startSelectionCell.startY === endSelectionCell.endY) {
height = 0;
}
// if (startSelectionCell.startY === endSelectionCell.endY) {
// height = 0;
// }

const sheetWidth = skeleton.rowHeaderWidth + skeleton.columnTotalWidth;
const sheetHeight = skeleton.columnHeaderHeight + skeleton.rowTotalHeight;
Expand Down
Loading

0 comments on commit b41e499

Please sign in to comment.