Fixes https://github.com/vector-im/element-web/issues/15745
This was surprisingly easy given the number of errors I remember last time, but here it is. This also includes an over-engineered VisibilityProvider with the intention that it'll get used in the future for things like Spaces and other X as Rooms stuff.
Fixes https://github.com/vector-im/element-web/issues/14848
When we're filtering the sticky room will be excluded from the filtered set, and thus won't even appear in the `getOrderedRoomsWithoutSticky()` result. Further, we will likely have to update the position ourselves to ensure the sticky room can be placed appropriately in the list.
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.
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/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.