Keep separate persistent change tracker for each doc

This commit is contained in:
James Allen 2016-11-15 15:48:12 +00:00
parent d0f451df2e
commit 4542d1094d
5 changed files with 95 additions and 53 deletions

View file

@ -42,8 +42,9 @@ div.full-size(
review-panel="reviewPanel",
on-scroll="onScroll",
scroll-events="scrollEvents",
track-changes-enabled="trackChangesFeatureFlag"
track-new-changes= "reviewPanel.trackNewChanges"
track-changes-enabled="trackChangesFeatureFlag",
track-new-changes= "reviewPanel.trackNewChanges",
changes-tracker="reviewPanel.changesTracker"
)
#review-panel
.review-panel-toolbar

View file

@ -57,6 +57,7 @@ define [
scrollEvents: "="
trackNewChanges: "="
trackChangesEnabled: "="
changesTracker: "="
}
link: (scope, element, attrs) ->
# Don't freak out if we're already in an apply callback
@ -216,13 +217,6 @@ define [
session = editor.getSession()
session.setOption("useWorker", value);
scope.$watch "trackNewChanges", (track_new_changes) ->
return if !track_new_changes?
if track_new_changes
trackChangesManager.turn_on_tracking()
else
trackChangesManager.turn_off_tracking()
scope.$watch "trackChangesEnabled", (enabled) ->
return if !enabled?
if enabled
@ -283,7 +277,9 @@ define [
session.setOption("useWorker", scope.syntaxValidation);
# now attach session to editor
console.log "setting session"
editor.setSession(session)
console.log "set session"
doc = session.getDocument()
doc.on "change", onChange

View file

@ -1,39 +1,23 @@
define [
"ace/ace"
"utils/EventEmitter"
"ide/editor/directives/aceEditor/track-changes/ChangesTracker"
"ide/colors/ColorManager"
], (_, EventEmitter, ChangesTracker, ColorManager) ->
], (_, EventEmitter, ColorManager) ->
class TrackChangesManager
Range = ace.require("ace/range").Range
constructor: (@$scope, @editor, @element) ->
@changesTracker = new ChangesTracker()
@changeIdToMarkerIdMap = {}
window.trackChangesManager ?= @
@changesTracker.on "insert:added", (change) =>
sl_console.log "[insert:added]", change
@_onInsertAdded(change)
@changesTracker.on "insert:removed", (change) =>
sl_console.log "[insert:removed]", change
@_onInsertRemoved(change)
@changesTracker.on "delete:added", (change) =>
sl_console.log "[delete:added]", change
@_onDeleteAdded(change)
@changesTracker.on "delete:removed", (change) =>
sl_console.log "[delete:removed]", change
@_onDeleteRemoved(change)
@changesTracker.on "changes:moved", (changes) =>
sl_console.log "[changes:moved]", changes
@_onChangesMoved(changes)
@$scope.$watch "changesTracker", (changesTracker) =>
return if !changesTracker?
@disconnectFromChangesTracker()
@changesTracker = changesTracker
@connectToChangesTracker()
@changesTracker.on "comment:added", (comment) =>
sl_console.log "[comment:added]", comment
@_onCommentAdded(comment)
@changesTracker.on "comment:moved", (comment) =>
sl_console.log "[comment:moved]", comment
@_onCommentMoved(comment)
@$scope.$watch "trackNewChanges", (track_new_changes) =>
return if !track_new_changes?
@changesTracker?.track_changes = track_new_changes
changingSelection = false
@editor.on "changeSelection", (args...) =>
@ -46,6 +30,9 @@ define [
@updateFocus()
@recalculateReviewEntriesScreenPositions()
@editor.on "changeSession", () =>
@redrawAnnotations()
@$scope.$on "comment:add", (e, comment) =>
@addCommentToSelection(comment)
@ -95,18 +82,61 @@ define [
@editor.renderer.on "resize", () =>
@recalculateReviewEntriesScreenPositions()
disconnectFromChangesTracker: () ->
@changeIdToMarkerIdMap = {}
@$scope.reviewPanel.entries = {}
if @changesTracker?
@changesTracker.off "insert:added"
@changesTracker.off "insert:removed"
@changesTracker.off "delete:added"
@changesTracker.off "delete:removed"
@changesTracker.off "changes:moved"
@changesTracker.off "comment:added"
@changesTracker.off "comment:removed"
connectToChangesTracker: () ->
@changesTracker.track_changes = @$scope.trackNewChanges
@changesTracker.on "insert:added", (change) =>
sl_console.log "[insert:added]", change
@_onInsertAdded(change)
@changesTracker.on "insert:removed", (change) =>
sl_console.log "[insert:removed]", change
@_onInsertRemoved(change)
@changesTracker.on "delete:added", (change) =>
sl_console.log "[delete:added]", change
@_onDeleteAdded(change)
@changesTracker.on "delete:removed", (change) =>
sl_console.log "[delete:removed]", change
@_onDeleteRemoved(change)
@changesTracker.on "changes:moved", (changes) =>
sl_console.log "[changes:moved]", changes
@_onChangesMoved(changes)
@changesTracker.on "comment:added", (comment) =>
sl_console.log "[comment:added]", comment
@_onCommentAdded(comment)
@changesTracker.on "comment:moved", (comment) =>
sl_console.log "[comment:moved]", comment
@_onCommentMoved(comment)
redrawAnnotations: () ->
for change in @changesTracker.changes
if change.op.i?
@_onInsertAdded(change)
else if change.op.d?
@_onDeleteAdded(change)
for comment in @changesTracker.comments
@_onCommentAdded(comment)
enable: () ->
@enabled = true
disable: () ->
@disabled = false
turn_on_tracking: () ->
@changesTracker.track_changes = true
turn_off_tracking: () ->
@changesTracker.track_changes = false
addComment: (offset, length, content) ->
@changesTracker.addComment offset, length, {
thread: [{
@ -196,13 +226,15 @@ define [
@changesTracker.applyOp(op, metadata)
updateReviewEntriesScope: () ->
entries = @_getCurrentDocEntries()
# Assume we'll delete everything until we see it, then we'll remove it from this object
delete_changes = {}
delete_changes[change_id] = true for change_id, change of @$scope.reviewPanel.entries
delete_changes[change_id] = true for change_id, change of entries
for change in @changesTracker.changes
delete delete_changes[change.id]
@$scope.reviewPanel.entries[change.id] ?= {}
entries[change.id] ?= {}
# Update in place to avoid a full DOM redraw via angular
metadata = {}
@ -214,11 +246,11 @@ define [
metadata: change.metadata
}
for key, value of new_entry
@$scope.reviewPanel.entries[change.id][key] = value
entries[change.id][key] = value
for comment in @changesTracker.comments
delete delete_changes[comment.id]
@$scope.reviewPanel.entries[comment.id] ?= {}
entries[comment.id] ?= {}
new_entry = {
type: "comment"
thread: comment.metadata.thread
@ -226,10 +258,10 @@ define [
length: comment.length
}
for key, value of new_entry
@$scope.reviewPanel.entries[comment.id][key] = value
entries[comment.id][key] = value
for change_id, _ of delete_changes
delete @$scope.reviewPanel.entries[change_id]
delete entries[change_id]
@updateFocus()
@recalculateReviewEntriesScreenPositions()
@ -238,8 +270,9 @@ define [
@updateEntryGeneration()
selection = @editor.getSelectionRange()
cursor_offset = @_aceRangeToShareJs(selection.start)
entries = @_getCurrentDocEntries()
for id, entry of @$scope.reviewPanel.entries
for id, entry of entries
if entry.type == "comment"
entry.focused = (entry.offset <= cursor_offset <= entry.offset + entry.length)
else if entry.type == "insert"
@ -249,9 +282,9 @@ define [
if selection.start.column == selection.end.column and selection.start.row == selection.end.row
# No selection
delete @$scope.reviewPanel.entries["add-comment"]
delete entries["add-comment"]
else
@$scope.reviewPanel.entries["add-comment"] = {
entries["add-comment"] = {
type: "add-comment"
offset: cursor_offset
}
@ -264,7 +297,8 @@ define [
recalculateReviewEntriesScreenPositions: () ->
session = @editor.getSession()
renderer = @editor.renderer
for entry_id, entry of (@$scope.reviewPanel?.entries or {})
entries = @_getCurrentDocEntries()
for entry_id, entry of entries or {}
doc_position = @_shareJsOffsetToAcePosition(entry.offset)
screen_position = session.documentToScreenPosition(doc_position.row, doc_position.column)
y = screen_position.row * renderer.lineHeight
@ -273,6 +307,9 @@ define [
@$scope.$apply()
_getCurrentDocEntries: () ->
return @$scope.reviewPanel.entries
_makeZeroWidthRange: (position) ->
ace_range = new Range(position.row, position.column, position.row, position.column)
# Our delete marker is zero characters wide, but Ace doesn't draw ranges

View file

@ -2,7 +2,8 @@ define [
"base",
"utils/EventEmitter"
"ide/colors/ColorManager"
], (App, EventEmitter, ColorManager) ->
"ide/review-panel/ChangesTracker"
], (App, EventEmitter, ColorManager, ChangesTracker) ->
App.controller "ReviewPanelController", ($scope, $element, ide, $timeout) ->
$scope.reviewPanel =
entries: {}
@ -12,6 +13,13 @@ define [
adding: false
content: ""
changesTrackers = {}
$scope.$watch "editor.open_doc_id", (open_doc_id) ->
return if !open_doc_id?
changesTrackers[open_doc_id] ?= new ChangesTracker()
$scope.reviewPanel.changesTracker = changesTrackers[open_doc_id]
# TODO Just for prototyping purposes; remove afterwards.
mockedUserId = '12345abc'