relatica/lib/controls/timeline/post_control.dart

163 wiersze
4.6 KiB
Dart

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<PostControl> createState() => _PostControlState();
}
class _PostControlState extends State<PostControl> {
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<TimelineManager>();
_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<FlattenedTreeItem> items,
TimelineManager manager,
) {
final widgets = <Widget>[];
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<FlattenedTreeItem> 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,
);
});
}
}