relatica/lib/controls/timeline/flattened_tree_entry_contro...

146 wiersze
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:logging/logging.dart';
import '../../models/flattened_tree_item.dart';
import '../../models/timeline_entry.dart';
import '../../utils/url_opening_utils.dart';
import '../media_attachment_viewer_control.dart';
import '../padding.dart';
import 'interactions_bar_control.dart';
import 'link_preview_control.dart';
import 'status_header_control.dart';
class FlattenedTreeEntryControl extends StatefulWidget {
final FlattenedTreeItem originalItem;
final bool openRemote;
final bool showStatusOpenButton;
const FlattenedTreeEntryControl(
{super.key,
required this.originalItem,
required this.openRemote,
required this.showStatusOpenButton});
@override
State<FlattenedTreeEntryControl> createState() => _StatusControlState();
}
class _StatusControlState extends State<FlattenedTreeEntryControl> {
static final _logger = Logger('$FlattenedTreeEntryControl');
var showContent = true;
var showComments = false;
FlattenedTreeItem get item => widget.originalItem;
TimelineEntry get entry => item.timelineEntry;
bool get isPublic => entry.isPublic;
bool get isPost => entry.parentId.isEmpty;
bool get hasComments => entry.engagementSummary.repliesCount > 0;
@override
void initState() {
showContent = entry.spoilerText.isEmpty;
showComments = isPost ? false : true;
}
@override
Widget build(BuildContext context) {
_logger.finest('Building ${entry.toShortString()}');
const otherPadding = 8.0;
final leftPadding = otherPadding + (widget.originalItem.level * 15.0);
final color = widget.originalItem.level.isOdd
? Theme.of(context).splashColor
: Theme.of(context).cardColor;
final body = Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusHeaderControl(
entry: entry,
),
const VerticalPadding(
height: 5,
),
if (entry.spoilerText.isNotEmpty)
TextButton(
onPressed: () {
setState(() {
showContent = !showContent;
});
},
child: Text(
'Content Summary: ${entry.spoilerText} (Click to ${showContent ? "Hide" : "Show"}}')),
if (showContent) ...[
buildBody(context),
const VerticalPadding(
height: 5,
),
if (entry.linkPreviewData != null)
LinkPreviewControl(preview: entry.linkPreviewData!),
buildMediaBar(context),
],
const VerticalPadding(
height: 5,
),
InteractionsBarControl(
entry: entry,
isMine: item.isMine,
openRemote: widget.openRemote,
showOpenControl: widget.showStatusOpenButton,
),
const VerticalPadding(
height: 5,
),
],
),
);
return Padding(
padding: EdgeInsets.only(
left: leftPadding,
right: otherPadding,
top: otherPadding,
bottom: otherPadding,
),
child: isPost ? body : Card(color: color, child: body),
);
}
Widget buildBody(BuildContext context) {
return HtmlWidget(
entry.body,
onTapUrl: (url) async {
return await openUrlStringInSystembrowser(context, url, 'link');
},
);
}
Widget buildMediaBar(BuildContext context) {
final items = entry.mediaAttachments;
if (items.isEmpty) {
return const SizedBox();
}
return SizedBox(
height: 250.0,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return MediaAttachmentViewerControl(
attachments: items,
index: index,
);
},
separatorBuilder: (context, index) {
return HorizontalPadding();
},
itemCount: items.length));
}
}