mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: doc open sync (#4732)
* chore: bump client api * fix: open document and folder * chore: bump collab rev * chore: fix wasm build * chore: fix warnings
This commit is contained in:
@ -18,7 +18,7 @@ flowy-notification = { workspace = true }
|
||||
parking_lot.workspace = true
|
||||
unicode-segmentation = "1.10"
|
||||
tracing.workspace = true
|
||||
flowy-error = { path = "../flowy-error", features = ["impl_from_dispatch_error"]}
|
||||
flowy-error = { path = "../flowy-error", features = ["impl_from_dispatch_error", "impl_from_collab_folder"]}
|
||||
lib-dispatch = { workspace = true }
|
||||
bytes.workspace = true
|
||||
lib-infra = { workspace = true }
|
||||
|
@ -4,8 +4,10 @@ use std::sync::{Arc, Weak};
|
||||
|
||||
use collab::core::collab::{CollabDocState, MutexCollab};
|
||||
use collab_entity::CollabType;
|
||||
use collab_folder::error::FolderError;
|
||||
use collab_folder::{
|
||||
Folder, FolderData, Section, SectionItem, TrashInfo, View, ViewLayout, ViewUpdate, Workspace,
|
||||
Folder, FolderData, FolderNotify, Section, SectionItem, TrashInfo, UserId, View, ViewLayout,
|
||||
ViewUpdate, Workspace,
|
||||
};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use tracing::{error, info, instrument};
|
||||
@ -15,6 +17,7 @@ use collab_integrate::{CollabKVDB, CollabPersistenceConfig};
|
||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_folder_pub::cloud::{gen_view_id, FolderCloudService};
|
||||
use flowy_folder_pub::folder_builder::ParentChildViews;
|
||||
|
||||
use lib_infra::conditional_send_sync_trait;
|
||||
|
||||
use crate::entities::icon::UpdateViewIconParams;
|
||||
@ -46,7 +49,7 @@ conditional_send_sync_trait! {
|
||||
pub struct FolderManager {
|
||||
pub(crate) workspace_id: RwLock<Option<String>>,
|
||||
pub(crate) mutex_folder: Arc<MutexFolder>,
|
||||
collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
pub(crate) collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||
pub(crate) user: Arc<dyn FolderUser>,
|
||||
pub(crate) operation_handlers: FolderOperationHandlers,
|
||||
pub cloud_service: Arc<dyn FolderCloudService>,
|
||||
@ -147,13 +150,15 @@ impl FolderManager {
|
||||
Ok(views)
|
||||
}
|
||||
|
||||
pub(crate) async fn collab_for_folder(
|
||||
pub(crate) async fn make_folder<T: Into<Option<FolderNotify>>>(
|
||||
&self,
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
collab_db: Weak<CollabKVDB>,
|
||||
collab_doc_state: CollabDocState,
|
||||
) -> Result<Arc<MutexCollab>, FlowyError> {
|
||||
folder_notifier: T,
|
||||
) -> Result<Folder, FlowyError> {
|
||||
let folder_notifier = folder_notifier.into();
|
||||
let collab = self
|
||||
.collab_builder
|
||||
.build_with_config(
|
||||
@ -168,6 +173,45 @@ impl FolderManager {
|
||||
CollabBuilderConfig::default().sync_enable(true),
|
||||
)
|
||||
.await?;
|
||||
let (should_clear, err) = match Folder::open(UserId::from(uid), collab, folder_notifier) {
|
||||
Ok(folder) => {
|
||||
return Ok(folder);
|
||||
},
|
||||
Err(err) => (matches!(err, FolderError::NoRequiredData(_)), err),
|
||||
};
|
||||
|
||||
// If opening the folder fails due to missing required data (indicated by a `FolderError::NoRequiredData`),
|
||||
// the function logs an informational message and attempts to clear the folder data by deleting its
|
||||
// document from the collaborative database. It then returns the encountered error.
|
||||
if should_clear {
|
||||
info!("Clear the folder data and try to open the folder again");
|
||||
if let Some(db) = self.user.collab_db(uid).ok().and_then(|a| a.upgrade()) {
|
||||
let _ = db.delete_doc(uid, workspace_id).await;
|
||||
}
|
||||
}
|
||||
Err(err.into())
|
||||
}
|
||||
|
||||
pub(crate) async fn create_empty_collab(
|
||||
&self,
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
collab_db: Weak<CollabKVDB>,
|
||||
) -> Result<Arc<MutexCollab>, FlowyError> {
|
||||
let collab = self
|
||||
.collab_builder
|
||||
.build_with_config(
|
||||
uid,
|
||||
workspace_id,
|
||||
CollabType::Folder,
|
||||
collab_db,
|
||||
vec![],
|
||||
CollabPersistenceConfig::new()
|
||||
.enable_snapshot(true)
|
||||
.snapshot_per_update(50),
|
||||
CollabBuilderConfig::default().sync_enable(true),
|
||||
)
|
||||
.await?;
|
||||
Ok(collab)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
use collab_entity::CollabType;
|
||||
|
||||
use collab_folder::{Folder, FolderNotify, UserId};
|
||||
|
||||
use collab_integrate::CollabKVDB;
|
||||
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use tracing::{event, Level};
|
||||
|
||||
@ -48,8 +52,9 @@ impl FolderManager {
|
||||
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 {
|
||||
event!(Level::INFO, "Init folder from local disk");
|
||||
self
|
||||
.open_local_folder(uid, &workspace_id, collab_db, folder_notifier)
|
||||
.make_folder(uid, &workspace_id, collab_db, vec![], 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
|
||||
@ -66,30 +71,40 @@ impl FolderManager {
|
||||
.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()))?
|
||||
self
|
||||
.make_folder(
|
||||
uid,
|
||||
&workspace_id,
|
||||
collab_db.clone(),
|
||||
doc_state,
|
||||
folder_notifier.clone(),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
},
|
||||
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)
|
||||
.make_folder(uid, &workspace_id, collab_db, vec![], folder_notifier)
|
||||
.await?
|
||||
} else {
|
||||
event!(Level::INFO, "Restore folder with remote data");
|
||||
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()))?
|
||||
event!(Level::INFO, "Restore folder from remote data");
|
||||
self
|
||||
.make_folder(
|
||||
uid,
|
||||
&workspace_id,
|
||||
collab_db.clone(),
|
||||
doc_state,
|
||||
folder_notifier.clone(),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
},
|
||||
FolderInitDataSource::FolderData(folder_data) => {
|
||||
event!(Level::INFO, "Restore folder with passed-in folder data");
|
||||
let collab = self
|
||||
.collab_for_folder(uid, &workspace_id, collab_db, vec![])
|
||||
.create_empty_collab(uid, &workspace_id, collab_db)
|
||||
.await?;
|
||||
Folder::create(
|
||||
UserId::from(uid),
|
||||
@ -135,7 +150,7 @@ impl FolderManager {
|
||||
let folder_data =
|
||||
DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers).await;
|
||||
let collab = self
|
||||
.collab_for_folder(uid, workspace_id, collab_db, vec![])
|
||||
.create_empty_collab(uid, workspace_id, collab_db)
|
||||
.await?;
|
||||
Ok(Folder::create(
|
||||
UserId::from(uid),
|
||||
@ -144,19 +159,4 @@ impl FolderManager {
|
||||
folder_data,
|
||||
))
|
||||
}
|
||||
|
||||
async fn open_local_folder(
|
||||
&self,
|
||||
uid: i64,
|
||||
workspace_id: &str,
|
||||
collab_db: Weak<CollabKVDB>,
|
||||
folder_notifier: FolderNotify,
|
||||
) -> Result<Folder, FlowyError> {
|
||||
event!(Level::INFO, "Init folder from local disk");
|
||||
let collab = self
|
||||
.collab_for_folder(uid, workspace_id, collab_db, vec![])
|
||||
.await?;
|
||||
let folder = Folder::open(UserId::from(uid), collab, Some(folder_notifier))?;
|
||||
Ok(folder)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user