feat: update yrs doc using ipc from yjs doc

This commit is contained in:
Lin Onetwo
2023-01-05 20:43:35 +08:00
parent 92ea3ee2a8
commit c83537aac6
12 changed files with 215 additions and 87 deletions

View File

@@ -16,7 +16,12 @@ export class TauriIPCProvider extends LocalProvider {
async initData() {
assert(this._workspace.room);
this._logger('Loading local data');
const { doc, room } = this._workspace;
const {
doc,
room,
meta: { id },
} = this._workspace;
this.#initDocFromIPC(id, doc);
doc.on(
'update',
async (
@@ -30,7 +35,7 @@ export class TauriIPCProvider extends LocalProvider {
// TODO: update seems too frequent upon each keydown, why no batching?
const success = await this.#ipc.updateYDocument({
update: Array.from(update),
room,
id: Number(id),
});
if (!success) {
throw new Error(
@@ -44,8 +49,25 @@ export class TauriIPCProvider extends LocalProvider {
}
);
this._logger('Local data loaded');
}
await this._globalConfig.set(this._workspace.room, true);
async #initDocFromIPC(workspaceID: string, doc: Y.Doc) {
this._logger(`Loading ${workspaceID}...`);
const updates = await this.#ipc.getYDocument({ id: Number(workspaceID) });
if (updates) {
await new Promise(resolve => {
doc.once('update', resolve);
Y.applyUpdate(doc, new Uint8Array(updates.update));
});
this._logger(`Loaded: ${workspaceID}`);
// only add to list as online workspace
this._signals.listAdd.emit({
workspace: workspaceID,
provider: this.id,
locally: true,
});
}
}
async clear() {

View File

@@ -1,54 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
import * as Y from 'yjs';
import { Observable } from 'lib0/observable';
import { DocProvider } from '@blocksuite/store';
import type { Awareness } from 'y-protocols/awareness';
import { invoke } from '@tauri-apps/api';
import { updateYDocument } from './methods';
export class TauriIPCProvider
extends Observable<string>
implements DocProvider
{
#yDocument: Y.Doc;
constructor(
room: string,
yDocument: Y.Doc,
options?: { awareness?: Awareness }
) {
super();
this.#yDocument = yDocument;
this.#yDocument.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 updateYDocument({
update: Array.from(update),
room,
});
} catch (error) {
// TODO: write error log to disk, and add button to open them in settings panel
console.error("#yDocument.on('update'", error);
}
}
);
}
connect() {}
destroy() {}
disconnect() {
// do nothing
}
async clearData() {}
}

View File

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

View File

@@ -1,18 +1,79 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "YDocumentUpdate",
"type": "object",
"required": ["room", "update"],
"properties": {
"room": {
"type": "string"
"title": "IDocumentParameters",
"oneOf": [
{
"type": "object",
"required": ["YDocumentUpdate"],
"properties": {
"YDocumentUpdate": {
"$ref": "#/definitions/YDocumentUpdate"
}
},
"additionalProperties": false
},
"update": {
"type": "array",
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0.0
{
"type": "object",
"required": ["GetDocumentParameter"],
"properties": {
"GetDocumentParameter": {
"$ref": "#/definitions/GetDocumentParameter"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": ["GetDocumentResponse"],
"properties": {
"GetDocumentResponse": {
"$ref": "#/definitions/GetDocumentResponse"
}
},
"additionalProperties": false
}
],
"definitions": {
"GetDocumentParameter": {
"type": "object",
"required": ["id"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
}
}
},
"GetDocumentResponse": {
"type": "object",
"required": ["update"],
"properties": {
"update": {
"type": "array",
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0.0
}
}
}
},
"YDocumentUpdate": {
"type": "object",
"required": ["id", "update"],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"update": {
"type": "array",
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0.0
}
}
}
}
}

View File

@@ -5,8 +5,27 @@
* and run json-schema-to-typescript to regenerate this file.
*/
export type IDocumentParameters =
| {
YDocumentUpdate: YDocumentUpdate;
}
| {
GetDocumentParameter: GetDocumentParameter;
}
| {
GetDocumentResponse: GetDocumentResponse;
};
export interface YDocumentUpdate {
room: string;
id: number;
update: number[];
[k: string]: unknown;
}
export interface GetDocumentParameter {
id: number;
[k: string]: unknown;
}
export interface GetDocumentResponse {
update: number[];
[k: string]: unknown;
}