Fixes https://github.com/vector-im/riot-web/issues/14798 (part 2)
This is in two parts itself: The `RoomSublist` needs to break its references to the `RoomListStore`, so it now clones the room arrays. The `Algorithm` is the other part, which is slightly more complicated.
It turns out that we weren't handling splicing as a change in the `ImportanceAlgorithm`, therefore the `Algorithm` wasn't really feeling like it needed to change anything. Further, the `Algorithm` was using the wrong reference to where it should be dumping rooms (`this.cachedRooms` is a getter which returns a different object depending on conditions), so having fixed that we need to ensure that the filtered and sticky maps are also updated when we remove a room. Because we send the new tag through a Timeline update, we'll end up updating the tag later on and don't need to update the filter and sticky collections.
The EchoTransaction was wrongly assuming that it knew better than the caller for when the success condition was met, so the echo marking has been left an exercise for the caller. In this case, we mark when we finally receive the sync with the updated rules.
We also have to cancel previous transactions otherwise if the user mashes buttons we could forever show the toast, and that would be bad.
The structure here might need some documentation and work, but overall the idea is that all calls pass through a CachedEcho instance, which are self-updating.
This reduces the update cost of rooms changing, and fixes a bug where when a sublist became filtered it would change the notification count of the sublist.
This does change the expected usage of the state store to ensuring that only one place updates the rooms on the list states, which is currently the room list store. Ideally the state store could listen to the room list store to update itself, however due to a complicated require() loop it is not possible.
In 9969b01c5f we stopped updating the sublist whenever we felt like it, which indirectly froze message previews for room tiles (badges, unread state, etc were unaffected because that is managed by a different store). To fix this, we simply have to listen for changes and perform an update.
We were taking 0.2ms to handle the registration of a timer per event during startup, even before the app is visible to the user. These timers would be short-circuited too, leading to a bunch of wasted time.
0.2ms isn't a lot of time, but multiplied by thousands of events at startup it's pretty significant.
On my account this reduces the full page spinner time from ~50 seconds to just over 20 seconds.
This means we're abusing the AsyncStoreWithClient to get access to a lifecycle, but overall that seems like a minor crime compared to the time spend abusing the store's state as a map.
With thousands of rooms shown, we can save on average 743ms per preview. The new preview time is 0.12ms on average.
Fixes https://github.com/vector-im/riot-web/issues/14694
Instead of spending 10-1000ms in a function iterating over a whole lot of room events, we can use our cached state from the Notification State Store.
This commit sets up a structure that could be applied to communities in the TagPanel too, as that could probably use a similar optimization.
This reduces the updateStatusIndicator() time to just 4ms on average.
Fixes https://github.com/vector-im/riot-web/issues/14475
Background: Sticky rooms are actually a pair of lies to the underlying algorithm as a combination of REMOVE_ROOM/NEW_ROOM calls so they don't get considered as needing to be sorted. When a room is added under the importance algorithm, it is expected that the category it is being added to will be re-sorted to account for the change, however we weren't doing that since we optimized the NewRoom path to be a splice operation.
Fixes https://github.com/vector-im/riot-web/issues/14091
Design needs work, however this is behind labs anyways. This re-implements the behaviour of the old room list.
The implementation ended up being a lot easier due to early confusion with what the TagOrderStore and TagPanel take care of. Turns out they don't deal with tags, but groups. As such, we don't need to do anything with filtering (though we keep some sanity checks in place for safety), and just have to wire up the CustomRoomTagPanel and CustomRoomTagStore.
We use `RoomListStore` as a singleton, and don't want the ugly `2` at the end of the actual store instance, so here we rename it to something half-decent.
Fixes https://github.com/vector-im/riot-web/issues/14442
Turns out that we are so good at moving a room that when it flows through as a TIMELINE update the algorithm no-ops and does nothing, so don't do that.
Fixes https://github.com/vector-im/riot-web/issues/14411
The act of setting/changing the algorithm was causing the update function to be marked, meaning we wouldn't trigger an update until something else happened later. To get around this, and still support internal functions spamming calls without multiple updates, we simply move the guts to an internalized function and make the public interface do a trigger.