diff options
author | Julius Härtl <jus@bitgrid.net> | 2021-01-23 19:32:53 +0300 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2021-01-26 10:34:18 +0300 |
commit | 7c7623222aeffdbf7ed2f513592d63b243f9dcbb (patch) | |
tree | cc100a49d65563ff83806f0e0fda28422590853e /src/extensions | |
parent | 886fd14249a02659b482b1aa6ba2b540bc9360e7 (diff) |
Track authors by step rather than transaction
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'src/extensions')
-rw-r--r-- | src/extensions/UserColor.js | 14 | ||||
-rw-r--r-- | src/extensions/tracking/TrackState.js | 59 | ||||
-rw-r--r-- | src/extensions/tracking/models.js | 14 |
3 files changed, 27 insertions, 60 deletions
diff --git a/src/extensions/UserColor.js b/src/extensions/UserColor.js index e3e4350c1..6ae68a0e6 100644 --- a/src/extensions/UserColor.js +++ b/src/extensions/UserColor.js @@ -60,20 +60,16 @@ export default class UserColor extends Extension { let { tracked, decos } = instance let tState = this.getState(oldState).tracked if (tr.docChanged) { + if (!tr.getMeta('clientID')) { + // we have an undefined client id for own transactions + tr.setMeta('clientID', tr.steps.map(i => this.spec.clientID)) + } tracked = tracked.applyTransform(tr) - const clientID = tr.getMeta('clientID') ? tr.getMeta('clientID') : this.spec.clientID - tracked = tracked.applyCommit(clientID, new Date(tr.time), { - clientID, - color: this.spec.color(clientID), - name: this.spec.name(clientID), - }) tState = tracked } decos = tState.blameMap - .filter(span => typeof tState.commits[span.commit]?.author?.color !== 'undefined') .map(span => { - const commit = tState.commits[span.commit] - const clientID = commit.author.clientID + const clientID = span.author return Decoration.inline(span.from, span.to, { class: 'author-annotation', style: 'background-color: ' + this.spec.color(clientID) + '66;', diff --git a/src/extensions/tracking/TrackState.js b/src/extensions/tracking/TrackState.js index 6a6d33d57..8193ecacb 100644 --- a/src/extensions/tracking/TrackState.js +++ b/src/extensions/tracking/TrackState.js @@ -20,32 +20,34 @@ * */ -import { Span, Commit } from './models' +import { Span } from './models' /* * This code is heavily inspired by the change tracking example of prosemirror * https://github.com/ProseMirror/website/blob/master/example/track/index.js */ -function updateBlameMap(map, transform, id) { - const result = []; const mapping = transform.mapping +function updateBlameMap(map, transform, clientIDs) { + const result = [] + const mapping = transform.mapping for (let i = 0; i < map.length; i++) { const span = map[i] - const from = mapping.map(span.from, 1); const to = mapping.map(span.to, -1) - if (from < to) result.push(new Span(from, to, span.commit)) + const from = mapping.map(span.from, 1) + const to = mapping.map(span.to, -1) + if (from < to) result.push(new Span(from, to, span.author)) } for (let i = 0; i < mapping.maps.length; i++) { const map = mapping.maps[i]; const after = mapping.slice(i + 1) map.forEach((_s, _e, start, end) => { - insertIntoBlameMap(result, after.map(start, 1), after.map(end, -1), id) + insertIntoBlameMap(result, after.map(start, 1), after.map(end, -1), clientIDs[i]) }) } return result } -function insertIntoBlameMap(map, from, to, commit) { +function insertIntoBlameMap(map, from, to, author) { if (from >= to) { return } @@ -53,11 +55,11 @@ function insertIntoBlameMap(map, from, to, commit) { let next for (; pos < map.length; pos++) { next = map[pos] - if (next.commit === commit) { + if (next.author === author) { if (next.to >= from) break - } else if (next.to > from) { // Different commit, not before + } else if (next.to > from) { // Different author, not before if (next.from < from) { // Sticks out to the left (loop below will handle right side) - const left = new Span(next.from, from, next.commit) + const left = new Span(next.from, from, next.author) if (next.to > to) map.splice(pos++, 0, left) else map[pos++] = left } @@ -67,7 +69,7 @@ function insertIntoBlameMap(map, from, to, commit) { // eslint-ignore while ((next = map[pos])) { - if (next.commit === commit) { + if (next.author === author) { if (next.from > to) break from = Math.min(from, next.from) to = Math.max(to, next.to) @@ -75,7 +77,7 @@ function insertIntoBlameMap(map, from, to, commit) { } else { if (next.from >= to) break if (next.to > to) { - map[pos] = new Span(to, next.to, next.commit) + map[pos] = new Span(to, next.to, next.author) break } else { map.splice(pos, 1) @@ -83,45 +85,26 @@ function insertIntoBlameMap(map, from, to, commit) { } } - map.splice(pos, 0, new Span(from, to, commit)) + map.splice(pos, 0, new Span(from, to, author)) } export default class TrackState { - constructor(blameMap, commits, uncommittedSteps, uncommittedMaps) { + constructor(blameMap) { // The blame map is a data structure that lists a sequence of - // document ranges, along with the commit that inserted them. This + // document ranges, along with the author that inserted them. This // can be used to, for example, highlight the part of the document - // that was inserted by a commit. + // that was inserted by a author. this.blameMap = blameMap - // The commit history, as an array of objects. - this.commits = commits - // Inverted steps and their maps corresponding to the changes that - // have been made since the last commit. - this.uncommittedSteps = uncommittedSteps - this.uncommittedMaps = uncommittedMaps } // Apply a transform to this state applyTransform(transform) { - // Invert the steps in the transaction, to be able to save them in - // the next commit - const inverted - = transform.steps.map((step, i) => step.invert(transform.docs[i])) - const newBlame = updateBlameMap(this.blameMap, transform, this.commits.length) + const clientID = transform.getMeta('clientID') ?? transform.steps.map(item => 'self') + const newBlame = updateBlameMap(this.blameMap, transform, clientID) // Create a new state—since these are part of the editor state, a // persistent data structure, they must not be mutated. - return new TrackState(newBlame, this.commits, - this.uncommittedSteps.concat(inverted), - this.uncommittedMaps.concat(transform.mapping.maps)) - } - - // When a transaction is marked as a commit, this is used to put any - // uncommitted steps into a new commit. - applyCommit(message, time, author) { - if (this.uncommittedSteps.length === 0) return this - const commit = new Commit(message, time, this.uncommittedSteps, this.uncommittedMaps, author) - return new TrackState(this.blameMap, this.commits.concat(commit), [], []) + return new TrackState(newBlame) } } diff --git a/src/extensions/tracking/models.js b/src/extensions/tracking/models.js index fbcacdb65..1c628f780 100644 --- a/src/extensions/tracking/models.js +++ b/src/extensions/tracking/models.js @@ -22,21 +22,9 @@ export class Span { - constructor(from, to, commit) { + constructor(from, to, author) { this.from = from this.to = to - this.commit = commit - } - -} - -export class Commit { - - constructor(message, time, steps, maps, author) { - this.message = message - this.time = time - this.steps = steps - this.maps = maps this.author = author } |