mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
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:
@ -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::*;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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))
|
||||
|
@ -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()),
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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| {
|
||||
|
@ -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()))?
|
||||
}
|
||||
|
Reference in New Issue
Block a user