add command to update username and color, add UI to show other users

This commit is contained in:
Hans Pagel 2020-09-26 17:35:07 +02:00
parent 0597936ab8
commit 79113aa394
3 changed files with 124 additions and 8 deletions

View File

@ -1,9 +1,33 @@
<template>
<div>
<editor-content :editor="editor" />
<button @click="setName">
set username
</button>
<button @click="changeColor">
change color
</button>
<div class="collaboration-status">
{{ numberOfConnectedUsers }} user{{ numberOfConnectedUsers === 1 ? '' : 's' }}
{{ users.length }} user{{ numberOfConnectedUsers === 1 ? '' : 's' }}
</div>
<div class="collaboration-users">
<div
class="collaboration-users__item"
:style="`background-color: ${user.color}`"
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</div>
</div>
<editor-content :editor="editor" />
<div class="collaboration-debug">
name: {{ name }};
color: {{ color }};
bcPeers: {{ numberOfBcPeers }};
webRtcPeers: {{ numberOfWebRtcPeers }};
</div>
</div>
</template>
@ -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()

View File

@ -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;

View File

@ -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<CollaborationCursorOptions>()
.name('collaboration_cursor')
.commands(({ options }) => ({
user: attributes => () => {
options.provider.awareness.setLocalStateField('user', attributes)
return true
},
}))
.defaults({
provider: null,
name: 'Someone',