From a787e3f8cef685e8aabe90e697531452cbb95512 Mon Sep 17 00:00:00 2001 From: john <johnbarlas39@gmail.com> Date: Fri, 31 Mar 2017 19:34:39 +0300 Subject: [PATCH] move all track changes selection helpers to their own file --- .../track_change/TrackChangesProvider.js | 200 +++--------------- .../track_change/utils/handlerHelpers.js | 24 ++- .../track_change/utils/historyHandlers.js | 39 ++++ .../track_change/utils/selectionHelpers.js | 42 +++- .../track_change/utils/transformations.js | 1 + 5 files changed, 125 insertions(+), 181 deletions(-) create mode 100644 app/components/SimpleEditor/elements/track_change/utils/historyHandlers.js diff --git a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js index bdf63bb..6ed4694 100644 --- a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js +++ b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js @@ -1,27 +1,16 @@ import { clone, - // each, - // filter, - // find, findIndex, includes, - keys, - // last, map, - // maxBy, - // minBy, pickBy, some, sortBy } from 'lodash' -import { - // annotationHelpers, - TOCProvider -} from 'substance' +import { TOCProvider } from 'substance' import { - // getAllAnnotationsByStatus, getAnnotationByStatus, isAnnotationFromTheSameUser, isNotOnTrackAnnotation, @@ -42,20 +31,26 @@ import { selectCharacterAndMarkDeleted } from './utils/handlerHelpers' +// import { handleUndoRedo } from './utils/historyHandlers' + +import { + isSelectionCollapsed, + isSelectionContainedWithin, + moveCursorTo, + updateSelection +} from './utils/selectionHelpers' + import { - // createTrackAnnotation, deleteCharacter, deleteSelection, - // expandTrackAnnotation, insertText, removeTrackAnnotation - // truncateTrackAnnotation } from './utils/transformations' class TrackChangesProvider extends TOCProvider { constructor (document, config) { super(document, config) - // config.documentSession.on('didUpdate', this.handleUndoRedo, this) + // config.documentSession.on('didUpdate', handleUndoRedo, this) // handle button actions const editor = this.config.controller @@ -75,7 +70,8 @@ class TrackChangesProvider extends TOCProvider { */ handleTransaction (options) { - options.editorSession = this.getEditorSession() + // options.editor = this.config.controller + options.editorSession = this.config.editorSession options.selection = this.getSelection() options.surface = this.getSurface() options.user = this.config.user @@ -89,15 +85,13 @@ class TrackChangesProvider extends TOCProvider { } handleAdd (options) { - const isSelectionCollapsed = this.isSelectionCollapsed() + const isCollapsed = isSelectionCollapsed(options) - if (isSelectionCollapsed) return this.handleAddCollapsed(options) - if (!isSelectionCollapsed) return this.handleAddNonCollapsed(options) + if (isCollapsed) return this.handleAddCollapsed(options) + if (!isCollapsed) return this.handleAddNonCollapsed(options) } handleAddCollapsed (options) { - // const { event } = options - const notOnTrack = isNotOnTrackAnnotation(options) const isOnAdd = isOnAnnotation(options, 'add') const isOnDelete = isOnAnnotation(options, 'delete') @@ -135,13 +129,13 @@ class TrackChangesProvider extends TOCProvider { const isOnLeftEdge = isSelectionOnLeftEdge(options, annotation) const isOnRightEdge = isSelectionOnRightEdge(options, annotation) - const withinAnnotation = this.isSelectionContainedWithin(annotation, true) + const withinAnnotation = isSelectionContainedWithin(options, annotation, true) // if contained within the delete annotation, move it to the edge, // insert character, set event to null so that the character does // not get inserted twice, and handle again if (withinAnnotation) { - this.moveCursorTo(annotation.endOffset) + moveCursorTo(options, annotation.end.offset) insertCharacterWithoutExpandingAnnotation(options, annotation) options.selection = this.getSelection() return this.handleAdd(options) @@ -169,18 +163,17 @@ class TrackChangesProvider extends TOCProvider { const shortenBy = deleteAllOwnAdditions(options, selection) const startOffset = selection.start.offset const endOffset = selection.end.offset - shortenBy - selection = this.updateSelection(selection, startOffset, endOffset) + selection = updateSelection(options, selection, startOffset, endOffset) options.selection = selection if (isOnDelete) { - // console.log('on delete') const annotation = getAnnotationByStatus(options, 'delete') - const withinAnnotation = this.isSelectionContainedWithin(annotation) + const withinAnnotation = isSelectionContainedWithin(options, annotation) if (withinAnnotation) { // if selection is wholly contained within a delete annotation, // move to the end of the annotation and handle again - this.moveCursorTo(annotation.endOffset) + moveCursorTo(options, annotation.end.offset) options.selection = this.getSelection() return this.handleAddCollapsed(options) } @@ -203,7 +196,7 @@ class TrackChangesProvider extends TOCProvider { handleDelete (options) { const { key, move } = options - const isSelectionCollapsed = this.isSelectionCollapsed() + const isCollapsed = isSelectionCollapsed(options) options.direction = { cursorTo: (move === 'left') ? 'start' : 'end', @@ -211,8 +204,8 @@ class TrackChangesProvider extends TOCProvider { move: move } - if (isSelectionCollapsed) return this.handleDeleteCollapsed(options) - if (!isSelectionCollapsed) return this.handleDeleteNonCollapsed(options) + if (isCollapsed) return this.handleDeleteCollapsed(options) + if (!isCollapsed) return this.handleDeleteNonCollapsed(options) } handleDeleteCollapsed (options) { @@ -273,7 +266,7 @@ class TrackChangesProvider extends TOCProvider { } if (moveOnly) { - return this.moveCursorTo(point) + return moveCursorTo(options, point) } if (isFromSameUser) { @@ -298,35 +291,23 @@ class TrackChangesProvider extends TOCProvider { const startOffset = selection.start.offset const endOffset = selection.end.offset - shortenBy - this.updateSelection(selection, startOffset, endOffset) + updateSelection(options, selection, startOffset, endOffset) // TODO -- validate that this is not needed // if (selection.isCollapsed()) return this.handleDeleteCollapsed(options) if (selection.isCollapsed()) return if (isOnDelete) { - // console.log const annotation = getAnnotationByStatus(options, 'delete') - const containedWithin = this.isSelectionContainedWithin(annotation) + const containedWithin = isSelectionContainedWithin(options, annotation) if (containedWithin) { const point = annotation[direction.cursorTo + 'Offset'] - return this.moveCursorTo(point) + return moveCursorTo(options, point) } - - // const selection = this.getSelection() - // this.expandTrackAnnotation(selection, annotation) - // - // const key = direction.key - // - // let point - // if (key === 'BACKSPACE') point = selection.startOffset - // if (key === 'DELETE') point = selection.endOffset - // this.moveCursorTo(point) } options.selection = deleteOrMergeAllOwnDeletions(options, selection) - // console.log(this.getSelection()) // options.selection = this.getSelection() markSelectionAsDeleted(options) } @@ -422,7 +403,7 @@ class TrackChangesProvider extends TOCProvider { const selection = annotation.getSelection() surface.editorSession.setSelection(selection) - this.moveCursorTo('start') + moveCursorTo({ surface }, 'start') } canAct () { @@ -431,121 +412,6 @@ class TrackChangesProvider extends TOCProvider { return some(accepted, (role) => includes(user.roles, role)) } - /** - - HISTORY HANDLERS - - */ - - // TODO -- shouldn't run both all the time - handleUndoRedo (update, info) { - if (!info.replay) return - // console.log('update', update) - // console.log('info', info) - // this.handleUndo(update) - // this.handleRedo(update) - } - - handleUndo (update) { - const deleted = update.change.deleted - const deletedLength = keys(deleted).length - - // console.log(keys(deleted)) - - if (deletedLength === 0) return - if (deletedLength > 1) { - return console.warn('FIXME: Multiple operations in track changes replay!') - } - - const deletedOp = deleted[keys(deleted)[0]] - if (!deletedOp.type === 'track-change') return - - const documentSession = this.getEditorSession() - documentSession.undo() - } - - handleRedo () { - // const documentSession = this.getEditorSession() - // const undoneChanges = documentSession.undoneChanges - // const lastChange = last(undoneChanges) - // const op = last(lastChange.ops) - // - // const isTrack = op.path[0].split('-').slice(0, -1).join('-') === 'track-change - } - - /* - - SELECTION HANDLERS - - */ - - // isAnnotationContainedWithinSelection (annotation, strict) { - // const selection = this.getSelection() - // const annotationSelection = annotation.getSelection() - // - // return selection.contains(annotationSelection, strict) - // } - - isSelectionCollapsed () { - const selection = this.getSelection() - const isCollapsed = selection.isCollapsed() - return isCollapsed - } - - // TODO -- refactor this and isAnnotationContainedWithinSelection into one - isSelectionContainedWithin (annotation, strict) { - const selection = this.getSelection() - // console.trace() - const annotationSelection = annotation.getSelection() - - return annotationSelection.contains(selection, strict) - - // const leftSide = (selection.startOffset < annotation.startOffset) - // const rightSide = (selection.endOffset > annotation.endOffset) - // - // if (leftSide || rightSide) return false - // return true - } - - moveCursorTo (point, sel) { - const selection = sel || this.getSelection() - const surface = this.getSurface() - - // TODO -- use substance's selection.collapse(direction) - if (point === 'start') { - selection.end.offset = selection.start.offset - } else if (point === 'end') { - selection.start.offset = selection.end.offset - } else { - selection.start.offset = point - selection.end.offset = point - } - - surface.editorSession.setSelection(selection) - } - - // setSelectionPlusOne (direction) { - // const selection = this.getSelection() - // const surface = this.getSurface() - // - // if (direction === 'left') selection.start.offset -= 1 - // if (direction === 'right') selection.end.offset += 1 - // - // surface.editorSession.setSelection(selection) - // - // return selection - // } - - updateSelection (selection, startOffset, endOffset) { - const surface = this.getSurface() - - selection.start.offset = startOffset - selection.end.offset = endOffset - - surface.editorSession.setSelection(selection) - return selection - } - /* GETTERS @@ -556,14 +422,6 @@ class TrackChangesProvider extends TOCProvider { return this.config.commandManager } - getCurrentUser () { - return this.config.user.id - } - - getEditorSession () { - return this.config.editorSession - } - getMode () { const trackState = this.getTrackState() return trackState.mode diff --git a/app/components/SimpleEditor/elements/track_change/utils/handlerHelpers.js b/app/components/SimpleEditor/elements/track_change/utils/handlerHelpers.js index 92f5df3..fee91d6 100644 --- a/app/components/SimpleEditor/elements/track_change/utils/handlerHelpers.js +++ b/app/components/SimpleEditor/elements/track_change/utils/handlerHelpers.js @@ -101,6 +101,8 @@ const deleteSelectedAndCreateAddition = (options) => { // selection is now collapsed, so handle it as collapsed options.status = 'add' + options.selection = getSelection(options.surface) + const provider = getProvider(options) provider.handleAddCollapsed(options) } @@ -132,18 +134,24 @@ const insertCharacterWithAddAnnotation = (options) => { } const insertCharacterWithoutExpandingAnnotation = (options, annotation) => { + // After text has been inserted, set the event to null to make sure it does + // not get added twice by a second iteration of the handlers. + // eg. if at the end of the logic path, handleAddCollapsed gets called + // that will assume that there is text still to be inserted insertText(options) + options.event = null - options.selection = getSelection(options.surface) - options.selection = setSelectionPlusOne(options, 'left') - // options.selection = selection - options.annotation = annotation - options.doc = options.editorSession.getDocument() + // Clone the options, to make sure that the annotation or the selection + // does not change while the truncate operation is in progress. + const opts = clone(options) - truncateTrackAnnotation(options) - moveCursorTo(options, 'end') + opts.selection = getSelection(opts.surface) + opts.selection = setSelectionPlusOne(opts, 'left') + opts.annotation = annotation + opts.doc = opts.editorSession.getDocument() // TODO -- should get from handler - options.event = null // ? + truncateTrackAnnotation(opts) + moveCursorTo(opts, 'end') } const markSelectionAsDeleted = (options) => { diff --git a/app/components/SimpleEditor/elements/track_change/utils/historyHandlers.js b/app/components/SimpleEditor/elements/track_change/utils/historyHandlers.js new file mode 100644 index 0000000..0d0a353 --- /dev/null +++ b/app/components/SimpleEditor/elements/track_change/utils/historyHandlers.js @@ -0,0 +1,39 @@ +// TODO -- shouldn't run both all the time +const handleUndoRedo = (update, info) => { + if (!info.replay) return + // console.log('update', update) + // console.log('info', info) + // this.handleUndo(update) + // this.handleRedo(update) +} + +// const handleUndo = (update) => { +// const deleted = update.change.deleted +// const deletedLength = keys(deleted).length +// +// // console.log(keys(deleted)) +// +// if (deletedLength === 0) return +// if (deletedLength > 1) { +// return console.warn('FIXME: Multiple operations in track changes replay!') +// } +// +// const deletedOp = deleted[keys(deleted)[0]] +// if (!deletedOp.type === 'track-change') return +// +// const documentSession = this.getEditorSession() +// documentSession.undo() +// } + +// const handleRedo = () => { +// // const documentSession = this.getEditorSession() +// // const undoneChanges = documentSession.undoneChanges +// // const lastChange = last(undoneChanges) +// // const op = last(lastChange.ops) +// // +// // const isTrack = op.path[0].split('-').slice(0, -1).join('-') === 'track-change +// } + +export { + handleUndoRedo +} diff --git a/app/components/SimpleEditor/elements/track_change/utils/selectionHelpers.js b/app/components/SimpleEditor/elements/track_change/utils/selectionHelpers.js index d803aad..0923d05 100644 --- a/app/components/SimpleEditor/elements/track_change/utils/selectionHelpers.js +++ b/app/components/SimpleEditor/elements/track_change/utils/selectionHelpers.js @@ -2,9 +2,34 @@ const getSelection = (surface) => { return surface.domSelection.getSelection() } +const isSelectionCollapsed = (options) => { + // const selection = this.getSelection() + const { selection } = options + const isCollapsed = selection.isCollapsed() + return isCollapsed +} + +// TODO -- refactor this and isAnnotationContainedWithinSelection into one +const isSelectionContainedWithin = (options, annotation, strict) => { + // const selection = this.getSelection() + const selection = getSelection(options.surface) + + const annotationSelection = annotation.getSelection() + + return annotationSelection.contains(selection, strict) + + // const leftSide = (selection.startOffset < annotation.startOffset) + // const rightSide = (selection.endOffset > annotation.endOffset) + // + // if (leftSide || rightSide) return false + // return true +} + const moveCursorTo = (options, point) => { // const selection = sel || this.getSelection() - const { selection, surface } = options + // const { selection, surface } = options + const { surface } = options + const selection = getSelection(surface) // const surface = this.getSurface() // TODO -- use substance's selection.collapse(direction) @@ -32,8 +57,21 @@ const setSelectionPlusOne = (options, direction) => { return selection } +const updateSelection = (options, selection, startOffset, endOffset) => { + const { surface } = options + + selection.start.offset = startOffset + selection.end.offset = endOffset + + surface.editorSession.setSelection(selection) + return selection +} + export { getSelection, + isSelectionCollapsed, + isSelectionContainedWithin, moveCursorTo, - setSelectionPlusOne + setSelectionPlusOne, + updateSelection } diff --git a/app/components/SimpleEditor/elements/track_change/utils/transformations.js b/app/components/SimpleEditor/elements/track_change/utils/transformations.js index 1d44240..abf3dd9 100644 --- a/app/components/SimpleEditor/elements/track_change/utils/transformations.js +++ b/app/components/SimpleEditor/elements/track_change/utils/transformations.js @@ -125,6 +125,7 @@ const truncateTrackAnnotation = options => { const info = getInfo() const transformation = (tx, args) => { + // console.log(selection) annotationHelpers.truncateAnnotation(doc, annotation, selection) } -- GitLab