11import 'package:flutter/cupertino.dart' ;
22import 'package:flutter/material.dart' ;
3+ import 'package:flutter_highlight/themes/paraiso-dark.dart' ;
34import 'package:habr_app/stores/app_settings.dart' ;
45import 'package:provider/provider.dart' ;
56import 'package:itertools/itertools.dart' ;
@@ -16,31 +17,59 @@ import 'package:habr_app/utils/log.dart';
1617class HtmlView extends StatelessWidget {
1718 final view.Node node;
1819 final TextAlign ? textAlign;
20+ final bool imagesWithPadding;
21+ final EdgeInsets ? padding;
1922
20- HtmlView (this .node, {this .textAlign});
23+ HtmlView (
24+ this .node, {
25+ this .textAlign,
26+ this .imagesWithPadding = true ,
27+ this .padding,
28+ });
2129
2230 @override
2331 Widget build (BuildContext context) {
2432 return Column (
2533 children: inlineTree (
2634 node,
2735 context,
28- BuildParams (textAlign: textAlign),
36+ BuildParams (
37+ textAlign: textAlign,
38+ imagesWithPadding: imagesWithPadding,
39+ padding: padding,
40+ ),
2941 ).toList (),
3042 crossAxisAlignment: CrossAxisAlignment .stretch,
3143 );
3244 }
3345
34- HtmlView .unparsed (String ? html, {this .textAlign})
35- : node = htmlAsParsedJson (html);
46+ HtmlView .unparsed (
47+ String ? html, {
48+ this .textAlign,
49+ this .imagesWithPadding = false ,
50+ this .padding,
51+ }) : node = htmlAsParsedJson (html);
3652}
3753
3854class BuildParams {
3955 final TextAlign ? textAlign;
56+ final bool imagesWithPadding;
57+ final EdgeInsets ? padding;
4058
41- BuildParams ({this .textAlign});
59+ BuildParams ({
60+ this .textAlign,
61+ required this .imagesWithPadding,
62+ this .padding,
63+ });
4264}
4365
66+ Widget wrapPadding (Widget child, BuildParams params) => params.padding != null
67+ ? Padding (
68+ padding: params.padding! ,
69+ child: child,
70+ )
71+ : child;
72+
4473// may be null
4574Widget ? buildTree (view.Node element, BuildContext context, BuildParams params) {
4675 final type = element.type;
@@ -56,11 +85,13 @@ Widget? buildTree(view.Node element, BuildContext context, BuildParams params) {
5685 if (element is view.HeadLine ) {
5786 final mode = HeadLineType .values[int .parse (element.mode.substring (1 )) - 1 ];
5887 widget = HeadLine (text: element.text, type: mode);
88+ widget = wrapPadding (widget, params);
5989 } else if (element is view.TextParagraph ) {
6090 widget = Text (
6191 element.text,
6292 textAlign: params.textAlign,
6393 );
94+ widget = wrapPadding (widget, params);
6495 } else if (element is view.Paragraph ) {
6596 widget = Text .rich (
6697 TextSpan (
@@ -69,6 +100,7 @@ Widget? buildTree(view.Node element, BuildContext context, BuildParams params) {
69100 .toList ()),
70101 textAlign: params.textAlign,
71102 );
103+ widget = wrapPadding (widget, params);
72104 } else if (element is view.Scrollable ) {
73105 widget = SingleChildScrollView (
74106 child: buildTree (element.child, context, params),
@@ -88,6 +120,12 @@ Widget? buildTree(view.Node element, BuildContext context, BuildParams params) {
88120 distance: 5 ,
89121 );
90122 }
123+ if (params.imagesWithPadding) {
124+ widget = Padding (
125+ padding: params.padding! ,
126+ child: widget,
127+ );
128+ }
91129 } else if (element is view.Code ) {
92130 final appSettings = Provider .of <AppSettings >(context, listen: false );
93131 widget = HighlightCode (
@@ -100,28 +138,33 @@ Widget? buildTree(view.Node element, BuildContext context, BuildParams params) {
100138 );
101139 } else if (element is view.BlockQuote ) {
102140 widget = BlockQuote (child: buildTree (element.child, context, params));
141+ widget = wrapPadding (widget, params);
103142 } else if (element is view.BlockList ) {
104143 // TODO: ordered list
105144 widget = UnorderedList (
106145 children: element.children
107146 .map <Widget ?>((li) => buildTree (li, context, params))
108147 .notNull
109148 .toList ());
149+ widget = wrapPadding (widget, params);
110150 } else if (element is view.BlockColumn ) {
111151 widget = WrappedContainer (
112152 children: element.children
113153 .map <Widget ?>((child) => buildTree (child, context, params))
114154 .notNull
115155 .toList ());
156+ widget = wrapPadding (widget, params);
116157 } else if (element is view.Details ) {
117158 widget = Spoiler (
118159 title: element.title,
119160 child: buildTree (element.child, context, params),
120161 );
162+ widget = wrapPadding (widget, params);
121163 } else if (element is view.Iframe ) {
122164 widget = Iframe (
123165 src: element.src,
124166 );
167+ widget = wrapPadding (widget, params);
125168 } else if (element is view.Table ) {
126169 try {
127170 widget = Table (
@@ -141,6 +184,7 @@ Widget? buildTree(view.Node element, BuildContext context, BuildParams params) {
141184 } catch (err) {
142185 widget = Text ("Unsupported table" );
143186 }
187+ widget = wrapPadding (widget, params);
144188 } else {
145189 logInfo ("Not found case for $type " );
146190 }
@@ -186,7 +230,8 @@ Iterable<Widget> inlineTree(
186230 }
187231 } else if (element is view.BlockList ) {
188232 for (final item in element.children) {
189- yield UnorderedItem (child: buildTree (item, context, params)! );
233+ yield wrapPadding (
234+ UnorderedItem (child: buildTree (item, context, params)! ), params);
190235 }
191236 } else {
192237 yield buildTree (element! , context, params)! ;
0 commit comments