chore: reload workspace when fail to load at the first time (#4633)

* chore: reload workspace when fail to load at the first time

* fix: clippy

* chore: update client api

* chore: fix wasm build

* chore: fix test
This commit is contained in:
Nathan.fooo
2024-02-08 23:53:05 +08:00
committed by GitHub
parent 747fe40648
commit 3b51a6e6be
26 changed files with 468 additions and 197 deletions

View File

@ -1,9 +1,7 @@
mod view_desc;
mod view_id;
mod view_name;
mod view_thumbnail;
pub use view_desc::*;
pub use view_id::*;
pub use view_name::*;
pub use view_thumbnail::*;

View File

@ -1,21 +0,0 @@
use flowy_error::ErrorCode;
use unicode_segmentation::UnicodeSegmentation;
#[derive(Debug)]
pub struct ViewDesc(pub String);
impl ViewDesc {
pub fn parse(s: String) -> Result<ViewDesc, ErrorCode> {
if s.graphemes(true).count() > 1000 {
return Err(ErrorCode::ViewDescTooLong);
}
Ok(Self(s))
}
}
impl AsRef<str> for ViewDesc {
fn as_ref(&self) -> &str {
&self.0
}
}

View File

@ -6,7 +6,7 @@ pub struct WorkspaceIdentify(pub String);
impl WorkspaceIdentify {
pub fn parse(s: String) -> Result<WorkspaceIdentify, ErrorCode> {
if s.trim().is_empty() {
return Err(ErrorCode::WorkspaceIdInvalid);
return Err(ErrorCode::WorkspaceInitializeError);
}
Ok(Self(s))

View File

@ -10,7 +10,7 @@ use flowy_error::ErrorCode;
use flowy_folder_pub::cloud::gen_view_id;
use crate::entities::icon::ViewIconPB;
use crate::entities::parser::view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail};
use crate::entities::parser::view::{ViewIdentify, ViewName, ViewThumbnail};
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct ChildViewUpdatePB {
@ -336,11 +336,6 @@ impl TryInto<UpdateViewParams> for UpdateViewPayloadPB {
Some(name) => Some(ViewName::parse(name)?.0),
};
let desc = match self.desc {
None => None,
Some(desc) => Some(ViewDesc::parse(desc)?.0),
};
let thumbnail = match self.thumbnail {
None => None,
Some(thumbnail) => Some(ViewThumbnail::parse(thumbnail)?.0),
@ -351,7 +346,7 @@ impl TryInto<UpdateViewParams> for UpdateViewPayloadPB {
Ok(UpdateViewParams {
view_id,
name,
desc,
desc: self.desc,
thumbnail,
is_favorite,
layout: self.layout.map(|ty| ty.into()),

View File

@ -329,3 +329,11 @@ pub(crate) async fn get_folder_snapshots_handler(
let snapshots = folder.get_folder_snapshots(&data.value, 10).await?;
data_result_ok(RepeatedFolderSnapshotPB { items: snapshots })
}
pub(crate) async fn reload_workspace_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> Result<(), FlowyError> {
let folder = upgrade_folder(folder)?;
folder.reload_workspace().await?;
Ok(())
}

View File

@ -37,6 +37,7 @@ pub fn init(folder: Weak<FolderManager>) -> AFPlugin {
.event(FolderEvent::ReadRecentViews, read_recent_views_handler)
.event(FolderEvent::ToggleFavorite, toggle_favorites_handler)
.event(FolderEvent::UpdateRecentViews, update_recent_views_handler)
.event(FolderEvent::ReloadWorkspace, reload_workspace_handler)
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
@ -152,4 +153,7 @@ pub enum FolderEvent {
// used for add or remove recent views, like history
#[event(input = "UpdateRecentViewPayloadPB")]
UpdateRecentViews = 37,
#[event()]
ReloadWorkspace = 38,
}

View File

@ -72,15 +72,39 @@ impl FolderManager {
Ok(manager)
}
pub async fn reload_workspace(&self) -> FlowyResult<()> {
let workspace_id = self
.workspace_id
.read()
.as_ref()
.ok_or_else(|| {
FlowyError::internal().with_context("workspace id is empty when trying to reload workspace")
})?
.clone();
let uid = self.user.user_id()?;
let doc_state = self
.cloud_service
.get_folder_doc_state(&workspace_id, uid, CollabType::Folder, &workspace_id)
.await?;
self
.initialize(uid, &workspace_id, FolderInitDataSource::Cloud(doc_state))
.await?;
Ok(())
}
#[instrument(level = "debug", skip(self), err)]
pub async fn get_current_workspace(&self) -> FlowyResult<WorkspacePB> {
self.with_folder(
|| {
let uid = self.user.user_id()?;
let workspace_id = self.workspace_id.read().as_ref().cloned().ok_or(
FlowyError::from(ErrorCode::WorkspaceIdInvalid)
.with_context("Unexpected empty workspace id"),
)?;
let workspace_id = self
.workspace_id
.read()
.as_ref()
.cloned()
.ok_or_else(|| FlowyError::from(ErrorCode::WorkspaceInitializeError))?;
Err(workspace_data_not_sync_error(uid, &workspace_id))
},
|folder| {

View File

@ -1,10 +1,9 @@
use std::sync::{Arc, Weak};
use collab_entity::CollabType;
use collab_folder::{Folder, FolderNotify, UserId};
use tracing::{event, Level};
use collab_integrate::CollabKVDB;
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_error::{FlowyError, FlowyResult};
use std::sync::{Arc, Weak};
use tracing::{event, Level};
use crate::manager::{FolderInitDataSource, FolderManager};
use crate::manager_observer::{
@ -47,25 +46,34 @@ impl FolderManager {
create_if_not_exist,
} => {
let is_exist = self.is_workspace_exist_in_local(uid, &workspace_id).await;
// 1. if the folder exists, open it from local disk
if is_exist {
self
.open_local_folder(uid, &workspace_id, collab_db, folder_notifier)
.await?
} else if create_if_not_exist {
// 2. if the folder doesn't exist and create_if_not_exist is true, create a default folder
// Currently, this branch is only used when the server type is supabase. For appflowy cloud,
// the default workspace is already created when the user sign up.
self
.create_default_folder(uid, &workspace_id, collab_db, folder_notifier)
.await?
} else {
return Err(FlowyError::new(
ErrorCode::RecordNotFound,
"Can't find any workspace data",
));
// 3. If the folder doesn't exist and create_if_not_exist is false, try to fetch the folder data from cloud/
// This will happen user can't fetch the folder data when the user sign in.
let doc_state = self
.cloud_service
.get_folder_doc_state(&workspace_id, uid, CollabType::Folder, &workspace_id)
.await?;
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db.clone(), doc_state)
.await?;
Folder::open(UserId::from(uid), collab, Some(folder_notifier.clone()))?
}
},
FolderInitDataSource::Cloud(raw_data) => {
if raw_data.is_empty() {
FolderInitDataSource::Cloud(doc_state) => {
if doc_state.is_empty() {
event!(Level::ERROR, "remote folder data is empty, open from local");
self
.open_local_folder(uid, &workspace_id, collab_db, folder_notifier)
@ -73,7 +81,7 @@ impl FolderManager {
} else {
event!(Level::INFO, "Restore folder with remote data");
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db.clone(), raw_data)
.collab_for_folder(uid, &workspace_id, collab_db.clone(), doc_state)
.await?;
Folder::open(UserId::from(uid), collab, Some(folder_notifier.clone()))?
}