diff --git a/lib/features/blog_post/presentation/pages/blog_post_screen.dart b/lib/features/blog_post/presentation/pages/blog_post_screen.dart index e8840cd2..915a61fb 100644 --- a/lib/features/blog_post/presentation/pages/blog_post_screen.dart +++ b/lib/features/blog_post/presentation/pages/blog_post_screen.dart @@ -26,11 +26,7 @@ class BlogPostScreen extends StatefulWidget { final int id; final int? highlightedCommentId; - const BlogPostScreen({ - super.key, - required this.id, - this.highlightedCommentId, - }); + const BlogPostScreen({super.key, required this.id, this.highlightedCommentId}); @override State createState() => _BlogPostScreenState(); @@ -49,10 +45,7 @@ class _BlogPostScreenState extends State { } void _openGallery(List imageUrls, int index, {Object? heroTag}) { - context.pushTransparentRoute( - rootNavigator: true, - PhotoViewScreen(imageUrls: imageUrls, index: index, heroTag: heroTag), - ); + context.pushTransparentRoute(rootNavigator: true, PhotoViewScreen(imageUrls: imageUrls, index: index, heroTag: heroTag)); } @override @@ -60,8 +53,7 @@ class _BlogPostScreenState extends State { return BlocProvider( create: (context) => sl()..getBlogPost(widget.id), child: BlocProvider( - create: (BuildContext context) => commentsCubit - ..getComments(widget.id.toString(), CommentSourceType.blogPost, true), + create: (BuildContext context) => commentsCubit..getComments(widget.id.toString(), CommentSourceType.blogPost, true), child: BlocBuilder( builder: (context, blogPostState) { return BlocConsumer( @@ -89,23 +81,15 @@ class _BlogPostScreenState extends State { body: const Loader(), ); } - final bool isLiked = - blogPostState.blogPostModel?.wasLikedByMe ?? false; - final int totalLikes = - blogPostState.blogPostModel?.totalLikes ?? 0; + final bool isLiked = blogPostState.blogPostModel?.wasLikedByMe ?? false; + final int totalLikes = blogPostState.blogPostModel?.totalLikes ?? 0; return Scaffold( resizeToAvoidBottomInset: true, bottomSheet: Container( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).padding.bottom + 8, - ), + padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 8), decoration: BoxDecoration( color: Colors.white, - border: Border( - top: BorderSide( - color: Colors.black.withValues(alpha: 0.1), - ), - ), + border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1))), ), child: Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 0), @@ -123,17 +107,10 @@ class _BlogPostScreenState extends State { FocusManager.instance.primaryFocus?.unfocus(); }, child: Container( - decoration: BoxDecoration( - color: appTheme.blueA400, - shape: BoxShape.circle, - ), + decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle), height: 32, width: 32, - child: const Icon( - Icons.close_rounded, - size: 18, - color: Colors.white, - ), + child: const Icon(Icons.close_rounded, size: 18, color: Colors.white), ), ), if (replyId != null) const SizedBox(width: 8), @@ -141,8 +118,7 @@ class _BlogPostScreenState extends State { child: ConstrainedBox( constraints: const BoxConstraints(minHeight: 52), child: TextFormField( - textCapitalization: - TextCapitalization.sentences, + textCapitalization: TextCapitalization.sentences, onChanged: (_) { setState(() {}); }, @@ -150,48 +126,26 @@ class _BlogPostScreenState extends State { maxLines: 5, minLines: 1, keyboardType: TextInputType.multiline, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Colors.black, - height: 1.2, - ), + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, height: 1.2), decoration: InputDecoration( isDense: false, // убираем true, чтобы padding учитывался корректно - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), // вертикальный паддинг увеличен hintText: S.of(context).comment_hint, - hintStyle: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - height: 1.2, - color: Color(0xFFAEAEB2), - ), + hintStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.2, color: Color(0xFFAEAEB2)), filled: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: Color(0xFFD1D1D6), - width: 1, - ), + borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: Color(0xFFD1D1D6), - width: 1, - ), + borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: const BorderSide( - color: Color(0xFFD1D1D6), - width: 1, - ), + borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1), ), ), ), @@ -209,10 +163,7 @@ class _BlogPostScreenState extends State { ); if (!context.mounted) return; - if (isSent) - context - .read() - .incrementCommentsState(widget.id); + if (isSent) context.read().incrementCommentsState(widget.id); context.read().setReplyId(null); setState(() { @@ -223,19 +174,10 @@ class _BlogPostScreenState extends State { } }, child: Container( - decoration: BoxDecoration( - color: textEditingController.text.length > 2 - ? appTheme.blueA400 - : Colors.grey, - shape: BoxShape.circle, - ), + decoration: BoxDecoration(color: textEditingController.text.length > 2 ? appTheme.blueA400 : Colors.grey, shape: BoxShape.circle), height: 32, width: 32, - child: const Icon( - Icons.send_rounded, - size: 18, - color: Colors.white, - ), + child: const Icon(Icons.send_rounded, size: 18, color: Colors.white), ), ), ], @@ -255,33 +197,23 @@ class _BlogPostScreenState extends State { ), actions: [ CustomPopup( - isAuthor: - blogPostState.blogPostModel?.author.authorIsMe ?? - false, + isAuthor: blogPostState.blogPostModel?.author.authorIsMe ?? false, complainedContentType: ComplainedContent.posts, path: 'blog_post/${(widget.id)}', id: widget.id, feedBlogPostModel: blogPostState.blogPostModel, - userSlug: - blogPostState.blogPostModel?.author.authorSlug ?? - '', + userSlug: blogPostState.blogPostModel?.author.authorSlug ?? '', ), const SizedBox(width: 16), ], ), body: SingleChildScrollView( - padding: EdgeInsets.only( - bottom: 160 + MediaQuery.of(context).padding.bottom, - ), // поле комментария (52-200) + padding (12+12+56) + safe area + padding: EdgeInsets.only(bottom: 160 + MediaQuery.of(context).padding.bottom), // поле комментария (52-200) + padding (12+12+56) + safe area physics: const BouncingScrollPhysics(), child: Column( children: [ GestureDetector( - onTap: () => GoRouter.of(context).pushNamed( - 'profileScreen', - extra: - blogPostState.blogPostModel?.author.authorSlug, - ), + onTap: () => GoRouter.of(context).pushNamed('profileScreen', extra: blogPostState.blogPostModel?.author.authorSlug), child: Ink( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( @@ -290,46 +222,21 @@ class _BlogPostScreenState extends State { children: [ CircleAvatar( radius: 16, - foregroundImage: NetworkImage( - sl().baseUrl + - (blogPostState - .blogPostModel - ?.author - .authorProfileIcon ?? - ''), - ), - backgroundImage: const AssetImage( - 'assets/images/no_avatar.png', - ), + foregroundImage: NetworkImage(sl().baseUrl + (blogPostState.blogPostModel?.author.authorProfileIcon ?? '')), + backgroundImage: const AssetImage('assets/images/no_avatar.png'), ), const SizedBox(width: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - blogPostState - .blogPostModel - ?.author - .authorName ?? - '', - style: const TextStyle( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.w400, - height: 1, - ), + blogPostState.blogPostModel?.author.authorName ?? '', + style: const TextStyle(color: Colors.black, fontSize: 14, fontWeight: FontWeight.w400, height: 1), ), const SizedBox(height: 2), Text( - (blogPostState.blogPostModel?.createdAt ?? - DateTime.now()) - .format('dd MMMM', 'ru'), - style: TextStyle( - color: Colors.grey.shade600, - fontSize: 12, - fontWeight: FontWeight.w400, - height: 1, - ), + (blogPostState.blogPostModel?.createdAt ?? DateTime.now()).format('dd MMMM', 'ru'), + style: TextStyle(color: Colors.grey.shade600, fontSize: 12, fontWeight: FontWeight.w400, height: 1), ), ], ), @@ -337,20 +244,10 @@ class _BlogPostScreenState extends State { ), ), ), - if (blogPostState - .blogPostModel - ?.description - .isNotEmpty ?? - false) + if (blogPostState.blogPostModel?.description.isNotEmpty ?? false) Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: MarkdownHtmlWidget( - markdownText: - blogPostState.blogPostModel!.description, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: MarkdownHtmlWidget(markdownText: blogPostState.blogPostModel!.description), ), const SizedBox(height: 8), Builder( @@ -359,31 +256,16 @@ class _BlogPostScreenState extends State { if (post == null) { return const SizedBox.shrink(); } - final imageUrl = PostFeedMapper.resolveMediaUrl( - post.image, - ); + final imageUrl = PostFeedMapper.resolveMediaUrl(post.image); final embedUrl = post.videoEmbedUrl?.trim(); return BlogPostMediaContent( galleryImages: post.images, imageUrl: imageUrl, - videoEmbedUrl: - embedUrl != null && embedUrl.isNotEmpty - ? embedUrl - : null, - videoUrlThumb: post.videoUrlThumb != null - ? PostFeedMapper.resolveMediaUrl( - post.videoUrlThumb, - ) - : null, + videoEmbedUrl: embedUrl != null && embedUrl.isNotEmpty ? embedUrl : null, + videoUrlThumb: post.videoUrlThumb != null ? PostFeedMapper.resolveMediaUrl(post.videoUrlThumb) : null, currentGalleryIndex: currentGalleryIndex, heroTag: 'blog-post-screen-${post.id}-cover', - onOpenGallery: (urls, index) => _openGallery( - urls, - index, - heroTag: urls.length == 1 - ? 'blog-post-screen-${post.id}-cover' - : null, - ), + onOpenGallery: (urls, index) => _openGallery(urls, index, heroTag: urls.length == 1 ? 'blog-post-screen-${post.id}-cover' : null), onGalleryChanged: (index) { setState(() { currentGalleryIndex = index; @@ -393,43 +275,22 @@ class _BlogPostScreenState extends State { }, ), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ _iconButton( - icon: isLiked - ? Icons.favorite_rounded - : Icons.favorite_border_rounded, + icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded, text: totalLikes.toString(), - iconColor: isLiked - ? Colors.red.withValues(alpha: 0.8) - : null, - backgroundColor: isLiked - ? Colors.red.withValues(alpha: 0.1) - : null, - textColor: isLiked - ? Colors.red.withValues(alpha: 0.8) - : null, + iconColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null, + backgroundColor: isLiked ? Colors.red.withValues(alpha: 0.1) : null, + textColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null, onTap: () async { - await context - .read() - .toggleLike(); + await context.read().toggleLike(); // ignore: use_build_context_synchronously - final updated = context - .read() - .state - .blogPostModel; + final updated = context.read().state.blogPostModel; if (updated != null) { // ignore: use_build_context_synchronously - context - .read() - .updateFeedBlogPostList( - updated, - updated.wasLikedByMe, - ); + context.read().updateFeedBlogPostList(updated, updated.wasLikedByMe); } }, ), @@ -437,36 +298,21 @@ class _BlogPostScreenState extends State { _iconButton( icon: Icons.reply_rounded, onTap: () { - final box = - context.findRenderObject() as RenderBox?; + final box = context.findRenderObject() as RenderBox?; SharePlus.instance.share( ShareParams( - uri: Uri.parse( - '${sl().baseUrl}/ru/blog_post/${widget.id}', - ), - sharePositionOrigin: - box!.localToGlobal(Offset.zero) & - box.size, + uri: Uri.parse('${sl().baseUrl}/ru/blog_post/${widget.id}'), + sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, ), ); }, ), const Spacer(), - Icon( - Icons.visibility_rounded, - size: 16, - color: appTheme.gray500, - ), + Icon(Icons.visibility_rounded, size: 16, color: appTheme.gray500), const SizedBox(width: 4), Text( - blogPostState.blogPostModel?.totalViews - .toString() ?? - '', - style: TextStyle( - fontSize: 12, - color: appTheme.gray500, - fontWeight: FontWeight.w400, - ), + blogPostState.blogPostModel?.totalViews.toString() ?? '', + style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400), ), ], ), @@ -474,10 +320,7 @@ class _BlogPostScreenState extends State { Container( width: MediaQuery.of(context).size.width - 32, height: 0.4, - decoration: BoxDecoration( - color: Colors.black.withValues(alpha: 0.2), - borderRadius: BorderRadius.circular(16), - ), + decoration: BoxDecoration(color: Colors.black.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(16)), ), const SizedBox(height: 8), Container( @@ -485,11 +328,7 @@ class _BlogPostScreenState extends State { alignment: Alignment.centerLeft, child: Text( '${blogPostState.blogPostModel?.totalComments} КОММЕНТАРИЕВ', - style: TextStyle( - fontSize: 12, - color: appTheme.gray500, - fontWeight: FontWeight.w400, - ), + style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400), ), ), const SizedBox(height: 16), @@ -514,23 +353,13 @@ class _BlogPostScreenState extends State { ); } - InkWell _iconButton({ - required IconData icon, - String? text, - Function()? onTap, - Color? iconColor, - Color? backgroundColor, - Color? textColor, - }) { + InkWell _iconButton({required IconData icon, String? text, Function()? onTap, Color? iconColor, Color? backgroundColor, Color? textColor}) { return InkWell( onTap: onTap ?? () {}, borderRadius: BorderRadius.circular(16), child: Ink( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: backgroundColor ?? appTheme.gray100, - borderRadius: BorderRadius.circular(16), - ), + decoration: BoxDecoration(color: backgroundColor ?? appTheme.gray100, borderRadius: BorderRadius.circular(16)), height: 32, child: Row( mainAxisSize: MainAxisSize.min, @@ -540,10 +369,7 @@ class _BlogPostScreenState extends State { if (text != null) Text( text, - style: TextStyle( - color: textColor ?? appTheme.gray600, - fontWeight: FontWeight.w500, - ), + style: TextStyle(color: textColor ?? appTheme.gray600, fontWeight: FontWeight.w500), ), ], ),