Merge pull request #610 from LucasXu0/feat/flowy_editor

chore: (draft) support text node widget editing
This commit is contained in:
Nathan.fooo 2022-07-14 10:51:30 +08:00 committed by GitHub
commit b859e2a252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 142 additions and 35 deletions

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flowy_editor/flowy_editor.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
class TextNodeBuilder extends NodeWidgetBuilder {
TextNodeBuilder.create({
@ -11,41 +13,7 @@ class TextNodeBuilder extends NodeWidgetBuilder {
@override
Widget build(BuildContext buildContext) {
final richText = SelectableText.rich(
TextSpan(
text: node.attributes['content'] as String,
style: node.attributes.toTextStyle(),
),
);
Widget? children;
if (node.children.isNotEmpty) {
children = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: node.children
.map(
(e) => renderPlugins.buildWidget(
context: NodeWidgetContext(
buildContext: buildContext,
node: e,
editorState: editorState,
),
),
)
.toList(),
);
}
if (children != null) {
return Column(
children: [
richText,
children,
],
);
} else {
return richText;
}
return _TextNodeWidget(node: node, editorState: editorState);
}
}
@ -57,3 +25,141 @@ extension on Attributes {
);
}
}
class _TextNodeWidget extends StatefulWidget {
final Node node;
final EditorState editorState;
const _TextNodeWidget({
Key? key,
required this.node,
required this.editorState,
}) : super(key: key);
@override
State<_TextNodeWidget> createState() => __TextNodeWidgetState();
}
class __TextNodeWidgetState extends State<_TextNodeWidget>
implements TextInputClient {
Node get node => widget.node;
EditorState get editorState => widget.editorState;
String get content => node.attributes['content'] as String;
TextEditingValue get textEditingValue => TextEditingValue(text: content);
TextInputConnection? _textInputConnection;
@override
Widget build(BuildContext context) {
final editableRichText = ChangeNotifierProvider.value(
value: node,
builder: (_, __) => Consumer<Node>(
builder: ((context, value, child) => SelectableText.rich(
TextSpan(
text: content,
style: node.attributes.toTextStyle(),
),
onTap: () {
_textInputConnection?.close();
_textInputConnection = TextInput.attach(
this,
const TextInputConfiguration(
enableDeltaModel: false,
inputType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
),
);
_textInputConnection
?..show()
..setEditingState(textEditingValue);
},
)),
),
);
final child = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
editableRichText,
if (node.children.isNotEmpty)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: node.children
.map(
(e) => editorState.renderPlugins.buildWidget(
context: NodeWidgetContext(
buildContext: context,
node: e,
editorState: editorState,
),
),
)
.toList(),
),
],
);
return child;
}
@override
void connectionClosed() {
// TODO: implement connectionClosed
}
@override
// TODO: implement currentAutofillScope
AutofillScope? get currentAutofillScope => throw UnimplementedError();
@override
// TODO: implement currentTextEditingValue
TextEditingValue? get currentTextEditingValue => textEditingValue;
@override
void insertTextPlaceholder(Size size) {
// TODO: implement insertTextPlaceholder
}
@override
void performAction(TextInputAction action) {
// TODO: implement performAction
}
@override
void performPrivateCommand(String action, Map<String, dynamic> data) {
// TODO: implement performPrivateCommand
}
@override
void removeTextPlaceholder() {
// TODO: implement removeTextPlaceholder
}
@override
void showAutocorrectionPromptRect(int start, int end) {
// TODO: implement showAutocorrectionPromptRect
}
@override
void showToolbar() {
// TODO: implement showToolbar
}
@override
void updateEditingValue(TextEditingValue value) {
debugPrint(value.text);
editorState.update(
node,
Attributes.from(node.attributes)
..addAll(
{
'content': value.text,
},
),
);
}
@override
void updateFloatingCursor(RawFloatingCursorPoint point) {
// TODO: implement updateFloatingCursor
}
}

View File

@ -29,6 +29,7 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
factory Node.fromJson(Map<String, Object> json) {
assert(json['type'] is String);
// TODO: check the type that not exist on plugins.
final jType = json['type'] as String;
final jChildren = json['children'] as List?;
final jAttributes = json['attributes'] != null