mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Create comments via comment ops
This commit is contained in:
parent
898277b4af
commit
5717cafcec
6 changed files with 71 additions and 48 deletions
|
@ -41,6 +41,8 @@ define [
|
|||
editorDoc = @ace?.getSession().getDocument()
|
||||
editorDoc?.off "change", @_checkConsistency
|
||||
@ide.$scope.$emit 'document:closed', @doc
|
||||
|
||||
submitOp: (args...) -> @doc?.submitOp(args...)
|
||||
|
||||
_checkConsistency: () ->
|
||||
# We've been seeing a lot of errors when I think there shouldn't be
|
||||
|
|
|
@ -61,6 +61,7 @@ define [
|
|||
@_doc._onMessage message
|
||||
catch error
|
||||
# Version mismatches are thrown as errors
|
||||
console.log error
|
||||
@_handleError(error)
|
||||
|
||||
if message?.meta?.type == "external"
|
||||
|
|
|
@ -20,8 +20,8 @@ define [
|
|||
@rangesTracker = doc.ranges
|
||||
@connectToRangesTracker()
|
||||
|
||||
@$scope.$on "comment:add", (e, comment) =>
|
||||
@addCommentToSelection(comment)
|
||||
@$scope.$on "comment:add", (e) =>
|
||||
@addCommentToSelection()
|
||||
|
||||
@$scope.$on "comment:select_line", (e) =>
|
||||
@selectLineIfNoSelection()
|
||||
|
@ -146,21 +146,16 @@ define [
|
|||
for comment in @rangesTracker.comments
|
||||
@_onCommentAdded(comment)
|
||||
|
||||
addComment: (offset, length, content) ->
|
||||
@rangesTracker.addComment offset, length, {
|
||||
thread: [{
|
||||
content: content
|
||||
user_id: window.user_id
|
||||
ts: new Date()
|
||||
}]
|
||||
}
|
||||
addComment: (offset, content) ->
|
||||
op = { c: content, p: offset }
|
||||
# @rangesTracker.applyOp op # Will apply via sharejs
|
||||
@$scope.sharejsDoc.submitOp op
|
||||
|
||||
addCommentToSelection: (content) ->
|
||||
addCommentToSelection: () ->
|
||||
range = @editor.getSelectionRange()
|
||||
content = @editor.getSelectedText()
|
||||
offset = @_aceRangeToShareJs(range.start)
|
||||
end = @_aceRangeToShareJs(range.end)
|
||||
length = end - offset
|
||||
@addComment(offset, length, content)
|
||||
@addComment(offset, content)
|
||||
|
||||
selectLineIfNoSelection: () ->
|
||||
if @editor.selection.isEmpty()
|
||||
|
@ -201,6 +196,7 @@ define [
|
|||
@rangesTracker.unresolveCommentId(comment_id)
|
||||
|
||||
checkMapping: () ->
|
||||
# TODO: reintroduce this check
|
||||
session = @editor.getSession()
|
||||
|
||||
# Make a copy of session.getMarkers() so we can modify it
|
||||
|
@ -224,8 +220,8 @@ define [
|
|||
for comment in @rangesTracker.comments
|
||||
if @changeIdToMarkerIdMap[comment.id]?
|
||||
{background_marker_id, callout_marker_id} = @changeIdToMarkerIdMap[comment.id]
|
||||
start = @_shareJsOffsetToAcePosition(comment.offset)
|
||||
end = @_shareJsOffsetToAcePosition(comment.offset + comment.length)
|
||||
start = @_shareJsOffsetToAcePosition(comment.op.p)
|
||||
end = @_shareJsOffsetToAcePosition(comment.op.p + comment.op.c.length)
|
||||
expected_markers.push { marker_id: background_marker_id, start, end }
|
||||
expected_markers.push { marker_id: callout_marker_id, start, end: start }
|
||||
|
||||
|
@ -341,8 +337,8 @@ define [
|
|||
_onCommentAdded: (comment) ->
|
||||
if !@changeIdToMarkerIdMap[comment.id]?
|
||||
# Only create new markers if they don't already exist
|
||||
start = @_shareJsOffsetToAcePosition(comment.offset)
|
||||
end = @_shareJsOffsetToAcePosition(comment.offset + comment.length)
|
||||
start = @_shareJsOffsetToAcePosition(comment.op.p)
|
||||
end = @_shareJsOffsetToAcePosition(comment.op.p + comment.op.c.length)
|
||||
session = @editor.getSession()
|
||||
doc = session.getDocument()
|
||||
background_range = new Range(start.row, start.column, end.row, end.column)
|
||||
|
@ -387,8 +383,8 @@ define [
|
|||
@broadcastChange()
|
||||
|
||||
_onCommentMoved: (comment) ->
|
||||
start = @_shareJsOffsetToAcePosition(comment.offset)
|
||||
end = @_shareJsOffsetToAcePosition(comment.offset + comment.length)
|
||||
start = @_shareJsOffsetToAcePosition(comment.op.p)
|
||||
end = @_shareJsOffsetToAcePosition(comment.op.p + comment.op.c.length)
|
||||
@_updateMarker(comment.id, start, end)
|
||||
@editor.renderer.updateBackMarkers()
|
||||
@broadcastChange()
|
||||
|
|
|
@ -28,5 +28,5 @@ text.api =
|
|||
for component in op
|
||||
if component.i != undefined
|
||||
@emit 'insert', component.p, component.i
|
||||
else
|
||||
else if component.d != undefined
|
||||
@emit 'delete', component.p, component.d
|
||||
|
|
|
@ -48,15 +48,6 @@ load = (EventEmitter) ->
|
|||
# sync with Ace ranges.
|
||||
@id = 0
|
||||
|
||||
addComment: (offset, length, metadata) ->
|
||||
# TODO: Don't allow overlapping comments?
|
||||
@comments.push comment = {
|
||||
id: @_newId()
|
||||
offset, length, metadata
|
||||
}
|
||||
@emit "comment:added", comment
|
||||
return comment
|
||||
|
||||
getComment: (comment_id) ->
|
||||
comment = null
|
||||
for c in @comments
|
||||
|
@ -97,7 +88,7 @@ load = (EventEmitter) ->
|
|||
return if !change?
|
||||
@_removeChange(change)
|
||||
|
||||
applyOp: (op, metadata) ->
|
||||
applyOp: (op, metadata = {}) ->
|
||||
metadata.ts ?= new Date()
|
||||
# Apply an op that has been applied to the document to our changes to keep them up to date
|
||||
if op.i?
|
||||
|
@ -106,14 +97,32 @@ load = (EventEmitter) ->
|
|||
else if op.d?
|
||||
@applyDeleteToChanges(op, metadata)
|
||||
@applyDeleteToComments(op)
|
||||
else if op.c?
|
||||
@addComment(op, metadata)
|
||||
else
|
||||
throw new Error("unknown op type")
|
||||
|
||||
addComment: (op, metadata) ->
|
||||
# TODO: Don't allow overlapping comments?
|
||||
@comments.push comment = {
|
||||
id: @_newId()
|
||||
op: # Copy because we'll modify in place
|
||||
c: op.c
|
||||
p: op.p
|
||||
t: op.t
|
||||
metadata
|
||||
}
|
||||
@emit "comment:added", comment
|
||||
return comment
|
||||
|
||||
applyInsertToComments: (op) ->
|
||||
for comment in @comments
|
||||
if op.p <= comment.offset
|
||||
comment.offset += op.i.length
|
||||
if op.p <= comment.op.p
|
||||
comment.op.p += op.i.length
|
||||
@emit "comment:moved", comment
|
||||
else if op.p < comment.offset + comment.length
|
||||
comment.length += op.i.length
|
||||
else if op.p < comment.op.p + comment.op.c.length
|
||||
offset = op.p - comment.op.p
|
||||
comment.op.c = comment.op.c[0..(offset-1)] + op.i + comment.op.c[offset...]
|
||||
@emit "comment:moved", comment
|
||||
|
||||
applyDeleteToComments: (op) ->
|
||||
|
@ -121,20 +130,35 @@ load = (EventEmitter) ->
|
|||
op_length = op.d.length
|
||||
op_end = op.p + op_length
|
||||
for comment in @comments
|
||||
comment_end = comment.offset + comment.length
|
||||
if op_end <= comment.offset
|
||||
comment_start = comment.op.p
|
||||
comment_end = comment.op.p + comment.op.c.length
|
||||
comment_length = comment_end - comment_start
|
||||
if op_end <= comment_start
|
||||
# delete is fully before comment
|
||||
comment.offset -= op_length
|
||||
comment.op.p -= op_length
|
||||
@emit "comment:moved", comment
|
||||
else if op_start >= comment_end
|
||||
# delete is fully after comment, nothing to do
|
||||
else
|
||||
# delete and comment overlap
|
||||
delete_length_before = Math.max(0, comment.offset - op_start)
|
||||
delete_length_after = Math.max(0, op_end - comment_end)
|
||||
delete_length_overlapping = op_length - delete_length_before - delete_length_after
|
||||
comment.offset = Math.min(comment.offset, op_start)
|
||||
comment.length -= delete_length_overlapping
|
||||
if op_start <= comment_start
|
||||
remaining_before = ""
|
||||
else
|
||||
remaining_before = comment.op.c.slice(0, op_start - comment_start)
|
||||
if op_end >= comment_end
|
||||
remaining_after = ""
|
||||
else
|
||||
remaining_after = comment.op.c.slice(op_end - comment_start)
|
||||
|
||||
# Check deleted content matches delete op
|
||||
deleted_comment = comment.op.c.slice(remaining_before.length, comment_length - remaining_after.length)
|
||||
offset = Math.max(0, comment_start - op_start)
|
||||
deleted_op_content = op.d.slice(offset).slice(0, deleted_comment.length)
|
||||
if deleted_comment != deleted_op_content
|
||||
throw new Error("deleted content does not match comment content")
|
||||
|
||||
comment.op.p = Math.min(comment_start, op_start)
|
||||
comment.op.c = remaining_before + remaining_after
|
||||
@emit "comment:moved", comment
|
||||
|
||||
applyInsertToChanges: (op, metadata) ->
|
||||
|
|
|
@ -218,11 +218,11 @@ define [
|
|||
entries[comment.id] ?= {}
|
||||
new_entry = {
|
||||
type: "comment"
|
||||
thread: comment.metadata.thread
|
||||
resolved: comment.metadata.resolved
|
||||
resolved_data: comment.metadata.resolved_data
|
||||
offset: comment.offset
|
||||
length: comment.length
|
||||
thread: comment.metadata.thread or []
|
||||
resolved: comment.metadata?.resolved
|
||||
resolved_data: comment.metadata?.resolved_data
|
||||
content: comment.op.c
|
||||
offset: comment.op.p
|
||||
}
|
||||
for key, value of new_entry
|
||||
entries[comment.id][key] = value
|
||||
|
|
Loading…
Reference in a new issue