Преглед на файлове

feat: 0.0.5 release preparation

Lucas.Xu преди 2 години
родител
ревизия
5bb5337de8

+ 7 - 0
frontend/app_flowy/packages/appflowy_editor/CHANGELOG.md

@@ -1,3 +1,10 @@
+## 0.0.5
+* Support customize the hotkey for a shortcut on different platform.
+* Support customize a theme.
+* Support localizations.
+* Support insert numbered list.
+* Fix some bugs.
+
 ## 0.0.4
 * Support more shortcut events.
 * Fix some bugs.

+ 16 - 3
frontend/app_flowy/packages/appflowy_editor/README.md

@@ -36,8 +36,8 @@ and the Flutter guide for
 * Design and modify an ever expanding list of customizable features including
   * components (such as form input controls, numbered lists, and rich text widgets)
   * shortcut events
+  * themes
   * menu options (**coming soon!**)
-  * themes (**coming soon!**)
 * [Test-coverage](https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_editor/documentation/testing.md) and on-going maintenance by AppFlowy's core team and community of more than 1,000 builders
 
 ## Getting Started
@@ -54,11 +54,13 @@ flutter pub get
 Start by creating a new empty AppFlowyEditor object. 
 
 ```dart
+final editorStyle = EditorStyle.defaultStyle();
 final editorState = EditorState.empty(); // an empty state
 final editor = AppFlowyEditor(
     editorState: editorState,
-    keyEventHandlers: const [],
+    shortcutEvents: const [],
     customBuilders: const {},
+    editorStyle: editorStyle,
 );
 ```
 
@@ -66,11 +68,22 @@ You can also create an editor from a JSON object in order to configure your init
 
 ```dart
 final json = ...;
+final editorStyle = EditorStyle.defaultStyle();
 final editorState = EditorState(StateTree.fromJson(data));
 final editor = AppFlowyEditor(
     editorState: editorState,
-    keyEventHandlers: const [],
+    shortcutEvents: const [],
     customBuilders: const {},
+    editorStyle: editorStyle,
+);
+```
+
+> Note: The parameters `localizationsDelegates` need to be assigned in MaterialApp widget
+```dart
+MaterialApp(
+    localizationsDelegates: const [
+        AppFlowyEditorLocalizations.delegate,
+    ],
 );
 ```
 

+ 101 - 1
frontend/app_flowy/packages/appflowy_editor/documentation/customizing.md

@@ -16,7 +16,9 @@ Widget build(BuildContext context) {
       alignment: Alignment.topCenter,
       child: AppFlowyEditor(
         editorState: EditorState.empty(),
+        editorStyle: EditorStyle.defaultStyle(),
         shortcutEvents: const [],
+        customBuilders: const {},
       ),
     ),
   );
@@ -116,6 +118,8 @@ Widget build(BuildContext context) {
       alignment: Alignment.topCenter,
       child: AppFlowyEditor(
         editorState: EditorState.empty(),
+        editorStyle: EditorStyle.defaultStyle(),
+        customBuilders: const {},
         shortcutEvents: [
             _underscoreToItalicHandler,
         ],
@@ -145,7 +149,9 @@ Widget build(BuildContext context) {
       alignment: Alignment.topCenter,
       child: AppFlowyEditor(
         editorState: EditorState.empty(),
-        keyEventHandlers: const [],
+        editorStyle: EditorStyle.defaultStyle(),
+        shortcutEvents: const [],
+        customBuilders: const {},
       ),
     ),
   );
@@ -283,6 +289,8 @@ final editorState = EditorState(
 );
 return AppFlowyEditor(
   editorState: editorState,
+  editorStyle: EditorStyle.defaultStyle(),
+  shortcutEvents: const [],
   customBuilders: {
     'network_image': NetworkImageNodeWidgetBuilder(),
   },
@@ -292,3 +300,95 @@ return AppFlowyEditor(
 ![Whew!](./images/customizing_a_component.gif)
 
 Check out the [complete code](https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/network_image_node_widget.dart) file of this example.
+
+## Customizing a Theme (New Feature in 0.0.5, Alpha)
+
+We will use a simple example to illustrate how to quickly customize a theme.
+
+Let's start with a blank document:
+
+```dart
+@override
+Widget build(BuildContext context) {
+  return Scaffold(
+    body: Container(
+      alignment: Alignment.topCenter,
+      child: AppFlowyEditor(
+        editorState: EditorState.empty(),
+        editorStyle: EditorStyle.defaultStyle(),
+        shortcutEvents: const [],
+        customBuilders: const {},
+      ),
+    ),
+  );
+}
+```
+
+At this point, the editor looks like ...
+![Before](./images/customizing_a_theme_before.png)
+
+
+Next, we will customize the `EditorStyle`.
+
+```dart
+EditorStyle _customizedStyle() {
+  final editorStyle = EditorStyle.defaultStyle();
+  return editorStyle.copyWith(
+    cursorColor: Colors.white,
+    selectionColor: Colors.blue.withOpacity(0.3),
+    textStyle: editorStyle.textStyle.copyWith(
+      defaultTextStyle: GoogleFonts.poppins().copyWith(
+        color: Colors.white,
+        fontSize: 14.0,
+      ),
+      defaultPlaceholderTextStyle: GoogleFonts.poppins().copyWith(
+        color: Colors.white.withOpacity(0.5),
+        fontSize: 14.0,
+      ),
+      bold: const TextStyle(fontWeight: FontWeight.w900),
+      code: TextStyle(
+        fontStyle: FontStyle.italic,
+        color: Colors.red[300],
+        backgroundColor: Colors.grey.withOpacity(0.3),
+      ),
+      highlightColorHex: '0x6FFFEB3B',
+    ),
+    pluginStyles: {
+      'text/quote': builtInPluginStyle
+        ..update(
+          'textStyle',
+          (_) {
+            return (EditorState editorState, Node node) {
+              return TextStyle(
+                color: Colors.blue[200],
+                fontStyle: FontStyle.italic,
+                fontSize: 12.0,
+              );
+            };
+          },
+        ),
+    },
+  );
+}
+```
+
+Now our 'customize style' function is done and the only task left is to inject it into the AppFlowyEditor.
+
+```dart
+@override
+Widget build(BuildContext context) {
+  return Scaffold(
+    body: Container(
+      alignment: Alignment.topCenter,
+      child: AppFlowyEditor(
+        editorState: EditorState.empty(),
+        editorStyle: _customizedStyle(),
+        shortcutEvents: const [],
+        customBuilders: const {},
+      ),
+    ),
+  );
+}
+```
+
+![After](./images/customizing_a_theme_after.png)

BIN
frontend/app_flowy/packages/appflowy_editor/documentation/images/customizing_a_theme_after.png


BIN
frontend/app_flowy/packages/appflowy_editor/documentation/images/customizing_a_theme_before.png


+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/example/assets/example.json

@@ -56,7 +56,7 @@
       {
         "type": "text",
         "attributes": { "subtype": "quote" },
-        "delta": [{ "insert": "Here is an exmaple you can give it a try" }]
+        "delta": [{ "insert": "Here is an example you can give a try" }]
       },
       { "type": "text", "delta": [] },
       {

+ 47 - 5
frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart

@@ -4,6 +4,8 @@ import 'dart:io';
 import 'package:example/plugin/underscore_to_italic_key_event_handler.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:google_fonts/google_fonts.dart';
 
 import 'package:path_provider/path_provider.dart';
 
@@ -22,6 +24,9 @@ class MyApp extends StatelessWidget {
   Widget build(BuildContext context) {
     return MaterialApp(
       localizationsDelegates: const [
+        GlobalMaterialLocalizations.delegate,
+        GlobalCupertinoLocalizations.delegate,
+        GlobalWidgetsLocalizations.delegate,
         AppFlowyEditorLocalizations.delegate,
       ],
       supportedLocales: AppFlowyEditorLocalizations.delegate.supportedLocales,
@@ -149,11 +154,8 @@ class _MyHomePageState extends State<MyHomePage> {
           icon: const Icon(Icons.color_lens),
           onPressed: () {
             setState(() {
-              _editorStyle = _editorStyle.copyWith(
-                textStyle: darkMode
-                    ? BuiltInTextStyle.builtIn()
-                    : BuiltInTextStyle.builtInDarkMode(),
-              );
+              _editorStyle =
+                  darkMode ? EditorStyle.defaultStyle() : _customizedStyle();
               darkMode = !darkMode;
             });
           },
@@ -196,4 +198,44 @@ class _MyHomePageState extends State<MyHomePage> {
       });
     }
   }
+
+  EditorStyle _customizedStyle() {
+    final editorStyle = EditorStyle.defaultStyle();
+    return editorStyle.copyWith(
+      cursorColor: Colors.white,
+      selectionColor: Colors.blue.withOpacity(0.3),
+      textStyle: editorStyle.textStyle.copyWith(
+        defaultTextStyle: GoogleFonts.poppins().copyWith(
+          color: Colors.white,
+          fontSize: 14.0,
+        ),
+        defaultPlaceholderTextStyle: GoogleFonts.poppins().copyWith(
+          color: Colors.white.withOpacity(0.5),
+          fontSize: 14.0,
+        ),
+        bold: const TextStyle(fontWeight: FontWeight.w900),
+        code: TextStyle(
+          fontStyle: FontStyle.italic,
+          color: Colors.red[300],
+          backgroundColor: Colors.grey.withOpacity(0.3),
+        ),
+        highlightColorHex: '0x6FFFEB3B',
+      ),
+      pluginStyles: {
+        'text/quote': builtInPluginStyle
+          ..update(
+            'textStyle',
+            (_) {
+              return (EditorState editorState, Node node) {
+                return TextStyle(
+                  color: Colors.blue[200],
+                  fontStyle: FontStyle.italic,
+                  fontSize: 12.0,
+                );
+              };
+            },
+          ),
+      },
+    );
+  }
 }

+ 3 - 1
frontend/app_flowy/packages/appflowy_editor/example/pubspec.yaml

@@ -39,8 +39,10 @@ dependencies:
   url_launcher: ^6.1.5
   video_player: ^2.4.5
   pod_player: 0.0.8
-  flutter_inappwebview: ^5.4.3+7
   path_provider: ^2.0.11
+  google_fonts: ^3.0.1
+  flutter_localizations:
+    sdk: flutter
 
 dev_dependencies:
   flutter_test:

+ 5 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/bulleted_list_text.dart

@@ -7,6 +7,7 @@ import 'package:appflowy_editor/src/render/rich_text/flowy_rich_text.dart';
 import 'package:appflowy_editor/src/render/selection/selectable.dart';
 import 'package:appflowy_editor/src/service/render_plugin_service.dart';
 import 'package:flutter/material.dart';
+import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
 
 class BulletedListTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
   @override
@@ -77,6 +78,10 @@ class _BulletedListTextNodeWidgetState extends State<BulletedListTextNodeWidget>
             child: FlowyRichText(
               key: _richTextKey,
               placeholderText: 'List',
+              textSpanDecorator: (textSpan) =>
+                  textSpan.updateTextStyle(textStyle),
+              placeholderTextSpanDecorator: (textSpan) =>
+                  textSpan.updateTextStyle(textStyle),
               lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
               textNode: widget.textNode,
               editorState: widget.editorState,

+ 5 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/quoted_text.dart

@@ -7,6 +7,7 @@ import 'package:appflowy_editor/src/render/rich_text/flowy_rich_text.dart';
 import 'package:appflowy_editor/src/render/selection/selectable.dart';
 import 'package:appflowy_editor/src/service/render_plugin_service.dart';
 import 'package:flutter/material.dart';
+import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
 
 class QuotedTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
   @override
@@ -77,6 +78,10 @@ class _QuotedTextNodeWidgetState extends State<QuotedTextNodeWidget>
                 key: _richTextKey,
                 placeholderText: 'Quote',
                 textNode: widget.textNode,
+                textSpanDecorator: (textSpan) =>
+                    textSpan.updateTextStyle(textStyle),
+                placeholderTextSpanDecorator: (textSpan) =>
+                    textSpan.updateTextStyle(textStyle),
                 lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
                 editorState: widget.editorState,
               ),

+ 4 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart

@@ -6,6 +6,7 @@ import 'package:appflowy_editor/src/render/rich_text/flowy_rich_text.dart';
 import 'package:appflowy_editor/src/render/selection/selectable.dart';
 import 'package:appflowy_editor/src/service/render_plugin_service.dart';
 import 'package:flutter/material.dart';
+import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
 
 class RichTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
   @override
@@ -64,6 +65,9 @@ class _RichTextNodeWidgetState extends State<RichTextNodeWidget>
       child: FlowyRichText(
         key: _richTextKey,
         textNode: widget.textNode,
+        textSpanDecorator: (textSpan) => textSpan.updateTextStyle(textStyle),
+        placeholderTextSpanDecorator: (textSpan) =>
+            textSpan.updateTextStyle(textStyle),
         lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
         editorState: widget.editorState,
       ),

+ 3 - 4
frontend/app_flowy/packages/appflowy_editor/pubspec.yaml

@@ -1,6 +1,6 @@
 name: appflowy_editor
 description: A highly customizable rich-text editor for Flutter
-version: 0.0.4
+version: 0.0.5
 homepage: https://github.com/AppFlowy-IO/AppFlowy
 
 platforms:
@@ -23,15 +23,14 @@ dependencies:
   url_launcher: ^6.1.5
   logging: ^1.0.2
   intl_utils: ^2.7.0
+  flutter_localizations:
+    sdk: flutter
 
 dev_dependencies:
   flutter_test:
     sdk: flutter
   flutter_lints: ^2.0.1
   network_image_mock: ^2.1.1
-  flutter_localizations:
-    sdk: flutter
-
 
 # For information on the generic Dart part of this file, see the
 # following page: https://dart.dev/tools/pub/pubspec