event_handler.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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. /// Handler for creating a text
  84. pub(crate) async fn create_text_handler(
  85. data: AFPluginData<TextDeltaPayloadPB>,
  86. manager: AFPluginState<Weak<DocumentManager>>,
  87. ) -> FlowyResult<()> {
  88. let manager = upgrade_document(manager)?;
  89. let params: TextDeltaParams = data.into_inner().try_into()?;
  90. let doc_id = params.document_id;
  91. let document = manager.get_document(&doc_id).await?;
  92. let document = document.lock();
  93. document.create_text(&params.text_id, params.delta);
  94. Ok(())
  95. }
  96. /// Handler for applying delta to a text
  97. pub(crate) async fn apply_text_delta_handler(
  98. data: AFPluginData<TextDeltaPayloadPB>,
  99. manager: AFPluginState<Weak<DocumentManager>>,
  100. ) -> FlowyResult<()> {
  101. let manager = upgrade_document(manager)?;
  102. let params: TextDeltaParams = data.into_inner().try_into()?;
  103. let doc_id = params.document_id;
  104. let document = manager.get_document(&doc_id).await?;
  105. let text_id = params.text_id;
  106. let delta = params.delta;
  107. let document = document.lock();
  108. document.apply_text_delta(&text_id, delta);
  109. Ok(())
  110. }
  111. pub(crate) async fn convert_data_to_document(
  112. data: AFPluginData<ConvertDataPayloadPB>,
  113. ) -> DataResult<DocumentDataPB, FlowyError> {
  114. let payload = data.into_inner();
  115. let document = convert_data_to_document_internal(payload)?;
  116. data_result_ok(document)
  117. }
  118. pub fn convert_data_to_document_internal(
  119. payload: ConvertDataPayloadPB,
  120. ) -> Result<DocumentDataPB, FlowyError> {
  121. let params: ConvertDataParams = payload.try_into()?;
  122. let convert_type = params.convert_type;
  123. let data = params.data;
  124. match convert_type {
  125. ConvertType::Json => {
  126. let json_str = String::from_utf8(data).map_err(|_| FlowyError::invalid_data())?;
  127. let document = JsonToDocumentParser::json_str_to_document(&json_str)?;
  128. Ok(document)
  129. },
  130. }
  131. }
  132. pub(crate) async fn redo_handler(
  133. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  134. manager: AFPluginState<Weak<DocumentManager>>,
  135. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  136. let manager = upgrade_document(manager)?;
  137. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  138. let doc_id = params.document_id;
  139. let document = manager.get_document(&doc_id).await?;
  140. let document = document.lock();
  141. let redo = document.redo();
  142. let can_redo = document.can_redo();
  143. let can_undo = document.can_undo();
  144. data_result_ok(DocumentRedoUndoResponsePB {
  145. can_redo,
  146. can_undo,
  147. is_success: redo,
  148. })
  149. }
  150. pub(crate) async fn undo_handler(
  151. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  152. manager: AFPluginState<Weak<DocumentManager>>,
  153. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  154. let manager = upgrade_document(manager)?;
  155. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  156. let doc_id = params.document_id;
  157. let document = manager.get_document(&doc_id).await?;
  158. let document = document.lock();
  159. let undo = document.undo();
  160. let can_redo = document.can_redo();
  161. let can_undo = document.can_undo();
  162. data_result_ok(DocumentRedoUndoResponsePB {
  163. can_redo,
  164. can_undo,
  165. is_success: undo,
  166. })
  167. }
  168. pub(crate) async fn can_undo_redo_handler(
  169. data: AFPluginData<DocumentRedoUndoPayloadPB>,
  170. manager: AFPluginState<Weak<DocumentManager>>,
  171. ) -> DataResult<DocumentRedoUndoResponsePB, FlowyError> {
  172. let manager = upgrade_document(manager)?;
  173. let params: DocumentRedoUndoParams = data.into_inner().try_into()?;
  174. let doc_id = params.document_id;
  175. let document = manager.get_document(&doc_id).await?;
  176. let document = document.lock();
  177. let can_redo = document.can_redo();
  178. let can_undo = document.can_undo();
  179. drop(document);
  180. data_result_ok(DocumentRedoUndoResponsePB {
  181. can_redo,
  182. can_undo,
  183. is_success: true,
  184. })
  185. }
  186. pub(crate) async fn get_snapshot_handler(
  187. data: AFPluginData<OpenDocumentPayloadPB>,
  188. manager: AFPluginState<Weak<DocumentManager>>,
  189. ) -> DataResult<RepeatedDocumentSnapshotPB, FlowyError> {
  190. let manager = upgrade_document(manager)?;
  191. let params: OpenDocumentParams = data.into_inner().try_into()?;
  192. let doc_id = params.document_id;
  193. let snapshots = manager.get_document_snapshots(&doc_id, 10).await?;
  194. data_result_ok(RepeatedDocumentSnapshotPB { items: snapshots })
  195. }
  196. impl From<BlockActionPB> for BlockAction {
  197. fn from(pb: BlockActionPB) -> Self {
  198. Self {
  199. action: pb.action.into(),
  200. payload: pb.payload.into(),
  201. }
  202. }
  203. }
  204. impl From<BlockActionTypePB> for BlockActionType {
  205. fn from(pb: BlockActionTypePB) -> Self {
  206. match pb {
  207. BlockActionTypePB::Insert => Self::Insert,
  208. BlockActionTypePB::Update => Self::Update,
  209. BlockActionTypePB::Delete => Self::Delete,
  210. BlockActionTypePB::Move => Self::Move,
  211. BlockActionTypePB::InsertText => Self::InsertText,
  212. BlockActionTypePB::ApplyTextDelta => Self::ApplyTextDelta,
  213. }
  214. }
  215. }
  216. impl From<BlockActionPayloadPB> for BlockActionPayload {
  217. fn from(pb: BlockActionPayloadPB) -> Self {
  218. Self {
  219. block: pb.block.map(|b| b.into()),
  220. parent_id: pb.parent_id,
  221. prev_id: pb.prev_id,
  222. text_id: pb.text_id,
  223. delta: pb.delta,
  224. }
  225. }
  226. }
  227. impl From<BlockPB> for Block {
  228. fn from(pb: BlockPB) -> Self {
  229. // Use `json_str_to_hashmap()` from the `collab_document` crate to convert the JSON data to a hashmap
  230. let data = json_str_to_hashmap(&pb.data).unwrap_or_default();
  231. // Convert the protobuf `BlockPB` to our internal `Block` struct
  232. Self {
  233. id: pb.id,
  234. ty: pb.ty,
  235. children: pb.children_id,
  236. parent: pb.parent_id,
  237. data,
  238. external_id: pb.external_id,
  239. external_type: pb.external_type,
  240. }
  241. }
  242. }
  243. impl From<BlockEvent> for BlockEventPB {
  244. fn from(payload: BlockEvent) -> Self {
  245. // Convert each individual `BlockEvent` to a protobuf `BlockEventPB`, and collect the results into a `Vec`
  246. Self {
  247. event: payload.iter().map(|e| e.to_owned().into()).collect(),
  248. }
  249. }
  250. }
  251. impl From<BlockEventPayload> for BlockEventPayloadPB {
  252. fn from(payload: BlockEventPayload) -> Self {
  253. Self {
  254. command: payload.command.into(),
  255. path: payload.path,
  256. id: payload.id,
  257. value: payload.value,
  258. }
  259. }
  260. }
  261. impl From<DeltaType> for DeltaTypePB {
  262. fn from(action: DeltaType) -> Self {
  263. match action {
  264. DeltaType::Inserted => Self::Inserted,
  265. DeltaType::Updated => Self::Updated,
  266. DeltaType::Removed => Self::Removed,
  267. }
  268. }
  269. }
  270. impl From<(&Vec<BlockEvent>, bool)> for DocEventPB {
  271. fn from((events, is_remote): (&Vec<BlockEvent>, bool)) -> Self {
  272. // Convert each individual `BlockEvent` to a protobuf `BlockEventPB`, and collect the results into a `Vec`
  273. Self {
  274. events: events.iter().map(|e| e.to_owned().into()).collect(),
  275. is_remote,
  276. }
  277. }
  278. }