event_handler.rs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * The following code defines functions that handle creating, opening, and closing documents,
  3. * as well as performing actions on documents. These functions make use of a DocumentManager,
  4. * which you can think of as a higher-level interface to interact with documents.
  5. */
  6. use std::sync::{Arc, Weak};
  7. use collab_document::blocks::{
  8. json_str_to_hashmap, Block, BlockAction, BlockActionPayload, BlockActionType, BlockEvent,
  9. BlockEventPayload, DeltaType,
  10. };
  11. use flowy_error::{FlowyError, FlowyResult};
  12. use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
  13. use crate::entities::*;
  14. use crate::{manager::DocumentManager, parser::json::parser::JsonToDocumentParser};
  15. fn upgrade_document(
  16. document_manager: AFPluginState<Weak<DocumentManager>>,
  17. ) -> FlowyResult<Arc<DocumentManager>> {
  18. let manager = document_manager
  19. .upgrade()
  20. .ok_or(FlowyError::internal().with_context("The document manager is already dropped"))?;
  21. Ok(manager)
  22. }
  23. // Handler for creating a new document
  24. pub(crate) async fn create_document_handler(
  25. data: AFPluginData<CreateDocumentPayloadPB>,
  26. manager: AFPluginState<Weak<DocumentManager>>,
  27. ) -> FlowyResult<()> {
  28. let manager = upgrade_document(manager)?;
  29. let params: CreateDocumentParams = data.into_inner().try_into()?;
  30. let uid = manager.user.user_id()?;
  31. manager
  32. .create_document(uid, &params.document_id, params.initial_data)
  33. .await?;
  34. Ok(())
  35. }
  36. // Handler for opening an existing document
  37. pub(crate) async fn open_document_handler(
  38. data: AFPluginData<OpenDocumentPayloadPB>,
  39. manager: AFPluginState<Weak<DocumentManager>>,
  40. ) -> DataResult<DocumentDataPB, FlowyError> {
  41. let manager = upgrade_document(manager)?;
  42. let params: OpenDocumentParams = data.into_inner().try_into()?;
  43. let doc_id = params.document_id;
  44. let document = manager.get_document(&doc_id).await?;
  45. let document_data = document.lock().get_document_data()?;
  46. data_result_ok(DocumentDataPB::from(document_data))
  47. }
  48. pub(crate) async fn close_document_handler(
  49. data: AFPluginData<CloseDocumentPayloadPB>,
  50. manager: AFPluginState<Weak<DocumentManager>>,
  51. ) -> FlowyResult<()> {
  52. let manager = upgrade_document(manager)?;
  53. let params: CloseDocumentParams = data.into_inner().try_into()?;
  54. let doc_id = params.document_id;
  55. manager.close_document(&doc_id)?;
  56. Ok(())
  57. }
  58. // Get the content of the existing document,
  59. // if the document does not exist, return an error.
  60. pub(crate) async fn get_document_data_handler(
  61. data: AFPluginData<OpenDocumentPayloadPB>,
  62. manager: AFPluginState<Weak<DocumentManager>>,
  63. ) -> DataResult<DocumentDataPB, FlowyError> {
  64. let manager = upgrade_document(manager)?;
  65. let params: OpenDocumentParams = data.into_inner().try_into()?;
  66. let doc_id = params.document_id;
  67. let document_data = manager.get_document_data(&doc_id).await?;
  68. data_result_ok(DocumentDataPB::from(document_data))
  69. }
  70. // Handler for applying an action to a document
  71. pub(crate) async fn apply_action_handler(
  72. data: AFPluginData<ApplyActionPayloadPB>,
  73. manager: AFPluginState<Weak<DocumentManager>>,
  74. ) -> FlowyResult<()> {
  75. let manager = upgrade_document(manager)?;
  76. let params: ApplyActionParams = data.into_inner().try_into()?;
  77. let doc_id = params.document_id;
  78. let document = manager.get_document(&doc_id).await?;
  79. let actions = params.actions;
  80. document.lock().apply_action(actions);
  81. Ok(())
  82. }
  83. pub(crate) async fn convert_data_to_document(
  84. data: AFPluginData<ConvertDataPayloadPB>,
  85. ) -> DataResult<DocumentDataPB, FlowyError> {
  86. let payload = data.into_inner();
  87. let document = convert_data_to_document_internal(payload)?;
  88. data_result_ok(document)
  89. }
  90. pub fn convert_data_to_document_internal(
  91. payload: ConvertDataPayloadPB,
  92. ) -> Result<DocumentDataPB, FlowyError> {
  93. let params: ConvertDataParams = payload.try_into()?;
  94. let convert_type = params.convert_type;
  95. let data = params.data;
  96. match convert_type {
  97. ConvertType::Json => {
  98. let json_str = String::from_utf8(data).map_err(|_| FlowyError::invalid_data())?;
  99. let document = JsonToDocumentParser::json_str_to_document(&json_str)?;
  100. Ok(document)
  101. },
  102. }
  103. }
  104. pub(crate) async fn redo_handler(
  105. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  106. manager: AFPluginState<Weak<DocumentManager>>,
  107. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  108. let manager = upgrade_document(manager)?;
  109. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  110. let doc_id = params.document_id;
  111. let document = manager.get_document(&doc_id).await?;
  112. let document = document.lock();
  113. let redo = document.redo();
  114. let can_redo = document.can_redo();
  115. let can_undo = document.can_undo();
  116. data_result_ok(DocumentRedoUndoResponsePB {
  117. can_redo,
  118. can_undo,
  119. is_success: redo,
  120. })
  121. }
  122. pub(crate) async fn undo_handler(
  123. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  124. manager: AFPluginState<Weak<DocumentManager>>,
  125. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  126. let manager = upgrade_document(manager)?;
  127. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  128. let doc_id = params.document_id;
  129. let document = manager.get_document(&doc_id).await?;
  130. let document = document.lock();
  131. let undo = document.undo();
  132. let can_redo = document.can_redo();
  133. let can_undo = document.can_undo();
  134. data_result_ok(DocumentRedoUndoResponsePB {
  135. can_redo,
  136. can_undo,
  137. is_success: undo,
  138. })
  139. }
  140. pub(crate) async fn can_undo_redo_handler(
  141. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  142. manager: AFPluginState<Weak<DocumentManager>>,
  143. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  144. let manager = upgrade_document(manager)?;
  145. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  146. let doc_id = params.document_id;
  147. let document = manager.get_document(&doc_id).await?;
  148. let document = document.lock();
  149. let can_redo = document.can_redo();
  150. let can_undo = document.can_undo();
  151. drop(document);
  152. data_result_ok(DocumentRedoUndoResponsePB {
  153. can_redo,
  154. can_undo,
  155. is_success: true,
  156. })
  157. }
  158. pub(crate) async fn get_snapshot_handler(
  159. data: AFPluginData<OpenDocumentPayloadPB>,
  160. manager: AFPluginState<Weak<DocumentManager>>,
  161. ) -> DataResult<RepeatedDocumentSnapshotPB, FlowyError> {
  162. let manager = upgrade_document(manager)?;
  163. let params: OpenDocumentParams = data.into_inner().try_into()?;
  164. let doc_id = params.document_id;
  165. let snapshots = manager.get_document_snapshots(&doc_id, 10).await?;
  166. data_result_ok(RepeatedDocumentSnapshotPB { items: snapshots })
  167. }
  168. impl From<BlockActionPB> for BlockAction {
  169. fn from(pb: BlockActionPB) -> Self {
  170. Self {
  171. action: pb.action.into(),
  172. payload: pb.payload.into(),
  173. }
  174. }
  175. }
  176. impl From<BlockActionTypePB> for BlockActionType {
  177. fn from(pb: BlockActionTypePB) -> Self {
  178. match pb {
  179. BlockActionTypePB::Insert => Self::Insert,
  180. BlockActionTypePB::Update => Self::Update,
  181. BlockActionTypePB::Delete => Self::Delete,
  182. BlockActionTypePB::Move => Self::Move,
  183. }
  184. }
  185. }
  186. impl From<BlockActionPayloadPB> for BlockActionPayload {
  187. fn from(pb: BlockActionPayloadPB) -> Self {
  188. Self {
  189. block: pb.block.into(),
  190. parent_id: pb.parent_id,
  191. prev_id: pb.prev_id,
  192. }
  193. }
  194. }
  195. impl From<BlockPB> for Block {
  196. fn from(pb: BlockPB) -> Self {
  197. // Use `json_str_to_hashmap()` from the `collab_document` crate to convert the JSON data to a hashmap
  198. let data = json_str_to_hashmap(&pb.data).unwrap_or_default();
  199. // Convert the protobuf `BlockPB` to our internal `Block` struct
  200. Self {
  201. id: pb.id,
  202. ty: pb.ty,
  203. children: pb.children_id,
  204. parent: pb.parent_id,
  205. data,
  206. external_id: None,
  207. external_type: None,
  208. }
  209. }
  210. }
  211. impl From<BlockEvent> for BlockEventPB {
  212. fn from(payload: BlockEvent) -> Self {
  213. // Convert each individual `BlockEvent` to a protobuf `BlockEventPB`, and collect the results into a `Vec`
  214. Self {
  215. event: payload.iter().map(|e| e.to_owned().into()).collect(),
  216. }
  217. }
  218. }
  219. impl From<BlockEventPayload> for BlockEventPayloadPB {
  220. fn from(payload: BlockEventPayload) -> Self {
  221. Self {
  222. command: payload.command.into(),
  223. path: payload.path,
  224. id: payload.id,
  225. value: payload.value,
  226. }
  227. }
  228. }
  229. impl From<DeltaType> for DeltaTypePB {
  230. fn from(action: DeltaType) -> Self {
  231. match action {
  232. DeltaType::Inserted => Self::Inserted,
  233. DeltaType::Updated => Self::Updated,
  234. DeltaType::Removed => Self::Removed,
  235. }
  236. }
  237. }
  238. impl From<(&Vec<BlockEvent>, bool)> for DocEventPB {
  239. fn from((events, is_remote): (&Vec<BlockEvent>, bool)) -> Self {
  240. // Convert each individual `BlockEvent` to a protobuf `BlockEventPB`, and collect the results into a `Vec`
  241. Self {
  242. events: events.iter().map(|e| e.to_owned().into()).collect(),
  243. is_remote,
  244. }
  245. }
  246. }