chore: optimize the UI if fail to open the workspace (#3246)

* chore: async load user profile

* chore: enable reset workspace

* chore: add confirm dialog
This commit is contained in:
Nathan.fooo
2023-08-22 00:19:15 +08:00
committed by GitHub
parent bd30e31f6c
commit 12d6cbd46a
64 changed files with 928 additions and 322 deletions

View File

@ -48,6 +48,9 @@ pub struct UserProfilePB {
#[pb(index = 9)]
pub encryption_type: EncryptionTypePB,
#[pb(index = 10)]
pub workspace_id: String,
}
#[derive(ProtoBuf_Enum, Eq, PartialEq, Debug, Clone)]
@ -78,6 +81,7 @@ impl std::convert::From<UserProfile> for UserProfilePB {
auth_type: user_profile.auth_type.into(),
encryption_sign,
encryption_type: encryption_ty,
workspace_id: user_profile.workspace_id,
}
}
}
@ -274,3 +278,12 @@ impl From<HistoricalUser> for HistoricalUserPB {
}
}
}
#[derive(ProtoBuf, Default, Clone)]
pub struct ResetWorkspacePB {
#[pb(index = 1)]
pub uid: i64,
#[pb(index = 2)]
pub workspace_id: String,
}

View File

@ -3,7 +3,7 @@ use std::{convert::TryInto, sync::Arc};
use serde_json::Value;
use flowy_error::{FlowyError, FlowyResult};
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_sqlite::kv::StorePreferences;
use flowy_user_deps::cloud::UserCloudConfig;
use flowy_user_deps::entities::*;
@ -20,7 +20,7 @@ use crate::services::cloud_config::{
fn upgrade_manager(manager: AFPluginState<Weak<UserManager>>) -> FlowyResult<Arc<UserManager>> {
let manager = manager
.upgrade()
.ok_or(FlowyError::internal().context("The user session is already drop"))?;
.ok_or(FlowyError::internal().with_context("The user session is already drop"))?;
Ok(manager)
}
@ -29,7 +29,7 @@ fn upgrade_store_preferences(
) -> FlowyResult<Arc<StorePreferences>> {
let store = store
.upgrade()
.ok_or(FlowyError::internal().context("The store preferences is already drop"))?;
.ok_or(FlowyError::internal().with_context("The store preferences is already drop"))?;
Ok(store)
}
@ -96,7 +96,15 @@ pub async fn get_user_profile_handler(
let manager = upgrade_manager(manager)?;
let uid = manager.get_session()?.user_id;
let user_profile = manager.get_user_profile(uid).await?;
let _ = manager.refresh_user_profile(&user_profile).await;
let weak_manager = Arc::downgrade(&manager);
let cloned_user_profile = user_profile.clone();
tokio::spawn(async move {
if let Some(manager) = weak_manager.upgrade() {
let _ = manager.refresh_user_profile(&cloned_user_profile).await;
}
});
data_result_ok(user_profile.into())
}
@ -250,7 +258,7 @@ pub async fn set_cloud_config_handler(
let update = data.into_inner();
let store_preferences = upgrade_store_preferences(store_preferences)?;
let mut config = get_cloud_config(session.user_id, &store_preferences)
.ok_or(FlowyError::internal().context("Can't find any cloud config"))?;
.ok_or(FlowyError::internal().with_context("Can't find any cloud config"))?;
if let Some(enable_sync) = update.enable_sync {
manager.cloud_services.set_enable_sync(enable_sync);
@ -429,3 +437,20 @@ pub async fn get_all_reminder_event_handler(
.collect::<Vec<_>>();
data_result_ok(reminders.into())
}
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn reset_workspace_handler(
data: AFPluginData<ResetWorkspacePB>,
manager: AFPluginState<Weak<UserManager>>,
) -> Result<(), FlowyError> {
let manager = upgrade_manager(manager)?;
let reset_pb = data.into_inner();
if reset_pb.workspace_id.is_empty() {
return Err(FlowyError::new(
ErrorCode::WorkspaceIdInvalid,
"The workspace id is empty",
));
}
manager.reset_workspace(reset_pb).await?;
Ok(())
}

View File

@ -54,6 +54,7 @@ pub fn init(user_session: Weak<UserManager>) -> AFPlugin {
.event(UserEvent::PushRealtimeEvent, push_realtime_event_handler)
.event(UserEvent::CreateReminder, create_reminder_event_handler)
.event(UserEvent::GetAllReminders, get_all_reminder_event_handler)
.event(UserEvent::ResetWorkspace, reset_workspace_handler)
}
pub struct SignUpContext {
@ -271,4 +272,7 @@ pub enum UserEvent {
#[event(output = "RepeatedReminderPB")]
GetAllReminders = 29,
#[event(input = "ResetWorkspacePB")]
ResetWorkspace = 30,
}

View File

@ -70,7 +70,7 @@ pub fn open_user_db(root: &str, user_id: i64) -> Result<Arc<ConnectionPool>, Flo
let dir = user_db_path_from_uid(root, user_id);
tracing::debug!("open sqlite db {} at path: {:?}", user_id, dir);
let db = flowy_sqlite::init(&dir)
.map_err(|e| FlowyError::internal().context(format!("open user db failed, {:?}", e)))?;
.map_err(|e| FlowyError::internal().with_context(format!("open user db failed, {:?}", e)))?;
let pool = db.get_pool();
write_guard.insert(user_id.to_owned(), db);
drop(write_guard);

View File

@ -1,12 +1,14 @@
use std::convert::TryFrom;
use std::sync::Arc;
use appflowy_integrate::{CollabObject, CollabType};
use flowy_error::{FlowyError, FlowyResult};
use flowy_sqlite::schema::user_workspace_table;
use flowy_sqlite::{query_dsl::*, ConnectionPool, ExpressionMethods};
use flowy_user_deps::entities::UserWorkspace;
use crate::entities::RepeatedUserWorkspacePB;
use crate::entities::{RepeatedUserWorkspacePB, ResetWorkspacePB};
use crate::manager::UserManager;
use crate::notification::{send_notification, UserNotification};
use crate::services::user_workspace_sql::UserWorkspaceTable;
@ -84,6 +86,20 @@ impl UserManager {
}
Ok(rows.into_iter().map(UserWorkspace::from).collect())
}
/// Reset the remote workspace using local workspace data. This is useful when a user wishes to
/// open a workspace on a new device that hasn't fully synchronized with the server.
pub async fn reset_workspace(&self, reset: ResetWorkspacePB) -> FlowyResult<()> {
let collab_object =
CollabObject::new(reset.uid, reset.workspace_id.clone(), CollabType::Folder)
.with_workspace_id(reset.workspace_id);
self
.cloud_services
.get_user_service()?
.reset_workspace(collab_object)
.await?;
Ok(())
}
}
pub fn save_user_workspaces(

View File

@ -21,10 +21,10 @@ impl TryFrom<(i64, &UserWorkspace)> for UserWorkspaceTable {
fn try_from(value: (i64, &UserWorkspace)) -> Result<Self, Self::Error> {
if value.1.id.is_empty() {
return Err(FlowyError::invalid_data().context("The id is empty"));
return Err(FlowyError::invalid_data().with_context("The id is empty"));
}
if value.1.database_storage_id.is_empty() {
return Err(FlowyError::invalid_data().context("The database storage id is empty"));
return Err(FlowyError::invalid_data().with_context("The database storage id is empty"));
}
Ok(Self {