Mahmoud Abulmagd

Add imageBuilder to config

Add imageBuilder to example
Fix file name typo
@@ -328,8 +328,15 @@ Markdown and LaTeX can be powerful tools for formatting text and mathematical ex @@ -328,8 +328,15 @@ Markdown and LaTeX can be powerful tools for formatting text and mathematical ex
328 RegExp(r"align\*"), 328 RegExp(r"align\*"),
329 (match) => "aligned"); 329 (match) => "aligned");
330 }, 330 },
  331 + imageBuilder: (context, url) {
  332 + return Image.network(
  333 + url,
  334 + width: 100,
  335 + height: 100,
  336 + );
  337 + },
331 latexBuilder: 338 latexBuilder:
332 - (contex, tex, textStyle, inline) { 339 + (context, tex, textStyle, inline) {
333 if (tex.contains(r"\begin{tabular}")) { 340 if (tex.contains(r"\begin{tabular}")) {
334 // return table. 341 // return table.
335 String tableString = "|${(RegExp( 342 String tableString = "|${(RegExp(
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 2
3 -import 'markdow_config.dart'; 3 +import 'markdown_config.dart';
4 4
5 class LinkButton extends StatefulWidget { 5 class LinkButton extends StatefulWidget {
6 final String text; 6 final String text;
@@ -14,6 +14,7 @@ class GptMarkdownConfig { @@ -14,6 +14,7 @@ class GptMarkdownConfig {
14 this.sourceTagBuilder, 14 this.sourceTagBuilder,
15 this.highlightBuilder, 15 this.highlightBuilder,
16 this.linkBuilder, 16 this.linkBuilder,
  17 + this.imageBuilder,
17 this.maxLines, 18 this.maxLines,
18 this.overflow, 19 this.overflow,
19 }); 20 });
@@ -55,6 +56,7 @@ class GptMarkdownConfig { @@ -55,6 +56,7 @@ class GptMarkdownConfig {
55 TextStyle style, 56 TextStyle style,
56 )? 57 )?
57 linkBuilder; 58 linkBuilder;
  59 + final Widget Function(BuildContext, String imageUrl)? imageBuilder;
58 60
59 GptMarkdownConfig copyWith({ 61 GptMarkdownConfig copyWith({
60 TextStyle? style, 62 TextStyle? style,
@@ -95,6 +97,7 @@ class GptMarkdownConfig { @@ -95,6 +97,7 @@ class GptMarkdownConfig {
95 TextStyle style, 97 TextStyle style,
96 )? 98 )?
97 linkBuilder, 99 linkBuilder,
  100 + final Widget Function(BuildContext, String imageUrl)? imageBuilder,
98 }) { 101 }) {
99 return GptMarkdownConfig( 102 return GptMarkdownConfig(
100 style: style ?? this.style, 103 style: style ?? this.style,
@@ -111,6 +114,7 @@ class GptMarkdownConfig { @@ -111,6 +114,7 @@ class GptMarkdownConfig {
111 overflow: overflow ?? this.overflow, 114 overflow: overflow ?? this.overflow,
112 highlightBuilder: highlightBuilder ?? this.highlightBuilder, 115 highlightBuilder: highlightBuilder ?? this.highlightBuilder,
113 linkBuilder: linkBuilder ?? this.linkBuilder, 116 linkBuilder: linkBuilder ?? this.linkBuilder,
  117 + imageBuilder: imageBuilder ?? this.imageBuilder,
114 ); 118 );
115 } 119 }
116 120
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 -import 'package:gpt_markdown/custom_widgets/markdow_config.dart'; 2 +import 'package:gpt_markdown/custom_widgets/markdown_config.dart';
3 3
4 import 'package:flutter/foundation.dart'; 4 import 'package:flutter/foundation.dart';
5 import 'package:flutter_math_fork/flutter_math.dart'; 5 import 'package:flutter_math_fork/flutter_math.dart';
@@ -28,6 +28,7 @@ class GptMarkdown extends StatelessWidget { @@ -28,6 +28,7 @@ class GptMarkdown extends StatelessWidget {
28 this.textDirection = TextDirection.ltr, 28 this.textDirection = TextDirection.ltr,
29 this.latexWorkaround, 29 this.latexWorkaround,
30 this.textAlign, 30 this.textAlign,
  31 + this.imageBuilder,
31 this.textScaler, 32 this.textScaler,
32 this.onLinkTab, 33 this.onLinkTab,
33 this.latexBuilder, 34 this.latexBuilder,
@@ -72,6 +73,7 @@ class GptMarkdown extends StatelessWidget { @@ -72,6 +73,7 @@ class GptMarkdown extends StatelessWidget {
72 TextStyle style, 73 TextStyle style,
73 )? 74 )?
74 linkBuilder; 75 linkBuilder;
  76 + final Widget Function(BuildContext, String imageUrl)? imageBuilder;
75 String _removeExtraLinesInsideBlockLatex(String text) { 77 String _removeExtraLinesInsideBlockLatex(String text) {
76 return text.replaceAllMapped( 78 return text.replaceAllMapped(
77 RegExp(r"\\\[(.*?)\\\]", multiLine: true, dotAll: true), 79 RegExp(r"\\\[(.*?)\\\]", multiLine: true, dotAll: true),
@@ -120,6 +122,7 @@ class GptMarkdown extends StatelessWidget { @@ -120,6 +122,7 @@ class GptMarkdown extends StatelessWidget {
120 sourceTagBuilder: sourceTagBuilder, 122 sourceTagBuilder: sourceTagBuilder,
121 highlightBuilder: highlightBuilder, 123 highlightBuilder: highlightBuilder,
122 linkBuilder: linkBuilder, 124 linkBuilder: linkBuilder,
  125 + imageBuilder: imageBuilder,
123 ), 126 ),
124 ), 127 ),
125 ); 128 );
@@ -755,35 +755,37 @@ class ImageMd extends InlineMd { @@ -755,35 +755,37 @@ class ImageMd extends InlineMd {
755 width = double.tryParse(size?[1]?.toString().trim() ?? 'a'); 755 width = double.tryParse(size?[1]?.toString().trim() ?? 'a');
756 height = double.tryParse(size?[2]?.toString().trim() ?? 'a'); 756 height = double.tryParse(size?[2]?.toString().trim() ?? 'a');
757 } 757 }
  758 + late final Widget image;
  759 + if (config.imageBuilder != null) {
  760 + image = config.imageBuilder!(context, '${match?[2]}');
  761 + } else {
  762 + image = Image(
  763 + image: NetworkImage("${match?[2]}"),
  764 + loadingBuilder: (
  765 + BuildContext context,
  766 + Widget child,
  767 + ImageChunkEvent? loadingProgress,
  768 + ) {
  769 + if (loadingProgress == null) {
  770 + return child;
  771 + }
  772 + return CustomImageLoading(
  773 + progress:
  774 + loadingProgress.expectedTotalBytes != null
  775 + ? loadingProgress.cumulativeBytesLoaded /
  776 + loadingProgress.expectedTotalBytes!
  777 + : 1,
  778 + );
  779 + },
  780 + fit: BoxFit.fill,
  781 + errorBuilder: (context, error, stackTrace) {
  782 + return const CustomImageError();
  783 + },
  784 + );
  785 + }
758 return WidgetSpan( 786 return WidgetSpan(
759 alignment: PlaceholderAlignment.bottom, 787 alignment: PlaceholderAlignment.bottom,
760 - child: SizedBox(  
761 - width: width,  
762 - height: height,  
763 - child: Image(  
764 - image: NetworkImage("${match?[2]}"),  
765 - loadingBuilder: (  
766 - BuildContext context,  
767 - Widget child,  
768 - ImageChunkEvent? loadingProgress,  
769 - ) {  
770 - if (loadingProgress == null) {  
771 - return child;  
772 - }  
773 - return CustomImageLoading(  
774 - progress:  
775 - loadingProgress.expectedTotalBytes != null  
776 - ? loadingProgress.cumulativeBytesLoaded /  
777 - loadingProgress.expectedTotalBytes!  
778 - : 1,  
779 - );  
780 - },  
781 - fit: BoxFit.fill,  
782 - errorBuilder: (context, error, stackTrace) {  
783 - return const CustomImageError();  
784 - },  
785 - ),  
786 - ), 788 + child: SizedBox(width: width, height: height, child: image),
787 ); 789 );
788 } 790 }
789 } 791 }