mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
config folder collaboration
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
mod version_1;
|
||||
pub mod version_1;
|
||||
mod version_2;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -4,6 +4,7 @@ use flowy_collaboration::entities::{
|
||||
revision::{RepeatedRevision, Revision},
|
||||
};
|
||||
|
||||
use flowy_collaboration::client_document::default::initial_delta_string;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
@ -61,7 +62,13 @@ impl ViewController {
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)]
|
||||
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> {
|
||||
let delta_data = Bytes::from(params.view_data.clone());
|
||||
let view_data = if params.view_data.is_empty() {
|
||||
initial_delta_string()
|
||||
} else {
|
||||
params.view_data.clone()
|
||||
};
|
||||
|
||||
let delta_data = Bytes::from(view_data);
|
||||
let user_id = self.user.user_id()?;
|
||||
let repeated_revision: RepeatedRevision =
|
||||
Revision::initial_revision(&user_id, ¶ms.view_id, delta_data).into();
|
||||
@ -110,22 +117,20 @@ impl ViewController {
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)]
|
||||
pub(crate) async fn open_view(&self, params: DocumentId) -> Result<DocumentDelta, FlowyError> {
|
||||
let doc_id = params.doc_id.clone();
|
||||
let editor = self.document_ctx.controller.open_document(¶ms.doc_id).await?;
|
||||
|
||||
KV::set_str(LATEST_VIEW_ID, doc_id.clone());
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub(crate) async fn open_view(&self, doc_id: &str) -> Result<DocumentDelta, FlowyError> {
|
||||
let editor = self.document_ctx.controller.open_document(doc_id).await?;
|
||||
KV::set_str(LATEST_VIEW_ID, doc_id.to_owned());
|
||||
let document_json = editor.document_json().await?;
|
||||
Ok(DocumentDelta {
|
||||
doc_id,
|
||||
doc_id: doc_id.to_string(),
|
||||
delta_json: document_json,
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), err)]
|
||||
pub(crate) async fn close_view(&self, params: DocumentId) -> Result<(), FlowyError> {
|
||||
let _ = self.document_ctx.controller.close_document(¶ms.doc_id)?;
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub(crate) async fn close_view(&self, doc_id: &str) -> Result<(), FlowyError> {
|
||||
let _ = self.document_ctx.controller.close_document(doc_id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -140,13 +145,13 @@ impl ViewController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)]
|
||||
pub(crate) async fn duplicate_view(&self, params: DocumentId) -> Result<(), FlowyError> {
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub(crate) async fn duplicate_view(&self, doc_id: &str) -> Result<(), FlowyError> {
|
||||
let view = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_view(¶ms.doc_id))?;
|
||||
.begin_transaction(|transaction| transaction.read_view(doc_id))?;
|
||||
|
||||
let editor = self.document_ctx.controller.open_document(¶ms.doc_id).await?;
|
||||
let editor = self.document_ctx.controller.open_document(doc_id).await?;
|
||||
let document_json = editor.document_json().await?;
|
||||
let duplicate_params = CreateViewParams {
|
||||
belong_to_id: view.belong_to_id.clone(),
|
||||
|
@ -84,7 +84,7 @@ pub(crate) async fn open_view_handler(
|
||||
controller: Unit<Arc<ViewController>>,
|
||||
) -> DataResult<DocumentDelta, FlowyError> {
|
||||
let params: ViewId = data.into_inner().try_into()?;
|
||||
let doc = controller.open_view(params.into()).await?;
|
||||
let doc = controller.open_view(¶ms.view_id).await?;
|
||||
data_result(doc)
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ pub(crate) async fn close_view_handler(
|
||||
controller: Unit<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: ViewId = data.into_inner().try_into()?;
|
||||
let _ = controller.close_view(params.into()).await?;
|
||||
let _ = controller.close_view(¶ms.view_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ pub(crate) async fn duplicate_view_handler(
|
||||
controller: Unit<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: ViewId = data.into_inner().try_into()?;
|
||||
let _ = controller.duplicate_view(params.into()).await?;
|
||||
let _ = controller.duplicate_view(¶ms.view_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -132,14 +132,20 @@ impl RevisionWSSinkDataProvider for DocumentWSSinkDataProviderAdapter {
|
||||
|
||||
async fn transform_pushed_revisions(
|
||||
revisions: Vec<Revision>,
|
||||
edit_cmd: &EditorCommandSender,
|
||||
edit_cmd_tx: &EditorCommandSender,
|
||||
) -> FlowyResult<TransformDeltas> {
|
||||
let (ret, rx) = oneshot::channel::<CollaborateResult<TransformDeltas>>();
|
||||
let _ = edit_cmd.send(EditorCommand::TransformRevision { revisions, ret });
|
||||
Ok(rx.await.map_err(internal_error)??)
|
||||
edit_cmd_tx
|
||||
.send(EditorCommand::TransformRevision { revisions, ret })
|
||||
.await
|
||||
.map_err(internal_error)?;
|
||||
let transform_delta = rx
|
||||
.await
|
||||
.map_err(|e| FlowyError::internal().context(format!("transform_pushed_revisions failed: {}", e)))??;
|
||||
Ok(transform_delta)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))]
|
||||
#[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes), err)]
|
||||
pub(crate) async fn handle_remote_revision(
|
||||
edit_cmd_tx: EditorCommandSender,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
@ -173,23 +179,33 @@ pub(crate) async fn handle_remote_revision(
|
||||
// The server_prime is None means the client local revisions conflict with the
|
||||
// server, and it needs to override the client delta.
|
||||
let (ret, rx) = oneshot::channel();
|
||||
let _ = edit_cmd_tx.send(EditorCommand::OverrideDelta {
|
||||
revisions,
|
||||
delta: client_prime,
|
||||
ret,
|
||||
});
|
||||
let _ = rx.await.map_err(internal_error)??;
|
||||
let _ = edit_cmd_tx
|
||||
.send(EditorCommand::OverrideDelta {
|
||||
revisions,
|
||||
delta: client_prime,
|
||||
ret,
|
||||
})
|
||||
.await;
|
||||
let _ = rx.await.map_err(|e| {
|
||||
FlowyError::internal().context(format!("handle EditorCommand::OverrideDelta failed: {}", e))
|
||||
})??;
|
||||
Ok(None)
|
||||
},
|
||||
Some(server_prime) => {
|
||||
let (ret, rx) = oneshot::channel();
|
||||
let _ = edit_cmd_tx.send(EditorCommand::ComposeRemoteDelta {
|
||||
revisions,
|
||||
client_delta: client_prime,
|
||||
server_delta: server_prime,
|
||||
ret,
|
||||
});
|
||||
Ok(rx.await.map_err(internal_error)??)
|
||||
edit_cmd_tx
|
||||
.send(EditorCommand::ComposeRemoteDelta {
|
||||
revisions,
|
||||
client_delta: client_prime,
|
||||
server_delta: server_prime,
|
||||
ret,
|
||||
})
|
||||
.await
|
||||
.map_err(internal_error)?;
|
||||
let result = rx.await.map_err(|e| {
|
||||
FlowyError::internal().context(format!("handle EditorCommand::ComposeRemoteDelta failed: {}", e))
|
||||
})??;
|
||||
Ok(result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use lib_ot::{
|
||||
core::*,
|
||||
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta},
|
||||
};
|
||||
use lib_ot::rich_text::RichTextOperation;
|
||||
|
||||
#[test]
|
||||
fn operation_insert_serialize_test() {
|
||||
|
@ -12,6 +12,8 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
// For the moment, we use memory to cache the data, it will be implemented with
|
||||
// other storage. Like the Firestore,Dropbox.etc.
|
||||
pub trait RevisionCloudStorage: Send + Sync {
|
||||
fn set_revisions(&self, repeated_revision: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError>;
|
||||
fn get_revisions(
|
||||
@ -28,8 +30,6 @@ pub trait RevisionCloudStorage: Send + Sync {
|
||||
}
|
||||
|
||||
pub(crate) struct LocalDocumentCloudPersistence {
|
||||
// For the moment, we use memory to cache the data, it will be implemented with other storage.
|
||||
// Like the Firestore,Dropbox.etc.
|
||||
storage: Arc<dyn RevisionCloudStorage>,
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,7 @@ fn crate_log_filter(level: String) -> String {
|
||||
filters.push(format!("lib_ot={}", level));
|
||||
filters.push(format!("lib_ws={}", level));
|
||||
filters.push(format!("lib_infra={}", level));
|
||||
filters.push(format!("flowy_sync={}", level));
|
||||
filters.join(",")
|
||||
}
|
||||
|
||||
|
@ -147,13 +147,13 @@ impl RevisionWSStream {
|
||||
yield msg
|
||||
},
|
||||
None => {
|
||||
tracing::debug!("[RevisionWSStream:{}] loop exit", object_id);
|
||||
tracing::debug!("[RevisionWSStream]:{} loop exit", object_id);
|
||||
break;
|
||||
},
|
||||
}
|
||||
},
|
||||
_ = stop_rx.recv() => {
|
||||
tracing::debug!("[RevisionWSStream:{}] loop exit", object_id);
|
||||
tracing::debug!("[RevisionWSStream]:{} loop exit", object_id);
|
||||
break
|
||||
},
|
||||
};
|
||||
@ -164,7 +164,7 @@ impl RevisionWSStream {
|
||||
.for_each(|msg| async {
|
||||
match self.handle_message(msg).await {
|
||||
Ok(_) => {},
|
||||
Err(e) => tracing::error!("[RevisionWSStream:{}] error: {}", self.object_id, e),
|
||||
Err(e) => tracing::error!("[RevisionWSStream]:{} error: {}", self.object_id, e),
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
Reference in New Issue
Block a user