fix: create yDoc for workspace created during createUser

This commit is contained in:
linonetwo 2023-01-12 16:17:30 +08:00
parent ac1ddba094
commit 4be968c421
7 changed files with 118 additions and 70 deletions

View File

@ -16,6 +16,7 @@ pub fn invoke_handler() -> impl Fn(tauri::Invoke) + Send + Sync + 'static {
get_workspaces, get_workspaces,
get_workspace, get_workspace,
create_user, create_user,
create_doc,
get_doc, get_doc,
put_blob, put_blob,
get_blob get_blob

View File

@ -1,9 +1,44 @@
use ipc_types::document::{GetDocumentParameter, GetDocumentResponse, YDocumentUpdate}; use ipc_types::document::{
CreateDocumentParameter, GetDocumentParameter, GetDocumentResponse, YDocumentUpdate,
};
use jwst::DocStorage; use jwst::DocStorage;
use jwst::Workspace as OctoBaseWorkspace;
use lib0::any::Any;
use yrs::StateVector; use yrs::StateVector;
use crate::state::AppState; use crate::state::AppState;
#[tauri::command]
/// get yDoc created by create_workspace, using same id
pub async fn create_doc<'s>(
state: tauri::State<'s, AppState>,
parameters: CreateDocumentParameter,
) -> Result<(), String> {
let workspace_doc = OctoBaseWorkspace::new(parameters.workspace_id.clone());
workspace_doc.with_trx(|mut workspace_doc_transaction| {
workspace_doc_transaction.set_metadata(
"name",
Any::String(parameters.workspace_name.clone().into_boxed_str()),
);
});
if let Err(error_message) = &state
.0
.lock()
.await
.doc_storage
.write_doc(parameters.workspace_id.clone(), workspace_doc.doc())
.await
{
Err(format!(
"Failed to write_doc during create_workspace with error {}",
error_message.to_string()
))
} else {
Ok(())
}
}
#[tauri::command] #[tauri::command]
/// get yDoc created by create_workspace, using same id /// get yDoc created by create_workspace, using same id
pub async fn get_doc<'s>( pub async fn get_doc<'s>(
@ -25,10 +60,7 @@ pub async fn get_doc<'s>(
update: doc.encode_state_as_update_v1(&StateVector::default()), update: doc.encode_state_as_update_v1(&StateVector::default()),
}) })
} else { } else {
Err(format!( Err(format!("Failed to get yDoc from {}", parameters.id))
"Failed to get yDoc from {}",
parameters.id
))
} }
} }
@ -48,9 +80,6 @@ pub async fn update_y_document<'s>(
{ {
Ok(true) Ok(true)
} else { } else {
Err(format!( Err(format!("Failed to update yDoc to {}", parameters.id))
"Failed to update yDoc to {}",
parameters.id
))
} }
} }

View File

@ -1,23 +1,38 @@
use ipc_types::document::CreateDocumentParameter;
use jwst_storage::{CreateUser, User}; use jwst_storage::{CreateUser, User};
use crate::state::AppState; use crate::state::AppState;
use super::document::create_doc;
#[tauri::command] #[tauri::command]
/// create yDoc for a workspace /// create new user and a private workspace
pub async fn create_user<'s>( pub async fn create_user<'s>(
state: tauri::State<'s, AppState>, state: tauri::State<'s, AppState>,
parameters: CreateUser, parameters: CreateUser,
) -> Result<User, String> { ) -> Result<User, String> {
match &state let new_user_result = &state
.0 .0
.lock() .lock()
.await .await
.metadata_db .metadata_db
.create_user(parameters.clone()) .create_user(parameters.clone())
.await .await;
{ match new_user_result{
Ok(new_user_option) => match new_user_option { Ok(new_user_option) => match new_user_option {
Some(new_user) => Ok(new_user.clone()), Some((new_user, new_workspace)) => {
// a new private workspace is created, we have to create a yDoc for it
create_doc(
state,
CreateDocumentParameter {
workspace_id: new_workspace.id.clone(),
workspace_name: parameters.name.clone(),
},
)
.await
.ok();
Ok(new_user.clone())
}
None => Err("User creation failed".to_string()), None => Err("User creation failed".to_string()),
}, },
Err(error_message) => Err(error_message.to_string()), Err(error_message) => Err(error_message.to_string()),

View File

@ -1,12 +1,15 @@
use ipc_types::workspace::{ use ipc_types::{
CreateWorkspace, CreateWorkspaceResult, GetWorkspace, GetWorkspaceResult, GetWorkspaces, document::CreateDocumentParameter,
GetWorkspacesResult, UpdateWorkspace, workspace::{
CreateWorkspace, CreateWorkspaceResult, GetWorkspace, GetWorkspaceResult, GetWorkspaces,
GetWorkspacesResult, UpdateWorkspace,
},
}; };
use jwst::{DocStorage, Workspace as OctoBaseWorkspace};
use lib0::any::Any;
use crate::state::AppState; use crate::state::AppState;
use super::document::create_doc;
#[tauri::command] #[tauri::command]
/// create yDoc for a workspace /// create yDoc for a workspace
pub async fn get_workspaces<'s>( pub async fn get_workspaces<'s>(
@ -46,7 +49,7 @@ pub async fn get_workspace<'s>(
Some(user_workspace) => Ok(GetWorkspaceResult { Some(user_workspace) => Ok(GetWorkspaceResult {
workspace: user_workspace.clone(), workspace: user_workspace.clone(),
}), }),
None => Err("Get workspace has no result".to_string()) None => Err("Get workspace has no result".to_string()),
}, },
Err(error_message) => Err(error_message.to_string()), Err(error_message) => Err(error_message.to_string()),
} }
@ -58,40 +61,33 @@ pub async fn create_workspace<'s>(
state: tauri::State<'s, AppState>, state: tauri::State<'s, AppState>,
parameters: CreateWorkspace, parameters: CreateWorkspace,
) -> Result<CreateWorkspaceResult, String> { ) -> Result<CreateWorkspaceResult, String> {
match &state let new_workspace_result = &state
.0 .0
.lock() .lock()
.await .await
.metadata_db .metadata_db
.create_normal_workspace(parameters.user_id) .create_normal_workspace(parameters.user_id)
.await .await;
{ match new_workspace_result {
Ok(new_workspace) => { Ok(new_workspace) => {
let workspace_doc = OctoBaseWorkspace::new(new_workspace.id.clone()); create_doc(
state,
workspace_doc.with_trx(|mut workspace_doc_transaction| { CreateDocumentParameter {
workspace_doc_transaction.set_metadata( workspace_id: new_workspace.id.clone(),
"name", workspace_name: parameters.name.clone(),
Any::String(parameters.name.clone().into_boxed_str()), },
); )
}); .await
if let Err(error_message) = &state .ok();
.0 Ok(CreateWorkspaceResult {
.lock() id: new_workspace.id.clone(),
.await name: parameters.name,
.doc_storage })
.write_doc(new_workspace.id.clone(), workspace_doc.doc())
.await
{
Err(error_message.to_string())
} else {
Ok(CreateWorkspaceResult {
id: new_workspace.id.clone(),
name: parameters.name,
})
}
} }
Err(error_message) => Err(error_message.to_string()), Err(error_message) => Err(format!(
"Failed to create_workspace with error {}",
error_message.to_string()
)),
} }
} }

View File

@ -12,6 +12,11 @@ pub struct GetDocumentParameter {
pub id: String, pub id: String,
} }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct CreateDocumentParameter {
pub workspace_id: String,
pub workspace_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct GetDocumentResponse { pub struct GetDocumentResponse {
pub update: Vec<u8>, pub update: Vec<u8>,
} }
@ -19,6 +24,7 @@ pub struct GetDocumentResponse {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub enum IDocumentParameters { pub enum IDocumentParameters {
YDocumentUpdate(YDocumentUpdate), YDocumentUpdate(YDocumentUpdate),
CreateDocumentParameter(CreateDocumentParameter),
GetDocumentParameter(GetDocumentParameter), GetDocumentParameter(GetDocumentParameter),
GetDocumentResponse(GetDocumentResponse), GetDocumentResponse(GetDocumentResponse),
} }

View File

@ -11,21 +11,35 @@ import {
import { BlockSchema } from '@blocksuite/blocks/models'; import { BlockSchema } from '@blocksuite/blocks/models';
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store'; import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
import { IPCBlobProvider } from './blocksuite-provider/blob.js'; import { IPCBlobProvider } from './blocksuite-provider/blob.js';
import { WorkspaceDetail } from '../affine/apis/workspace.js'; import type { WorkspaceDetail } from '../affine/apis/workspace.js';
import { setDefaultAvatar } from '../utils.js'; import { setDefaultAvatar } from '../utils.js';
export class TauriIPCProvider extends LocalProvider { export class TauriIPCProvider extends LocalProvider {
static id = 'tauri-ipc'; static id = 'tauri-ipc';
private _workspacesCache: Map<string, BlocksuiteWorkspace> = new Map(); private _workspacesCache: Map<string, BlocksuiteWorkspace> = new Map();
/**
* // TODO: We only have one user in this version of app client. But may support switch user later.
*/
#defaultUserID = 1;
constructor(params: ProviderConstructorParams) { constructor(params: ProviderConstructorParams) {
super(params); super(params);
// TODO: let blocksuite's blob provider get blob receive workspace id. Currently, all blobs are placed together
this.loadWorkspaces();
} }
async init() { async init() {
// nothing to init until load workspace // we create a default user if we don't have one.
try {
const user = await ipcMethods.createUser({
email: 'xxx@xx.xx',
name: 'xxx',
password: 'xxx',
avatar_url: '',
});
this.#defaultUserID = user.id;
} catch (error) {
// maybe user existed, which can be omited
console.error(error);
}
} }
async #initDocFromIPC(workspaceID: string, doc: Y.Doc) { async #initDocFromIPC(workspaceID: string, doc: Y.Doc) {
@ -70,7 +84,7 @@ export class TauriIPCProvider extends LocalProvider {
const { id } = await ipcMethods.createWorkspace({ const { id } = await ipcMethods.createWorkspace({
name: meta.name, name: meta.name,
// TODO: get userID here // TODO: get userID here
user_id: 0, user_id: this.#defaultUserID,
}); });
const workspaceInfo: WorkspaceMeta0 = { const workspaceInfo: WorkspaceMeta0 = {
@ -104,8 +118,6 @@ export class TauriIPCProvider extends LocalProvider {
assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).'); assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).');
this._logger('Creating affine workspace'); this._logger('Creating affine workspace');
this.linkLocal(blocksuiteWorkspace);
const workspaceInfo: WorkspaceMeta0 = { const workspaceInfo: WorkspaceMeta0 = {
name: meta.name, name: meta.name,
id: workspaceId, id: workspaceId,
@ -125,23 +137,8 @@ export class TauriIPCProvider extends LocalProvider {
} }
override async loadWorkspaces() { override async loadWorkspaces() {
// TODO: get user id here
// try create a default user, otherwise getWorkspaces will failed due to user not exists
let createdUserID = 0;
try {
const user = await ipcMethods.createUser({
email: 'xxx@xx.xx',
name: 'xxx',
password: 'xxx',
avatar_url: '',
});
createdUserID = user.id;
} catch (error) {
// maybe user existed, which can be omited
console.error(error);
}
const { workspaces: workspacesList } = await ipcMethods.getWorkspaces({ const { workspaces: workspacesList } = await ipcMethods.getWorkspaces({
user_id: createdUserID, user_id: this.#defaultUserID,
}); });
const workspaces: WorkspaceMeta0[] = workspacesList.map(w => { const workspaces: WorkspaceMeta0[] = workspacesList.map(w => {
return { return {

View File

@ -51,6 +51,10 @@ export const getBlob = async (parameters: GetBlob) =>
parameters, parameters,
}); });
/**
* This will create a private workspace too.
* @returns
*/
export const createUser = async (parameters: CreateUser) => export const createUser = async (parameters: CreateUser) =>
await invoke<User>('create_user', { await invoke<User>('create_user', {
parameters, parameters,