Skip to content

Threaded conversations

Implementation will follow the product discovery issue: https://gitlab.com/gitlab-org/gitter/webapp/issues/2143

Terms

  • Plain message - a message that is not a part of any threaded conversation
  • Parent message - a message that has got at least one reply
  • Child message - a message that replies to a Parent message
    • can be created by typing message directly into a chat input in Thread message feed
  • Main message feed - panel taking the center of the screen, currently the only way to view messages
  • Parent message indicator - an icon and a label with number of replies placed in the main message feed marking message as a parent message
  • Thread message feed - collapse-able right-hand side panel showing parent message on top with all child messages
    • can be opened in three ways:
      • selecting Start a thread from context menu on a plain message
      • selecting Reply in a thread from a context menu on a parent message
      • clicking on the parent message indicator

Plan of implementation

(roughly 2 MRs per item)

  1. Introduce feature toggle threaded-conversations, remove Reply from message context menu and add Start a thread. #2186 (closed)
  2. Add thread message feed panel that will open when Start a thread button is clicked. Include chat input panel and make it submit plain messages to the main message feed #2190 (closed)
  3. Submitting child message, storing it into the database #2201 (closed)
    • Introduce parentId attribute on the chatMessage model (see model change section)
  4. Showing child messages in the Thread message feed #2202 (closed)
  5. Showing the parent message indicator in the main message feed #2203 (closed)
    • adding threadMessageCount to the parent message, creation of a child message increments it, deletion decrements it
  6. Permalinks in Thread message feed #2218 (closed)
  7. Unread indicator - all child messages show as unread parent message #2244 (closed)
  8. Create and document bayeux channel for Thread message feed #2204 (closed)
  9. Connect thread message feed to the Bayeux channel #2205 (closed)
  10. Infinite scrolling of Thread message feed #2245 (closed)
  11. Not logged in view #2206 (closed)

chatMessages model change

There are at least 3 options to consider when it comes to modeling threaded conversation in our main MongoDB.

🏁 Chosen option: parentId 🏁

Each child message would have a parentId attribute that would point to its parent message.

Main benefits of choosing the parentId option are visible in the table bellow.

replyIds

A parent message would have a replyIds attribute with an array of all its child messages in chronological order

replies

A parent message would have a replies attribute that would contain array of all messages (whole entities).

Table comparing the different implementation of operations on messages

  • 💎 clean solution
  • less optimal solution
  • blocker (too much effort/unknown)
  • needs more investigation
Operation parentId replyIds replies
Reply to a thread Create a new child message with parentId + increase counter on parent message Create a new child message, mark it as child, and add its id to replyIds of its parent message Create a new child message and store it in replies array in its parent
Edit child message same as plain message same as plain message edit child message in replies array of its parent message
Delete child message same as plain message + decrease counter on parent message same as plain message + remove its id from replyIds of the parent message delete child message from the replies array of its parent message
Delete parent message delete parent message + all child messages by parentId delete parent message + child messages in replyIds 💎 delete parent message
Show all child messages in Thread message Feed find all messages with parentId === parent.id get all messages from replyIds 💎 return parent.replies
Show parent message indicator counter on the parent message chatMessage.replyIds.length chatMessage.replies.length
Child message permalink fetch child message on the client + highlight parentId in the main message feed, then child message id in the tread message feed extra lookup for each permalink to decide whether it's a child message permalink would have to be a combination of parent message id and child message id/index
Selecting messages for the main message feed 💎 adding {$ne: 'parentId'} to the query for messages there would have to be a flag on the child message 💎 child messages wouldn't be part of the mongo query by default
Search for messages in a room child message will appear marked with parentId message will appear but there would have to be an indicator for child message messages wouldn't appear without changing the mongo river logic
Notifications

Needs more investigation

  1. Do we have an endpoint that can return multiple messages by id's or do we have to create one?
  2. Bayeux channel so we can listen on new child messages being posted to a Thread message feed
  3. Should the thread message feed be represented in the URL? (e.g. https://gitter.im/gitterHQ/gitter#thread/{parentId})

Out of scope for the initial release

  1. Archive view - are there going to be any complications with showing parent messages in the archive main message feed and opening a thread message feed there?
  2. Mobile view - the proportion of mobile users is 12%. Maybe we can omit mobile experience from the initial release (hide the parent message indicator)
  3. Notifications - for online and offline users, notifying them about a new message in a thread, especially when the message in a thread happened at a later date (see https://gitlab.com/gitlab-org/gitter/webapp/issues/741#note_184865053)
Original notes *Created by: ktoso*

We are trying to switch from Flowdock to Gitter in order to open up our internal communication to the wider developer community (we as in @akka), however one of the killer features we loved in Flowdock is not available in gitter: Threaded discussions.

They are very important to not be completely confused when catching up on a discussion which one did not track in real time, and also allow to ignore a discussion I don't care about (at this moment). For example me and another dev discuss feature X in one "thread", so we want to see only responses in that "thread" (and pop back out to the "see everything" easily), while others discuss features Y and Z, all in parallel. Without threads the amount of noise makes it hard to track these multiple independent conversations.

Are you guys thinking of implementing something that would address this? It is even more visible the more popular an open source project is, as many people chime in and there's usually at least a few discussions in parallel.

As an illustration of what I mean, see the below picture: __akka__typesafe-_flowdock

Edited by Tomas Vik