When we send an encrypted message with Olm, we need to know who to send it
to. Currently that is based on a user list passed to setRoomEncryption. We want
to be able to change the list as people join and leave the room; I also want to
not have to keep the member list in local storage.
So, use the member list at the point of enabling encryption to set up sessions,
and at the point of sending a message to encrypt the message.
Further work here includes:
* updating the react-sdk not to bother setting the member list
* monitoring for new users/devices in the room, and setting up new sessions
with them
Separate the helper functions from the tests, and order them by functionality
rather than by test order.
I've been struggling to find the tests among the helpers, and struggling to
find the helpers among the other helpers. Hopefully this will help.
If an exception was thrown by the encryption process, the event would be
queued, but the exception would not be handled. This meant that the event got
stuck as a grey 'sending' event in the UI.
Fixing this correctly is slightly more complex than just handling the exception
correctly. A naive approach would mean that the event would be shown as a red
'unsent' message, and clicking 'resend' would then send the message *in the
clear*. Hence, move the encryption to _sendEvent, where it will be called again
when the event is resent.
Add a 'verified' property to the response from MatrixClient.listDeviceKeys, and
add MatrixClient.setDeviceVerified to set it. Also changes the format of data
stored for user devices in the session store slightly (in a
backwards-compatible way).
Use different mock http backends for the two different clients, so that we can
better control what each of them is doing (in particular, this is a
prerequisite for having them both running /sync loops)
The pyramid of doom was getting unmanageable, not to mention the difficulty of
diagnosing why tests were failing, so replace the callbacks with promises.
Fix a bug in the error handling in downloadKeys: If the http request failed,
then the exception would get silently swallowed and the promise would never
resolve.
Also: tests!
... and add some sanity checks
Two things here:
1. Clean up the Room API for adding new events to the timeline. Where before
we had addEvents and addEventsToTimeline, whose purposes were unclear, we now
have addLiveEvents which must be used for adding events to the end of the live
timeline, and addEventsToTimeline which should be used for pagination (either
back-pagination of the live timeline, or pagination of an old timeline).
2. Add some sanity checks for the live timeline. Today we have seen problems
where somehow the live timeline had gained a forward pagination token, or the
live timeline had got joined to another timeline, leading to much confusion -
and I would like to notice these sooner.
We need to reset things at the UI level when we get a gappy sync, so give the
clients something to listen for.
Also add a bunch of tests for that bit of code.
In order to resolve the conflict between local and remote read-receipts, try to
give precedence to the read-receipt which refers to the most recent event.
Also fix the read-receipt synthesis in _addLiveEvents so that it actually works
(drop the spurious MatrixEvent wrapper), and remove the synthesis in
recalculate() (which appears to be redundant).
This provides optional support for fetching old events via the /context API,
and paginating backwards and forwards from them, eventually merging into the
live timeline.
To support it, events are now stored in an EventTimeline, rather than directly
in an array in the Room; the old names are maintained as references for
compatibility.
The feature has to be enabled explicitly, otherwise it would be impossible for
existing clients to back-paginate to the old events after a gappy /sync.
Still TODO here:
* An object which provides a window into the timelines to make them possible to
use. This will be a separate PR.
* Rewrite the 'EventContext' used by the searchRoomEvents API in terms of an
EventTimeline - it is essentially a subset.
It was possible for the test to end (via done()) before the final /events req
was flushed, resulting in a fail as there were requests outstanding. We now wait
until the final flush is done before done()ing.