relatica/lib/controls/timeline/status_control.dart

176 wiersze
5.0 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 'package:provider/provider.dart';
import '../../models/entry_tree_item.dart';
import '../../models/timeline_entry.dart';
import '../../services/timeline_manager.dart';
import '../../utils/url_opening_utils.dart';
import '../media_attachment_viewer_control.dart';
import '../padding.dart';
import 'interactions_bar_control.dart';
import 'status_header_control.dart';
class StatusControl extends StatefulWidget {
final EntryTreeItem originalItem;
final bool openRemote;
final bool showStatusOpenButton;
const StatusControl(
{super.key,
required this.originalItem,
required this.openRemote,
required this.showStatusOpenButton});
@override
State<StatusControl> createState() => _StatusControlState();
}
class _StatusControlState extends State<StatusControl> {
static final _logger = Logger('$StatusControl');
var showContent = true;
var showComments = false;
EntryTreeItem get item => widget.originalItem;
TimelineEntry get entry => item.entry;
bool get isPublic => item.entry.isPublic;
bool get isPost => item.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) {
final manager = context.watch<TimelineManager>();
_logger.finest('Building ${item.entry.toShortString()}');
final padding = isPost ? 8.0 : 8.0;
final body = Padding(
padding: EdgeInsets.all(padding),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusHeaderControl(
entry: entry,
openRemote: widget.openRemote,
showOpenControl: widget.showStatusOpenButton,
),
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,
),
buildMediaBar(context),
],
const VerticalPadding(
height: 5,
),
InteractionsBarControl(
entry: entry,
isMine: item.isMine,
),
const VerticalPadding(
height: 5,
),
if (isPost && hasComments)
TextButton(
onPressed: () async {
setState(() {
showComments = !showComments;
});
if (showComments) {
await manager.refreshStatusChain(item.id);
}
},
child:
Text(showComments ? 'Hide Comments' : 'Load & Show Comments'),
),
if (item.totalChildren > 0 && showComments)
buildChildComments(context),
],
),
);
return isPost
? body
: Card(color: Theme.of(context).splashColor, child: body);
}
Widget buildBody(BuildContext context) {
return HtmlWidget(
entry.body,
onTapUrl: (url) async {
return await openUrlStringInSystembrowser(context, url, 'video');
},
);
}
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(attachment: items[index]);
},
separatorBuilder: (context, index) {
return HorizontalPadding();
},
itemCount: items.length));
}
Widget buildChildComments(BuildContext context) {
final comments = widget.originalItem.children;
if (comments.isEmpty) {
return Text('No comments');
}
return Padding(
padding: EdgeInsets.only(left: 5.0, top: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
children: comments
.map((c) => StatusControl(
originalItem: c,
openRemote: false,
showStatusOpenButton: false,
))
.toList(),
),
),
],
));
}
}