Skip to content

Commit d67be76

Browse files
committed
msglist [nfc]: Pull out sliver helper for our SliverStickyHeaderList
1 parent 3196263 commit d67be76

File tree

1 file changed

+38
-35
lines changed

1 file changed

+38
-35
lines changed

lib/widgets/message_list.dart

+38-35
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,43 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
298298
Widget _buildListView(BuildContext context) {
299299
final length = model!.items.length;
300300
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+
301338
return CustomScrollView(
302339
// TODO: Offer `ScrollViewKeyboardDismissBehavior.interactive` (or
303340
// similar) if that is ever offered:
@@ -316,41 +353,7 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
316353
center: centerSliverKey,
317354

318355
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,
354357

355358
// This is a trivial placeholder that occupies no space. Its purpose is
356359
// to have the key that's passed to [ScrollView.center], and so to cause

0 commit comments

Comments
 (0)