Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sync): add blob engine #6937

Merged
merged 24 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/blocks/src/__tests__/adapters/html.unit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BlockSnapshot } from '@blocksuite/store';
import { MemoryBlobManager } from '@blocksuite/store';
import { MemoryBlobCRUD } from '@blocksuite/store';
import { AssetsManager } from '@blocksuite/store';
import { describe, expect, test } from 'vitest';

Expand Down Expand Up @@ -814,10 +814,10 @@ describe('snapshot to html', () => {
);

const htmlAdapter = new HtmlAdapter();
const blobManager = new MemoryBlobManager();
const blobManager = new MemoryBlobCRUD();
await blobManager.set(
new Blob(),
'YXXTjRmLlNyiOUnHb8nAIvUP6V7PAXhwW9F5_tc2LGs='
'YXXTjRmLlNyiOUnHb8nAIvUP6V7PAXhwW9F5_tc2LGs=',
new Blob()
);
const assets = new AssetsManager({ blob: blobManager });

Expand Down
12 changes: 6 additions & 6 deletions packages/blocks/src/__tests__/adapters/markdown.unit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BlockSnapshot } from '@blocksuite/store';
import { MemoryBlobManager } from '@blocksuite/store';
import { MemoryBlobCRUD } from '@blocksuite/store';
import { AssetsManager } from '@blocksuite/store';
import { describe, expect, test } from 'vitest';

Expand Down Expand Up @@ -1141,12 +1141,12 @@ hhh
'![](assets/YXXTjRmLlNyiOUnHb8nAIvUP6V7PAXhwW9F5_tc2LGs=.blob "aaa")\n\n';

const mdAdapter = new MarkdownAdapter();
const blobManager = new MemoryBlobManager();
await blobManager.set(
new Blob(),
'YXXTjRmLlNyiOUnHb8nAIvUP6V7PAXhwW9F5_tc2LGs='
const blobCRUD = new MemoryBlobCRUD();
await blobCRUD.set(
'YXXTjRmLlNyiOUnHb8nAIvUP6V7PAXhwW9F5_tc2LGs=',
new Blob()
);
const assets = new AssetsManager({ blob: blobManager });
const assets = new AssetsManager({ blob: blobCRUD });

const target = await mdAdapter.fromBlockSnapshot({
snapshot: blockSnapshot,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
AssetsManager,
type BlockSnapshot,
MemoryBlobManager,
MemoryBlobCRUD,
} from '@blocksuite/store';
import { describe, expect, test } from 'vitest';

Expand Down Expand Up @@ -1084,7 +1084,7 @@ describe('notion html to snapshot', () => {
const adapter = new NotionHtmlAdapter();
const rawBlockSnapshot = await adapter.toBlockSnapshot({
file: html,
assets: new AssetsManager({ blob: new MemoryBlobManager() }),
assets: new AssetsManager({ blob: new MemoryBlobCRUD() }),
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
Expand Down Expand Up @@ -1176,9 +1176,9 @@ describe('notion html to snapshot', () => {
};

const adapter = new NotionHtmlAdapter();
const blobManager = new MemoryBlobManager();
const key = await blobManager.set(new File([], 'README.pdf'));
const assestsManager = new AssetsManager({ blob: blobManager });
const blobCRUD = new MemoryBlobCRUD();
const key = await blobCRUD.set(new File([], 'README.pdf'));
const assestsManager = new AssetsManager({ blob: blobCRUD });
await assestsManager.readFromBlob(key);
const rawBlockSnapshot = await adapter.toBlockSnapshot({
file: html,
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/_common/adapters/attachment.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sha } from '@blocksuite/global/utils';
import type { AssetsManager } from '@blocksuite/store';
import {
BaseAdapter,
Expand All @@ -10,7 +11,6 @@ import {
type FromSliceSnapshotPayload,
type FromSliceSnapshotResult,
nanoid,
sha,
type SliceSnapshot,
type ToBlockSnapshotPayload,
type ToDocSnapshotPayload,
Expand Down
3 changes: 1 addition & 2 deletions packages/blocks/src/_common/adapters/html.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals } from '@blocksuite/global/utils';
import { assertEquals, sha } from '@blocksuite/global/utils';
import type { DeltaInsert } from '@blocksuite/inline';
import type {
FromBlockSnapshotPayload,
Expand All @@ -15,7 +15,6 @@ import {
BlockSnapshotSchema,
getAssetName,
nanoid,
sha,
} from '@blocksuite/store';
import { ASTWalker, BaseAdapter } from '@blocksuite/store';
import {
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/_common/adapters/image.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sha } from '@blocksuite/global/utils';
import type { AssetsManager } from '@blocksuite/store';
import {
BaseAdapter,
Expand All @@ -10,7 +11,6 @@ import {
type FromSliceSnapshotPayload,
type FromSliceSnapshotResult,
nanoid,
sha,
type SliceSnapshot,
type ToBlockSnapshotPayload,
type ToDocSnapshotPayload,
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/_common/adapters/markdown.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sha } from '@blocksuite/global/utils';
import type { DeltaInsert } from '@blocksuite/inline/types';
import type {
FromBlockSnapshotPayload,
Expand All @@ -18,7 +19,6 @@ import {
} from '@blocksuite/store';
import { nanoid } from '@blocksuite/store';
import { ASTWalker, BaseAdapter } from '@blocksuite/store';
import { sha } from '@blocksuite/store';
import { format } from 'date-fns/format';
import type { Heading, Root, RootContentMap, TableRow } from 'mdast';
import remarkParse from 'remark-parse';
Expand Down
3 changes: 1 addition & 2 deletions packages/blocks/src/_common/adapters/notion-html.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isEqual } from '@blocksuite/global/utils';
import { isEqual, sha } from '@blocksuite/global/utils';
import type { DeltaInsert } from '@blocksuite/inline';
import type {
FromBlockSnapshotPayload,
Expand All @@ -16,7 +16,6 @@ import {
type DocSnapshot,
getAssetName,
nanoid,
sha,
type SliceSnapshot,
} from '@blocksuite/store';
import rehypeParse from 'rehype-parse';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export class ExportManager {
if (matchFlavours(block, ['affine:image'])) {
if (!block.sourceId) return;

const blob = await block.doc.blob.get(block.sourceId);
const blob = await block.doc.blobSync.get(block.sourceId);
if (!blob) return;

const blobToImage = (blob: Blob) =>
Expand Down
4 changes: 2 additions & 2 deletions packages/blocks/src/_common/transformers/zip.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { assertExists } from '@blocksuite/global/utils';
import { assertExists, sha } from '@blocksuite/global/utils';
import type {
CollectionInfoSnapshot,
Doc,
DocCollection,
DocSnapshot,
JobMiddleware,
} from '@blocksuite/store';
import { extMimeMap, getAssetName, Job, sha } from '@blocksuite/store';
import { extMimeMap, getAssetName, Job } from '@blocksuite/store';
import JSZip from 'jszip';

import { replaceIdMiddleware } from './middlewares.js';
Expand Down
25 changes: 0 additions & 25 deletions packages/blocks/src/_common/utils/filesys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { BlobManager } from '@blocksuite/store';

// Polyfill for `showOpenFilePicker` API
// See https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/wicg-file-system-access/index.d.ts
// See also https://caniuse.com/?search=showOpenFilePicker
Expand Down Expand Up @@ -219,29 +217,6 @@ export async function getImageFilesFromLocal() {
return imageFiles;
}

export async function uploadImageFromLocal(storage: BlobManager) {
const imageFiles = await openFileOrFiles({
acceptType: 'Images',
multiple: true,
});
if (!imageFiles) return [];
return loadImages(imageFiles, storage);
}

export async function loadImages(images: File[], storage: BlobManager) {
const res: { file: File; sourceId: string }[] = [];
for (let i = 0; i < images.length; i++) {
const file = images[i];
const sourceId = await storage.set(file);
res.push({ file, sourceId });
}
const { saveAttachmentData } = withTempBlobData();
res.forEach(({ file, sourceId }) => {
saveAttachmentData(sourceId, { name: file.name });
});
return res;
}

export function downloadBlob(blob: Blob, name: string) {
const dataURL = URL.createObjectURL(blob);
const tmpLink = document.createElement('a');
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/_common/utils/render-linked-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ async function renderImageAbstract(
const sourceId = (image as ImageBlockModel).sourceId;
if (!sourceId) return;

const storage = card.linkedDoc?.blob;
const storage = card.linkedDoc?.blobSync;
if (!storage) return;

const blob = await storage.get(sourceId);
Expand Down
4 changes: 2 additions & 2 deletions packages/blocks/src/attachment-block/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async function uploadAttachmentBlob(

try {
setAttachmentUploading(blockId);
sourceId = await doc.blob.set(blob);
sourceId = await doc.blobSync.set(blob);
} catch (error) {
console.error(error);
if (error instanceof Error) {
Expand Down Expand Up @@ -84,7 +84,7 @@ async function getAttachmentBlob(model: AttachmentBlockModel) {
}

const doc = model.doc;
let blob = await doc.blob.get(sourceId);
let blob = await doc.blobSync.get(sourceId);

if (blob) {
blob = new Blob([blob], { type: model.type });
Expand Down
6 changes: 3 additions & 3 deletions packages/blocks/src/image-block/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function uploadBlobForImage(

try {
setImageUploaded(blockId);
sourceId = await doc.blob.set(blob);
sourceId = await doc.blobSync.set(blob);
} catch (error) {
console.error(error);
if (error instanceof Error) {
Expand Down Expand Up @@ -69,7 +69,7 @@ async function getImageBlob(model: ImageBlockModel) {
}

const doc = model.doc;
const blob = await doc.blob.get(sourceId);
const blob = await doc.blobSync.get(sourceId);

if (!blob) {
return null;
Expand Down Expand Up @@ -123,7 +123,7 @@ export async function fetchImageBlob(block: ImageBlockComponent) {
throw new Error('Image sourceId is missing!');
}

const blob = await doc.blob.get(sourceId);
const blob = await doc.blobSync.get(sourceId);
if (!blob) {
throw new Error('Image blob is missing!');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ export class EdgelessRootBlockComponent extends BlockElement<
const uploadPromises = imageFiles.map(async (file, index) => {
const { point, blockId } = dropInfos[index];

const sourceId = await this.doc.blob.set(file);
const sourceId = await this.doc.blobSync.set(file);
const imageSize = await readImageSize(file);

const center = Vec.toVec(point);
Expand Down Expand Up @@ -501,7 +501,7 @@ export class EdgelessRootBlockComponent extends BlockElement<
let sourceId: string | undefined;
try {
setAttachmentUploading(blockId);
sourceId = await this.doc.blob.set(file);
sourceId = await this.doc.blobSync.set(file);
} catch (error) {
console.error(error);
if (error instanceof Error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import '../../../../_common/components/loader.js';

import { WithDisposable } from '@blocksuite/block-std';
import { type DocCollection, extMimeMap, sha } from '@blocksuite/store';
import { sha } from '@blocksuite/global/utils';
import { type DocCollection, extMimeMap } from '@blocksuite/store';
import { Job } from '@blocksuite/store';
import JSZip from 'jszip';
import { html, LitElement, type PropertyValues } from 'lit';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ export class MiniMindmapPreview extends WithDisposable(LitElement) {
id: 'MINI_MINDMAP_TEMPORARY',
schema,
idGenerator: Generator.NanoID,
blobStorages: [],
awarenessSources: [],
};

Expand Down
1 change: 1 addition & 0 deletions packages/framework/global/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"!dist/__tests__"
],
"dependencies": {
"lib0": "^0.2.93",
"zod": "^3.22.4"
}
}
1 change: 1 addition & 0 deletions packages/framework/global/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './assert.js';
export * from './crypto.js';
export * from './disposable.js';
export * from './function.js';
export * from './logger.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from 'vitest';
import * as Y from 'yjs';

import { MemoryBlobManager } from '../adapter/index.js';
import { MemoryBlobCRUD } from '../adapter/index.js';
import { Text } from '../reactive/index.js';
import {
type BlockModel,
Expand Down Expand Up @@ -51,8 +51,8 @@ function createTestOptions() {
}

const transformer = new BaseBlockTransformer();
const blobManager = new MemoryBlobManager();
const assets = new AssetsManager({ blob: blobManager });
const blobCRUD = new MemoryBlobCRUD();
const assets = new AssetsManager({ blob: blobCRUD });

test('model to snapshot', () => {
const options = createTestOptions();
Expand Down
50 changes: 20 additions & 30 deletions packages/framework/store/src/adapter/assets.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import { assertExists } from '@blocksuite/global/utils';
import { assertExists, sha } from '@blocksuite/global/utils';

import { sha } from '../persistence/blob/utils.js';

export class MemoryBlobManager {
/**
* @internal just for test
*/
export class MemoryBlobCRUD {
private readonly _map = new Map<string, Blob>();
private readonly _blobsRef = new Map<string, number>();

get(key: string) {
return this._map.get(key) ?? null;
}

async set(value: Blob, key?: string) {
const _key = key || (await sha(await value.arrayBuffer()));
this._map.set(_key, value);
return _key;
async set(value: Blob): Promise<string>;
async set(key: string, value: Blob): Promise<string>;
async set(valueOrKey: string | Blob, _value?: Blob) {
const key =
typeof valueOrKey === 'string'
? valueOrKey
: await sha(await valueOrKey.arrayBuffer());
const value = typeof valueOrKey === 'string' ? _value : valueOrKey;

if (!value) {
throw new Error('value is required');
}

this._map.set(key, value);
return key;
}

delete(key: string) {
Expand All @@ -23,27 +34,6 @@ export class MemoryBlobManager {
list() {
return Array.from(this._map.keys());
}

gc() {
const blobs = this.list();
blobs.forEach(blobId => {
const ref = this._blobsRef.get(blobId);
if (!ref || ref <= 0) {
this.delete(blobId);
this._blobsRef.delete(blobId);
}
});
}

increaseRef(blobId: string) {
const ref = this._blobsRef.get(blobId) ?? 0;
this._blobsRef.set(blobId, ref + 1);
}

decreaseRef(blobId: string) {
const ref = this._blobsRef.get(blobId) ?? 0;
this._blobsRef.set(blobId, Math.max(ref - 1, 0));
}
}

export const mimeExtMap = new Map([
Expand Down
Loading
Loading