feat: add bulleted-list and number-list

This commit is contained in:
Lucas.Xu 2022-07-28 19:59:15 +08:00
parent 734b642fcc
commit 51bc965029
6 changed files with 168 additions and 15 deletions

View File

@ -111,8 +111,8 @@
{ "insert": " and just typing." } { "insert": " and just typing." }
], ],
"attributes": { "attributes": {
"list": "todo", "subtype": "checkbox",
"todo": true "checkbox": true
} }
}, },
{ {
@ -130,8 +130,8 @@
} }
], ],
"attributes": { "attributes": {
"list": "todo", "subtype": "checkbox",
"todo": true "checkbox": true
} }
}, },
{ {
@ -146,8 +146,8 @@
{ "insert": "." } { "insert": "." }
], ],
"attributes": { "attributes": {
"list": "todo", "subtype": "checkbox",
"todo": true "checkbox": true
} }
}, },
{ {
@ -170,7 +170,7 @@
} }
], ],
"attributes": { "attributes": {
"list": "bullet" "subtype": "bullet-list"
} }
}, },
{ {
@ -181,7 +181,7 @@
} }
], ],
"attributes": { "attributes": {
"list": "bullet" "subtype": "bullet-list"
} }
}, },
{ {
@ -192,7 +192,7 @@
} }
], ],
"attributes": { "attributes": {
"list": "bullet" "subtype": "bullet-list"
} }
}, },
{ {
@ -225,6 +225,7 @@
} }
], ],
"attributes": { "attributes": {
"subtype": "number-list",
"number": 1 "number": 1
} }
}, },
@ -236,6 +237,7 @@
} }
], ],
"attributes": { "attributes": {
"subtype": "number-list",
"number": 2 "number": 2
} }
}, },
@ -247,6 +249,7 @@
} }
], ],
"attributes": { "attributes": {
"subtype": "number-list",
"number": 3 "number": 3
} }
} }

View File

@ -1,7 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'package:flowy_editor/render/rich_text/bulleted_list_text.dart';
import 'package:flowy_editor/render/rich_text/checkbox_text.dart'; import 'package:flowy_editor/render/rich_text/checkbox_text.dart';
import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart'; import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart';
import 'package:flowy_editor/render/rich_text/heading_text.dart'; import 'package:flowy_editor/render/rich_text/heading_text.dart';
import 'package:flowy_editor/render/rich_text/number_list_text.dart';
import 'package:flowy_editor/service/service.dart'; import 'package:flowy_editor/service/service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -47,6 +49,10 @@ class EditorState {
renderPlugins.register('text', RichTextNodeWidgetBuilder.create); renderPlugins.register('text', RichTextNodeWidgetBuilder.create);
renderPlugins.register('text/checkbox', CheckboxNodeWidgetBuilder.create); renderPlugins.register('text/checkbox', CheckboxNodeWidgetBuilder.create);
renderPlugins.register('text/heading', HeadingTextNodeWidgetBuilder.create); renderPlugins.register('text/heading', HeadingTextNodeWidgetBuilder.create);
renderPlugins.register(
'text/bullet-list', BulletedListTextNodeWidgetBuilder.create);
renderPlugins.register(
'text/number-list', NumberListTextNodeWidgetBuilder.create);
undoManager.state = this; undoManager.state = this;
} }

View File

@ -0,0 +1,73 @@
import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/editor_state.dart';
import 'package:flowy_editor/infra/flowy_svg.dart';
import 'package:flowy_editor/render/node_widget_builder.dart';
import 'package:flowy_editor/render/rich_text/default_selectable.dart';
import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart';
import 'package:flowy_editor/render/selection/selectable.dart';
import 'package:flutter/material.dart';
class BulletedListTextNodeWidgetBuilder extends NodeWidgetBuilder {
BulletedListTextNodeWidgetBuilder.create({
required super.editorState,
required super.node,
required super.key,
}) : super.create();
@override
Widget build(BuildContext context) {
return BulletedListTextNodeWidget(
key: key,
textNode: node as TextNode,
editorState: editorState,
);
}
}
class BulletedListTextNodeWidget extends StatefulWidget {
const BulletedListTextNodeWidget({
Key? key,
required this.textNode,
required this.editorState,
}) : super(key: key);
final TextNode textNode;
final EditorState editorState;
@override
State<BulletedListTextNodeWidget> createState() =>
_BulletedListTextNodeWidgetState();
}
// customize
class _BulletedListTextNodeWidgetState extends State<BulletedListTextNodeWidget>
with Selectable, DefaultSelectable {
final _richTextKey = GlobalKey(debugLabel: 'heading_text');
final leftPadding = 20.0;
@override
Selectable<StatefulWidget> get forward =>
_richTextKey.currentState as Selectable;
@override
Offset get baseOffset {
return Offset(leftPadding, 0);
}
@override
Widget build(BuildContext context) {
return Row(
children: [
const FlowySvg(
name: 'point',
),
FlowyRichText(
key: _richTextKey,
textNode: widget.textNode,
editorState: widget.editorState,
),
],
);
}
}

View File

@ -68,15 +68,15 @@ class _FlowyRichTextState extends State<FlowyRichText> with Selectable {
final attributes = _textNode.attributes; final attributes = _textNode.attributes;
// TODO: use factory method ?? // TODO: use factory method ??
if (attributes.list == 'todo') { if (attributes.list == 'todo') {
return _buildTodoListRichText(context); // return _buildTodoListRichText(context);
} else if (attributes.list == 'bullet') { } else if (attributes.list == 'bullet') {
return _buildBulletedListRichText(context); // return _buildBulletedListRichText(context);
} else if (attributes.quote == true) { } else if (attributes.quote == true) {
return _buildQuotedRichText(context); return _buildQuotedRichText(context);
} else if (attributes.heading != null) { } else if (attributes.heading != null) {
// return _buildHeadingRichText(context); // return _buildHeadingRichText(context);
} else if (attributes.number != null) { } else if (attributes.number != null) {
return _buildNumberListRichText(context); // return _buildNumberListRichText(context);
} }
return _buildRichText(context); return _buildRichText(context);
} }

View File

@ -1,13 +1,10 @@
import 'package:flowy_editor/document/node.dart'; import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/editor_state.dart'; import 'package:flowy_editor/editor_state.dart';
import 'package:flowy_editor/infra/flowy_svg.dart';
import 'package:flowy_editor/render/node_widget_builder.dart'; import 'package:flowy_editor/render/node_widget_builder.dart';
import 'package:flowy_editor/render/render_plugins.dart';
import 'package:flowy_editor/render/rich_text/default_selectable.dart'; import 'package:flowy_editor/render/rich_text/default_selectable.dart';
import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart'; import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart';
import 'package:flowy_editor/render/rich_text/rich_text_style.dart'; import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
import 'package:flowy_editor/render/selection/selectable.dart'; import 'package:flowy_editor/render/selection/selectable.dart';
import 'package:flowy_editor/extensions/object_extensions.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class HeadingTextNodeWidgetBuilder extends NodeWidgetBuilder { class HeadingTextNodeWidgetBuilder extends NodeWidgetBuilder {

View File

@ -0,0 +1,74 @@
import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/editor_state.dart';
import 'package:flowy_editor/infra/flowy_svg.dart';
import 'package:flowy_editor/render/node_widget_builder.dart';
import 'package:flowy_editor/render/rich_text/default_selectable.dart';
import 'package:flowy_editor/render/rich_text/flowy_rich_text.dart';
import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
import 'package:flowy_editor/render/selection/selectable.dart';
import 'package:flutter/material.dart';
class NumberListTextNodeWidgetBuilder extends NodeWidgetBuilder {
NumberListTextNodeWidgetBuilder.create({
required super.editorState,
required super.node,
required super.key,
}) : super.create();
@override
Widget build(BuildContext context) {
return NumberListTextNodeWidget(
key: key,
textNode: node as TextNode,
editorState: editorState,
);
}
}
class NumberListTextNodeWidget extends StatefulWidget {
const NumberListTextNodeWidget({
Key? key,
required this.textNode,
required this.editorState,
}) : super(key: key);
final TextNode textNode;
final EditorState editorState;
@override
State<NumberListTextNodeWidget> createState() =>
_NumberListTextNodeWidgetState();
}
// customize
class _NumberListTextNodeWidgetState extends State<NumberListTextNodeWidget>
with Selectable, DefaultSelectable {
final _richTextKey = GlobalKey(debugLabel: 'heading_text');
final leftPadding = 20.0;
@override
Selectable<StatefulWidget> get forward =>
_richTextKey.currentState as Selectable;
@override
Offset get baseOffset {
return Offset(leftPadding, 0);
}
@override
Widget build(BuildContext context) {
return Row(
children: [
FlowySvg(
number: widget.textNode.attributes.number,
),
FlowyRichText(
key: _richTextKey,
textNode: widget.textNode,
editorState: widget.editorState,
),
],
);
}
}