DocumentPage.hooks.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { useCallback, useEffect, useState } from 'react';
  2. import { useParams } from 'react-router-dom';
  3. import { DocumentData } from '../interfaces/document';
  4. import { DocumentController } from '$app/stores/effects/document/document_controller';
  5. import { useAppDispatch } from '../stores/store';
  6. import { Log } from '../utils/log';
  7. import {
  8. documentActions,
  9. rangeActions,
  10. rectSelectionActions,
  11. slashCommandActions,
  12. } from '$app/stores/reducers/document/slice';
  13. import { BlockEventPayloadPB } from '@/services/backend/models/flowy-document2';
  14. export const useDocument = () => {
  15. const params = useParams();
  16. const [documentId, setDocumentId] = useState<string>();
  17. const [documentData, setDocumentData] = useState<DocumentData>();
  18. const [controller, setController] = useState<DocumentController | null>(null);
  19. const dispatch = useAppDispatch();
  20. const onDocumentChange = useCallback(
  21. (props: { docId: string; isRemote: boolean; data: BlockEventPayloadPB }) => {
  22. dispatch(documentActions.onDataChange(props));
  23. },
  24. [dispatch]
  25. );
  26. const initializeDocument = useCallback(
  27. (docId: string) => {
  28. Log.debug('initialize document', docId);
  29. dispatch(documentActions.initialState(docId));
  30. dispatch(rangeActions.initialState(docId));
  31. dispatch(rectSelectionActions.initialState(docId));
  32. dispatch(slashCommandActions.initialState(docId));
  33. },
  34. [dispatch]
  35. );
  36. const clearDocument = useCallback(
  37. (docId: string) => {
  38. Log.debug('clear document', docId);
  39. dispatch(documentActions.clear(docId));
  40. dispatch(rangeActions.clear(docId));
  41. dispatch(rectSelectionActions.clear(docId));
  42. dispatch(slashCommandActions.clear(docId));
  43. },
  44. [dispatch]
  45. );
  46. useEffect(() => {
  47. let documentController: DocumentController | null = null;
  48. void (async () => {
  49. if (!params?.id) return;
  50. documentController = new DocumentController(params.id, onDocumentChange);
  51. const docId = documentController.documentId;
  52. Log.debug('open document', params.id);
  53. initializeDocument(documentController.documentId);
  54. setController(documentController);
  55. try {
  56. const res = await documentController.open();
  57. if (!res) return;
  58. dispatch(
  59. documentActions.create({
  60. ...res,
  61. docId,
  62. })
  63. );
  64. setDocumentData(res);
  65. setDocumentId(params.id);
  66. } catch (e) {
  67. Log.error(e);
  68. }
  69. })();
  70. return () => {
  71. if (documentController) {
  72. void (async () => {
  73. await documentController.dispose();
  74. clearDocument(documentController.documentId);
  75. })();
  76. }
  77. Log.debug('close document', params.id);
  78. };
  79. }, [clearDocument, dispatch, initializeDocument, onDocumentChange, params.id]);
  80. return { documentId, documentData, controller };
  81. };