import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; import 'package:loris/business_logic/account/account.dart'; import 'package:loris/business_logic/timeline/media.dart'; import 'package:loris/partials/media_attachment.dart'; import 'package:loris/partials/post_options.dart'; import 'package:loris/partials/post_text_renderer.dart'; import '../business_logic/timeline/timeline.dart' as tl; class Post extends StatefulWidget { const Post({required this.model, Key? key}) : super(key: key); final tl.PostModel model; @override State createState() => _PostState(); } class _PostState extends State { @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ DisplayName(account: widget.model.account), PostBody( sensitive: widget.model.sensitive, content: widget.model.content, spoilerText: widget.model.spoilerText, media: widget.model.attachments, ), postActionBar(context, widget.model), RebloggedBy(account: widget.model.rebloggedBy), ], ); } } class DisplayName extends StatelessWidget { const DisplayName({ required this.account, Key? key, }) : super(key: key); final AccountModel account; @override Widget build(BuildContext context) { return Row( children: [ ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(8)), child: ProfilePic( url: account.avatar, )), const SizedBox(width: 8), Flexible( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( account.displayName, style: Theme.of(context).textTheme.displaySmall, ), Text( account.acct, style: Theme.of(context).textTheme.bodySmall, ), ], ), ), ], ); } } class RebloggedBy extends StatelessWidget { const RebloggedBy({ required this.account, Key? key, }) : super(key: key); final AccountModel? account; @override Widget build(BuildContext context) { if (account != null) { return Column( children: [ Row( children: [ const Icon(Icons.repeat), Flexible(child: SelectableText("reblogged-by".i18n())), ], ), DisplayName(account: account!), ], ); } else { return const SizedBox.shrink(); } } } class ProfilePic extends StatelessWidget { const ProfilePic({required this.url, Key? key}) : super(key: key); final String url; @override Widget build(BuildContext context) { const double width = 64; if (url.isNotEmpty) { return Image.network( url, errorBuilder: (context, error, stackTrace) => const Icon( Icons.cruelty_free, size: width, ), height: width, width: width, ); } else { return const Icon( Icons.cruelty_free, size: width, ); } } } class PostBody extends StatefulWidget { const PostBody({ required this.sensitive, required this.spoilerText, required this.content, required this.media, Key? key, }) : super(key: key); final String content; final String spoilerText; final bool sensitive; final List media; @override State createState() => _PostBodyState(); } class _PostBodyState extends State { bool visible = false; String cwButtonText = "show".i18n(); Icon cwButtonIcon = const Icon(Icons.visibility); @override Widget build(BuildContext context) { if (!widget.sensitive) { visible = true; } return Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(0, 6, 0, 6), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Visibility( visible: widget.sensitive, child: Text(widget.spoilerText), ), Visibility( visible: widget.sensitive, child: OutlinedButton.icon( onPressed: () { setState(() { visible = !visible; if (visible) { cwButtonIcon = const Icon(Icons.visibility_off); cwButtonText = "hide".i18n(); } else { cwButtonText = "show".i18n(); cwButtonIcon = const Icon(Icons.visibility); } }); }, icon: cwButtonIcon, label: Text(cwButtonText)), ), Visibility( visible: visible, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ PostTextRenderer(htmlInput: widget.content), MediaAttachments(models: widget.media), ], ), ), ], ), ); } } Widget postActionBar(context, tl.PostModel model) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () {}, icon: const Icon(Icons.reply), ), IconButton( onPressed: () {}, icon: const Icon(Icons.repeat), ), IconButton( onPressed: () {}, icon: const Icon(Icons.favorite_outline), ), IconButton( onPressed: () { popupPostOptions(context, model); }, icon: const Icon(Icons.more_horiz), ) ], ); }