From ab5dec661e212e8742f9ac211f32721bc473fd47 Mon Sep 17 00:00:00 2001 From: john <johnbarlas39@gmail.com> Date: Fri, 30 Dec 2016 00:25:11 +0200 Subject: [PATCH] add and delete refactored --- .../SimpleEditor/ContainerEditor.js | 69 +--- .../track_change/TrackChangesProvider.js | 340 ++++++++++++++---- 2 files changed, 280 insertions(+), 129 deletions(-) diff --git a/app/components/SimpleEditor/ContainerEditor.js b/app/components/SimpleEditor/ContainerEditor.js index 8d5ccc2..4eb554e 100644 --- a/app/components/SimpleEditor/ContainerEditor.js +++ b/app/components/SimpleEditor/ContainerEditor.js @@ -73,72 +73,39 @@ class ContainerEditor extends SubstanceContainerEditor { } onTextInput (event) { - // console.log(this.context) + if (!this.props.trackChanges) return super.onTextInput(event) + event.preventDefault() event.stopPropagation() if (!event.data) return this._state.skipNextObservation = true - if (!this.props.trackChanges) { - this.transaction(function (tx, args) { - if (this.domSelection) this.domSelection.clear() - args.text = event.data - return this.insertText(tx, args) - }.bind(this), { action: 'type' }) - return - } - const trackChangesProvider = this.context.trackChangesProvider - const status = 'add' - trackChangesProvider.handleTransaction(event, status) - - // const isSelCollapsed = this.getSelection().isCollapsed() - // if (!isSelCollapsed) { - // const trackChangesProvider = this.context.trackChangesProvider - // const status = 'delete' - // trackChangesProvider.handleTransaction(status) - // } - // - // this.transaction(function (tx, args) { - // if (this.domSelection) this.domSelection.clear() - // args.text = event.data - // return this.insertText(tx, args) - // }.bind(this), { action: 'type' }) - // - // // don't rewrite the above, call it with super - // if (this.props.trackChanges) { - // const status = 'add' - // trackChangesProvider.handleTransaction(status) - // } + const options = { + event: event, + status: 'add' + } + trackChangesProvider.handleTransaction(options) } _handleDeleteKey (event) { + if (!this.props.trackChanges) return super._handleDeleteKey(event) + event.preventDefault() event.stopPropagation() - let direction = (event.keyCode === keys.BACKSPACE) ? 'left' : 'right' - - if (this.props.trackChanges) { - const trackChangesProvider = this.context.trackChangesProvider - const status = 'delete' - trackChangesProvider.handleTransaction(event, status, direction) - } else { - this.transaction(function (tx, args) { - args.direction = direction - return this.delete(tx, args) - }.bind(this), { action: 'delete' }) + + // TODO -- needed? + const direction = (event.keyCode === keys.BACKSPACE) ? 'left' : 'right' + + const trackChangesProvider = this.context.trackChangesProvider + const options = { + direction: direction, + status: 'delete' } + trackChangesProvider.handleTransaction(options) } - // delete (tx, args) { - // let sel = args.selection - // if (!sel.isCollapsed()) { - // return deleteSelection(tx, args) - // } else if (sel.isPropertySelection() || sel.isNodeSelection()) { - // return deleteCharacter(tx, args) - // } - // } - // create an empty paragraph with an empty node // then select it for cursor focus createText () { diff --git a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js index 4325616..032bd81 100644 --- a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js +++ b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js @@ -1,5 +1,15 @@ -import { keys, last } from 'lodash' -import { createAnnotation, expandAnnotation } from 'substance' +import { + filter, + find, + keys, + last +} from 'lodash' + +import { + createAnnotation, + expandAnnotation, + truncateAnnotation +} from 'substance' class TrackChangesProvider { constructor (config) { @@ -7,22 +17,94 @@ class TrackChangesProvider { this.config.documentSession.on('didUpdate', this.handleUndoRedo, this) } - handleTransaction (event, status) { - if (status === 'add') { - const isSelCollapsed = this.isSelectionCollapsed() - if (!isSelCollapsed) { - const options = { 'deleteCollapsed': true } - this.createDeletionAnnotation(options) - } + handleTransaction (options) { + // const status = options.status + + this.handleAdd(options) + this.handleDelete(options) + // if (this.shouldDelete(status)) this.delete() + } + + handleAdd (options) { + const { event, status } = options + if (status !== 'add') return + + const isSelectionCollapsed = this.isSelectionCollapsed() + const mode = this.getMode() + + let selection + + if (isSelectionCollapsed) { this.insertText(event) - this.createAdditionAnnotation() + if (mode) return + selection = this.setSelectionPlusOne('left') + this.createAddAnnotation(selection) + this.moveCursorTo('end') return } + } + + handleDelete (options) { + const { status } = options + if (status !== 'delete') return - if (status === 'delete') { - this.createDeletionAnnotation() + const mode = this.getMode() + let selection + + if (!mode) { + selection = this.setSelectionPlusOne('left') + this.createDeleteAnnotation(selection) + this.moveCursorTo('start') return } + if (mode === 'delete') { + selection = this.setSelectionPlusOne('left') + const annotation = this.getAnnotationByStatus('delete') + this.expandTrackAnnotation(selection, annotation) + this.moveCursorTo('start') + } + + // const isSelectionCollapsed = this.isSelectionCollapsed() + + // if (!this.isSelectionCollapsed()) options.deleteCollapsed = true + // this.createDeletionAnnotation(options) + } + + // expand annotation + // truncate annotation + + createAddAnnotation (selection) { + this.createTrackAnnotation(selection, 'add') + } + + createDeleteAnnotation (selection) { + this.createTrackAnnotation(selection, 'delete') + } + + createTrackAnnotation (selection, status) { + const surface = this.getSurface() + + surface.transaction((tx, args) => { + const newNode = { + selection: selection, + node: { + status: status, + type: 'track-change' + } + } + createAnnotation(tx, newNode) + }) + } + + expandTrackAnnotation (selection, annotation) { + const surface = this.getSurface() + + surface.transaction((tx, args) => { + args.selection = selection + args.anno = annotation + + expandAnnotation(tx, args) + }) } insertText (event) { @@ -34,15 +116,13 @@ class TrackChangesProvider { }, { action: 'type' }) } - onDeleteAnnotation () { - const anno = this.getExistingAnnotation() - const isDelete = (anno.status === 'delete') - return isDelete - } - createAdditionAnnotation () { const mode = this.getMode() - const onDelete = this.onDeleteAnnotation() + const onDelete = this.isOnAnnotation('delete') + // const onAdd = this.isOnAnnotation('add') + // console.log('mode', mode) + // console.log('on delete', onDelete) + // console.log('on add', onAdd) if (mode && !onDelete) return const surface = this.getSurface() @@ -65,54 +145,34 @@ class TrackChangesProvider { const info = {} surface.transaction(transformation, info) - surface.transaction((tx, args) => { - if (onDelete) { - // console.log(this.getAllExistingAnnotations()) - const annos = this.getAllExistingAnnotations() - const deleteAnno = annos.find((obj) => { - // console.log(obj) - return obj.type === 'track-change' && obj.status === 'delete' - }) - const addAnno = annos.find((obj) => { - // console.log(obj) - return obj.type === 'track-change' && obj.status === 'add' - }) - // console.log(deleteAnno) - deleteAnno.updateRange(tx, { - start: { - startPath: deleteAnno.startPath, - offset: deleteAnno.startOffset - }, - end: { - offset: addAnno.startOffset - } - }) - // deleteAnno.endOffset = addAnno.startOffset - // console.log(deleteAnno) - } - }) - } + if (onDelete) { + this.separateAnnotations() + } - getExistingAnnotation () { - const documentSession = this.getDocumentSession() - const selectionState = documentSession.getSelectionState() - const annotations = selectionState.getAnnotationsForType('track-change') - return annotations[0] + // if (onAdd) { + // + // } } - getAllExistingAnnotations () { - const documentSession = this.getDocumentSession() - const selectionState = documentSession.getSelectionState() - const annotations = selectionState.getAnnotationsForType('track-change') - return annotations + separateAnnotations () { + console.log('separate') + const surface = this.getSurface() + const deleteAnnotation = this.getAnnotationByStatus('delete') + const addAnnotation = this.getAnnotationByStatus('add') + console.log('delete anno', deleteAnnotation) + console.log('add anno', addAnnotation) + + surface.transaction((tx, args) => { + args.anno = deleteAnnotation + args.selection = addAnnotation.getSelection() + truncateAnnotation(tx, args) + }) } createDeletionAnnotation (options) { - let deleteCollapsed - if (options && options.deleteCollapsed) deleteCollapsed = true - - const surface = this.getSurface() + const deleteCollapsed = options.deleteCollapsed const mode = this.getMode() + const surface = this.getSurface() const transformation = (tx, args) => { let selection = args.selection @@ -141,13 +201,90 @@ class TrackChangesProvider { surface.transaction(transformation, info) } - isSelectionCollapsed () { - const surface = this.getSurface() - const selection = surface.getSelection() - const isCollapsed = selection.isCollapsed() - return isCollapsed + /* + + DECISION MAKERS + + */ + + shouldAdd (status) { + if (status !== 'add') return false + + const mode = this.getMode() + if (mode) return false + + return true } + shouldDelete (status) { + if (status === 'delete') return true + + console.log(status) + console.log(this.isSelectionCollapsed()) + if (status === 'create' && !this.isSelectionCollapsed()) return true + return false + } + + // shouldExpand () { + // + // } + + // shouldTruncate () { + // + // } + + /* + + ANNOTATION HELPERS + + */ + + // is on left edge + // is on right edge + // is annotation from the same user + + // TODO -- handle multiple delete and add annotations + getAnnotationByStatus (status) { + const annotations = this.getAllExistingTrackAnnotations() + console.log('annos', annotations) + const annos = filter(annotations, (annotation) => { + return annotation.status === status + }) + return annos[0] + } + + getExistingAnnotation () { + const documentSession = this.getDocumentSession() + const selectionState = documentSession.getSelectionState() + const annotations = selectionState.getAnnotationsForType('track-change') + console.log(annotations) + return annotations[0] + } + + getAllExistingTrackAnnotations () { + const documentSession = this.getDocumentSession() + const selectionState = documentSession.getSelectionState() + const annotations = selectionState.getAnnotationsForType('track-change') + return annotations + } + + // returns whether the selection is on an add / delete tracked change + isOnAnnotation (status) { + const annotations = this.getAllExistingTrackAnnotations() + const annotation = find(annotations, (annotation) => { + return annotation.status === status + }) + + if (!annotation) return false + return true + } + + /** + + HISTORY HANDLERS + + */ + // TODO -- shouldn't run both all the time handleUndoRedo (update, info) { if (!info.replay) return @@ -185,14 +322,40 @@ class TrackChangesProvider { console.log(isTrack) } - // removeAnnotationFromHistory () { - // const documentSession = this.getDocumentSession() - // // console.log(documentSession.doneChanges) - // setTimeout(() => { - // console.log(documentSession.doneChanges[1].toJSON()) - // // documentSession.doneChanges.pop() - // }) // ensure that text insertion has finished - // } + /* + + SELECTION HANDLERS + + */ + + // get delete direction + // is part of the selection outside the annotation + // move cursor to + + setSelectionPlusOne (direction) { + const selection = this.getSelection() + + if (direction === 'left') selection.startOffset -= 1 + if (direction === 'right') selection.endOffset += 1 + + return selection + } + + moveCursorTo (point) { + const selection = this.getSelection() + const surface = this.getSurface() + + if (point === 'start') { + selection.endOffset = selection.startOffset + } else if (point === 'end') { + selection.startOffset = selection.endOffset + } else { + selection.startOffset = point + selection.endOffset = point + } + + surface.setSelection(selection) + } clearSelection (args, status) { const selection = args.selection @@ -213,14 +376,29 @@ class TrackChangesProvider { return selection } + isSelectionCollapsed () { + const selection = this.getSelection() + const isCollapsed = selection.isCollapsed() + return isCollapsed + } + + /* + + GETTERS + + */ + getCommandManager () { return this.config.commandManager } - getTrackState () { + getCommandStates () { const commandManager = this.getCommandManager() - const commandStates = commandManager.getCommandStates() - return commandStates['track-change'] + return commandManager.getCommandStates() + } + + getDocumentSession () { + return this.config.documentSession } getMode () { @@ -228,8 +406,9 @@ class TrackChangesProvider { return state.mode } - getDocumentSession () { - return this.config.documentSession + getSelection () { + const surface = this.getSurface() + return surface.getSelection() } getSurface () { @@ -238,6 +417,11 @@ class TrackChangesProvider { return surfaceManager.getSurface(id) } + + getTrackState () { + const commandStates = this.getCommandStates() + return commandStates['track-change'] + } } export default TrackChangesProvider -- GitLab