feat: success show cursor position

This commit is contained in:
cudr 2019-10-12 08:02:37 +03:00
parent 2a4d64b074
commit 4efc8db60e
6 changed files with 109 additions and 58 deletions

View File

@ -40,10 +40,18 @@ class Connection {
} }
private saveDoc = throttle(pathname => { private saveDoc = throttle(pathname => {
if (this.options.onDocumentSave) { try {
const doc = this.docSet.getDoc(pathname) if (this.options.onDocumentSave) {
const doc = this.docSet.getDoc(pathname)
this.options.onDocumentSave(pathname, toJS(doc)) const data = toJS(doc)
delete data.cursors
this.options.onDocumentSave(pathname, data)
}
} catch (e) {
console.log(e)
} }
}, (this.options && this.options.saveTreshold) || 2000) }, (this.options && this.options.saveTreshold) || 2000)

View File

@ -1,17 +1,17 @@
import { Operation, SyncDoc } from '../model' import { Operation, SyncDoc } from '../model'
export const addAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { export const addAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => {
console.log('addAnnotation!!!', op) console.log('addAnnotation!!!', op.toJS())
return doc return doc
} }
export const removeAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { export const removeAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => {
console.log('removeAnnotation!!!', op) console.log('removeAnnotation!!!', op.toJS())
return doc return doc
} }
export const setAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => { export const setAnnotation = (doc: SyncDoc, op: Operation): SyncDoc => {
console.log('setAnnotation!!!', op) console.log('setAnnotation!!!', op.toJS())
return doc return doc
} }

View File

@ -3,43 +3,19 @@ import { Operation, Operations, SyncDoc } from '../model'
import node from './node' import node from './node'
import mark from './mark' import mark from './mark'
import text from './text' import text from './text'
import selection from './selection'
import annotation from './annotation' import annotation from './annotation'
const setSelection = (doc, op, { id, selection }) => { const setSelection = doc => doc
console.log('selection', selection.toJSON()) const setValue = doc => doc
if (!doc.cursors) {
doc.cursors = {}
}
// console.log('setSelection', op.toJSON(), id)
const operation = op.toJSON()
if (!doc.cursors[id]) {
doc.cursors[id] = {
key: id,
type: 'collaborative_selection'
}
}
const cursor = doc.cursors[id]
const { focus, anchor } = operation.newProperties
if (focus) cursor.focus = focus
if (anchor) cursor.anchor = anchor
return doc
}
const setValue = (doc, op) => doc
const opType: any = { const opType: any = {
...text, ...text,
...annotation, ...annotation,
...node, ...node,
...mark, ...mark,
...selection
set_selection: setSelection, // set_value: setValue
set_value: setValue
} }
export const applyOperation = meta => ( export const applyOperation = meta => (
@ -49,7 +25,7 @@ export const applyOperation = meta => (
try { try {
const applyOp = opType[op.type] const applyOp = opType[op.type]
if (!applyOp) throw new TypeError('Invalid operation type!') if (!applyOp) throw new TypeError('Unsupported operation type!')
return applyOp(doc, op, meta) return applyOp(doc, op, meta)
} catch (e) { } catch (e) {

View File

@ -0,0 +1,35 @@
import { toJS } from '../utils'
const setSelection = (doc, op, { id, selection, annotationType }) => {
if (!doc.cursors) {
doc.cursors = {}
}
const operation = op.toJS()
if (!doc.cursors[id]) {
doc.cursors[id] = {
key: id,
type: annotationType,
data: {}
}
}
const cursor = doc.cursors[id]
const { focus, anchor } = operation.newProperties
if (focus) cursor.focus = focus
if (anchor) cursor.anchor = anchor
const cursorPath = (anchor && anchor.path) || (focus && focus.path)
if (cursorPath) cursor.data.cursorPath = toJS(cursorPath)
cursor.data.isBackward = selection.isBackward
return doc
}
export default {
set_selection: setSelection
}

View File

@ -87,29 +87,23 @@ class Connection {
setCursors = cursors => { setCursors = cursors => {
if (!cursors) return if (!cursors) return
// console.log('setCursors', cursors)
const { const {
value: { annotations } value: { annotations }
} = this.editor } = this.editor
const keyMap = {} const keyMap = {}
console.log('cursors', cursors)
this.editor.withoutSaving(() => { this.editor.withoutSaving(() => {
annotations.forEach(anno => { annotations.forEach(anno => {
// if (cursors[anno.key]) {
// console.log('set cursor', anno, )
// this.editor.setAnnotation(anno, cursors[anno.key])
// keyMap[anno.key] = true
// } else {
// this.editor.removeAnnotation(anno)
// }
this.editor.removeAnnotation(anno) this.editor.removeAnnotation(anno)
}) })
Object.keys(cursors).forEach(key => { Object.keys(cursors).forEach(key => {
if (key !== this.socket.id && !keyMap[key]) { if (key !== this.socket.id && !keyMap[key]) {
this.editor.addAnnotation(cursors[key]) this.editor.addAnnotation(toJS(cursors[key]))
} }
}) })
}) })
@ -121,11 +115,42 @@ class Connection {
if (!doc) return if (!doc) return
const selectionOps = operations.filter(op => op.type === 'set_selection')
console.log('hasSelectionOps', selectionOps.size)
const { value } = this.editor
const { selection } = value
const meta = {
id: this.socket.id,
selection,
annotationType: 'collaborative_selection'
}
const cursor = doc.cursors[meta.id]
const cursorOffset = cursor && cursor.anchor && cursor.anchor.offset
if (!selectionOps.size && selection.start.offset !== cursorOffset) {
const opData = {
type: 'set_selection',
properties: {},
newProperties: {
anchor: selection.start,
focus: selection.end
}
}
const op = Operation.fromJSON(opData)
operations = operations.push(op)
}
console.log('operations', operations.toJSON())
const changed = Automerge.change(doc, message, (d: any) => const changed = Automerge.change(doc, message, (d: any) =>
applySlateOps(d, operations, { applySlateOps(d, operations, meta)
id: this.socket.id,
selection: this.editor.value.selection
})
) )
this.docSet.setDoc(this.docId, changed) this.docSet.setDoc(this.docId, changed)

View File

@ -15,23 +15,30 @@ const cursorStyleBase = {
} as any } as any
const renderAnnotation = (props, editor, next) => { const renderAnnotation = (props, editor, next) => {
const { children, annotation, attributes } = props const { children, annotation, attributes, node } = props
const isLeft = annotation.focus.offset >= annotation.anchor.offset const isBackward = annotation.data.get('isBackward')
const cursorPath = annotation.data.get('cursorPath')
console.log('isLeft', isLeft) const cursorStyles = { ...cursorStyleBase, left: isBackward ? '0%' : '100%' }
const cursorStyles = { ...cursorStyleBase, left: isLeft ? '0%' : '100%' } const { document } = editor.value
console.log('renderAnnotation', annotation.toJSON()) const targetNode = document.getNode(cursorPath)
const isTarget = targetNode && targetNode.key === node.key
const showCursor = isTarget
switch (annotation.type) { switch (annotation.type) {
case 'collaborative_selection': case 'collaborative_selection':
return ( return (
<span {...attributes} style={wrapStyles}> <span {...attributes} style={wrapStyles}>
<span contentEditable={false} style={cursorStyles}> {showCursor ? (
{annotation.key} <span contentEditable={false} style={cursorStyles}>
</span> {annotation.key}
</span>
) : null}
{children} {children}
</span> </span>
) )