import type { Workbook, Worksheet } from '@univerjs/core';
|
import type { Observable } from 'rxjs';
|
|
import {
|
generateRandomId,
|
IImageIoService,
|
IImageIoServiceParam,
|
ImageSourceType,
|
ImageUploadStatusType,
|
Inject,
|
Injector,
|
IUniverInstanceService,
|
Nullable,
|
UniverInstanceType,
|
} from '@univerjs/core';
|
import { IRenderManagerService } from '@univerjs/engine-render';
|
import { SheetSkeletonManagerService } from '@univerjs/sheets-ui';
|
import { Subject } from 'rxjs';
|
|
export const DRAWING_IMAGE_ALLOW_SIZE = 5 * 1024 * 1024;
|
|
export const DRAWING_IMAGE_ALLOW_IMAGE_LIST = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'];
|
|
export class JnpfSheetImageIoImplService implements IImageIoService {
|
private _change$ = new Subject<number>();
|
|
change$ = this._change$ as Observable<number>;
|
private _imageSourceCache: Map<string, HTMLImageElement> = new Map();
|
|
private _waitCount = 0;
|
|
constructor(
|
@Inject(Injector) private readonly _accessor: Injector,
|
@IUniverInstanceService protected readonly _univerInstanceService: IUniverInstanceService,
|
) {}
|
|
addImageSourceCache(source: string, imageSourceType: ImageSourceType, imageSource: Nullable<HTMLImageElement>) {
|
if (imageSourceType === ImageSourceType.BASE64 || imageSource == null) {
|
return;
|
}
|
this._imageSourceCache.set(source, imageSource);
|
}
|
|
cacheImages() {
|
const { sheet, unitId, subUnitId } = this._sheet();
|
const skeleton = this._getSkeleton(unitId, subUnitId);
|
if (!skeleton) {
|
return;
|
}
|
skeleton.resetCache();
|
sheet.getCellMatrix().forValue((_row, _col, value) => {
|
if (value && value.p && value.p.drawings) {
|
Object.keys(value.p.drawings).forEach(drawing => {
|
const drawingItem: any = value.p?.drawings?.[drawing];
|
if (value.p && value.p.drawings && drawingItem && drawingItem.imageSourceType === 'BASE64' && drawingItem.source) {
|
this._imageSourceCache.set(drawingItem.imageSourceType, drawingItem.source);
|
// 强制缓存
|
skeleton.imageCacheMap.getImage(drawingItem.imageSourceType, drawingItem.source);
|
}
|
});
|
}
|
});
|
}
|
|
clearMemory() {}
|
|
async getImage(imageId: string): Promise<string> {
|
return imageId;
|
}
|
|
getImageSourceCache(source: string, imageSourceType: ImageSourceType) {
|
if (imageSourceType === ImageSourceType.BASE64) {
|
const image = new Image();
|
image.src = source;
|
return image;
|
}
|
return this._imageSourceCache.get(source);
|
}
|
|
async saveImage(imageFile: File): Promise<Nullable<IImageIoServiceParam>> {
|
return new Promise((resolve, reject) => {
|
if (!DRAWING_IMAGE_ALLOW_IMAGE_LIST.includes(imageFile.type)) {
|
reject(new Error(ImageUploadStatusType.ERROR_IMAGE_TYPE));
|
this._decreaseWaiting();
|
return;
|
}
|
if (imageFile.size > DRAWING_IMAGE_ALLOW_SIZE) {
|
reject(new Error(ImageUploadStatusType.ERROR_EXCEED_SIZE));
|
this._decreaseWaiting();
|
return;
|
}
|
// 获取上传的图片的宽高
|
const reader = new FileReader();
|
reader.readAsDataURL(imageFile);
|
reader.addEventListener('load', evt => {
|
const replaceSrc = evt.target?.result as string;
|
if (replaceSrc == null) {
|
reject(new Error(ImageUploadStatusType.ERROR_IMAGE));
|
this._decreaseWaiting();
|
return;
|
}
|
|
const imageId = generateRandomId(6);
|
resolve({
|
imageId,
|
imageSourceType: ImageSourceType.BASE64,
|
source: replaceSrc,
|
base64Cache: replaceSrc,
|
status: ImageUploadStatusType.SUCCUSS,
|
});
|
|
this._decreaseWaiting();
|
});
|
});
|
}
|
|
setWaitCount(count: number) {
|
this._waitCount = count;
|
this._change$.next(count);
|
}
|
|
private _decreaseWaiting() {
|
this._waitCount -= 1;
|
this._change$.next(this._waitCount);
|
}
|
|
private _getSkeleton(unitId: string, subUnitId: string) {
|
return this._accessor.get(IRenderManagerService)?.getRenderById(unitId)?.with(SheetSkeletonManagerService)?.getOrCreateSkeleton({ sheetId: subUnitId });
|
}
|
|
private _sheet() {
|
// 使用 `UniverInstanceService` 获取当前类型为 `UNIVER_SHEET` 的活动单元实例
|
const unit: Nullable<Workbook> = this._univerInstanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET);
|
const unitId = unit!.getUnitId();
|
const sheet: Worksheet = unit!.getActiveSheet();
|
const subUnitId = sheet?.getSheetId();
|
return {
|
unit,
|
sheet,
|
unitId,
|
subUnitId,
|
};
|
}
|
}
|