import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_portal/services/entry_manager_service.dart'; import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; import 'package:result_monad/result_monad.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../globals.dart'; import '../../models/attachment_media_type_enum.dart'; import '../../models/connection.dart'; import '../../models/entry_tree_item.dart'; import '../../models/timeline_entry.dart'; import '../../screens/image_viewer_screen.dart'; import '../../services/connections_manager.dart'; import '../../utils/dateutils.dart'; import '../../utils/snackbar_builder.dart'; import '../padding.dart'; import 'interactions_bar_control.dart'; class StatusControl extends StatefulWidget { final EntryTreeItem originalItem; const StatusControl({super.key, required this.originalItem}); @override State createState() => _StatusControlState(); } class _StatusControlState extends State { late EntryTreeItem item; TimelineEntry get entry => item.entry; @override void initState() { super.initState(); item = widget.originalItem; } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ buildHeader(context), const VerticalPadding( height: 5, ), buildBody(context), const VerticalPadding( height: 5, ), buildMediaBar(context), const VerticalPadding( height: 5, ), InteractionsBarControl(entry: entry), const VerticalPadding( height: 5, ), buildChildComments(context), ], ), ); } Widget buildHeader(BuildContext context) { final author = getIt() .getById(entry.authorId) .getValueOrElse(() => Connection()); return Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ CachedNetworkImage( imageUrl: author.avatarUrl.toString(), width: 32.0, ), const HorizontalPadding(), Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( author.name, style: Theme.of(context).textTheme.bodyText1, ), Text( ElapsedDateUtils.epochSecondsToString(entry.backdatedTimestamp), style: Theme.of(context).textTheme.caption, ), Text( item.id, ), ], ), ], ); } Widget buildBody(BuildContext context) { return HtmlWidget( entry.body, onTapUrl: (url) async { final uri = Uri.tryParse(url); if (uri == null) { buildSnackbar(context, 'Bad link: $url'); return false; } if (await canLaunchUrl(uri)) { buildSnackbar( context, 'Attempting to launch video: $url', ); await launchUrl(uri); } else { buildSnackbar(context, 'Unable to launch video: $url'); return false; } return true; }, onTapImage: (imageMetadata) { print(imageMetadata); }, ); } Widget buildMediaBar(BuildContext context) { final items = entry.mediaAttachments; if (items.isEmpty) { return const SizedBox(); } return SizedBox( width: 250.0, height: 250.0, child: ListView.separated( scrollDirection: Axis.horizontal, itemBuilder: (context, index) { final item = items[index]; if (item.explicitType == AttachmentMediaType.video) { return ElevatedButton( onPressed: () async { if (await canLaunchUrl(item.uri)) { buildSnackbar( context, 'Attempting to launch video: ${item.uri}', ); await launchUrl(item.uri); } else { buildSnackbar( context, 'Unable to launch video: ${item.uri}'); } }, child: Text(item.description.isNotEmpty ? item.description : 'Video')); } if (item.explicitType != AttachmentMediaType.image) { return Text('${item.explicitType}: ${item.uri}'); } return InkWell( onTap: () async { Navigator.push(context, MaterialPageRoute(builder: (context) { return ImageViewerScreen(attachment: item); })); }, child: CachedNetworkImage( width: 250.0, height: 250.0, imageUrl: item.thumbnailUri.toString(), ), ); // return Text(item.toString()); }, 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: 20.0, top: 5.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (entry.parentId.isEmpty) ElevatedButton( onPressed: () async { await getIt() .refreshPost(widget.originalItem) .andThenSuccessAsync((newItem) async => setState(() { print('Updated item'); item = newItem; })); }, child: Center( child: Text('Load All'), ), ), Icon(Icons.subdirectory_arrow_right), Expanded( child: Column( children: comments .map((c) => StatusControl(originalItem: c)) .toList(), ), ), ], )); } }