import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../../models/entry_tree_item.dart'; import '../../models/flattened_tree_item.dart'; import '../../models/timeline_entry.dart'; import '../../services/timeline_manager.dart'; import '../../utils/entry_tree_item_flattening.dart'; import 'flattened_tree_entry_control.dart'; class PostControl extends StatefulWidget { final EntryTreeItem originalItem; final String scrollToId; final bool openRemote; final bool showStatusOpenButton; final bool isRoot; const PostControl({ super.key, required this.originalItem, required this.scrollToId, required this.openRemote, required this.showStatusOpenButton, required this.isRoot, }); @override State createState() => _PostControlState(); } class _PostControlState extends State { static final _logger = Logger('$PostControl'); final ItemScrollController itemScrollController = ItemScrollController(); final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create(); var showContent = true; var showComments = false; EntryTreeItem get item => widget.originalItem; TimelineEntry get entry => item.entry; bool get isPublic => item.entry.isPublic; bool get hasComments => entry.engagementSummary.repliesCount > 0; @override void initState() { showContent = entry.spoilerText.isEmpty; showComments = widget.scrollToId != item.id; } @override Widget build(BuildContext context) { final manager = context.watch(); _logger.finest('Building ${item.entry.toShortString()}'); final items = widget.originalItem.flatten(topLevelOnly: !showComments); if (widget.isRoot) { return buildListView(context, items, manager); } else { return buildColumnView(context, items, manager); } } Widget buildColumnView( BuildContext context, List items, TimelineManager manager, ) { final widgets = []; for (var i = 0; i < items.length; i++) { final itemWidget = FlattenedTreeEntryControl( originalItem: items[i], openRemote: widget.openRemote, showStatusOpenButton: widget.showStatusOpenButton, ); widgets.add(itemWidget); if (i == 0 && hasComments) { widgets.add( TextButton( onPressed: () async { setState(() { showComments = !showComments; }); if (showComments) { await manager.refreshStatusChain(entry.id); } }, child: Text(showComments ? 'Hide Comments' : 'Load & Show Comments'), ), ); } } return Column(children: widgets); } Widget buildListView( BuildContext context, List items, TimelineManager manager, ) { final int count; final int offset; final int scrollToIndex; if (hasComments && showComments) { count = items.length + 1; offset = 1; scrollToIndex = items.indexWhere( (e) => e.timelineEntry.id == widget.scrollToId, ); } else if (hasComments) { count = 2; offset = 0; scrollToIndex = 0; } else { count = 1; offset = 0; scrollToIndex = 0; } return ScrollablePositionedList.builder( itemCount: count, initialScrollIndex: scrollToIndex, itemScrollController: itemScrollController, itemPositionsListener: itemPositionsListener, itemBuilder: (context, index) { if (index == 0) { return FlattenedTreeEntryControl( originalItem: items.first, openRemote: widget.openRemote, showStatusOpenButton: widget.showStatusOpenButton, ); } if (index == 1 && hasComments) { return TextButton( onPressed: () async { setState(() { showComments = !showComments; }); if (showComments) { await manager.refreshStatusChain(entry.id); } }, child: Text(showComments ? 'Hide Comments' : 'Load & Show Comments'), ); } return FlattenedTreeEntryControl( originalItem: items[index - offset], openRemote: widget.openRemote, showStatusOpenButton: widget.showStatusOpenButton, ); }); } }