Age | Commit message (Collapse) | Author |
|
This will be used from Quaternion for a better algorithm dealing with read markers
|
|
timeline + no more discarding read markers to events that haven't arrived yet
When using deque::const_reverse_iterator for read markers and eventsIndex, I didn't realise that insertions into std::deque invalidate iterators (though preserve references and pointers). Therefore, a small TimelineItem class has been introduced that stores an event together with a persistent index that is generated upon insertion into the timeline (timeline.back()+1 for newer events, timeline.front()-1 for older events). Using such indices, we can still reach an event by it's index in constant time, while avoiding a problem with invalidating iterators.
While rewriting the code, another problem has been detected with read markers to events that haven't yet arrived to the timeline (in particular, older events). The old code simply discarded such read markers. The new code stores such read markers anyway, so that when that event arrives, it could be matched against the stored last-read-event id.
|
|
Also, Room now uses callApi<PostReceiptJob>() instead of postReceipt()
(to allow further removal of postReceipt() from Connection)
|
|
forbid empty event id's
Added assertions and enhanced debug messages along the way
|
|
Turns out that because the read marker is positioned _after_ the last read message, a reverse iterator models it much better than the usual one. This commit switches the internal representation to reverse iterators (externally, we operate in terms of event id's, still).
|
|
A new hashmap, eventsIndex, is provided, that allows you to find the event in the timeline if you have eventId. This hashmap uses the fact that deque iterators don't invalidate upon insertion of elements to either end of the deque. Thanks to that, promoteReadMarker() and doAddNewMessageEvents() have been considerably simplified; also, it should be easier now to calculate event indices without rolling back and forth over the timeline.
|
|
|
|
|
|
Unread messages implementation in the library
|
|
|
|
|
|
The first change allows to use the read marker from QML (hint to Tensor). The second change is actually a fix for a case when markMessagesAsRead() is called with an iterator behind the last read event (in that case markMessagesAsRead() would post a receipt for that older event, which is not quite right).
|
|
This code is useful for any client that uses the Room class and needs to display the list of room members. Also removed an unused #include.
|
|
The implementation allows further extension to actually counting unread messages (in their Room::isEventNotable() sense - see the code) but so far just replicates what Quaternion previously provided. The only difference from the Quaternion implementation is that last own message is not marked as read immediately - so that we can allow the local user to send messages while staying with the read marker well above. This implies, though, that the read marker won't reset to the timeline bottom at any movement of the user - rather that it resets to the bottom of the current view (which is the ultimately correct behaviour, anyway).
|
|
|
|
Room::markMessagesAsRead: use the iterator to the message, not after the message.
Room::setLastReadEvent: moved to protected
|
|
setLastReadEvent() is called in any case (read marks a stored in a hashmap so it's a constant time operation anyway); postReceipt() is now called for the nearest previous non-local message.
|
|
receipts for own messages to the server
As discussed with Matthew in #quaternion: https://matrix.to/#/!PCzUtxtOjUySxSelof:matrix.org/$14768896199130qcJqe:matrix.org
|
|
|
|
|
|
This replaces the one-by-one timestamp-ordering algorithm of adding new
messages with copying the whole group of just-arrived messages to either
the beginning or the end of the timeline.
Since origin timestamps do not provide a reasonable order,
findInsertionPos() is entirely deleted. processMessageEvent() is
replaced by two functions: addNewMessageEvents() appends at
messageEvents.end() while addHistoricalMessageEvents() inserts them at
messageEvents.begin(). There's no official way to insert messages in the
middle; cases when getPreviousContent() is called in parallel or a
RoomMessagesJob runs on a gap somewhere in the middle of the timeline
weren't considered before this commit and aren't considered in it.
The new ordering requires you to understand where you have got your
events from (or rather, where you want to insert them). In particular,
updateData() that processes /sync results uses addNewMessageEvents();
getPreviousContent() calls addHistoricalMessageEvents().
In order to notify clients, a single newMessages() signal gives way to
3 new signals: 2 aboutToAdd*Messages() and a common addedMessages().
In addition, clients can derive from Room and use doAdd*Messages()
virtual functions to alter/extend the behaviour.
|
|
To facilitate a possible change of a container type.
|
|
|
|
|
|
|
|
signal, which clients should use in the room context.
Processing changes of user displaynames is tricky: we have to not only deal with the currently renamed user but also with its past and new namesakes which might change representation due to that renaming. So in the worst case a single User::nameChanged signal may lead to three Room::memberRenamed references (and 3 user displaynames updated in the UI, respectively). And the newly added users should be taken care of in a similar manner, of course.
|
|
a displayname update.
This changes the way displayname is supplied to a client application - instead of calculating immediately, displayname becomes a separate stored value that is refreshed with every change of the list of members, or the name, or the canonical alias. displaynameChanged signal is supplied to subscribe to these updates: in case of displaying a room in the roomlist a client should use this new signal instead of Room::namesChanged.
The displaname calculation algorithm is described in section 11.2.2.5 of the CS spec: https://matrix.org/docs/spec/r0.0.1/client_server.html#calculating-the-display-name-for-a-room
|
|
|
|
According to section 11.2.2.3 of the CS spec, clients SHOULD follow a certain algorithm of making a non-ambiguous display name of a user in the room context. This algorithm implies checking whether other room members have the same display name. This commit prepares for implementation of the algorithm:
1. Use a hash map instead of a list to store room members. The external Room::users() API is kept intact.
2. Convenience CRUD methods are implemented to deal with the hash map.
3. An additional slot for user renaming is introduced (because renaming affects the hash map). Binding of actual signals is left for the next commit.
4. nullptr is the recommended representation of a null pointer since C++11. Use that and mandate compiler support of that.
|
|
In particular, this will be needed to render room names according to the CS spec.
|
|
|
|
Originally by Felx Rohrbach (kde@fxrh.de)
|
|
|