Add Markdown support
Would it be relevant to add markdown support ? Generative AI uses markdown so for example instead of showing text wrapped in "**", markdown will show bold text.
flutter_markdown package could be used.
I can submit the PR if you want, my code is ready.
Otherwise, why not take a Widget child as parameter instead of a String text ? This way, you won't have to add a dependency to your package. That would be a breaking change though. Or a new widget MarkdownBubble ?
Nice idea :D
I've come across this problem. This is how I solved:
- Go to source code of the widget you want to use (I use
BubbleSpecialTwo). In VSCode, you can do it by F12 or ALT+LeftClick. - Copy the related widget and paste it to your codebase somewhere, wherever you hold your custom components.
- Rename the component to something else. I renamed to
CustomBubbleSpecialTwo. - Change
textwithchild, which should beWidgetinstead ofString.
I could send a PR for this but kinda busy right now. When I get freer and nobody still takes this issue, I can send a PR maybe.
I leave CustomBubbleSpecialTwo as an example:
import 'package:chat_bubbles/bubbles/bubble_special_two.dart';
import 'package:flutter/material.dart';
class CustomBubbleSpecialTwo extends StatelessWidget {
final bool isSender;
final Widget child;
final bool tail;
final Color color;
final bool sent;
final bool delivered;
final bool seen;
final TextStyle textStyle;
final BoxConstraints? constraints;
const CustomBubbleSpecialTwo({
required this.child,
super.key,
this.isSender = true,
this.constraints,
this.color = Colors.white70,
this.tail = true,
this.sent = false,
this.delivered = false,
this.seen = false,
this.textStyle = const TextStyle(
color: Colors.black87,
fontSize: 16,
),
});
///chat bubble builder method
@override
Widget build(BuildContext context) {
bool stateTick = false;
Icon? stateIcon;
if (sent) {
stateTick = true;
stateIcon = const Icon(
Icons.done,
size: 18,
color: Color(0xFF97AD8E),
);
}
if (delivered) {
stateTick = true;
stateIcon = const Icon(
Icons.done_all,
size: 18,
color: Color(0xFF97AD8E),
);
}
if (seen) {
stateTick = true;
stateIcon = const Icon(
Icons.done_all,
size: 18,
color: Color(0xFF92DEDA),
);
}
return Align(
alignment: isSender ? Alignment.topRight : Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
child: CustomPaint(
painter: SpecialChatBubbleTwo(
color: color,
alignment: isSender ? Alignment.topRight : Alignment.topLeft,
tail: tail,
),
child: Container(
constraints: constraints ??
BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * .8,
),
margin: isSender
? stateTick
? const EdgeInsets.fromLTRB(7, 7, 14, 7)
: const EdgeInsets.fromLTRB(7, 7, 17, 7)
: const EdgeInsets.fromLTRB(17, 7, 7, 7),
child: Stack(
children: <Widget>[
Padding(
padding: stateTick
? const EdgeInsets.only(right: 20)
// ignore: use_named_constants
: const EdgeInsets.symmetric(),
child: child,
),
if (stateIcon != null && stateTick)
Positioned(
bottom: 0,
right: 0,
child: stateIcon,
)
else
const SizedBox(
width: 1,
),
],
),
),
),
),
);
}
}