From 0ac10e783111178e5f8eb1e0a7ac839cbe899e9c Mon Sep 17 00:00:00 2001 From: bniwredyc Date: Wed, 29 Mar 2023 17:36:12 +0200 Subject: [PATCH] hocuspocus --- package-lock.json | 61 ++++++++++++++++++++++---- package.json | 1 + src/components/Editor/Editor.tsx | 15 ++++--- src/components/Editor/Prosemirror.scss | 27 ++++++++++++ 4 files changed, 90 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ea354ea..262dd59d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@aws-sdk/abort-controller": "^3.272.0", "@aws-sdk/client-s3": "^3.282.0", "@aws-sdk/lib-storage": "^3.282.0", + "@hocuspocus/provider": "^1.1.3", "formidable": "^2.1.1", "i18next": "^22.4.11", "mailgun.js": "^8.2.1" @@ -4327,6 +4328,28 @@ "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, + "node_modules/@hocuspocus/common": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@hocuspocus/common/-/common-1.1.3.tgz", + "integrity": "sha512-U5wQcMsVTooUKSqAq8m2bmMPWaVp78oTl1YFcJ2v3Dq0Wt1MBik3AohcnuUZ2JcP1fblf8lZVugCs9qg9mbu6g==", + "dependencies": { + "lib0": "^0.2.47" + } + }, + "node_modules/@hocuspocus/provider": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@hocuspocus/provider/-/provider-1.1.3.tgz", + "integrity": "sha512-8AYFM1q3ICEyK835USGskMsT/z9QgiJOqYz1IStR4OrC08RVBTEm0vDdtHx+5y3wxIMg22tHQL7ubghWRj3BPg==", + "dependencies": { + "@hocuspocus/common": "^1.1.3", + "@lifeomic/attempt": "^3.0.2", + "lib0": "^0.2.46" + }, + "peerDependencies": { + "y-protocols": "^1.0.5", + "yjs": "^13.5.29" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -5233,6 +5256,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@lifeomic/attempt": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@lifeomic/attempt/-/attempt-3.0.3.tgz", + "integrity": "sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==" + }, "node_modules/@linaria/core": { "version": "3.0.0-beta.13", "resolved": "https://registry.npmjs.org/@linaria/core/-/core-3.0.0-beta.13.tgz", @@ -12678,7 +12706,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", - "dev": true, "funding": { "type": "GitHub Sponsors ❤", "url": "https://github.com/sponsors/dmonad" @@ -15037,7 +15064,6 @@ "version": "0.2.73", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.73.tgz", "integrity": "sha512-aJJIElCLWnHMcYZPtsM07QoSfHwpxCy4VUzBYGXFYEmh/h2QS5uZNbCCfL0CqnkOE30b7Tp9DVfjXag+3qzZjQ==", - "dev": true, "dependencies": { "isomorphic.js": "^0.2.4" }, @@ -23358,7 +23384,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.5.tgz", "integrity": "sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==", - "dev": true, "dependencies": { "lib0": "^0.2.42" }, @@ -23560,7 +23585,6 @@ "version": "13.5.51", "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.5.51.tgz", "integrity": "sha512-F1Nb3z3TdandD80IAeQqgqy/2n9AhDLcXoBhZvCUX1dNVe0ef7fIwi6MjSYaGAYF2Ev8VcLcsGnmuGGOl7AWbw==", - "dev": true, "dependencies": { "lib0": "^0.2.72" }, @@ -26746,6 +26770,24 @@ "dev": true, "requires": {} }, + "@hocuspocus/common": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@hocuspocus/common/-/common-1.1.3.tgz", + "integrity": "sha512-U5wQcMsVTooUKSqAq8m2bmMPWaVp78oTl1YFcJ2v3Dq0Wt1MBik3AohcnuUZ2JcP1fblf8lZVugCs9qg9mbu6g==", + "requires": { + "lib0": "^0.2.47" + } + }, + "@hocuspocus/provider": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@hocuspocus/provider/-/provider-1.1.3.tgz", + "integrity": "sha512-8AYFM1q3ICEyK835USGskMsT/z9QgiJOqYz1IStR4OrC08RVBTEm0vDdtHx+5y3wxIMg22tHQL7ubghWRj3BPg==", + "requires": { + "@hocuspocus/common": "^1.1.3", + "@lifeomic/attempt": "^3.0.2", + "lib0": "^0.2.46" + } + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -27433,6 +27475,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@lifeomic/attempt": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@lifeomic/attempt/-/attempt-3.0.3.tgz", + "integrity": "sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==" + }, "@linaria/core": { "version": "3.0.0-beta.13", "resolved": "https://registry.npmjs.org/@linaria/core/-/core-3.0.0-beta.13.tgz", @@ -32850,8 +32897,7 @@ "isomorphic.js": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", - "dev": true + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -34606,7 +34652,6 @@ "version": "0.2.73", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.73.tgz", "integrity": "sha512-aJJIElCLWnHMcYZPtsM07QoSfHwpxCy4VUzBYGXFYEmh/h2QS5uZNbCCfL0CqnkOE30b7Tp9DVfjXag+3qzZjQ==", - "dev": true, "requires": { "isomorphic.js": "^0.2.4" } @@ -40594,7 +40639,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.5.tgz", "integrity": "sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==", - "dev": true, "requires": { "lib0": "^0.2.42" } @@ -40735,7 +40779,6 @@ "version": "13.5.51", "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.5.51.tgz", "integrity": "sha512-F1Nb3z3TdandD80IAeQqgqy/2n9AhDLcXoBhZvCUX1dNVe0ef7fIwi6MjSYaGAYF2Ev8VcLcsGnmuGGOl7AWbw==", - "dev": true, "requires": { "lib0": "^0.2.72" } diff --git a/package.json b/package.json index 4ae9066f..02c6986f 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@aws-sdk/abort-controller": "^3.272.0", "@aws-sdk/client-s3": "^3.282.0", "@aws-sdk/lib-storage": "^3.282.0", + "@hocuspocus/provider": "^1.1.3", "formidable": "^2.1.1", "i18next": "^22.4.11", "mailgun.js": "^8.2.1" diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index d01bd33a..f0940c83 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -37,6 +37,7 @@ import './Prosemirror.scss' import { IndexeddbPersistence } from 'y-indexeddb' import { useSession } from '../../context/session' import uniqolor from 'uniqolor' +import { HocuspocusProvider } from '@hocuspocus/provider' type EditorProps = { shoutId: number @@ -46,19 +47,23 @@ type EditorProps = { const yDoc = new Y.Doc() const persisters: Record = {} -const providers: Record = {} +const providers: Record = {} export const Editor = (props: EditorProps) => { const { t } = useLocalize() const { user } = useSession() const docName = `shout-${props.shoutId}` - // if (!persisters[docName]) { - // persisters[docName] = new IndexeddbPersistence(docName, yDoc) - // } + if (!persisters[docName]) { + persisters[docName] = new IndexeddbPersistence(docName, yDoc) + } if (!providers[docName]) { - providers[docName] = new WebrtcProvider(docName, yDoc) + providers[docName] = new HocuspocusProvider({ + url: 'ws://v2.discours.io:4242', + name: docName, + document: yDoc + }) } const editorElRef: { diff --git a/src/components/Editor/Prosemirror.scss b/src/components/Editor/Prosemirror.scss index 23c12835..03ca073c 100644 --- a/src/components/Editor/Prosemirror.scss +++ b/src/components/Editor/Prosemirror.scss @@ -20,3 +20,30 @@ line-height: 30px; opacity: 0.3; } + +/* Give a remote user a caret */ +.collaboration-cursor__caret { + border-left: 1px solid #0d0d0d; + border-right: 1px solid #0d0d0d; + margin-left: -1px; + margin-right: -1px; + pointer-events: none; + position: relative; + word-break: normal; +} + +/* Render the username above the caret */ +.collaboration-cursor__label { + border-radius: 3px 3px 3px 0; + color: #0d0d0d; + font-size: 12px; + font-style: normal; + font-weight: 600; + left: -1px; + line-height: normal; + padding: 0.1rem 0.3rem; + position: absolute; + top: -1.4em; + user-select: none; + white-space: nowrap; +}