event_handler.rs 8.6 KB

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