Skip to content

Commit

Permalink
Merge pull request #66 from The-Redhat/master
Browse files Browse the repository at this point in the history
use preCacheImage to catch errors while image loading
  • Loading branch information
Sub6Resources committed May 13, 2019
2 parents f8cb452 + fa50be5 commit 1169d15
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [0.9.7] - March 26, 2019:

* Added onImageError callback

## [0.9.6] - March 11, 2019:

* Fix whitespace issue. ([#59](https://github.com/Sub6Resources/flutter_html/issues/59))
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A Flutter widget for rendering static html tags as Flutter widgets. (Will render
Add the following to your `pubspec.yaml` file:

dependencies:
flutter_html: ^0.9.6
flutter_html: ^0.9.7

## Currently Supported HTML Tags:
`a`, `abbr`, `acronym`, `address`, `article`, `aside`, `b`, `bdi`, `bdo`, `big`, `blockquote`, `body`, `br`, `caption`, `cite`, `code`, `data`, `dd`, `del`, `dfn`, `div`, `dl`, `dt`, `em`, `figcaption`, `figure`, `footer`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `header`, `hr`, `i`, `img`, `ins`, `kbd`, `li`, `main`, `mark`, `nav`, `noscript`, `ol`, `p`, `pre`, `q`, `rp`, `rt`, `ruby`, `s`, `samp`, `section`, `small`, `span`, `strike`, `strong`, `sub`, `sup`, `table`, `tbody`, `td`, `template`, `tfoot`, `th`, `thead`, `time`, `tr`, `tt`, `u`, `ul`, `var`
Expand Down
4 changes: 4 additions & 0 deletions lib/flutter_html.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Html extends StatelessWidget {
this.customRender,
this.blockSpacing = 14.0,
this.useRichText = false,
this.onImageError,
this.linkStyle = const TextStyle(
decoration: TextDecoration.underline,
color: Colors.blueAccent,
Expand All @@ -29,6 +30,7 @@ class Html extends StatelessWidget {
final bool renderNewlines;
final double blockSpacing;
final bool useRichText;
final ImageErrorListener onImageError;
final TextStyle linkStyle;

/// Either return a custom widget for specific node types or return null to
Expand All @@ -51,6 +53,7 @@ class Html extends StatelessWidget {
onLinkTap: onLinkTap,
renderNewlines: renderNewlines,
html: data,
onImageError: onImageError,
linkStyle: linkStyle,
)
: HtmlOldParser(
Expand All @@ -60,6 +63,7 @@ class Html extends StatelessWidget {
customRender: customRender,
html: data,
blockSpacing: blockSpacing,
onImageError: onImageError,
linkStyle: linkStyle,
),
),
Expand Down
81 changes: 58 additions & 23 deletions lib/html_parser.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:html/parser.dart' as parser;
import 'package:flutter/material.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as parser;

typedef CustomRender = Widget Function(dom.Node node, List<Widget> children);
typedef OnLinkTap = void Function(String url);
Expand Down Expand Up @@ -144,6 +144,7 @@ class HtmlRichTextParser extends StatelessWidget {
this.onLinkTap,
this.renderNewlines = false,
this.html,
this.onImageError,
this.linkStyle = const TextStyle(
decoration: TextDecoration.underline,
color: Colors.blueAccent,
Expand All @@ -156,6 +157,7 @@ class HtmlRichTextParser extends StatelessWidget {
final onLinkTap;
final bool renderNewlines;
final String html;
final ImageErrorListener onImageError;
final TextStyle linkStyle;

// style elements set a default style
Expand Down Expand Up @@ -266,7 +268,8 @@ class HtmlRichTextParser extends StatelessWidget {
);

// ignore the top level "body"
body.nodes.forEach((dom.Node node) => _parseNode(node, parseContext));
body.nodes
.forEach((dom.Node node) => _parseNode(node, parseContext, context));
// _parseNode(body, parseContext);

// filter out empty widgets
Expand Down Expand Up @@ -303,7 +306,8 @@ class HtmlRichTextParser extends StatelessWidget {
// function can add child nodes to the parent if it should
//
// each iteration creates a new parseContext as a copy of the previous one if it needs to
void _parseNode(dom.Node node, ParseContext parseContext) {
void _parseNode(
dom.Node node, ParseContext parseContext, BuildContext buildContext) {
// TEXT ONLY NODES
// a text only node is a child of a tag with no inner html
if (node is dom.Text) {
Expand Down Expand Up @@ -624,9 +628,23 @@ class HtmlRichTextParser extends StatelessWidget {
if (node.attributes['src'] != null) {
if (node.attributes['src'].startsWith("data:image") &&
node.attributes['src'].contains("base64,")) {
precacheImage(
MemoryImage(
base64.decode(
node.attributes['src'].split("base64,")[1].trim(),
),
),
buildContext,
onError: onImageError,
);
parseContext.rootWidgetList.add(Image.memory(base64.decode(
node.attributes['src'].split("base64,")[1].trim())));
} else {
precacheImage(
NetworkImage(node.attributes['src']),
buildContext,
onError: onImageError,
);
parseContext.rootWidgetList
.add(Image.network(node.attributes['src']));
}
Expand Down Expand Up @@ -743,7 +761,7 @@ class HtmlRichTextParser extends StatelessWidget {
}

node.nodes.forEach((dom.Node childNode) {
_parseNode(childNode, nextContext);
_parseNode(childNode, nextContext, buildContext);
});
}
}
Expand Down Expand Up @@ -817,6 +835,7 @@ class HtmlOldParser extends StatelessWidget {
this.customRender,
this.blockSpacing,
this.html,
this.onImageError,
this.linkStyle = const TextStyle(
decoration: TextDecoration.underline,
color: Colors.blueAccent,
Expand All @@ -829,6 +848,7 @@ class HtmlOldParser extends StatelessWidget {
final CustomRender customRender;
final double blockSpacing;
final String html;
final ImageErrorListener onImageError;
final TextStyle linkStyle;

static const _supportedElements = [
Expand Down Expand Up @@ -1291,24 +1311,39 @@ class HtmlOldParser extends StatelessWidget {
),
);
case "img":
if (node.attributes['src'] != null) {
if (node.attributes['src'].startsWith("data:image") &&
node.attributes['src'].contains("base64,")) {
return Image.memory(base64
.decode(node.attributes['src'].split("base64,")[1].trim()));
}
return Image.network(node.attributes['src']);
} else if (node.attributes['alt'] != null) {
//Temp fix for https://github.com/flutter/flutter/issues/736
if (node.attributes['alt'].endsWith(" ")) {
return Container(
padding: EdgeInsets.only(right: 2.0),
child: Text(node.attributes['alt']));
} else {
return Text(node.attributes['alt']);
}
}
return Container();
return Builder(
builder: (BuildContext context) {
if (node.attributes['src'] != null) {
if (node.attributes['src'].startsWith("data:image") &&
node.attributes['src'].contains("base64,")) {
precacheImage(
MemoryImage(base64.decode(
node.attributes['src'].split("base64,")[1].trim())),
context,
onError: onImageError,
);
return Image.memory(base64.decode(
node.attributes['src'].split("base64,")[1].trim()));
}
precacheImage(
NetworkImage(node.attributes['src']),
context,
onError: onImageError,
);
return Image.network(node.attributes['src']);
} else if (node.attributes['alt'] != null) {
//Temp fix for https://github.com/flutter/flutter/issues/736
if (node.attributes['alt'].endsWith(" ")) {
return Container(
padding: EdgeInsets.only(right: 2.0),
child: Text(node.attributes['alt']));
} else {
return Text(node.attributes['alt']);
}
}
return Container();
},
);
case "ins":
return DefaultTextStyle.merge(
child: Wrap(
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_html
description: A Flutter widget for rendering static html tags as Flutter widgets. (Will render over 70 different html tags!)
version: 0.9.6
version: 0.9.7
author: Matthew Whitaker <sub6resources@gmail.com>
homepage: https://github.com/Sub6Resources/flutter_html

Expand Down

0 comments on commit 1169d15

Please sign in to comment.