Starts work on a class which is intended to just wrap the Matrix apis with very
simple functions.
There is a lot more work to be done here. For now, I have just taken methods
which don't refer to anything in MatrixClient except _http. This excludes a
bunch of things which refer to $userId, as well as the login stuff because of
the deviceId stuff I've just added :/.
For now, it's an internal class. I don't really see any reason it can't be
exposed to applications, though.
Make `MatrixEvent.event` contain the *encrypted* event, and keep the plaintext
payload in a separate `_clearEvent` property.
This achieves several aims:
* means that we have a record of the actual object which was received over
the wire, which can be shown by clients for 'view source'.
* makes sent and received encrypted MatrixEvents more consistent (previously
sent ones had `encryptedType` and `encryptedContent` properties, whereas
received ones threw away the ciphertext).
* Avoids having to make two MatrixEvents in the receive path, and copying
fields from one to the other.
*Hopefully* most clients have followed the advice given in the jsdoc of not
relying on MatrixEvent.event to get at events. If they haven't, I guess they'll
break in the face of encrypted events.
(The pushprocessor didn't follow this advice, so needed some tweaks.)
... 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.
In TimelineWindow.paginate, keep a count of the number of API requests we have
made, and bail out if it gets too high, to ensure that we don't get stuck in a
loop of paginating right back to the start of the room.
Hopefully this will improve our recovery time after a laptop is suspended. The
idea is to treat the timeouts on the http apis as being in realtime, rather
than in elapsed time while the machine is awake.
To do this, we add a layer on top of window.setTimeout. We run a callback every
second, which then checks the wallclock time and runs any pending callbacks.
The existing 'pendingEventOrdering'=='end' semantics had been substantially
broken by the introduction of timelines and gappy syncs: after a gappy
sync, pending events would get stuck in the old timeline section. (Part of
https://github.com/vector-im/vector-web/issues/1120).
This is some preparatory work for fixing up the problems with te timeline
ordering of unsent messages
(https://github.com/vector-im/vector-web/issues/1120). The functional changes
here should be minimal (bar an extra `Room.localEchoUpdated` when the local
echo is first added to the timeline).
Give `MatrixClient.sendEvent` its own entry point `Room.addPendingMessage`
instead of pushing it through `addEventsToTimeline`; this considerably
simplifies the implementation of the latter and also means that we can contain
the `_txnId` ming to MatrixClient.
Move the code which deals with a successful `/send` response from
`MatrixClient` into `Room.updatePendingEvent`, since it involves fiddling with
the innards of the Room.
Also adds a new EventStatus 'SENT' for events which have been successfully sent
but whose remote echo we still haven't received.
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.
Removing the last event in an EventTimeline (as we might, for instance, if it
was a local echo in an empty timeline) got us into a state where the baseIndex
would increment when adding events to the end of the timeline, causing much
confusion.
* This should fix the problem where we could end up with two concurrent syncs
due to both retrying /sync and hitting /versions. There is now one and only
one mechanism for connection recovery.
* Hit /versions a little less often as I think every 2 seconds is a little
over-aggressive. Also introduce randomness to minimize possibility of
thundering herds.
* Add a listener for the 'online' event in case any browser is nice enough
to ever fire it.
* Treat a 400 response from /versions as successful since older synapses
will not support it.
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.