Comments - P2Pvalue/jetpad GitHub Wiki
This is a brief tech/functional design of the comments feature for Jetpad.
A user selects a range of text of a document and write a small note related to that selected text. Others or herself can reply to that note forming a simple plain thread of notes. That whole thread of notes for that particular selected text is named "Comment".
A document can have an arbitrary number of comments. A comment can have an arbitrary number of notes.
Actions related with a comment are:
- Create a comment for a selected text.
- Add (reply) a note, a comment requires at least one note.
- Delete a note, only by the author of the note.
- Resolve the comment, that is, delete it.
.
To create a comment following data is required:
- Selected text and its range (from-to document positions)
- An initial note or reply
- An generated id for the comment.
With all these info, first create a new comment annotation assigning as value the generated id:
editor.setTextAnnotationOverlap(<comment_annotation_key>, <comment id>, <initial_range>)
A comment's annotation can overlap with other existing annotations, so actually, this method could generate a list of spread annotations sharing the same "id" as value. Get all the annotation ranges sharing a same value with the method:
let annotationParts = editor.seekTextAnnotationsByValue(<comment_annotation_key, <comment id>, <initial_range>)
On the other hand, a comment's replies will be stored in an additional property of the swellrt object containing the text:
object.put('comments', swellrt.Map.create());
This map stores two types of keys:
object.get('comments').get('<comment_id>')
-> Array of replies.
object.get('comments').get('<comment_id>-state')
-> State of the comment, "open" or "resolved".
A reply object stores following info:
- The participant id who writes the reply.
- Time stamp.
- The reply's text.
When the cursor was placed whithin a commented text the text of that comment must be highlighted. A comment can span a set of spread annotations sharing the same comment id, hence, in order to highlight the whole range a transient annotation must be create for a container range.
Anytime the cursor is placed within a commented text, the application must show the comment along with:
- The chunk of text commented
- List of replies or notes.
The actions the user could make are:
- Navigate to the previous or next comment in the document.
- Add a reply or delete one written by the user.
- Mark the comment as resolved.
Comment
A simple plain object with a comment description:
{
commentId : <id>,
range : <range>,
focus: <boolean>,
replies: [ ... ]
}
EditorService
Listen current comment changes from comment service's commentSubject. Highlight the current comment using the provided comment.range to mark a transient annotation. Scroll the document to the comment if the property comment.focus is true.
The editor service will notify of changes in comment annotations. (An annotation can be created or delete by a remote participant)
The editor service will delete comment annotations on demand of the comments service.
CommentService
Listen selection changes from editor's selectionSubject Checks whether there is a comment in the selection. If true, sets a new current comment, and notifies sending a Comment object through the commentSubject . This service will listen to changes for the current comment array of replies to update the current comment subject if necessary.
Other methods of this service are:
-
reply(<comment_id>)
adds a new reply to the comment -
deleteReply(<comment_id>, <reply_object>)
delete a reply -
next()
sets current comment to the next one in the document. -
prev()
sets current comment to the previous one in the document. -
resolve(<comment_id>)
delete a comment: change the state and delete the annotation.
CommentComponent
Listen to commentSubject of the comments service to display the replies thread and rest of comment information. Provide UI to navigate through comments, to reply and resolve them.