diff --git a/frontend/app_flowy/packages/flowy_editor/example/assets/document.json b/frontend/app_flowy/packages/flowy_editor/example/assets/document.json index 7692c8b00b..c2ba9fbb09 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/assets/document.json +++ b/frontend/app_flowy/packages/flowy_editor/example/assets/document.json @@ -12,50 +12,65 @@ { "type": "text", "delta": [ - { "insert": "With " }, - { "insert": "AppFlowy", "attributes": { "href": "https://www.appflowy.io/" } }, - { "insert": ", you can build detailed lists of to-do’s for different projects while tracking the status of each one" } + { "insert": "👋 Welcome to AppFlowy!", "attributes": { "href": "https://www.appflowy.io/", "heading": "h1" } } + ], + "attributes": { + "subtype": "with-heading", + "heading": "h1" + } + }, + { + "type": "text", + "delta": [ + { "insert": "Here are the basics", "attributes": { "heading": "h2" } } + ], + "attributes": { + "subtype": "with-heading", + "heading": "h2" + } + }, + { + "type": "text", + "delta": [ + { "insert": "Click anywhere and just start typing." } + ], + "attributes": { + "subtype": "with-checkbox", + "checkbox": true + } + }, + { + "type": "text", + "delta": [ + { "insert": "Highlight", "attributes": { "highlight": "0xFFFFFF00" } }, + { "insert": " Click anywhere and just start typing" }, + { "insert": " any text, and use the menu at the bottom to " }, + { "insert": "style", "attributes": { "italic": true } }, + { "insert": " your ", "attributes": { "bold": true } }, + { "insert": "writing", "attributes": { "underline": true } }, + { "insert": " howeverv you like.", "attributes": { "strikethrough": true } } ], "attributes": { "subtype": "with-checkbox", - "font-size": 30, "checkbox": false } }, { "type": "text", "delta": [ - { "insert": "You can " }, - { "insert": "host", "attributes": { "italic": true } }, - { "insert": " " }, - { "insert": "AppFlowy", "attributes": { "bold": true } }, - { "insert": " " }, - { "insert": "wherever you want", "attributes": { "underline": true }}, - { "insert": "; no vendor lock-in." } + { "insert": "Have a question? ", "attributes": { "heading": "h2" } } ], - "attributes": { - "subtype": "with-checkbox", - "text-type": "heading1", - "font-size": 30, - "checkbox": false + "attributes": { + "subtype": "with-heading", + "heading": "h2" } }, { "type": "text", - "delta": [{ "insert": "Design and modify AppFlowy your way with an open core codebase." }], - "attributes": { - "text-type": "heading1", - "font-size": 30 - } - }, - { - "type": "text", - "delta": [{ "insert": "AppFlowy is built with Flutter and Rust. What does this mean? Faster development, better native experience, and more reliable performance." }], - "attributes": { - "text-type": "heading1", - "font-size": 30, - "content": "dddddddddddddddddddd" - } + "delta": [ + { "insert": "Click the '?' at the bottom right for help and support."} + ], + "attributes": {} } ] } diff --git a/frontend/app_flowy/packages/flowy_editor/example/lib/main.dart b/frontend/app_flowy/packages/flowy_editor/example/lib/main.dart index cc9acce929..8a413f78b1 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/lib/main.dart +++ b/frontend/app_flowy/packages/flowy_editor/example/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:example/plugin/document_node_widget.dart'; +import 'package:example/plugin/text_with_heading_node_widget.dart'; import 'package:example/plugin/image_node_widget.dart'; import 'package:example/plugin/text_node_widget.dart'; import 'package:example/plugin/text_with_check_box_node_widget.dart'; @@ -66,7 +67,8 @@ class _MyHomePageState extends State { ..register('editor', EditorNodeWidgetBuilder.create) ..register('text', TextNodeBuilder.create) ..register('image', ImageNodeBuilder.create) - ..register('text/with-checkbox', TextWithCheckBoxNodeBuilder.create); + ..register('text/with-checkbox', TextWithCheckBoxNodeBuilder.create) + ..register('text/with-heading', TextWithHeadingNodeBuilder.create); } @override diff --git a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart index 6884a7aedc..692d00baf2 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart +++ b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart @@ -30,17 +30,7 @@ class _ImageNodeWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( - child: _build(context), - onTap: () { - TransactionBuilder(editorState) - ..updateNode(node, { - 'image_src': - "https://images.pexels.com/photos/9995076/pexels-photo-9995076.png?cs=srgb&dl=pexels-temmuz-uzun-9995076.jpg&fm=jpg&w=640&h=400" - }) - ..commit(); - }, - ); + return _build(context); } Widget _build(BuildContext context) { diff --git a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_node_widget.dart b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_node_widget.dart index d58f2fef1d..2b66e3ea7f 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_node_widget.dart +++ b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_node_widget.dart @@ -158,6 +158,8 @@ TextSpan _textInsertToTextSpan(TextInsert textInsert) { TextDecoration? decoration; GestureRecognizer? gestureRecognizer; Color? color; + Color highLightColor = Colors.transparent; + double fontSize = 16.0; final attributes = textInsert.attributes; if (attributes?['bold'] == true) { fontWeight = FontWeight.bold; @@ -168,6 +170,12 @@ TextSpan _textInsertToTextSpan(TextInsert textInsert) { if (attributes?['underline'] == true) { decoration = TextDecoration.underline; } + if (attributes?['strikethrough'] == true) { + decoration = TextDecoration.lineThrough; + } + if (attributes?['highlight'] is String) { + highLightColor = Color(int.parse(attributes!['highlight'])); + } if (attributes?['href'] is String) { color = const Color.fromARGB(255, 55, 120, 245); decoration = TextDecoration.underline; @@ -176,6 +184,16 @@ TextSpan _textInsertToTextSpan(TextInsert textInsert) { launchUrlString(attributes?['href']); }; } + final heading = attributes?['heading'] as String?; + if (heading != null) { + // TODO: make it better + if (heading == 'h1') { + fontSize = 30.0; + } else if (heading == 'h2') { + fontSize = 20.0; + } + fontWeight = FontWeight.bold; + } return TextSpan( text: textInsert.content, style: TextStyle( @@ -183,7 +201,8 @@ TextSpan _textInsertToTextSpan(TextInsert textInsert) { fontStyle: fontStyle, decoration: decoration, color: color, - fontSize: 16, + fontSize: fontSize, + backgroundColor: highLightColor, ), recognizer: gestureRecognizer, ); diff --git a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_with_heading_node_widget.dart b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_with_heading_node_widget.dart new file mode 100644 index 0000000000..9519e130f2 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/text_with_heading_node_widget.dart @@ -0,0 +1,45 @@ +import 'package:flowy_editor/flowy_editor.dart'; +import 'package:flutter/material.dart'; + +class TextWithHeadingNodeBuilder extends NodeWidgetBuilder { + TextWithHeadingNodeBuilder.create({ + required super.editorState, + required super.node, + }) : super.create() { + nodeValidator = (node) => node.attributes.containsKey('heading'); + } + + String get heading => node.attributes['heading'] as String; + Widget buildPadding() { + if (heading == 'h1') { + return const Padding( + padding: EdgeInsets.only(top: 10), + ); + } else if (heading == 'h1') { + return const Padding( + padding: EdgeInsets.only(top: 10), + ); + } + return const Padding( + padding: EdgeInsets.only(top: 0), + ); + } + + @override + Widget build(BuildContext buildContext) { + return Column( + children: [ + buildPadding(), + renderPlugins.buildWidget( + context: NodeWidgetContext( + buildContext: buildContext, + node: node, + editorState: editorState, + ), + withSubtype: false, + ), + buildPadding(), + ], + ); + } +}