diff --git a/docs/src/demos/Examples/CollaborativeEditing/index.vue b/docs/src/demos/Examples/CollaborativeEditing/index.vue index 5b5f11c0..47d0763e 100644 --- a/docs/src/demos/Examples/CollaborativeEditing/index.vue +++ b/docs/src/demos/Examples/CollaborativeEditing/index.vue @@ -71,29 +71,33 @@ - - -
- {{ users.length }} user{{ users.length === 1 ? '' : 's' }} -
- {{ user.name }} + {{ otherUser.name }}
+ +
+ + {{ users.length }} user{{ users.length === 1 ? '' : 's' }} online +
@@ -103,8 +107,13 @@ import Collaboration from '@tiptap/extension-collaboration' import CollaborationCursor from '@tiptap/extension-collaboration-cursor' import * as Y from 'yjs' import { WebrtcProvider } from 'y-webrtc' +// import { WebsocketProvider } from 'y-websocket' import { IndexeddbPersistence } from 'y-indexeddb' +const getRandomElement = list => { + return list[Math.floor(Math.random() * list.length)] +} + export default { components: { EditorContent, @@ -112,18 +121,26 @@ export default { data() { return { - name: this.getRandomName(), - color: this.getRandomColor(), + currentUser: { + name: this.getRandomName(), + color: this.getRandomColor(), + }, provider: null, indexdb: null, editor: null, users: [], + status: null, } }, mounted() { const ydoc = new Y.Doc() this.provider = new WebrtcProvider('tiptap-collaboration-example', ydoc) + // this.provider = new WebsocketProvider('ws://127.0.0.1:1234', 'tiptap-collaboration-example', ydoc) + this.provider.on('status', event => { + this.status = event.status + }) + this.indexdb = new IndexeddbPersistence('tiptap-collaboration-example', ydoc) this.editor = new Editor({ @@ -134,10 +151,7 @@ export default { }), CollaborationCursor.configure({ provider: this.provider, - user: { - name: this.name, - color: this.color, - }, + user: this.currentUser, onUpdate: users => { this.users = users }, @@ -151,32 +165,19 @@ export default { const name = window.prompt('Name') if (name) { - this.name = name - return this.updateUser() + return this.updateCurrentUser({ + name, + }) } }, - changeName() { - this.name = this.getRandomName() - this.updateUser() - }, - - changeColor() { - this.color = this.getRandomColor() - this.updateUser() - }, - - updateUser() { - this.editor.chain().focus().user({ - name: this.name, - color: this.color, - }).run() - - // this.updateState() + updateCurrentUser(attributes) { + this.currentUser = { ...this.currentUser, ...attributes } + this.editor.chain().focus().user(this.currentUser).run() }, getRandomColor() { - return this.getRandomElement([ + return getRandomElement([ '#616161', '#A975FF', '#FB5151', @@ -189,14 +190,10 @@ export default { }, getRandomName() { - return this.getRandomElement([ + return getRandomElement([ 'Lea Thompson', 'Cyndi Lauper', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder', 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John', 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey', 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet', ]) }, - - getRandomElement(list) { - return list[Math.floor(Math.random() * list.length)] - }, }, beforeDestroy() { @@ -223,21 +220,27 @@ export default { /* Some information about the status */ .collaboration-status { - background: #eee; - color: #666; border-radius: 5px; - padding: 0.5rem 1rem; margin-top: 1rem; + color: #616161; &::before { content: ' '; display: inline-block; width: 0.5rem; height: 0.5rem; - background: green; + background: #ccc; border-radius: 50%; margin-right: 0.5rem; } + + &--connecting::before { + background: #fd9170; + } + + &--connected::before { + background: #9DEF8F; + } } /* Give a remote user a caret */ diff --git a/docs/src/demos/Examples/CollaborativeEditingWs/index.vue b/docs/src/demos/Examples/CollaborativeEditingWs/index.vue deleted file mode 100644 index 1e2421bf..00000000 --- a/docs/src/demos/Examples/CollaborativeEditingWs/index.vue +++ /dev/null @@ -1,354 +0,0 @@ - - - - - diff --git a/docs/src/demos/Examples/CollaborativeEditingWs/server.js b/docs/src/demos/Examples/CollaborativeEditingWs/server.js deleted file mode 100644 index 7db8af28..00000000 --- a/docs/src/demos/Examples/CollaborativeEditingWs/server.js +++ /dev/null @@ -1,14 +0,0 @@ -/* -import { Server } from '@hocuspocus/server' -import { LevelDB } from '@hocuspocus/leveldb' - -const server = Server.configure({ - port: 1234, - - persistence: new LevelDB({ - path: './database', - }), -}) - -server.listen() -*/ diff --git a/docs/src/docPages/examples/collaborative-editing-ws.md b/docs/src/docPages/examples/collaborative-editing-ws.md deleted file mode 100644 index fd0ffe4a..00000000 --- a/docs/src/docPages/examples/collaborative-editing-ws.md +++ /dev/null @@ -1,5 +0,0 @@ -# Collaborative editing - -Websockets - - diff --git a/docs/src/docPages/examples/collaborative-editing.md b/docs/src/docPages/examples/collaborative-editing.md index 2af3c0b5..3ddfe3f0 100644 --- a/docs/src/docPages/examples/collaborative-editing.md +++ b/docs/src/docPages/examples/collaborative-editing.md @@ -1,14 +1,8 @@ # Collaborative editing -:::premium Requires Pro Extensions -We kindly ask you to sponsor us, before using this example in production. [Read more](/sponsor) -::: +This example shows how you can use tiptap to let multiple users collaborate in the same document in real-time. -This example shows how you can use tiptap to let different users collaboratively work on the same text in real-time. - -It connects client with WebRTC and merges changes to the document (no matter where they come from) with the awesome library [Y.js](https://github.com/yjs/yjs) by Kevin Jahns. Be aware that in a real-world scenario you would probably add a server, which is also able to merge changes with Y.js. - -If you want to learn more about collaborative text editing, [check out our guide on that topic](/guide/collaborative-editing). Anyway, it’s showtime now: +It connects all clients to a WebSocket server and merges changes to the document with the power of [Y.js](https://github.com/yjs/yjs). If you want to learn more about collaborative text editing, check out [our guide on collaborative editing](/guide/collaborative-editing). :::warning Shared Document Be nice! The content of this editor is shared with other users from the Internet. diff --git a/docs/src/links.yaml b/docs/src/links.yaml index 17ac6409..3ce72e60 100644 --- a/docs/src/links.yaml +++ b/docs/src/links.yaml @@ -20,9 +20,6 @@ - title: Collaborative editing link: /examples/collaborative-editing pro: true - - title: Collaborative editing 🚧 - link: /examples/collaborative-editing-ws - draft: true - title: Markdown shortcuts link: /examples/markdown-shortcuts # - title: Formatting diff --git a/packages/extension-collaboration-cursor/src/index.ts b/packages/extension-collaboration-cursor/src/index.ts index fb97257e..785a2e1f 100644 --- a/packages/extension-collaboration-cursor/src/index.ts +++ b/packages/extension-collaboration-cursor/src/index.ts @@ -46,7 +46,8 @@ const CollaborationCursor = Extension.create({ * Update details of the current user */ user: (attributes: { [key: string]: any }): Command => () => { - this.options.provider.awareness.setLocalStateField('user', attributes) + this.options.user = attributes + this.options.provider.awareness.setLocalStateField('user', this.options.user) this.options.onUpdate(awarenessStatesToArray(this.options.provider.awareness.states)) return true