@@ -298,6 +298,43 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
298
298
Widget _buildListView (BuildContext context) {
299
299
final length = model! .items.length;
300
300
const centerSliverKey = ValueKey ('center sliver' );
301
+
302
+ final sliver = SliverStickyHeaderList (
303
+ headerPlacement: HeaderPlacement .scrollingStart,
304
+ delegate: SliverChildBuilderDelegate (
305
+ // To preserve state across rebuilds for individual [MessageItem]
306
+ // widgets as the size of [MessageListView.items] changes we need
307
+ // to match old widgets by their key to their new position in
308
+ // the list.
309
+ //
310
+ // The keys are of type [ValueKey] with a value of [Message.id]
311
+ // and here we use a O(log n) binary search method. This could
312
+ // be improved but for now it only triggers for materialized
313
+ // widgets. As a simple test, flinging through Combined feed in
314
+ // CZO on a Pixel 5, this only runs about 10 times per rebuild
315
+ // and the timing for each call is <100 microseconds.
316
+ //
317
+ // Non-message items (e.g., start and end markers) that do not
318
+ // have state that needs to be preserved have not been given keys
319
+ // and will not trigger this callback.
320
+ findChildIndexCallback: (Key key) {
321
+ final valueKey = key as ValueKey <int >;
322
+ final index = model! .findItemWithMessageId (valueKey.value);
323
+ if (index == - 1 ) return null ;
324
+ return length - 1 - (index - 2 );
325
+ },
326
+ childCount: length + 2 ,
327
+ (context, i) {
328
+ // To reinforce that the end of the feed has been reached:
329
+ // https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20Mark-as-read/near/1680603
330
+ if (i == 0 ) return const SizedBox (height: 36 );
331
+
332
+ if (i == 1 ) return MarkAsReadWidget (narrow: widget.narrow);
333
+
334
+ final data = model! .items[length - 1 - (i - 2 )];
335
+ return _buildItem (data, i);
336
+ }));
337
+
301
338
return CustomScrollView (
302
339
// TODO: Offer `ScrollViewKeyboardDismissBehavior.interactive` (or
303
340
// similar) if that is ever offered:
@@ -316,41 +353,7 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
316
353
center: centerSliverKey,
317
354
318
355
slivers: [
319
- SliverStickyHeaderList (
320
- headerPlacement: HeaderPlacement .scrollingStart,
321
- delegate: SliverChildBuilderDelegate (
322
- // To preserve state across rebuilds for individual [MessageItem]
323
- // widgets as the size of [MessageListView.items] changes we need
324
- // to match old widgets by their key to their new position in
325
- // the list.
326
- //
327
- // The keys are of type [ValueKey] with a value of [Message.id]
328
- // and here we use a O(log n) binary search method. This could
329
- // be improved but for now it only triggers for materialized
330
- // widgets. As a simple test, flinging through Combined feed in
331
- // CZO on a Pixel 5, this only runs about 10 times per rebuild
332
- // and the timing for each call is <100 microseconds.
333
- //
334
- // Non-message items (e.g., start and end markers) that do not
335
- // have state that needs to be preserved have not been given keys
336
- // and will not trigger this callback.
337
- findChildIndexCallback: (Key key) {
338
- final valueKey = key as ValueKey <int >;
339
- final index = model! .findItemWithMessageId (valueKey.value);
340
- if (index == - 1 ) return null ;
341
- return length - 1 - (index - 2 );
342
- },
343
- childCount: length + 2 ,
344
- (context, i) {
345
- // To reinforce that the end of the feed has been reached:
346
- // https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20Mark-as-read/near/1680603
347
- if (i == 0 ) return const SizedBox (height: 36 );
348
-
349
- if (i == 1 ) return MarkAsReadWidget (narrow: widget.narrow);
350
-
351
- final data = model! .items[length - 1 - (i - 2 )];
352
- return _buildItem (data, i);
353
- })),
356
+ sliver,
354
357
355
358
// This is a trivial placeholder that occupies no space. Its purpose is
356
359
// to have the key that's passed to [ScrollView.center], and so to cause
0 commit comments