feat(feed): mdToHtml

This commit is contained in:
mso7nueh
2025-10-24 18:55:01 +03:00
parent ce0099c385
commit fb5a0d52bc
10 changed files with 355 additions and 329 deletions

View File

@@ -15,15 +15,13 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:share_plus/share_plus.dart';
class MyRecipeWidget extends StatefulWidget {
final MyRecipeModel recipe;
const MyRecipeWidget({
super.key,
required this.recipe,
});
const MyRecipeWidget({super.key, required this.recipe});
@override
State<MyRecipeWidget> createState() => _MyRecipeWidgetState();
@@ -50,10 +48,7 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
Widget build(BuildContext context) {
final s = S.of(context);
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: Colors.white),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -61,13 +56,7 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
Stack(
children: [
InkWell(
onTap: () async => GoRouter.of(context).pushNamed(
'aboutRecipesScreen',
extra: {
'recipe': widget.recipe.slug,
'navigateToComments': false,
},
),
onTap: () async => GoRouter.of(context).pushNamed('aboutRecipesScreen', extra: {'recipe': widget.recipe.slug, 'navigateToComments': false}),
child: ClipRRect(
borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
child: CachedNetworkImage(
@@ -99,28 +88,48 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
widget.recipe.title!,
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
),
child: Text(widget.recipe.title!, style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
),
if (widget.recipe.description.isNotEmpty) ...[
const SizedBox(
height: 12,
),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Html(
data: widget.recipe.description.length > 200
? '${widget.recipe.description.substring(0, 200).replaceAll('\n', '<br>')}...'
: widget.recipe.description.replaceAll('\n', '<br>'),
data: md.markdownToHtml(
widget.recipe.description.length > 200
? '${widget.recipe.description.substring(0, 200).replaceAll('\n', '<br>')}...'
: widget.recipe.description.replaceAll('\n', '<br>'),
),
style: {
"*": Style(
"body": Style(
margin: Margins.zero,
color: appTheme.black,
padding: HtmlPaddings.zero,
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
lineHeight: const LineHeight(1.5),
),
"p": Style(margin: Margins.only(bottom: 12), color: appTheme.black),
"h1, h2, h3, h4, h5, h6": Style(margin: Margins.only(top: 16, bottom: 8), color: appTheme.black, fontWeight: FontWeight.bold),
"h1": Style(fontSize: FontSize(24)),
"h2": Style(fontSize: FontSize(20)),
"h3": Style(fontSize: FontSize(18)),
"ul, ol": Style(margin: Margins.only(bottom: 12), padding: HtmlPaddings.only(left: 16)),
"li": Style(margin: Margins.only(bottom: 4), color: appTheme.black),
"strong, b": Style(fontWeight: FontWeight.bold, color: appTheme.black),
"em, i": Style(fontStyle: FontStyle.italic),
"code": Style(
backgroundColor: Colors.grey.shade100,
padding: HtmlPaddings.symmetric(horizontal: 4, vertical: 2),
fontFamily: 'monospace',
),
"pre": Style(backgroundColor: Colors.grey.shade100, padding: HtmlPaddings.all(12), margin: Margins.only(bottom: 12)),
"blockquote": Style(
padding: HtmlPaddings.only(left: 16),
margin: Margins.only(left: 8, bottom: 12),
fontStyle: FontStyle.italic,
color: Colors.grey.shade700,
),
"a": Style(color: Colors.blue, textDecoration: TextDecoration.underline),
"img": Style(width: Width(MediaQuery.of(context).size.width - 32)),
},
),
),
@@ -192,26 +201,17 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
Container _iconButton(String iconPath, [String? text]) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
color: appTheme.whiteA700,
borderRadius: BorderRadius.circular(16),
),
decoration: BoxDecoration(color: appTheme.whiteA700, borderRadius: BorderRadius.circular(16)),
height: 32,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
iconPath,
),
SvgPicture.asset(iconPath),
if (text != null) const SizedBox(width: 8),
if (text != null)
Text(
text,
style: const TextStyle(
fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.w500,
),
style: const TextStyle(fontSize: 12, color: Colors.black, fontWeight: FontWeight.w500),
),
],
),