feat: add some ipc provider method

This commit is contained in:
Lin Onetwo
2023-01-05 18:38:05 +08:00
parent 1cd17ea31b
commit 646fcea816
15 changed files with 290 additions and 84 deletions

View File

@@ -2,6 +2,7 @@
import type { Workspace } from '@blocksuite/store';
import type { Apis, Logger, InitialParams, ConfigStore } from './index';
import type { BlobURL } from '@blocksuite/store/dist/blob/types';
export class BaseProvider {
static id = 'base';
@@ -41,8 +42,10 @@ export class BaseProvider {
throw Error('Not implemented: initData');
}
// should return a blob url
async getBlob(_id: string): Promise<string | null> {
/**
* should return a blob url
*/
async getBlob(_id: string): Promise<BlobURL | null> {
throw Error('Not implemented: getBlob');
}

View File

@@ -1,35 +1,48 @@
import type { BlobStorage } from '@blocksuite/store';
import * as Y from 'yjs';
import assert from 'assert';
import type { ConfigStore, InitialParams } from '../index.js';
import { BaseProvider } from '../base.js';
import { IndexedDBProvider } from './indexeddb.js';
import { LocalProvider } from '../local/index.js';
import * as ipcMethods from './ipc/methods.js';
export class LocalProvider extends BaseProvider {
export class TauriIPCProvider extends LocalProvider {
static id = 'local';
private _blobs!: BlobStorage;
private _idb?: IndexedDBProvider = undefined;
#ipc = ipcMethods;
constructor() {
super();
}
async init(params: InitialParams) {
super.init(params);
const blobs = await this._workspace.blobs;
assert(blobs);
this._blobs = blobs;
}
async initData() {
assert(this._workspace.room);
this._logger('Loading local data');
this._idb = new IndexedDBProvider(
this._workspace.room,
this._workspace.doc
const { doc, room } = this._workspace;
doc.on(
'update',
async (
update: Uint8Array,
_origin: any,
_yDocument: Y.Doc,
_transaction: Y.Transaction
) => {
try {
// TODO: need handle potential data race when update is frequent?
// TODO: update seems too frequent upon each keydown, why no batching?
const success = await this.#ipc.updateYDocument({
update: Array.from(update),
room,
});
if (!success) {
throw new Error(
`YDoc update failed, id: ${this.workspace.meta.id}`
);
}
} catch (error) {
// TODO: write error log to disk, and add button to open them in settings panel
console.error("#yDocument.on('update'", error);
}
}
);
await this._idb.whenSynced;
this._logger('Local data loaded');
await this._globalConfig.set(this._workspace.room, true);
@@ -37,25 +50,37 @@ export class LocalProvider extends BaseProvider {
async clear() {
await super.clear();
await this._blobs.clear();
await this._idb?.clearData();
await this._globalConfig.delete(this._workspace.room!);
}
async destroy(): Promise<void> {
super.destroy();
await this._idb?.destroy();
}
async getBlob(id: string): Promise<string | null> {
return this._blobs.get(id);
async getBlob(id: string) {
const blobArray = await this.#ipc.getBlob({
workspace_id: this.id,
id,
});
// Make a Blob from the bytes
const blob = new Blob([new Uint8Array(blobArray)], { type: 'image/bmp' });
return window.URL.createObjectURL(blob);
}
async setBlob(blob: Blob): Promise<string> {
return this._blobs.set(blob);
async setBlob(blob: Blob) {
return this.#ipc.putBlob({
blob: Array.from(new Uint8Array(await blob.arrayBuffer())),
workspace_id: this.id,
});
}
static async list(
async createWorkspace(
name: string
): Promise<{ id: string; name: string } | undefined> {
// TODO: get userID here
return this.#ipc.createWorkspace({ name, user_id: 0 });
}
async getWorkspaces(
config: Readonly<ConfigStore<boolean>>
): Promise<Map<string, boolean> | undefined> {
const entries = await config.entries();

View File

@@ -1,6 +1,6 @@
import { invoke } from '@tauri-apps/api';
import { YDocumentUpdate } from './types/document';
import { CreateWorkspace } from './types/workspace';
import { CreateWorkspace, CreateWorkspaceResult } from './types/workspace';
import { GetBlob, PutBlob } from './types/blob';
export const updateYDocument = async (parameters: YDocumentUpdate) =>
@@ -9,7 +9,7 @@ export const updateYDocument = async (parameters: YDocumentUpdate) =>
});
export const createWorkspace = async (parameters: CreateWorkspace) =>
await invoke<boolean>('create_workspace', {
await invoke<CreateWorkspaceResult>('create_workspace', {
parameters,
});

View File

@@ -32,9 +32,7 @@
"type": "string"
},
"workspace_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
"type": "string"
}
}
},
@@ -51,9 +49,7 @@
}
},
"workspace_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
"type": "string"
}
}
}

View File

@@ -15,11 +15,11 @@ export type IBlobParameters =
export interface PutBlob {
blob: number[];
workspace_id: number;
workspace_id: string;
[k: string]: unknown;
}
export interface GetBlob {
id: string;
workspace_id: number;
workspace_id: string;
[k: string]: unknown;
}

View File

@@ -1,18 +1,77 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CreateWorkspace",
"type": "object",
"required": ["avatar", "id", "name"],
"properties": {
"avatar": {
"type": "string"
"title": "IWorkspaceParameters",
"oneOf": [
{
"type": "object",
"required": ["CreateWorkspace"],
"properties": {
"CreateWorkspace": {
"$ref": "#/definitions/CreateWorkspace"
}
},
"additionalProperties": false
},
"id": {
"type": "integer",
"format": "int64"
{
"type": "object",
"required": ["UpdateWorkspace"],
"properties": {
"UpdateWorkspace": {
"$ref": "#/definitions/UpdateWorkspace"
}
},
"additionalProperties": false
},
"name": {
"type": "string"
{
"type": "object",
"required": ["CreateWorkspaceResult"],
"properties": {
"CreateWorkspaceResult": {
"$ref": "#/definitions/CreateWorkspaceResult"
}
},
"additionalProperties": false
}
],
"definitions": {
"CreateWorkspace": {
"type": "object",
"required": ["name", "user_id"],
"properties": {
"name": {
"description": "only set name, avatar is update in datacenter to yDoc directly",
"type": "string"
},
"user_id": {
"type": "integer",
"format": "int32"
}
}
},
"CreateWorkspaceResult": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"UpdateWorkspace": {
"type": "object",
"required": ["id", "public"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"public": {
"type": "boolean"
}
}
}
}
}

View File

@@ -5,9 +5,32 @@
* and run json-schema-to-typescript to regenerate this file.
*/
export type IWorkspaceParameters =
| {
CreateWorkspace: CreateWorkspace;
}
| {
UpdateWorkspace: UpdateWorkspace;
}
| {
CreateWorkspaceResult: CreateWorkspaceResult;
};
export interface CreateWorkspace {
avatar: string;
/**
* only set name, avatar is update in datacenter to yDoc directly
*/
name: string;
user_id: number;
[k: string]: unknown;
}
export interface UpdateWorkspace {
id: number;
public: boolean;
[k: string]: unknown;
}
export interface CreateWorkspaceResult {
id: string;
name: string;
[k: string]: unknown;
}