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