Browse Source

fix: delete useless files

qinluhe 2 years ago
parent
commit
9ed5bfa51e
20 changed files with 274 additions and 242 deletions
  1. 7 3
      frontend/appflowy_tauri/package.json
  2. 130 0
      frontend/appflowy_tauri/pnpm-lock.yaml
  3. 3 4
      frontend/appflowy_tauri/src/appflowy_app/components/document/DocumentTitle/DocumentTitle.hooks.ts
  4. 17 17
      frontend/appflowy_tauri/src/appflowy_app/components/document/Node/Node.hooks.ts
  5. 17 6
      frontend/appflowy_tauri/src/appflowy_app/components/document/Node/index.tsx
  6. 1 2
      frontend/appflowy_tauri/src/appflowy_app/components/document/Root/Tree.hooks.tsx
  7. 1 1
      frontend/appflowy_tauri/src/appflowy_app/components/document/Root/index.tsx
  8. 0 61
      frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/BindYjs.hooks.ts
  9. 2 2
      frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/TextBlock.hooks.ts
  10. 3 5
      frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/index.tsx
  11. 0 0
      frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizedList/VirtualizedList.hooks.tsx
  12. 0 0
      frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizedList/index.tsx
  13. 0 21
      frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizerList/VirtualizerList.hooks.tsx
  14. 0 7
      frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.hooks.ts
  15. 0 4
      frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.tsx
  16. 10 18
      frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/SubscribeNode.hooks.ts
  17. 27 29
      frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/TextInput.hooks.ts
  18. 6 5
      frontend/appflowy_tauri/src/appflowy_app/interfaces/document.ts
  19. 10 17
      frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_controller.ts
  20. 40 40
      frontend/appflowy_tauri/src/appflowy_app/stores/reducers/document/slice.ts

+ 7 - 3
frontend/appflowy_tauri/package.json

@@ -23,6 +23,7 @@
     "@slate-yjs/core": "^0.3.1",
     "@tanstack/react-virtual": "3.0.0-beta.54",
     "@tauri-apps/api": "^1.2.0",
+    "dayjs": "^1.11.7",
     "events": "^3.3.0",
     "google-protobuf": "^3.21.2",
     "i18next": "^22.4.10",
@@ -32,6 +33,8 @@
     "nanoid": "^4.0.0",
     "protoc-gen-ts": "^0.8.5",
     "react": "^18.2.0",
+    "react-beautiful-dnd": "^13.1.1",
+    "react-calendar": "^4.1.0",
     "react-dom": "^18.2.0",
     "react-error-boundary": "^3.1.4",
     "react-i18next": "^12.2.0",
@@ -44,8 +47,8 @@
     "slate-react": "^0.91.9",
     "ts-results": "^3.3.0",
     "utf8": "^3.0.0",
-    "yjs": "^13.5.51",
-		"y-indexeddb": "^9.0.9"
+    "y-indexeddb": "^9.0.9",
+    "yjs": "^13.5.51"
   },
   "devDependencies": {
     "@tauri-apps/cli": "^1.2.2",
@@ -53,6 +56,7 @@
     "@types/is-hotkey": "^0.1.7",
     "@types/node": "^18.7.10",
     "@types/react": "^18.0.15",
+    "@types/react-beautiful-dnd": "^13.1.3",
     "@types/react-dom": "^18.0.6",
     "@types/utf8": "^3.0.1",
     "@types/uuid": "^9.0.1",
@@ -70,4 +74,4 @@
     "uuid": "^9.0.0",
     "vite": "^4.0.0"
   }
-}
+}

+ 130 - 0
frontend/appflowy_tauri/pnpm-lock.yaml

@@ -14,6 +14,7 @@ specifiers:
   '@types/is-hotkey': ^0.1.7
   '@types/node': ^18.7.10
   '@types/react': ^18.0.15
+  '@types/react-beautiful-dnd': ^13.1.3
   '@types/react-dom': ^18.0.6
   '@types/utf8': ^3.0.1
   '@types/uuid': ^9.0.1
@@ -21,6 +22,7 @@ specifiers:
   '@typescript-eslint/parser': ^5.51.0
   '@vitejs/plugin-react': ^3.0.0
   autoprefixer: ^10.4.13
+  dayjs: ^1.11.7
   eslint: ^8.34.0
   eslint-plugin-react: ^7.32.2
   events: ^3.3.0
@@ -35,6 +37,8 @@ specifiers:
   prettier-plugin-tailwindcss: ^0.2.2
   protoc-gen-ts: ^0.8.5
   react: ^18.2.0
+  react-beautiful-dnd: ^13.1.1
+  react-calendar: ^4.1.0
   react-dom: ^18.2.0
   react-error-boundary: ^3.1.4
   react-i18next: ^12.2.0
@@ -63,6 +67,7 @@ dependencies:
   '@slate-yjs/core': [email protected][email protected]
   '@tanstack/react-virtual': [email protected]
   '@tauri-apps/api': 1.2.0
+  dayjs: 1.11.7
   events: 3.3.0
   google-protobuf: 3.21.2
   i18next: 22.4.10
@@ -72,6 +77,8 @@ dependencies:
   nanoid: 4.0.1
   protoc-gen-ts: 0.8.6_ss7alqtodw6rv4lluxhr36xjoa
   react: 18.2.0
+  react-beautiful-dnd: 13.1.1_biqbaboplfbrettd7655fr4n2y
+  react-calendar: 4.2.1_biqbaboplfbrettd7655fr4n2y
   react-dom: [email protected]
   react-error-boundary: [email protected]
   react-i18next: 12.2.0_3yopsigl4h4eb2nqrqfsy65uwi
@@ -93,6 +100,7 @@ devDependencies:
   '@types/is-hotkey': 0.1.7
   '@types/node': 18.14.6
   '@types/react': 18.0.28
+  '@types/react-beautiful-dnd': 13.1.4
   '@types/react-dom': 18.0.11
   '@types/utf8': 3.0.1
   '@types/uuid': 9.0.1
@@ -1513,6 +1521,12 @@ packages:
     resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
     dev: true
 
+  /@types/lodash.memoize/4.1.7:
+    resolution: {integrity: sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==}
+    dependencies:
+      '@types/lodash': 4.14.191
+    dev: false
+
   /@types/lodash/4.14.191:
     resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==}
     dev: false
@@ -1531,6 +1545,12 @@ packages:
   /@types/prop-types/15.7.5:
     resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
 
+  /@types/react-beautiful-dnd/13.1.4:
+    resolution: {integrity: sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==}
+    dependencies:
+      '@types/react': 18.0.28
+    dev: true
+
   /@types/react-dom/18.0.11:
     resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==}
     dependencies:
@@ -1542,6 +1562,15 @@ packages:
       '@types/react': 18.0.28
     dev: false
 
+  /@types/react-redux/7.1.25:
+    resolution: {integrity: sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==}
+    dependencies:
+      '@types/hoist-non-react-statics': 3.3.1
+      '@types/react': 18.0.28
+      hoist-non-react-statics: 3.3.2
+      redux: 4.2.1
+    dev: false
+
   /@types/react-transition-group/4.4.5:
     resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==}
     dependencies:
@@ -1734,6 +1763,10 @@ packages:
       - supports-color
     dev: true
 
+  /@wojtekmaj/date-utils/1.1.3:
+    resolution: {integrity: sha512-rHrDuTl1cx5LYo8F4K4HVauVjwzx4LwrKfEk4br4fj4nK8JjJZ8IG6a6pBHkYmPLBQHCOEDwstb0WNXMGsmdOw==}
+    dev: false
+
   /acorn-jsx/[email protected]:
     resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
     peerDependencies:
@@ -2149,6 +2182,12 @@ packages:
       shebang-command: 2.0.0
       which: 2.0.2
 
+  /css-box-model/1.2.1:
+    resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==}
+    dependencies:
+      tiny-invariant: 1.0.6
+    dev: false
+
   /cssesc/3.0.0:
     resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
     engines: {node: '>=4'}
@@ -2158,6 +2197,10 @@ packages:
   /csstype/3.1.1:
     resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
 
+  /dayjs/1.11.7:
+    resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==}
+    dev: false
+
   /debug/4.3.4:
     resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
     engines: {node: '>=6.0'}
@@ -2723,6 +2766,13 @@ packages:
       get-intrinsic: 1.2.0
     dev: true
 
+  /get-user-locale/2.2.1:
+    resolution: {integrity: sha512-3814zipTZ2MvczOcppEXB3jXu+0HWwj5WmPI6//SeCnUIUaRXu7W4S54eQZTEPadlMZefE+jAlPOn+zY3tD4Qw==}
+    dependencies:
+      '@types/lodash.memoize': 4.1.7
+      lodash.memoize: 4.1.2
+    dev: false
+
   /glob-parent/5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
@@ -3635,6 +3685,10 @@ packages:
       p-locate: 5.0.0
     dev: true
 
+  /lodash.memoize/4.1.2:
+    resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+    dev: false
+
   /lodash.merge/4.6.2:
     resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
     dev: true
@@ -3680,6 +3734,10 @@ packages:
       tmpl: 1.0.5
     dev: false
 
+  /memoize-one/5.2.1:
+    resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
+    dev: false
+
   /merge-stream/2.0.0:
     resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
     dev: false
@@ -4121,6 +4179,44 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
+  /raf-schd/4.0.3:
+    resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==}
+    dev: false
+
+  /react-beautiful-dnd/13.1.1_biqbaboplfbrettd7655fr4n2y:
+    resolution: {integrity: sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==}
+    peerDependencies:
+      react: ^16.8.5 || ^17.0.0 || ^18.0.0
+      react-dom: ^16.8.5 || ^17.0.0 || ^18.0.0
+    dependencies:
+      '@babel/runtime': 7.21.0
+      css-box-model: 1.2.1
+      memoize-one: 5.2.1
+      raf-schd: 4.0.3
+      react: 18.2.0
+      react-dom: [email protected]
+      react-redux: 7.2.9_biqbaboplfbrettd7655fr4n2y
+      redux: 4.2.1
+      use-memo-one: [email protected]
+    transitivePeerDependencies:
+      - react-native
+    dev: false
+
+  /react-calendar/4.2.1_biqbaboplfbrettd7655fr4n2y:
+    resolution: {integrity: sha512-T5oKXD+KLy/g6bmJJkZ7E9wj0iRMesWMZcrC7q2kI6ybOsu9NlPQx8uXJzG4A4C3Sh5Xi0deznyzWIVsUpF8tA==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+      react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+    dependencies:
+      '@types/react': 18.0.28
+      '@wojtekmaj/date-utils': 1.1.3
+      clsx: 1.2.1
+      get-user-locale: 2.2.1
+      prop-types: 15.8.1
+      react: 18.2.0
+      react-dom: [email protected]
+    dev: false
+
   /react-dom/[email protected]:
     resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
     peerDependencies:
@@ -4164,10 +4260,36 @@ packages:
   /react-is/16.13.1:
     resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
 
+  /react-is/17.0.2:
+    resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+    dev: false
+
   /react-is/18.2.0:
     resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
     dev: false
 
+  /react-redux/7.2.9_biqbaboplfbrettd7655fr4n2y:
+    resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==}
+    peerDependencies:
+      react: ^16.8.3 || ^17 || ^18
+      react-dom: '*'
+      react-native: '*'
+    peerDependenciesMeta:
+      react-dom:
+        optional: true
+      react-native:
+        optional: true
+    dependencies:
+      '@babel/runtime': 7.21.0
+      '@types/react-redux': 7.1.25
+      hoist-non-react-statics: 3.3.2
+      loose-envify: 1.4.0
+      prop-types: 15.8.1
+      react: 18.2.0
+      react-dom: [email protected]
+      react-is: 17.0.2
+    dev: false
+
   /react-redux/8.0.5_ctrls2ti7t7iutxbwkm5ipogyy:
     resolution: {integrity: sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==}
     peerDependencies:
@@ -4752,6 +4874,14 @@ packages:
       punycode: 2.3.0
     dev: true
 
+  /use-memo-one/[email protected]:
+    resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    dependencies:
+      react: 18.2.0
+    dev: false
+
   /use-sync-external-store/[email protected]:
     resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
     peerDependencies:

+ 3 - 4
frontend/appflowy_tauri/src/appflowy_app/components/document/DocumentTitle/DocumentTitle.hooks.ts

@@ -1,8 +1,7 @@
 import { useSubscribeNode } from '../_shared/SubscribeNode.hooks';
 export function useDocumentTitle(id: string) {
-  const { node, delta } = useSubscribeNode(id);
+  const { node } = useSubscribeNode(id);
   return {
     node,
-    delta
-  }
-}
+  };
+}

+ 17 - 17
frontend/appflowy_tauri/src/appflowy_app/components/document/Node/Node.hooks.ts

@@ -1,11 +1,10 @@
-
 import { useEffect, useRef } from 'react';
 import { useSubscribeNode } from '../_shared/SubscribeNode.hooks';
 import { useAppDispatch } from '$app/stores/store';
 import { documentActions } from '$app/stores/reducers/document/slice';
 
 export function useNode(id: string) {
-  const { node, childIds, delta, isSelected } = useSubscribeNode(id);
+  const { node, childIds, isSelected } = useSubscribeNode(id);
   const ref = useRef<HTMLDivElement>(null);
 
   const dispatch = useAppDispatch();
@@ -15,22 +14,23 @@ export function useNode(id: string) {
     const rect = ref.current.getBoundingClientRect();
 
     const scrollContainer = document.querySelector('.doc-scroller-container') as HTMLDivElement;
-    dispatch(documentActions.updateNodePosition({
-      id,
-      rect: {
-        x: rect.x,
-        y: rect.y + scrollContainer.scrollTop,
-        height: rect.height,
-        width: rect.width
-      }
-    }))
-  }, [])
-  
+    dispatch(
+      documentActions.updateNodePosition({
+        id,
+        rect: {
+          x: rect.x,
+          y: rect.y + scrollContainer.scrollTop,
+          height: rect.height,
+          width: rect.width,
+        },
+      })
+    );
+  }, []);
+
   return {
     ref,
     node,
     childIds,
-    delta,
-    isSelected
-  }
-}
+    isSelected,
+  };
+}

+ 17 - 6
frontend/appflowy_tauri/src/appflowy_app/components/document/Node/index.tsx

@@ -7,14 +7,26 @@ import TextBlock from '../TextBlock';
 import { TextDelta } from '@/appflowy_app/interfaces/document';
 
 function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<HTMLDivElement>) {
-  const { node, childIds, delta, isSelected, ref } = useNode(id);
+  const { node, childIds, isSelected, ref } = useNode(id);
 
   console.log('=====', id);
-  const renderBlock = useCallback((_props: { node: Node; childIds?: string[]; delta?: TextDelta[] }) => {
+  const renderBlock = useCallback((_props: { node: Node; childIds?: string[] }) => {
     switch (_props.node.type) {
-      case 'text':
-        if (!_props.delta) return null;
-        return <TextBlock {..._props} delta={_props.delta} />;
+      case 'text': {
+        const delta = _props.node.data.delta;
+        if (!delta) return null;
+        return (
+          <TextBlock
+            node={{
+              ..._props.node,
+              data: {
+                delta,
+              },
+            }}
+            childIds={childIds}
+          />
+        );
+      }
       default:
         break;
     }
@@ -27,7 +39,6 @@ function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<H
       {renderBlock({
         node,
         childIds,
-        delta,
       })}
       <div className='block-overlay' />
       {isSelected ? <div className='pointer-events-none absolute inset-0 z-[-1] rounded-[4px] bg-[#E0F8FF]' /> : null}

+ 1 - 2
frontend/appflowy_tauri/src/appflowy_app/components/document/Root/Tree.hooks.tsx

@@ -11,8 +11,7 @@ export function useParseTree(documentData: DocumentData) {
     dispatch(
       documentActions.create({
         nodes: blocks,
-        delta: meta.text_map,
-        children: meta.children_map,
+        children: meta.childrenMap,
       })
     );
 

+ 1 - 1
frontend/appflowy_tauri/src/appflowy_app/components/document/Root/index.tsx

@@ -4,7 +4,7 @@ import { useRoot } from './Root.hooks';
 import Node from '../Node';
 import { withErrorBoundary } from 'react-error-boundary';
 import { ErrorBoundaryFallbackComponent } from '../_shared/ErrorBoundaryFallbackComponent';
-import VirtualizedList from '../VirtualizerList';
+import VirtualizedList from '../VirtualizedList';
 import { Skeleton } from '@mui/material';
 
 function Root({ documentData }: { documentData: DocumentData }) {

+ 0 - 61
frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/BindYjs.hooks.ts

@@ -1,61 +0,0 @@
-
-
-import { useEffect, useMemo, useRef } from "react";
-import { createEditor } from "slate";
-import { withReact } from "slate-react";
-
-import * as Y from 'yjs';
-import { withYjs, YjsEditor, slateNodesToInsertDelta } from '@slate-yjs/core';
-import { Delta } from '@slate-yjs/core/dist/model/types';
-import { TextDelta } from '@/appflowy_app/interfaces/document';
-
-const initialValue = [{
-  type: 'paragraph',
-  children: [{ text: '' }],
-}];
-
-export function useBindYjs(delta: TextDelta[], update: (_delta: TextDelta[]) => void) {
-  const yTextRef = useRef<Y.XmlText>();
-  // Create a yjs document and get the shared type
-  const sharedType = useMemo(() => {
-    const ydoc = new Y.Doc()
-    const _sharedType = ydoc.get('content', Y.XmlText) as Y.XmlText;
-    
-    const insertDelta = slateNodesToInsertDelta(initialValue);
-    // Load the initial value into the yjs document
-    _sharedType.applyDelta(insertDelta);
-
-    const yText = insertDelta[0].insert as Y.XmlText;
-    yTextRef.current = yText;
-    
-    return _sharedType;
-  }, []);
-
-  const editor = useMemo(() => withYjs(withReact(createEditor()), sharedType), []);
-
-  useEffect(() => {
-    YjsEditor.connect(editor);
-    return () => {
-      yTextRef.current = undefined;
-      YjsEditor.disconnect(editor);
-    }
-  }, [editor]);
-
-  useEffect(() => {
-    const yText = yTextRef.current;
-    if (!yText) return;
-
-    const textEventHandler = (event: Y.YTextEvent) => {
-      update(event.changes.delta as TextDelta[]);
-    }
-    yText.applyDelta(delta);
-    yText.observe(textEventHandler);
-  
-    return () => {
-      yText.unobserve(textEventHandler);
-    }
-  }, [delta])
-  
-
-  return { editor }
-}

+ 2 - 2
frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/TextBlock.hooks.ts

@@ -4,8 +4,8 @@ import { Descendant, Range } from 'slate';
 import { TextDelta } from '$app/interfaces/document';
 import { useTextInput } from '../_shared/TextInput.hooks';
 
-export function useTextBlock(text: string, delta: TextDelta[]) {
-  const { editor } = useTextInput(text, delta);
+export function useTextBlock(delta: TextDelta[]) {
+  const { editor } = useTextInput(delta);
   const [value, setValue] = useState<Descendant[]>([]);
 
   const onChange = useCallback(

+ 3 - 5
frontend/appflowy_tauri/src/appflowy_app/components/document/TextBlock/index.tsx

@@ -4,22 +4,20 @@ import { useTextBlock } from './TextBlock.hooks';
 import { Node } from '@/appflowy_app/stores/reducers/document/slice';
 import NodeComponent from '../Node';
 import HoveringToolbar from '../_shared/HoveringToolbar';
-import { TextDelta } from '@/appflowy_app/interfaces/document';
 import React from 'react';
+import { TextDelta } from '@/appflowy_app/interfaces/document';
 
 function TextBlock({
   node,
   childIds,
   placeholder,
-  delta,
   ...props
 }: {
-  node: Node;
-  delta: TextDelta[];
+  node: Node & { data: { delta: TextDelta[] } };
   childIds?: string[];
   placeholder?: string;
 } & React.HTMLAttributes<HTMLDivElement>) {
-  const { editor, value, onChange, onKeyDownCapture, onDOMBeforeInput } = useTextBlock(node.data.text!, delta);
+  const { editor, value, onChange, onKeyDownCapture, onDOMBeforeInput } = useTextBlock(node.data.delta);
 
   return (
     <div {...props} className={`py-[2px] ${props.className}`}>

+ 0 - 0
frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizerList/VirtualizedList.hooks.tsx → frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizedList/VirtualizedList.hooks.tsx


+ 0 - 0
frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizerList/index.tsx → frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizedList/index.tsx


+ 0 - 21
frontend/appflowy_tauri/src/appflowy_app/components/document/VirtualizerList/VirtualizerList.hooks.tsx

@@ -1,21 +0,0 @@
-import { useVirtualizer } from '@tanstack/react-virtual';
-import { useRef } from 'react';
-
-const defaultSize = 60;
-
-export function useVirtualizerList(count: number) {
-  const parentRef = useRef<HTMLDivElement>(null);
-
-  const rowVirtualizer = useVirtualizer({
-    count,
-    getScrollElement: () => parentRef.current,
-    estimateSize: () => {
-      return defaultSize;
-    },
-  });
-
-  return {
-    rowVirtualizer,
-    parentRef,
-  };
-}

+ 0 - 7
frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.hooks.ts

@@ -1,13 +1,6 @@
 import { useEffect, useRef } from 'react';
 import { useFocused, useSlate } from 'slate-react';
-<<<<<<<< HEAD:frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.hooks.ts
 import { calcToolbarPosition } from '$app/utils/slate/toolbar';
-
-========
-import { calcToolbarPosition } from '@/appflowy_app/utils/slate/toolbar';
-
-
->>>>>>>> 341dce67d45ebe46ae55e11349a19191ac99b4cf:frontend/appflowy_tauri/src/appflowy_app/components/document/HoveringToolbar/index.hooks.ts
 export function useHoveringToolbar(id: string) {
   const editor = useSlate();
   const inFocus = useFocused();

+ 0 - 4
frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.tsx

@@ -1,9 +1,5 @@
 import FormatButton from './FormatButton';
-<<<<<<<< HEAD:frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/HoveringToolbar/index.tsx
 import Portal from '../../BlockPortal';
-========
-import Portal from '../BlockPortal';
->>>>>>>> 341dce67d45ebe46ae55e11349a19191ac99b4cf:frontend/appflowy_tauri/src/appflowy_app/components/document/HoveringToolbar/index.tsx
 import { useHoveringToolbar } from './index.hooks';
 
 const HoveringToolbar = ({ id }: { id: string }) => {

+ 10 - 18
frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/SubscribeNode.hooks.ts

@@ -1,7 +1,6 @@
 import { Node } from '@/appflowy_app/stores/reducers/document/slice';
 import { useAppSelector } from '@/appflowy_app/stores/store';
 import { useMemo } from 'react';
-import { TextDelta } from '@/appflowy_app/interfaces/document';
 
 /**
  * Subscribe to a node and its children
@@ -10,37 +9,30 @@ import { TextDelta } from '@/appflowy_app/interfaces/document';
  * @param id
  */
 export function useSubscribeNode(id: string) {
-  const node = useAppSelector<Node>(state => state.document.nodes[id]);
+  const node = useAppSelector<Node>((state) => state.document.nodes[id]);
 
-  const childIds = useAppSelector<string[] | undefined>(state => {
+  const childIds = useAppSelector<string[] | undefined>((state) => {
     const childrenId = state.document.nodes[id]?.children;
     if (!childrenId) return;
     return state.document.children[childrenId];
   });
 
-  const delta = useAppSelector<TextDelta[] | undefined>(state => {
-    const externalType = state.document.nodes[id]?.externalType;
-    if (externalType !== 'text') return;
-    const deltaId = state.document.nodes[id]?.externalId;
-    if (!deltaId) return;
-    return state.document.delta[deltaId];
-  });
-
-  const isSelected = useAppSelector<boolean>(state => {
+  const isSelected = useAppSelector<boolean>((state) => {
     return state.document.selections?.includes(id) || false;
   });
 
   // Memoize the node and its children
   // So that the component will not be re-rendered when other node is changed
   // It very important for performance
-  const memoizedNode = useMemo(() => node, [node?.id, node?.data, node?.parent, node?.type, node?.children]);
+  const memoizedNode = useMemo(
+    () => node,
+    [node?.id, JSON.stringify(node?.data), node?.parent, node?.type, node?.children]
+  );
   const memoizedChildIds = useMemo(() => childIds, [JSON.stringify(childIds)]);
-  const memoizedDelta = useMemo(() => delta, [JSON.stringify(delta)]);
-  
+
   return {
     node: memoizedNode,
     childIds: memoizedChildIds,
-    delta: memoizedDelta,
-    isSelected
+    isSelected,
   };
-}
+}

+ 27 - 29
frontend/appflowy_tauri/src/appflowy_app/components/document/_shared/TextInput.hooks.ts

@@ -8,8 +8,8 @@ import { withReact } from 'slate-react';
 import * as Y from 'yjs';
 import { withYjs, YjsEditor, slateNodesToInsertDelta } from '@slate-yjs/core';
 
-export function useTextInput(text: string, delta: TextDelta[]) {
-  const { sendDelta } = useTransact(text);
+export function useTextInput(delta: TextDelta[]) {
+  const { sendDelta } = useTransact();
   const { editor } = useBindYjs(delta, sendDelta);
 
   return {
@@ -17,49 +17,45 @@ export function useTextInput(text: string, delta: TextDelta[]) {
   };
 }
 
-function useController(textId: string) {
+function useController() {
   const docController = useContext(DocumentControllerContext);
 
   const update = useCallback(
     (delta: TextDelta[]) => {
-      docController?.yTextApply(textId, delta);
+      docController?.applyActions([
+        {
+          type: 'update',
+          payload: {
+            block: {
+              data: {
+                delta,
+              },
+            },
+          },
+        },
+      ]);
     },
-    [textId]
-  );
-  const transact = useCallback(
-    (actions: (() => void)[]) => {
-      docController?.transact(actions);
-    },
-    [textId]
+    [docController]
   );
 
   return {
     update,
-    transact,
   };
 }
 
-function useTransact(textId: string) {
-  const pendingActions = useRef<(() => void)[]>([]);
-  const { update, transact } = useController(textId);
-
-  const sendTransact = useCallback(() => {
-    const actions = pendingActions.current;
-    transact(actions);
-  }, [transact]);
-
-  const debounceSendTransact = useMemo(() => debounce(sendTransact, 300), [transact]);
+function useTransact() {
+  const { update } = useController();
 
   const sendDelta = useCallback(
     (delta: TextDelta[]) => {
-      const action = () => update(delta);
-      pendingActions.current.push(action);
-      debounceSendTransact();
+      update(delta);
     },
-    [update, debounceSendTransact]
+    [update]
   );
+  const debounceSendDelta = useMemo(() => debounce(sendDelta, 300), [sendDelta]);
+
   return {
-    sendDelta,
+    sendDelta: debounceSendDelta,
   };
 }
 
@@ -70,7 +66,7 @@ const initialValue = [
   },
 ];
 
-export function useBindYjs(delta: TextDelta[], update: (_delta: TextDelta[]) => void) {
+function useBindYjs(delta: TextDelta[], update: (_delta: TextDelta[]) => void) {
   const yTextRef = useRef<Y.XmlText>();
   // Create a yjs document and get the shared type
   const sharedType = useMemo(() => {
@@ -102,7 +98,9 @@ export function useBindYjs(delta: TextDelta[], update: (_delta: TextDelta[]) =>
     if (!yText) return;
 
     const textEventHandler = (event: Y.YTextEvent) => {
-      update(event.changes.delta as TextDelta[]);
+      const textDelta = event.target.toDelta();
+      console.log('delta', textDelta);
+      update(textDelta);
     };
     yText.applyDelta(delta);
     yText.observe(textEventHandler);

+ 6 - 5
frontend/appflowy_tauri/src/appflowy_app/interfaces/document.ts

@@ -10,12 +10,14 @@ export enum BlockType {
   DividerBlock = 'divider',
   MediaBlock = 'media',
   TableBlock = 'table',
-  ColumnBlock = 'column'
+  ColumnBlock = 'column',
 }
 export interface NestedBlock {
   id: string;
   type: BlockType;
-  data: Record<string, any>;
+  data: {
+    delta?: TextDelta[];
+  };
   externalId: string;
   externalType: 'text' | 'array' | 'map';
   parent: string | null;
@@ -29,7 +31,6 @@ export interface DocumentData {
   rootId: string;
   blocks: Record<string, NestedBlock>;
   meta: {
-    text_map: Record<string, TextDelta[]>;
-    children_map: Record<string, string[]>;
-  }
+    childrenMap: Record<string, string[]>;
+  };
 }

+ 10 - 17
frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_controller.ts

@@ -17,30 +17,23 @@ export class DocumentController {
       return {
         rootId: '',
         blocks: {},
-        ytexts: {},
-        yarrays: {}
+        meta: {
+          childrenMap: {},
+        },
       };
     } else {
       return null;
     }
   };
 
-
-  insert(node: {
-    id: string,
-    type: BlockType,
-    delta?: TextDelta[]
-  }, parentId: string, prevId: string) {
+  applyActions = (
+    actions: {
+      type: string;
+      payload: any;
+    }[]
+  ) => {
     //
-  }
-
-  transact(actions: (() => void)[]) {
-    //
-  }
-
-  yTextApply = (yTextId: string, delta: TextDelta[]) => {
-    //
-  }
+  };
 
   dispose = async () => {
     await this.backendService.close();

+ 40 - 40
frontend/appflowy_tauri/src/appflowy_app/stores/reducers/document/slice.ts

@@ -1,13 +1,12 @@
-import { BlockType, NestedBlock, TextDelta } from "@/appflowy_app/interfaces/document";
-import { PayloadAction, createSlice } from "@reduxjs/toolkit";
-import { RegionGrid } from "./region_grid";
+import { BlockType, NestedBlock, TextDelta } from '@/appflowy_app/interfaces/document';
+import { PayloadAction, createSlice } from '@reduxjs/toolkit';
+import { RegionGrid } from './region_grid';
 
 export type Node = NestedBlock;
 
 export interface NodeState {
   nodes: Record<string, Node>;
   children: Record<string, string[]>;
-  delta: Record<string, TextDelta[]>;
   selections: string[];
 }
 
@@ -16,7 +15,6 @@ const regionGrid = new RegionGrid(50);
 const initialState: NodeState = {
   nodes: {},
   children: {},
-  delta: {},
   selections: [],
 };
 
@@ -28,42 +26,52 @@ export const documentSlice = createSlice({
       return initialState;
     },
 
-    create: (state, action: PayloadAction<{
-      nodes: Record<string, Node>;
-      children: Record<string, string[]>;
-      delta: Record<string, TextDelta[]>;
-    }>) => {
-      const { nodes, children, delta } = action.payload;
+    create: (
+      state,
+      action: PayloadAction<{
+        nodes: Record<string, Node>;
+        children: Record<string, string[]>;
+      }>
+    ) => {
+      const { nodes, children } = action.payload;
       state.nodes = nodes;
       state.children = children;
-      state.delta = delta;
     },
 
     updateSelections: (state, action: PayloadAction<string[]>) => {
       state.selections = action.payload;
     },
 
-    setSelectionByRect: (state, action: PayloadAction<{
-      startX: number;
-      startY: number;
-      endX: number;
-      endY: number
-    }>) => {
+    setSelectionByRect: (
+      state,
+      action: PayloadAction<{
+        startX: number;
+        startY: number;
+        endX: number;
+        endY: number;
+      }>
+    ) => {
       const { startX, startY, endX, endY } = action.payload;
       const blocks = regionGrid.getIntersectBlocks(startX, startY, endX, endY);
-      state.selections = blocks.map(block => block.id);
+      state.selections = blocks.map((block) => block.id);
     },
 
-    updateNodePosition: (state, action: PayloadAction<{id: string; rect: {
-      x: number;
-      y: number;
-      width: number;
-      height: number;
-    }}>) => {
+    updateNodePosition: (
+      state,
+      action: PayloadAction<{
+        id: string;
+        rect: {
+          x: number;
+          y: number;
+          width: number;
+          height: number;
+        };
+      }>
+    ) => {
       const { id, rect } = action.payload;
       const position = {
         id,
-        ...rect
+        ...rect,
       };
       regionGrid.updateBlock(id, position);
     },
@@ -72,13 +80,13 @@ export const documentSlice = createSlice({
       state.nodes[action.payload.id] = action.payload;
     },
 
-    addChild: (state, action: PayloadAction<{ parentId: string, childId: string, prevId: string }>) => {
+    addChild: (state, action: PayloadAction<{ parentId: string; childId: string; prevId: string }>) => {
       const { parentId, childId, prevId } = action.payload;
       const parentChildrenId = state.nodes[parentId].children;
       const children = state.children[parentChildrenId];
       const prevIndex = children.indexOf(prevId);
       if (prevIndex === -1) {
-        children.push(childId)
+        children.push(childId);
       } else {
         children.splice(prevIndex + 1, 0, childId);
       }
@@ -89,16 +97,11 @@ export const documentSlice = createSlice({
       state.children[id] = childIds;
     },
 
-    updateDelta: (state, action: PayloadAction<{ id: string; delta: TextDelta[] }>) => {
-      const { id, delta } = action.payload;
-      state.delta[id] = delta;
-    },
-
-    updateNode: (state, action: PayloadAction<{id: string; type?: BlockType; data?: any }>) => {
+    updateNode: (state, action: PayloadAction<{ id: string; data: any }>) => {
       state.nodes[action.payload.id] = {
         ...state.nodes[action.payload.id],
-        ...action.payload
-      }
+        ...action.payload,
+      };
     },
 
     removeNode: (state, action: PayloadAction<string>) => {
@@ -114,10 +117,7 @@ export const documentSlice = createSlice({
       if (children) {
         delete state.children[children];
       }
-      // remove delta
-      if (data && data.text) {
-        delete state.delta[data.text];
-      }
+
       // remove node
       delete state.nodes[action.payload];
     },