chore: rm fut (#5958)

* chore: rm fut

* chore: clippy
This commit is contained in:
Nathan.fooo 2024-08-14 10:33:23 +08:00 committed by GitHub
parent b3a0119c18
commit 4b24b41dd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 477 additions and 664 deletions

View File

@ -1,4 +1,4 @@
use flowy_core::MutexAppFlowyCore;
use flowy_core::;
use lib_dispatch::prelude::{
AFPluginDispatcher, AFPluginEventResponse, AFPluginRequest, StatusCode,
};

View File

@ -1,4 +1,4 @@
use flowy_core::{AppFlowyCore, MutexAppFlowyCore};
use flowy_core::MutexAppFlowyCore;
use lib_dispatch::prelude::{
AFPluginDispatcher, AFPluginEventResponse, AFPluginRequest, StatusCode,
};

View File

@ -11,7 +11,6 @@ use client_api::error::AppResponseError;
use flowy_error::FlowyError;
use futures::stream::BoxStream;
use lib_infra::async_trait::async_trait;
use lib_infra::future::FutureResult;
use serde_json::Value;
use std::collections::HashMap;
use std::path::Path;
@ -21,12 +20,12 @@ pub type StreamAnswer = BoxStream<'static, Result<QuestionStreamValue, FlowyErro
pub type StreamComplete = BoxStream<'static, Result<Bytes, FlowyError>>;
#[async_trait]
pub trait ChatCloudService: Send + Sync + 'static {
fn create_chat(
async fn create_chat(
&self,
uid: &i64,
workspace_id: &str,
chat_id: &str,
) -> FutureResult<(), FlowyError>;
) -> Result<(), FlowyError>;
async fn create_question(
&self,

View File

@ -14,7 +14,6 @@ use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
use lib_infra::isolate_stream::IsolateSink;
use std::sync::{Arc, Weak};
use tokio::sync::oneshot;
use tracing::trace;
use validator::Validate;
@ -114,15 +113,9 @@ pub(crate) async fn get_related_question_handler(
) -> DataResult<RepeatedRelatedQuestionPB, FlowyError> {
let ai_manager = upgrade_ai_manager(ai_manager)?;
let data = data.into_inner();
let (tx, rx) = tokio::sync::oneshot::channel();
tokio::spawn(async move {
let messages = ai_manager
.get_related_questions(&data.chat_id, data.message_id)
.await?;
let _ = tx.send(messages);
Ok::<_, FlowyError>(())
});
let messages = rx.await?;
let messages = ai_manager
.get_related_questions(&data.chat_id, data.message_id)
.await?;
data_result_ok(messages)
}
@ -133,15 +126,9 @@ pub(crate) async fn get_answer_handler(
) -> DataResult<ChatMessagePB, FlowyError> {
let ai_manager = upgrade_ai_manager(ai_manager)?;
let data = data.into_inner();
let (tx, rx) = tokio::sync::oneshot::channel();
tokio::spawn(async move {
let message = ai_manager
.generate_answer(&data.chat_id, data.message_id)
.await?;
let _ = tx.send(message);
Ok::<_, FlowyError>(())
});
let message = rx.await?;
let message = ai_manager
.generate_answer(&data.chat_id, data.message_id)
.await?;
data_result_ok(message)
}
@ -163,25 +150,17 @@ pub(crate) async fn refresh_local_ai_info_handler(
ai_manager: AFPluginState<Weak<AIManager>>,
) -> DataResult<LLMModelInfoPB, FlowyError> {
let ai_manager = upgrade_ai_manager(ai_manager)?;
let (tx, rx) = oneshot::channel::<Result<LLMModelInfo, FlowyError>>();
tokio::spawn(async move {
let model_info = ai_manager.local_ai_controller.refresh().await;
if model_info.is_err() {
if let Some(llm_model) = ai_manager.local_ai_controller.get_current_model() {
let model_info = LLMModelInfo {
selected_model: llm_model.clone(),
models: vec![llm_model],
};
let _ = tx.send(Ok(model_info));
return;
}
let model_info = ai_manager.local_ai_controller.refresh().await;
if model_info.is_err() {
if let Some(llm_model) = ai_manager.local_ai_controller.get_current_model() {
let model_info = LLMModelInfo {
selected_model: llm_model.clone(),
models: vec![llm_model],
};
return data_result_ok(model_info.into());
}
let _ = tx.send(model_info);
});
let model_info = rx.await??;
data_result_ok(model_info.into())
}
data_result_ok(model_info?.into())
}
#[tracing::instrument(level = "debug", skip_all, err)]
@ -268,16 +247,9 @@ pub(crate) async fn chat_file_handler(
}
tracing::debug!("File size: {} bytes", file_size);
let (tx, rx) = oneshot::channel::<Result<(), FlowyError>>();
tokio::spawn(async move {
let ai_manager = upgrade_ai_manager(ai_manager)?;
ai_manager.chat_with_file(&data.chat_id, file_path).await?;
let _ = tx.send(Ok(()));
Ok::<_, FlowyError>(())
});
rx.await?
let ai_manager = upgrade_ai_manager(ai_manager)?;
ai_manager.chat_with_file(&data.chat_id, file_path).await?;
Ok(())
}
#[tracing::instrument(level = "debug", skip_all, err)]
@ -420,17 +392,10 @@ pub(crate) async fn get_offline_app_handler(
ai_manager: AFPluginState<Weak<AIManager>>,
) -> DataResult<OfflineAIPB, FlowyError> {
let ai_manager = upgrade_ai_manager(ai_manager)?;
let (tx, rx) = oneshot::channel::<Result<String, FlowyError>>();
tokio::spawn(async move {
let link = ai_manager
.local_ai_controller
.get_offline_ai_app_download_link()
.await?;
let _ = tx.send(Ok(link));
Ok::<_, FlowyError>(())
});
let link = rx.await??;
let link = ai_manager
.local_ai_controller
.get_offline_ai_app_download_link()
.await?;
data_result_ok(OfflineAIPB { link })
}

View File

@ -14,7 +14,6 @@ use flowy_ai_pub::cloud::{
use flowy_error::{FlowyError, FlowyResult};
use futures::{stream, Sink, StreamExt, TryStreamExt};
use lib_infra::async_trait::async_trait;
use lib_infra::future::FutureResult;
use crate::local_ai::stream_util::QuestionStream;
use crate::stream_message::StreamMessage;
@ -108,13 +107,16 @@ impl AICloudServiceMiddleware {
#[async_trait]
impl ChatCloudService for AICloudServiceMiddleware {
fn create_chat(
async fn create_chat(
&self,
uid: &i64,
workspace_id: &str,
chat_id: &str,
) -> FutureResult<(), FlowyError> {
self.cloud_service.create_chat(uid, workspace_id, chat_id)
) -> Result<(), FlowyError> {
self
.cloud_service
.create_chat(uid, workspace_id, chat_id)
.await
}
async fn create_question(

View File

@ -26,7 +26,7 @@ use flowy_sqlite::kv::KVStorePreferences;
use flowy_user::services::authenticate_user::AuthenticateUser;
use flowy_user::services::data_import::{load_collab_by_object_id, load_collab_by_object_ids};
use lib_dispatch::prelude::ToBytes;
use lib_infra::future::FutureResult;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::sync::{Arc, Weak};
@ -35,6 +35,7 @@ use tokio::sync::RwLock;
use crate::integrate::server::ServerProvider;
use collab_plugins::local_storage::kv::KVTransactionDB;
use lib_infra::async_trait::async_trait;
pub struct FolderDepsResolver();
#[allow(clippy::too_many_arguments)]
@ -113,363 +114,305 @@ impl FolderUser for FolderUserImpl {
}
struct DocumentFolderOperation(Arc<DocumentManager>);
#[async_trait]
impl FolderOperationHandler for DocumentFolderOperation {
fn create_workspace_view(
async fn create_workspace_view(
&self,
uid: i64,
workspace_view_builder: Arc<RwLock<NestedViewBuilder>>,
) -> FutureResult<(), FlowyError> {
) -> Result<(), FlowyError> {
let manager = self.0.clone();
FutureResult::new(async move {
let mut write_guard = workspace_view_builder.write().await;
// Create a view named "Getting started" with an icon ⭐️ and the built-in README data.
// Don't modify this code unless you know what you are doing.
write_guard
.with_view_builder(|view_builder| async {
let view = view_builder
.with_name("Getting started")
.with_icon("⭐️")
.build();
// create a empty document
let json_str = include_str!("../../assets/read_me.json");
let document_pb = JsonToDocumentParser::json_str_to_document(json_str).unwrap();
manager
.create_document(uid, &view.parent_view.id, Some(document_pb.into()))
.await
.unwrap();
view
})
.await;
Ok(())
})
let mut write_guard = workspace_view_builder.write().await;
// Create a view named "Getting started" with an icon ⭐️ and the built-in README data.
// Don't modify this code unless you know what you are doing.
write_guard
.with_view_builder(|view_builder| async {
let view = view_builder
.with_name("Getting started")
.with_icon("⭐️")
.build();
// create a empty document
let json_str = include_str!("../../assets/read_me.json");
let document_pb = JsonToDocumentParser::json_str_to_document(json_str).unwrap();
manager
.create_document(uid, &view.parent_view.id, Some(document_pb.into()))
.await
.unwrap();
view
})
.await;
Ok(())
}
fn open_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.open_document(&view_id).await?;
Ok(())
})
async fn open_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.open_document(view_id).await?;
Ok(())
}
/// Close the document view.
fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.close_document(&view_id).await?;
Ok(())
})
async fn close_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.close_document(view_id).await?;
Ok(())
}
fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
match manager.delete_document(&view_id).await {
Ok(_) => tracing::trace!("Delete document: {}", view_id),
Err(e) => tracing::error!("🔴delete document failed: {}", e),
}
Ok(())
})
async fn delete_view(&self, view_id: &str) -> Result<(), FlowyError> {
match self.0.delete_document(view_id).await {
Ok(_) => tracing::trace!("Delete document: {}", view_id),
Err(e) => tracing::error!("🔴delete document failed: {}", e),
}
Ok(())
}
fn duplicate_view(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
let data: DocumentDataPB = manager.get_document_data(&view_id).await?.into();
let data_bytes = data.into_bytes().map_err(|_| FlowyError::invalid_data())?;
Ok(data_bytes)
})
async fn duplicate_view(&self, view_id: &str) -> Result<Bytes, FlowyError> {
let data: DocumentDataPB = self.0.get_document_data(view_id).await?.into();
let data_bytes = data.into_bytes().map_err(|_| FlowyError::invalid_data())?;
Ok(data_bytes)
}
fn create_view_with_view_data(
async fn create_view_with_view_data(
&self,
user_id: i64,
params: CreateViewParams,
) -> FutureResult<Option<EncodedCollab>, FlowyError> {
) -> Result<Option<EncodedCollab>, FlowyError> {
debug_assert_eq!(params.layout, ViewLayoutPB::Document);
let view_id = params.view_id.to_string();
let manager = self.0.clone();
FutureResult::new(async move {
let data = DocumentDataPB::try_from(Bytes::from(params.initial_data))?;
let encoded_collab = manager
.create_document(user_id, &view_id, Some(data.into()))
.await?;
Ok(Some(encoded_collab))
})
let data = DocumentDataPB::try_from(Bytes::from(params.initial_data))?;
let encoded_collab = self
.0
.create_document(user_id, &params.view_id, Some(data.into()))
.await?;
Ok(Some(encoded_collab))
}
fn get_encoded_collab_v1_from_disk(
async fn get_encoded_collab_v1_from_disk(
&self,
user: Arc<dyn FolderUser>,
view_id: &str,
) -> FutureResult<EncodedCollabWrapper, FlowyError> {
) -> Result<EncodedCollabWrapper, FlowyError> {
// get the collab_object_id for the document.
// the collab_object_id for the document is the view_id.
let oid = view_id.to_string();
FutureResult::new(async move {
let uid = user
.user_id()
.map_err(|e| e.with_context("unable to get the uid: {}"))?;
let uid = user
.user_id()
.map_err(|e| e.with_context("unable to get the uid: {}"))?;
// get the collab db
let collab_db = user
.collab_db(uid)
.map_err(|e| e.with_context("unable to get the collab"))?;
let collab_db = collab_db.upgrade().ok_or_else(|| {
FlowyError::internal().with_context(
"The collab db has been dropped, indicating that the user has switched to a new account",
)
})?;
let collab_read_txn = collab_db.read_txn();
// get the collab db
let collab_db = user
.collab_db(uid)
.map_err(|e| e.with_context("unable to get the collab"))?;
let collab_db = collab_db.upgrade().ok_or_else(|| {
FlowyError::internal().with_context(
"The collab db has been dropped, indicating that the user has switched to a new account",
)
})?;
let collab_read_txn = collab_db.read_txn();
// read the collab from the db
let collab = load_collab_by_object_id(uid, &collab_read_txn, &oid).map_err(|e| {
FlowyError::internal().with_context(format!("load document collab failed: {}", e))
})?;
// read the collab from the db
let collab = load_collab_by_object_id(uid, &collab_read_txn, view_id).map_err(|e| {
FlowyError::internal().with_context(format!("load document collab failed: {}", e))
})?;
let encoded_collab = collab
let encoded_collab = collab
// encode the collab and check the integrity of the collab
.encode_collab_v1(|collab| CollabType::Document.validate_require_data(collab))
.map_err(|e| {
FlowyError::internal().with_context(format!("encode document collab failed: {}", e))
})?;
Ok(EncodedCollabWrapper::Document(DocumentEncodedCollab {
document_encoded_collab: encoded_collab,
}))
})
Ok(EncodedCollabWrapper::Document(DocumentEncodedCollab {
document_encoded_collab: encoded_collab,
}))
}
/// Create a view with built-in data.
fn create_built_in_view(
async fn create_built_in_view(
&self,
user_id: i64,
view_id: &str,
_name: &str,
layout: ViewLayout,
) -> FutureResult<(), FlowyError> {
) -> Result<(), FlowyError> {
debug_assert_eq!(layout, ViewLayout::Document);
let view_id = view_id.to_string();
let manager = self.0.clone();
FutureResult::new(async move {
match manager.create_document(user_id, &view_id, None).await {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
})
match self.0.create_document(user_id, view_id, None).await {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
}
fn import_from_bytes(
async fn import_from_bytes(
&self,
uid: i64,
view_id: &str,
_name: &str,
_import_type: ImportType,
bytes: Vec<u8>,
) -> FutureResult<EncodedCollab, FlowyError> {
let view_id = view_id.to_string();
let manager = self.0.clone();
FutureResult::new(async move {
let data = DocumentDataPB::try_from(Bytes::from(bytes))?;
let encoded_collab = manager
.create_document(uid, &view_id, Some(data.into()))
.await?;
Ok(encoded_collab)
})
) -> Result<EncodedCollab, FlowyError> {
let data = DocumentDataPB::try_from(Bytes::from(bytes))?;
let encoded_collab = self
.0
.create_document(uid, view_id, Some(data.into()))
.await?;
Ok(encoded_collab)
}
// will implement soon
fn import_from_file_path(
async fn import_from_file_path(
&self,
_view_id: &str,
_name: &str,
_path: String,
) -> FutureResult<(), FlowyError> {
FutureResult::new(async move { Ok(()) })
) -> Result<(), FlowyError> {
Ok(())
}
}
struct DatabaseFolderOperation(Arc<DatabaseManager>);
#[async_trait]
impl FolderOperationHandler for DatabaseFolderOperation {
fn open_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let database_manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
database_manager.open_database_view(view_id).await?;
Ok(())
})
async fn open_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.open_database_view(view_id).await?;
Ok(())
}
fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let database_manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
database_manager.close_database_view(view_id).await?;
Ok(())
})
async fn close_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.close_database_view(view_id).await?;
Ok(())
}
fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let database_manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
match database_manager.delete_database_view(&view_id).await {
Ok(_) => tracing::trace!("Delete database view: {}", view_id),
Err(e) => tracing::error!("🔴delete database failed: {}", e),
}
Ok(())
})
async fn delete_view(&self, view_id: &str) -> Result<(), FlowyError> {
match self.0.delete_database_view(view_id).await {
Ok(_) => tracing::trace!("Delete database view: {}", view_id),
Err(e) => tracing::error!("🔴delete database failed: {}", e),
}
Ok(())
}
fn get_encoded_collab_v1_from_disk(
async fn get_encoded_collab_v1_from_disk(
&self,
user: Arc<dyn FolderUser>,
view_id: &str,
) -> FutureResult<EncodedCollabWrapper, FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
) -> Result<EncodedCollabWrapper, FlowyError> {
// get the collab_object_id for the database.
//
// the collab object_id for the database is not the view_id,
// we should use the view_id to get the database_id
let oid = self.0.get_database_id_with_view_id(view_id).await?;
let row_oids = self.0.get_database_row_ids_with_view_id(view_id).await?;
let row_oids = row_oids
.into_iter()
.map(|oid| oid.into_inner())
.collect::<Vec<_>>();
let database_metas = self.0.get_all_databases_meta().await;
FutureResult::new(async move {
// get the collab_object_id for the database.
//
// the collab object_id for the database is not the view_id,
// we should use the view_id to get the database_id
let oid = manager.get_database_id_with_view_id(&view_id).await?;
let row_oids = manager.get_database_row_ids_with_view_id(&view_id).await?;
let row_oids = row_oids
.into_iter()
.map(|oid| oid.into_inner())
.collect::<Vec<_>>();
let database_metas = manager.get_all_databases_meta().await;
let uid = user
.user_id()
.map_err(|e| e.with_context("unable to get the uid: {}"))?;
let uid = user
.user_id()
.map_err(|e| e.with_context("unable to get the uid: {}"))?;
// get the collab db
let collab_db = user
.collab_db(uid)
.map_err(|e| e.with_context("unable to get the collab"))?;
let collab_db = collab_db.upgrade().ok_or_else(|| {
FlowyError::internal().with_context(
"The collab db has been dropped, indicating that the user has switched to a new account",
)
})?;
// get the collab db
let collab_db = user
.collab_db(uid)
.map_err(|e| e.with_context("unable to get the collab"))?;
let collab_db = collab_db.upgrade().ok_or_else(|| {
FlowyError::internal().with_context(
"The collab db has been dropped, indicating that the user has switched to a new account",
)
})?;
let collab_read_txn = collab_db.read_txn();
let collab_read_txn = collab_db.read_txn();
// read the database collab from the db
let database_collab = load_collab_by_object_id(uid, &collab_read_txn, &oid).map_err(|e| {
FlowyError::internal().with_context(format!("load database collab failed: {}", e))
})?;
// read the database collab from the db
let database_collab = load_collab_by_object_id(uid, &collab_read_txn, &oid).map_err(|e| {
FlowyError::internal().with_context(format!("load database collab failed: {}", e))
})?;
let database_encoded_collab = database_collab
let database_encoded_collab = database_collab
// encode the collab and check the integrity of the collab
.encode_collab_v1(|collab| CollabType::Database.validate_require_data(collab))
.map_err(|e| {
FlowyError::internal().with_context(format!("encode database collab failed: {}", e))
})?;
// read the database rows collab from the db
let database_row_collabs = load_collab_by_object_ids(uid, &collab_read_txn, &row_oids);
let database_row_encoded_collabs = database_row_collabs
.into_iter()
.map(|(oid, collab)| {
// encode the collab and check the integrity of the collab
let encoded_collab = collab
.encode_collab_v1(|collab| CollabType::DatabaseRow.validate_require_data(collab))
.map_err(|e| {
FlowyError::internal()
.with_context(format!("encode database row collab failed: {}", e))
})?;
Ok((oid, encoded_collab))
})
.collect::<Result<HashMap<_, _>, FlowyError>>()?;
// read the database rows collab from the db
let database_row_collabs = load_collab_by_object_ids(uid, &collab_read_txn, &row_oids);
let database_row_encoded_collabs = database_row_collabs
.into_iter()
.map(|(oid, collab)| {
// encode the collab and check the integrity of the collab
let encoded_collab = collab
.encode_collab_v1(|collab| CollabType::DatabaseRow.validate_require_data(collab))
.map_err(|e| {
FlowyError::internal().with_context(format!("encode database row collab failed: {}", e))
})?;
Ok((oid, encoded_collab))
})
.collect::<Result<HashMap<_, _>, FlowyError>>()?;
// get the relation info from the database meta
let database_relations = database_metas
.into_iter()
.filter_map(|meta| {
let linked_views = meta.linked_views.into_iter().next()?;
Some((meta.database_id, linked_views))
})
.collect::<HashMap<_, _>>();
// get the relation info from the database meta
let database_relations = database_metas
.into_iter()
.filter_map(|meta| {
let linked_views = meta.linked_views.into_iter().next()?;
Some((meta.database_id, linked_views))
})
.collect::<HashMap<_, _>>();
Ok(EncodedCollabWrapper::Database(DatabaseEncodedCollab {
database_encoded_collab,
database_row_encoded_collabs,
database_relations,
}))
})
Ok(EncodedCollabWrapper::Database(DatabaseEncodedCollab {
database_encoded_collab,
database_row_encoded_collabs,
database_relations,
}))
}
fn duplicate_view(&self, view_id: &str) -> FutureResult<Bytes, FlowyError> {
let database_manager = self.0.clone();
let view_id = view_id.to_owned();
FutureResult::new(async move {
let delta_bytes = database_manager.duplicate_database(&view_id).await?;
Ok(Bytes::from(delta_bytes))
})
async fn duplicate_view(&self, view_id: &str) -> Result<Bytes, FlowyError> {
let delta_bytes = self.0.duplicate_database(view_id).await?;
Ok(Bytes::from(delta_bytes))
}
/// Create a database view with duplicated data.
/// If the ext contains the {"database_id": "xx"}, then it will link
/// to the existing database.
fn create_view_with_view_data(
async fn create_view_with_view_data(
&self,
_user_id: i64,
params: CreateViewParams,
) -> FutureResult<Option<EncodedCollab>, FlowyError> {
) -> Result<Option<EncodedCollab>, FlowyError> {
match CreateDatabaseExtParams::from_map(params.meta.clone()) {
None => {
let database_manager = self.0.clone();
let view_id = params.view_id.to_string();
FutureResult::new(async move {
let encoded_collab = database_manager
.create_database_with_database_data(&view_id, params.initial_data)
.await?;
Ok(Some(encoded_collab))
})
let encoded_collab = self
.0
.create_database_with_database_data(&params.view_id, params.initial_data)
.await?;
Ok(Some(encoded_collab))
},
Some(database_params) => {
let database_manager = self.0.clone();
let layout = match params.layout {
ViewLayoutPB::Board => DatabaseLayoutPB::Board,
ViewLayoutPB::Calendar => DatabaseLayoutPB::Calendar,
ViewLayoutPB::Grid => DatabaseLayoutPB::Grid,
ViewLayoutPB::Document | ViewLayoutPB::Chat => {
return FutureResult::new(async move { Err(FlowyError::not_support()) });
return Err(FlowyError::not_support());
},
};
let name = params.name.to_string();
let database_view_id = params.view_id.to_string();
let database_parent_view_id = params.parent_view_id.to_string();
FutureResult::new(async move {
database_manager
.create_linked_view(
name,
layout.into(),
database_params.database_id,
database_view_id,
database_parent_view_id,
)
.await?;
Ok(None)
})
self
.0
.create_linked_view(
name,
layout.into(),
database_params.database_id,
database_view_id,
database_parent_view_id,
)
.await?;
Ok(None)
},
}
}
@ -478,110 +421,90 @@ impl FolderOperationHandler for DatabaseFolderOperation {
/// If the ext contains the {"database_id": "xx"}, then it will link to
/// the existing database. The data of the database will be shared within
/// these references views.
fn create_built_in_view(
async fn create_built_in_view(
&self,
_user_id: i64,
view_id: &str,
name: &str,
layout: ViewLayout,
) -> FutureResult<(), FlowyError> {
) -> Result<(), FlowyError> {
let name = name.to_string();
let database_manager = self.0.clone();
let data = match layout {
ViewLayout::Grid => make_default_grid(view_id, &name),
ViewLayout::Board => make_default_board(view_id, &name),
ViewLayout::Calendar => make_default_calendar(view_id, &name),
ViewLayout::Document => {
return FutureResult::new(async move {
Err(FlowyError::internal().with_context(format!("Can't handle {:?} layout type", layout)))
});
},
ViewLayout::Chat => {
// TODO(nathan): AI
todo!("AI")
ViewLayout::Document | ViewLayout::Chat => {
return Err(
FlowyError::internal().with_context(format!("Can't handle {:?} layout type", layout)),
);
},
};
FutureResult::new(async move {
let result = database_manager.create_database_with_params(data).await;
match result {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
})
let result = self.0.create_database_with_params(data).await;
match result {
Ok(_) => Ok(()),
Err(err) => {
if err.is_already_exists() {
Ok(())
} else {
Err(err)
}
},
}
}
fn import_from_bytes(
async fn import_from_bytes(
&self,
_uid: i64,
view_id: &str,
_name: &str,
import_type: ImportType,
bytes: Vec<u8>,
) -> FutureResult<EncodedCollab, FlowyError> {
let database_manager = self.0.clone();
let view_id = view_id.to_string();
) -> Result<EncodedCollab, FlowyError> {
let format = match import_type {
ImportType::CSV => CSVFormat::Original,
ImportType::HistoryDatabase => CSVFormat::META,
ImportType::RawDatabase => CSVFormat::META,
_ => CSVFormat::Original,
};
FutureResult::new(async move {
let content = tokio::task::spawn_blocking(move || {
String::from_utf8(bytes).map_err(|err| FlowyError::internal().with_context(err))
})
.await??;
let result = database_manager
.import_csv(view_id, content, format)
.await?;
Ok(result.encoded_collab)
let content = tokio::task::spawn_blocking(move || {
String::from_utf8(bytes).map_err(|err| FlowyError::internal().with_context(err))
})
.await??;
let result = self
.0
.import_csv(view_id.to_string(), content, format)
.await?;
Ok(result.encoded_collab)
}
fn import_from_file_path(
async fn import_from_file_path(
&self,
_view_id: &str,
_name: &str,
path: String,
) -> FutureResult<(), FlowyError> {
let database_manager = self.0.clone();
FutureResult::new(async move {
database_manager
.import_csv_from_file(path, CSVFormat::META)
.await?;
Ok(())
})
) -> Result<(), FlowyError> {
self.0.import_csv_from_file(path, CSVFormat::META).await?;
Ok(())
}
fn did_update_view(&self, old: &View, new: &View) -> FutureResult<(), FlowyError> {
async fn did_update_view(&self, old: &View, new: &View) -> Result<(), FlowyError> {
let database_layout = match new.layout {
ViewLayout::Document | ViewLayout::Chat => {
return FutureResult::new(async {
Err(FlowyError::internal().with_context("Can't handle document layout type"))
});
return Err(FlowyError::internal().with_context("Can't handle document layout type"));
},
ViewLayout::Grid => DatabaseLayoutPB::Grid,
ViewLayout::Board => DatabaseLayoutPB::Board,
ViewLayout::Calendar => DatabaseLayoutPB::Calendar,
};
let database_manager = self.0.clone();
let view_id = new.id.clone();
if old.layout != new.layout {
FutureResult::new(async move {
database_manager
.update_database_layout(&view_id, database_layout)
.await?;
Ok(())
})
self
.0
.update_database_layout(&new.id, database_layout)
.await?;
Ok(())
} else {
FutureResult::new(async move { Ok(()) })
Ok(())
}
}
}
@ -599,78 +522,61 @@ impl CreateDatabaseExtParams {
}
struct ChatFolderOperation(Arc<AIManager>);
#[async_trait]
impl FolderOperationHandler for ChatFolderOperation {
fn open_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.open_chat(&view_id).await?;
Ok(())
})
async fn open_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.open_chat(view_id).await
}
fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.close_chat(&view_id).await?;
Ok(())
})
async fn close_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.close_chat(view_id).await
}
fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.delete_chat(&view_id).await?;
Ok(())
})
async fn delete_view(&self, view_id: &str) -> Result<(), FlowyError> {
self.0.delete_chat(view_id).await
}
fn duplicate_view(&self, _view_id: &str) -> FutureResult<ViewData, FlowyError> {
FutureResult::new(async move { Err(FlowyError::not_support()) })
async fn duplicate_view(&self, _view_id: &str) -> Result<ViewData, FlowyError> {
Err(FlowyError::not_support())
}
fn create_view_with_view_data(
async fn create_view_with_view_data(
&self,
_user_id: i64,
_params: CreateViewParams,
) -> FutureResult<Option<EncodedCollab>, FlowyError> {
FutureResult::new(async move { Err(FlowyError::not_support()) })
) -> Result<Option<EncodedCollab>, FlowyError> {
Err(FlowyError::not_support())
}
fn create_built_in_view(
async fn create_built_in_view(
&self,
user_id: i64,
view_id: &str,
_name: &str,
_layout: ViewLayout,
) -> FutureResult<(), FlowyError> {
let manager = self.0.clone();
let view_id = view_id.to_string();
FutureResult::new(async move {
manager.create_chat(&user_id, &view_id).await?;
Ok(())
})
) -> Result<(), FlowyError> {
self.0.create_chat(&user_id, view_id).await?;
Ok(())
}
fn import_from_bytes(
async fn import_from_bytes(
&self,
_uid: i64,
_view_id: &str,
_name: &str,
_import_type: ImportType,
_bytes: Vec<u8>,
) -> FutureResult<EncodedCollab, FlowyError> {
FutureResult::new(async move { Err(FlowyError::not_support()) })
) -> Result<EncodedCollab, FlowyError> {
Err(FlowyError::not_support())
}
fn import_from_file_path(
async fn import_from_file_path(
&self,
_view_id: &str,
_name: &str,
_path: String,
) -> FutureResult<(), FlowyError> {
FutureResult::new(async move { Err(FlowyError::not_support()) })
) -> Result<(), FlowyError> {
Err(FlowyError::not_support())
}
}

View File

@ -595,22 +595,17 @@ impl CollabCloudPluginProvider for ServerProvider {
#[async_trait]
impl ChatCloudService for ServerProvider {
fn create_chat(
async fn create_chat(
&self,
uid: &i64,
workspace_id: &str,
chat_id: &str,
) -> FutureResult<(), FlowyError> {
let workspace_id = workspace_id.to_string();
) -> Result<(), FlowyError> {
let server = self.get_server();
let chat_id = chat_id.to_string();
let uid = *uid;
FutureResult::new(async move {
server?
.chat_service()
.create_chat(&uid, &workspace_id, &chat_id)
.await
})
server?
.chat_service()
.create_chat(uid, workspace_id, chat_id)
.await
}
async fn create_question(

View File

@ -15,7 +15,7 @@ use flowy_storage::manager::StorageManager;
use flowy_user::event_map::UserStatusCallback;
use flowy_user_pub::cloud::{UserCloudConfig, UserCloudServiceProvider};
use flowy_user_pub::entities::{Authenticator, UserProfile, UserWorkspace};
use lib_infra::future::{to_fut, Fut};
use lib_infra::async_trait::async_trait;
use crate::integrate::server::{Server, ServerProvider};
@ -29,21 +29,16 @@ pub(crate) struct UserStatusCallbackImpl {
pub(crate) ai_manager: Arc<AIManager>,
}
#[async_trait]
impl UserStatusCallback for UserStatusCallbackImpl {
fn did_init(
async fn did_init(
&self,
user_id: i64,
user_authenticator: &Authenticator,
cloud_config: &Option<UserCloudConfig>,
user_workspace: &UserWorkspace,
_device_id: &str,
) -> Fut<FlowyResult<()>> {
let user_id = user_id.to_owned();
let user_workspace = user_workspace.clone();
let folder_manager = self.folder_manager.clone();
let database_manager = self.database_manager.clone();
let document_manager = self.document_manager.clone();
) -> FlowyResult<()> {
self
.server_provider
.set_user_authenticator(user_authenticator);
@ -59,159 +54,142 @@ impl UserStatusCallback for UserStatusCallbackImpl {
}
}
to_fut(async move {
folder_manager
.initialize(
user_id,
&user_workspace.id,
FolderInitDataSource::LocalDisk {
create_if_not_exist: false,
},
)
.await?;
database_manager.initialize(user_id).await?;
document_manager.initialize(user_id).await?;
Ok(())
})
self
.folder_manager
.initialize(
user_id,
&user_workspace.id,
FolderInitDataSource::LocalDisk {
create_if_not_exist: false,
},
)
.await?;
self.database_manager.initialize(user_id).await?;
self.document_manager.initialize(user_id).await?;
Ok(())
}
fn did_sign_in(
async fn did_sign_in(
&self,
user_id: i64,
user_workspace: &UserWorkspace,
device_id: &str,
) -> Fut<FlowyResult<()>> {
let device_id = device_id.to_owned();
let user_id = user_id.to_owned();
let user_workspace = user_workspace.clone();
let folder_manager = self.folder_manager.clone();
let database_manager = self.database_manager.clone();
let document_manager = self.document_manager.clone();
) -> FlowyResult<()> {
event!(
tracing::Level::TRACE,
"Notify did sign in: latest_workspace: {:?}, device_id: {}",
user_workspace,
device_id
);
to_fut(async move {
event!(
tracing::Level::TRACE,
"Notify did sign in: latest_workspace: {:?}, device_id: {}",
user_workspace,
device_id
);
folder_manager.initialize_with_workspace_id(user_id).await?;
database_manager.initialize(user_id).await?;
document_manager.initialize(user_id).await?;
Ok(())
})
self
.folder_manager
.initialize_with_workspace_id(user_id)
.await?;
self.database_manager.initialize(user_id).await?;
self.document_manager.initialize(user_id).await?;
Ok(())
}
fn did_sign_up(
async fn did_sign_up(
&self,
is_new_user: bool,
user_profile: &UserProfile,
user_workspace: &UserWorkspace,
device_id: &str,
) -> Fut<FlowyResult<()>> {
let device_id = device_id.to_owned();
let user_profile = user_profile.clone();
let folder_manager = self.folder_manager.clone();
let database_manager = self.database_manager.clone();
let user_workspace = user_workspace.clone();
let document_manager = self.document_manager.clone();
) -> FlowyResult<()> {
self
.server_provider
.set_user_authenticator(&user_profile.authenticator);
let server_type = self.server_provider.get_server_type();
to_fut(async move {
event!(
tracing::Level::TRACE,
"Notify did sign up: is new: {} user_workspace: {:?}, device_id: {}",
is_new_user,
user_workspace,
device_id
);
event!(
tracing::Level::TRACE,
"Notify did sign up: is new: {} user_workspace: {:?}, device_id: {}",
is_new_user,
user_workspace,
device_id
);
// In the current implementation, when a user signs up for AppFlowy Cloud, a default workspace
// is automatically created for them. However, for users who sign up through Supabase, the creation
// of the default workspace relies on the client-side operation. This means that the process
// for initializing a default workspace differs depending on the sign-up method used.
let data_source = match folder_manager
.cloud_service
.get_folder_doc_state(
&user_workspace.id,
user_profile.uid,
CollabType::Folder,
&user_workspace.id,
)
.await
{
Ok(doc_state) => match server_type {
Server::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
Server::AppFlowyCloud => FolderInitDataSource::Cloud(doc_state),
Server::Supabase => {
if is_new_user {
FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
}
} else {
FolderInitDataSource::Cloud(doc_state)
// In the current implementation, when a user signs up for AppFlowy Cloud, a default workspace
// is automatically created for them. However, for users who sign up through Supabase, the creation
// of the default workspace relies on the client-side operation. This means that the process
// for initializing a default workspace differs depending on the sign-up method used.
let data_source = match self
.folder_manager
.cloud_service
.get_folder_doc_state(
&user_workspace.id,
user_profile.uid,
CollabType::Folder,
&user_workspace.id,
)
.await
{
Ok(doc_state) => match server_type {
Server::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
Server::AppFlowyCloud => FolderInitDataSource::Cloud(doc_state),
Server::Supabase => {
if is_new_user {
FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
}
},
} else {
FolderInitDataSource::Cloud(doc_state)
}
},
Err(err) => match server_type {
Server::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
Server::AppFlowyCloud | Server::Supabase => {
return Err(FlowyError::from(err));
},
},
Err(err) => match server_type {
Server::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
};
Server::AppFlowyCloud | Server::Supabase => {
return Err(FlowyError::from(err));
},
},
};
folder_manager
.initialize_with_new_user(
user_profile.uid,
&user_profile.token,
is_new_user,
data_source,
&user_workspace.id,
)
.await
.context("FolderManager error")?;
self
.folder_manager
.initialize_with_new_user(
user_profile.uid,
&user_profile.token,
is_new_user,
data_source,
&user_workspace.id,
)
.await
.context("FolderManager error")?;
database_manager
.initialize_with_new_user(user_profile.uid)
.await
.context("DatabaseManager error")?;
self
.database_manager
.initialize_with_new_user(user_profile.uid)
.await
.context("DatabaseManager error")?;
document_manager
.initialize_with_new_user(user_profile.uid)
.await
.context("DocumentManager error")?;
Ok(())
})
self
.document_manager
.initialize_with_new_user(user_profile.uid)
.await
.context("DocumentManager error")?;
Ok(())
}
fn did_expired(&self, _token: &str, user_id: i64) -> Fut<FlowyResult<()>> {
let folder_manager = self.folder_manager.clone();
to_fut(async move {
folder_manager.clear(user_id).await;
Ok(())
})
async fn did_expired(&self, _token: &str, user_id: i64) -> FlowyResult<()> {
self.folder_manager.clear(user_id).await;
Ok(())
}
fn open_workspace(&self, user_id: i64, _user_workspace: &UserWorkspace) -> Fut<FlowyResult<()>> {
let folder_manager = self.folder_manager.clone();
let database_manager = self.database_manager.clone();
let document_manager = self.document_manager.clone();
to_fut(async move {
folder_manager.initialize_with_workspace_id(user_id).await?;
database_manager.initialize(user_id).await?;
document_manager.initialize(user_id).await?;
Ok(())
})
async fn open_workspace(&self, user_id: i64, _user_workspace: &UserWorkspace) -> FlowyResult<()> {
self
.folder_manager
.initialize_with_workspace_id(user_id)
.await?;
self.database_manager.initialize(user_id).await?;
self.document_manager.initialize(user_id).await?;
Ok(())
}
fn did_update_network(&self, reachable: bool) {

View File

@ -1,16 +1,15 @@
use std::collections::HashMap;
use std::sync::Arc;
use async_trait::async_trait;
use bytes::Bytes;
use collab::entity::EncodedCollab;
pub use collab_folder::View;
use collab_folder::ViewLayout;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use flowy_error::FlowyError;
use flowy_folder_pub::folder_builder::NestedViewBuilder;
use lib_infra::future::FutureResult;
use lib_infra::util::timestamp;
use crate::entities::{CreateViewParams, ViewLayoutPB};
@ -42,36 +41,37 @@ pub struct DatabaseEncodedCollab {
/// view layout. Each [ViewLayout] will have a handler. So when creating a new
/// view, the [ViewLayout] will be used to get the handler.
///
#[async_trait]
pub trait FolderOperationHandler {
/// Create the view for the workspace of new user.
/// Only called once when the user is created.
fn create_workspace_view(
async fn create_workspace_view(
&self,
_uid: i64,
_workspace_view_builder: Arc<RwLock<NestedViewBuilder>>,
) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
) -> Result<(), FlowyError> {
Ok(())
}
fn open_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
async fn open_view(&self, view_id: &str) -> Result<(), FlowyError>;
/// Closes the view and releases the resources that this view has in
/// the backend
fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
async fn close_view(&self, view_id: &str) -> Result<(), FlowyError>;
/// Called when the view is deleted.
/// This will called after the view is deleted from the trash.
fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
async fn delete_view(&self, view_id: &str) -> Result<(), FlowyError>;
/// Returns the [ViewData] that can be used to create the same view.
fn duplicate_view(&self, view_id: &str) -> FutureResult<ViewData, FlowyError>;
async fn duplicate_view(&self, view_id: &str) -> Result<ViewData, FlowyError>;
/// get the encoded collab data from the disk.
fn get_encoded_collab_v1_from_disk(
async fn get_encoded_collab_v1_from_disk(
&self,
_user: Arc<dyn FolderUser>,
_view_id: &str,
) -> FutureResult<EncodedCollabWrapper, FlowyError> {
FutureResult::new(async move { Err(FlowyError::not_support()) })
) -> Result<EncodedCollabWrapper, FlowyError> {
Err(FlowyError::not_support())
}
/// Create a view with the data.
@ -92,46 +92,46 @@ pub trait FolderOperationHandler {
///
/// The return value is the [Option<EncodedCollab>] that can be used to create the view.
/// It can be used in syncing the view data to cloud.
fn create_view_with_view_data(
async fn create_view_with_view_data(
&self,
user_id: i64,
params: CreateViewParams,
) -> FutureResult<Option<EncodedCollab>, FlowyError>;
) -> Result<Option<EncodedCollab>, FlowyError>;
/// Create a view with the pre-defined data.
/// For example, the initial data of the grid/calendar/kanban board when
/// you create a new view.
fn create_built_in_view(
async fn create_built_in_view(
&self,
user_id: i64,
view_id: &str,
name: &str,
layout: ViewLayout,
) -> FutureResult<(), FlowyError>;
) -> Result<(), FlowyError>;
/// Create a view by importing data
///
/// The return value
fn import_from_bytes(
async fn import_from_bytes(
&self,
uid: i64,
view_id: &str,
name: &str,
import_type: ImportType,
bytes: Vec<u8>,
) -> FutureResult<EncodedCollab, FlowyError>;
) -> Result<EncodedCollab, FlowyError>;
/// Create a view by importing data from a file
fn import_from_file_path(
async fn import_from_file_path(
&self,
view_id: &str,
name: &str,
path: String,
) -> FutureResult<(), FlowyError>;
) -> Result<(), FlowyError>;
/// Called when the view is updated. The handler is the `old` registered handler.
fn did_update_view(&self, _old: &View, _new: &View) -> FutureResult<(), FlowyError> {
FutureResult::new(async move { Ok(()) })
async fn did_update_view(&self, _old: &View, _new: &View) -> Result<(), FlowyError> {
Ok(())
}
}

View File

@ -13,7 +13,6 @@ use flowy_ai_pub::cloud::{
use flowy_error::FlowyError;
use futures_util::{StreamExt, TryStreamExt};
use lib_infra::async_trait::async_trait;
use lib_infra::future::FutureResult;
use lib_infra::util::{get_operating_system, OperatingSystem};
use serde_json::{json, Value};
use std::collections::HashMap;
@ -28,29 +27,25 @@ impl<T> ChatCloudService for AFCloudChatCloudServiceImpl<T>
where
T: AFServer,
{
fn create_chat(
async fn create_chat(
&self,
_uid: &i64,
workspace_id: &str,
chat_id: &str,
) -> FutureResult<(), FlowyError> {
let workspace_id = workspace_id.to_string();
) -> Result<(), FlowyError> {
let chat_id = chat_id.to_string();
let try_get_client = self.inner.try_get_client();
let params = CreateChatParams {
chat_id,
name: "".to_string(),
rag_ids: vec![],
};
try_get_client?
.create_chat(workspace_id, params)
.await
.map_err(FlowyError::from)?;
FutureResult::new(async move {
let params = CreateChatParams {
chat_id,
name: "".to_string(),
rag_ids: vec![],
};
try_get_client?
.create_chat(&workspace_id, params)
.await
.map_err(FlowyError::from)?;
Ok(())
})
Ok(())
}
async fn create_question(

View File

@ -5,7 +5,6 @@ use flowy_ai_pub::cloud::{
};
use flowy_error::FlowyError;
use lib_infra::async_trait::async_trait;
use lib_infra::future::FutureResult;
use serde_json::Value;
use std::collections::HashMap;
use std::path::Path;
@ -14,15 +13,13 @@ pub(crate) struct DefaultChatCloudServiceImpl;
#[async_trait]
impl ChatCloudService for DefaultChatCloudServiceImpl {
fn create_chat(
async fn create_chat(
&self,
_uid: &i64,
_workspace_id: &str,
_chat_id: &str,
) -> FutureResult<(), FlowyError> {
FutureResult::new(async move {
Err(FlowyError::not_support().with_context("Chat is not supported in local server."))
})
) -> Result<(), FlowyError> {
Err(FlowyError::not_support().with_context("Chat is not supported in local server."))
}
async fn create_question(

View File

@ -7,7 +7,7 @@ use flowy_error::FlowyResult;
use flowy_user_pub::cloud::UserCloudConfig;
use flowy_user_pub::entities::*;
use lib_dispatch::prelude::*;
use lib_infra::future::{to_fut, Fut};
use lib_infra::async_trait::async_trait;
use crate::event_handler::*;
use crate::user_manager::UserManager;
@ -276,38 +276,53 @@ pub enum UserEvent {
NotifyDidSwitchPlan = 63,
}
#[async_trait]
pub trait UserStatusCallback: Send + Sync + 'static {
/// When the [Authenticator] changed, this method will be called. Currently, the auth type
/// will be changed when the user sign in or sign up.
fn authenticator_did_changed(&self, _authenticator: Authenticator) {}
/// This will be called after the application launches if the user is already signed in.
/// If the user is not signed in, this method will not be called
fn did_init(
async fn did_init(
&self,
user_id: i64,
user_authenticator: &Authenticator,
cloud_config: &Option<UserCloudConfig>,
user_workspace: &UserWorkspace,
device_id: &str,
) -> Fut<FlowyResult<()>>;
_user_id: i64,
_user_authenticator: &Authenticator,
_cloud_config: &Option<UserCloudConfig>,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> FlowyResult<()> {
Ok(())
}
/// Will be called after the user signed in.
fn did_sign_in(
async fn did_sign_in(
&self,
user_id: i64,
user_workspace: &UserWorkspace,
device_id: &str,
) -> Fut<FlowyResult<()>>;
_user_id: i64,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> FlowyResult<()> {
Ok(())
}
/// Will be called after the user signed up.
fn did_sign_up(
async fn did_sign_up(
&self,
is_new_user: bool,
user_profile: &UserProfile,
user_workspace: &UserWorkspace,
device_id: &str,
) -> Fut<FlowyResult<()>>;
_is_new_user: bool,
_user_profile: &UserProfile,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> FlowyResult<()> {
Ok(())
}
fn did_expired(&self, token: &str, user_id: i64) -> Fut<FlowyResult<()>>;
fn open_workspace(&self, user_id: i64, user_workspace: &UserWorkspace) -> Fut<FlowyResult<()>>;
async fn did_expired(&self, _token: &str, _user_id: i64) -> FlowyResult<()> {
Ok(())
}
async fn open_workspace(
&self,
_user_id: i64,
_user_workspace: &UserWorkspace,
) -> FlowyResult<()> {
Ok(())
}
fn did_update_network(&self, _reachable: bool) {}
fn did_update_plans(&self, _plans: Vec<SubscriptionPlan>) {}
fn did_update_storage_limitation(&self, _can_write: bool) {}
@ -315,42 +330,4 @@ pub trait UserStatusCallback: Send + Sync + 'static {
/// Acts as a placeholder [UserStatusCallback] for the user session, but does not perform any function
pub(crate) struct DefaultUserStatusCallback;
impl UserStatusCallback for DefaultUserStatusCallback {
fn did_init(
&self,
_user_id: i64,
_authenticator: &Authenticator,
_cloud_config: &Option<UserCloudConfig>,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> Fut<FlowyResult<()>> {
to_fut(async { Ok(()) })
}
fn did_sign_in(
&self,
_user_id: i64,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> Fut<FlowyResult<()>> {
to_fut(async { Ok(()) })
}
fn did_sign_up(
&self,
_is_new_user: bool,
_user_profile: &UserProfile,
_user_workspace: &UserWorkspace,
_device_id: &str,
) -> Fut<FlowyResult<()>> {
to_fut(async { Ok(()) })
}
fn did_expired(&self, _token: &str, _user_id: i64) -> Fut<FlowyResult<()>> {
to_fut(async { Ok(()) })
}
fn open_workspace(&self, _user_id: i64, _user_workspace: &UserWorkspace) -> Fut<FlowyResult<()>> {
to_fut(async { Ok(()) })
}
}
impl UserStatusCallback for DefaultUserStatusCallback {}

View File

@ -33,7 +33,7 @@ where
pub fn load_collab_by_object_id<'a, R>(
uid: i64,
collab_read_txn: &R,
object_id: &String,
object_id: &str,
) -> Result<Collab, PersistenceError>
where
R: CollabKVAction<'a>,

View File

@ -581,7 +581,6 @@ impl UserManager {
Ok(UseAISettingPB::from(settings))
}
#[instrument(level = "debug", skip(self), err)]
pub async fn get_workspace_member_info(&self, uid: i64) -> FlowyResult<WorkspaceMember> {
let workspace_id = self.get_session()?.user_workspace.id.clone();
let db = self.authenticate_user.get_sqlite_connection(uid)?;