@@ -30,6 +30,13 @@ class _ChatListSortRoomsState extends State<ChatListSortRooms> {
3030 Map <String , Event ?> _lastEventByRoomId = {};
3131 List <Room > _sortCache = [];
3232 Map <String , StreamSubscription ?> _roomSubscriptions = {};
33+ Future <List <Room >>? _sortFuture;
34+
35+ /// Monotonically increasing counter to invalidate stale sort futures.
36+ /// Each call to [_triggerSort] increments this value. When a sort future
37+ /// completes, it checks whether its generation matches [_sortGeneration] .
38+ /// If not, the result is discarded (a newer sort has been triggered).
39+ int _sortGeneration = 0 ;
3340
3441 RoomSorter sortRoomsBy (Client client) => (a, b) {
3542 if (client.pinInvitedRooms &&
@@ -53,19 +60,34 @@ class _ChatListSortRoomsState extends State<ChatListSortRooms> {
5360 );
5461 };
5562
56- Future <List <Room >> sortRooms ( ) async {
63+ Future <List <Room >> _sortRooms ( int generation ) async {
5764 await Matrix .of (context).initSettingsCompleter.future;
5865 for (final room in widget.rooms) {
66+ // Bail out early if the widget was disposed or a newer sort was
67+ // triggered while we were awaiting.
68+ if (! mounted || generation != _sortGeneration) return _sortCache;
69+
5970 if (_lastEventByRoomId[room.id] != null ) continue ;
6071
6172 final event = await room.lastEventAvailableInPreview ();
73+
74+ if (! mounted || generation != _sortGeneration) return _sortCache;
75+
6276 _lastEventByRoomId[room.id] = event;
6377 }
78+
79+ if (! mounted) return _sortCache;
80+
6481 widget.sortingRoomsNotifier.value = false ;
6582 return List .from (widget.rooms)
6683 ..sort (sortRoomsBy (Matrix .of (context).client));
6784 }
6885
86+ void _triggerSort () {
87+ _sortGeneration++ ;
88+ _sortFuture = _sortRooms (_sortGeneration);
89+ }
90+
6991 @override
7092 void initState () {
7193 super .initState ();
@@ -82,6 +104,7 @@ class _ChatListSortRoomsState extends State<ChatListSortRooms> {
82104 ),
83105 ),
84106 );
107+ _triggerSort ();
85108 }
86109
87110 @override
@@ -114,12 +137,24 @@ class _ChatListSortRoomsState extends State<ChatListSortRooms> {
114137 ),
115138 ),
116139 );
140+ _triggerSort ();
141+ }
142+
143+ @override
144+ void dispose () {
145+ for (final subscription in _roomSubscriptions.values) {
146+ subscription? .cancel ();
147+ }
148+ _roomSubscriptions.clear ();
149+ // Invalidate any in-flight sort future so its callbacks become no-ops.
150+ _sortGeneration++ ;
151+ super .dispose ();
117152 }
118153
119154 @override
120155 Widget build (BuildContext context) {
121156 return FutureBuilder (
122- future: sortRooms () ,
157+ future: _sortFuture ,
123158 builder: (context, snapshot) {
124159 if (snapshot.data != null ) {
125160 _sortCache = snapshot.data! ;
0 commit comments