Virtuoso's rangeChanged was forwarded to updateVisibleRooms unmapped:
- In grouped mode the range is in entry space (one slot per section
header), while updateVisibleRooms slices the rooms-only array. The
retained window was shifted down by the number of headers above it,
so the view models of the top rendered rooms were disposed and
recreated on every range change.
- Virtuoso's endIndex is inclusive but slice() is end-exclusive, so
the boundary row's view model was disposed and recreated on nearly
every range change.