Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions packages/fleather/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,17 @@ class _HomePageState extends State<HomePage> {
);
}

Widget _embedBuilder(BuildContext context, EmbedNode node) {
FleatherEmbed _embedBuilder(BuildContext context, EmbedNode node) {
if (node.value.type == 'icon') {
final data = node.value.data;
// Icons.rocket_launch_outlined
return Icon(
IconData(int.parse(data['codePoint']), fontFamily: data['fontFamily']),
color: Color(int.parse(data['color'])),
size: 18,
return FleatherSpanEmbed(
child: Icon(
IconData(int.parse(data['codePoint']),
fontFamily: data['fontFamily']),
color: Color(int.parse(data['color'])),
size: 18,
),
);
}

Expand All @@ -176,14 +179,17 @@ class _HomePageState extends State<HomePage> {
}
}
if (image != null) {
return Padding(
// Caret takes 2 pixels, hence not symmetric padding values.
padding: const EdgeInsets.only(left: 4, right: 2, top: 2, bottom: 2),
child: Container(
width: (node.value.data['width'] as num?)?.toDouble() ?? 300,
height: (node.value.data['height'] as num?)?.toDouble() ?? 300,
decoration: BoxDecoration(
image: DecorationImage(image: image, fit: BoxFit.cover),
return FleatherEmbed(
child: Padding(
// Caret takes 2 pixels, hence not symmetric padding values.
padding:
const EdgeInsets.only(left: 4, right: 2, top: 2, bottom: 2),
child: Container(
width: (node.value.data['width'] as num?)?.toDouble() ?? 300,
height: (node.value.data['height'] as num?)?.toDouble() ?? 300,
decoration: BoxDecoration(
image: DecorationImage(image: image, fit: BoxFit.cover),
),
),
),
);
Expand Down
29 changes: 25 additions & 4 deletions packages/fleather/lib/src/widgets/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,29 +76,50 @@ Widget defaultSpellCheckMenuBuilder(
}

/// Builder function for embeddable objects in [FleatherEditor].
typedef FleatherEmbedBuilder = Widget Function(
typedef FleatherEmbedBuilder = FleatherEmbed Function(
BuildContext context, EmbedNode node);

/// Default implementation of a builder function for embeddable objects in
/// Fleather.
///
/// Only supports "horizontal rule" embeds.
Widget defaultFleatherEmbedBuilder(BuildContext context, EmbedNode node) {
FleatherEmbed defaultFleatherEmbedBuilder(
BuildContext context, EmbedNode node) {
if (node.value.type == 'hr') {
final fleatherThemeData = FleatherTheme.of(context)!;

return Divider(
return FleatherEmbed(
child: Divider(
height: fleatherThemeData.horizontalRule.height,
thickness: fleatherThemeData.horizontalRule.thickness,
color: fleatherThemeData.horizontalRule.color,
);
));
}
throw UnimplementedError(
'Embeddable type "${node.value.type}" is not supported by default embed '
'builder of FleatherEditor. You must pass your own builder function to '
'embedBuilder property of FleatherEditor or FleatherField widgets.');
}

final class FleatherEmbed {
final Widget child;

const FleatherEmbed({required this.child});
}

final class FleatherSpanEmbed extends FleatherEmbed {
final PlaceholderAlignment placeholderAlignment;
final TextBaseline? textBaseline;
final TextStyle? textStyle;

const FleatherSpanEmbed({
required super.child,
this.placeholderAlignment = PlaceholderAlignment.bottom,
this.textBaseline,
this.textStyle,
});
}

/// Widget for editing rich text documents.
class FleatherEditor extends StatefulWidget {
/// Controller object which establishes a link between a rich text document
Expand Down
19 changes: 15 additions & 4 deletions packages/fleather/lib/src/widgets/text_line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ class _TextLineState extends State<TextLine> {
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
if (widget.node.hasBlockEmbed) {
final embed = widget.node.children.single as EmbedNode;
return EmbedProxy(child: widget.embedBuilder(context, embed));
final embedNode = widget.node.children.single as EmbedNode;
final embedObject = widget.embedBuilder(context, embedNode);
return EmbedProxy(child: embedObject.child);
}
final theme = FleatherTheme.of(context)!;
final text = buildText(context, widget.node, theme);
Expand Down Expand Up @@ -174,8 +175,18 @@ class _TextLineState extends State<TextLine> {

InlineSpan _segmentToTextSpan(Node segment, FleatherThemeData theme) {
if (segment is EmbedNode) {
return WidgetSpan(
child: EmbedProxy(child: widget.embedBuilder(context, segment)));
final embedObject = widget.embedBuilder(context, segment);
final embedWidget = EmbedProxy(child: embedObject.child);
if (embedObject is FleatherSpanEmbed) {
return WidgetSpan(
child: embedWidget,
alignment: embedObject.placeholderAlignment,
baseline: embedObject.textBaseline,
style: embedObject.textStyle,
);
} else {
return WidgetSpan(child: embedWidget);
}
}
final text = segment as TextNode;
final attrs = text.style;
Expand Down
Loading