From 79113aa394fb9d8a89fdf9285a29e8a30ad70011 Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Sat, 26 Sep 2020 17:35:07 +0200 Subject: [PATCH] add command to update username and color, add UI to show other users --- .../demos/Examples/Collaboration/index.vue | 92 +++++++++++++++++-- .../demos/Examples/Collaboration/style.scss | 20 ++++ .../extension-collaboration-cursor/index.ts | 20 +++- 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/docs/src/demos/Examples/Collaboration/index.vue b/docs/src/demos/Examples/Collaboration/index.vue index a00fc8eeb..50c298bb3 100644 --- a/docs/src/demos/Examples/Collaboration/index.vue +++ b/docs/src/demos/Examples/Collaboration/index.vue @@ -1,9 +1,33 @@ @@ -26,12 +50,17 @@ export default { data() { return { + name: 'Other User', + color: this.getRandomColor(), ydoc: null, provider: null, type: null, indexdb: null, numberOfConnectedUsers: 0, + numberOfBcPeers: 0, + numberOfWebRtcPeers: 0, editor: null, + users: [], } }, @@ -43,9 +72,7 @@ export default { this.type = this.ydoc.getXmlFragment('prosemirror') this.indexdb = new IndexeddbPersistence(documentName, this.ydoc) - this.provider.on('peers', ({ webrtcPeers }) => { - this.numberOfConnectedUsers = webrtcPeers.length - }) + this.provider.awareness.on('change', this.updateState) this.editor = new Editor({ // TODO: This is added by every new user. @@ -62,13 +89,64 @@ export default { }), CollaborationCursor({ provider: this.provider, - name: 'Other User', - color: '#d6336c', + name: this.name, + color: this.color, }), ], }) }, + methods: { + setName() { + this.name = window.prompt('Name') + this.updateUser() + }, + + changeColor() { + this.color = this.getRandomColor() + this.updateUser() + }, + + updateUser() { + this.editor.chain().focus().user({ + name: this.name, + color: this.color, + }).run() + + this.updateState() + }, + + getRandomColor() { + const colors = [ + '#f03e3e', + '#d6336c', + '#ae3ec9', + '#7048e8', + '#4263eb', + '#1c7ed6', + '#1098ad', + '#0ca678', + '#37b24d', + '#74b816', + '#f59f00', + '#f76707', + ] + + return colors[Math.floor(Math.random() * colors.length)] + }, + + updateState() { + const { states } = this.provider.awareness + + this.users = Array.from(states.entries()).map(state => { + return { + id: state[0], + ...state[1].user, + } + }) + }, + }, + beforeDestroy() { this.editor.destroy() this.provider.destroy() diff --git a/docs/src/demos/Examples/Collaboration/style.scss b/docs/src/demos/Examples/Collaboration/style.scss index 45408c848..f87ecf367 100644 --- a/docs/src/demos/Examples/Collaboration/style.scss +++ b/docs/src/demos/Examples/Collaboration/style.scss @@ -1,3 +1,23 @@ +.collaboration-users { + margin-top: 0.5rem; + &__item { + display: inline-block; + border-radius: 5px; + padding: 0.25rem 0.5rem; + color: white; + margin-right: 0.5rem; + margin-bottom: 0.5rem; + } +} + +.collaboration-debug { + background: #eee; + color: #666; + border-radius: 5px; + padding: 0.5rem 1rem; + margin-top: 1rem; +} + .collaboration-status { background: #eee; color: #666; diff --git a/packages/extension-collaboration-cursor/index.ts b/packages/extension-collaboration-cursor/index.ts index 287f56fd7..8fcd0fcf2 100644 --- a/packages/extension-collaboration-cursor/index.ts +++ b/packages/extension-collaboration-cursor/index.ts @@ -1,4 +1,4 @@ -import { Extension } from '@tiptap/core' +import { Extension, Command } from '@tiptap/core' import { yCursorPlugin } from 'y-prosemirror' export interface CollaborationCursorOptions { @@ -8,8 +8,26 @@ export interface CollaborationCursorOptions { render (user: { name: string, color: string }): HTMLElement, } +export type UserCommand = (attributes: { + name: string, + color: string, +}) => Command + +declare module '@tiptap/core/src/Editor' { + interface Commands { + user: UserCommand, + } +} + export default new Extension() .name('collaboration_cursor') + .commands(({ options }) => ({ + user: attributes => () => { + options.provider.awareness.setLocalStateField('user', attributes) + + return true + }, + })) .defaults({ provider: null, name: 'Someone',