mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: 0.0.5 release preparation
This commit is contained in:
parent
a371cf3a7c
commit
5bb5337de8
@ -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
|
## 0.0.4
|
||||||
* Support more shortcut events.
|
* Support more shortcut events.
|
||||||
* Fix some bugs.
|
* Fix some bugs.
|
||||||
|
@ -36,8 +36,8 @@ and the Flutter guide for
|
|||||||
* Design and modify an ever expanding list of customizable features including
|
* Design and modify an ever expanding list of customizable features including
|
||||||
* components (such as form input controls, numbered lists, and rich text widgets)
|
* components (such as form input controls, numbered lists, and rich text widgets)
|
||||||
* shortcut events
|
* shortcut events
|
||||||
|
* themes
|
||||||
* menu options (**coming soon!**)
|
* 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
|
* [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
|
## Getting Started
|
||||||
@ -54,11 +54,13 @@ flutter pub get
|
|||||||
Start by creating a new empty AppFlowyEditor object.
|
Start by creating a new empty AppFlowyEditor object.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
|
final editorStyle = EditorStyle.defaultStyle();
|
||||||
final editorState = EditorState.empty(); // an empty state
|
final editorState = EditorState.empty(); // an empty state
|
||||||
final editor = AppFlowyEditor(
|
final editor = AppFlowyEditor(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
keyEventHandlers: const [],
|
shortcutEvents: const [],
|
||||||
customBuilders: 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
|
```dart
|
||||||
final json = ...;
|
final json = ...;
|
||||||
|
final editorStyle = EditorStyle.defaultStyle();
|
||||||
final editorState = EditorState(StateTree.fromJson(data));
|
final editorState = EditorState(StateTree.fromJson(data));
|
||||||
final editor = AppFlowyEditor(
|
final editor = AppFlowyEditor(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
keyEventHandlers: const [],
|
shortcutEvents: const [],
|
||||||
customBuilders: const {},
|
customBuilders: const {},
|
||||||
|
editorStyle: editorStyle,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note: The parameters `localizationsDelegates` need to be assigned in MaterialApp widget
|
||||||
|
```dart
|
||||||
|
MaterialApp(
|
||||||
|
localizationsDelegates: const [
|
||||||
|
AppFlowyEditorLocalizations.delegate,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ Widget build(BuildContext context) {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: AppFlowyEditor(
|
child: AppFlowyEditor(
|
||||||
editorState: EditorState.empty(),
|
editorState: EditorState.empty(),
|
||||||
|
editorStyle: EditorStyle.defaultStyle(),
|
||||||
shortcutEvents: const [],
|
shortcutEvents: const [],
|
||||||
|
customBuilders: const {},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -116,6 +118,8 @@ Widget build(BuildContext context) {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: AppFlowyEditor(
|
child: AppFlowyEditor(
|
||||||
editorState: EditorState.empty(),
|
editorState: EditorState.empty(),
|
||||||
|
editorStyle: EditorStyle.defaultStyle(),
|
||||||
|
customBuilders: const {},
|
||||||
shortcutEvents: [
|
shortcutEvents: [
|
||||||
_underscoreToItalicHandler,
|
_underscoreToItalicHandler,
|
||||||
],
|
],
|
||||||
@ -145,7 +149,9 @@ Widget build(BuildContext context) {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: AppFlowyEditor(
|
child: AppFlowyEditor(
|
||||||
editorState: EditorState.empty(),
|
editorState: EditorState.empty(),
|
||||||
keyEventHandlers: const [],
|
editorStyle: EditorStyle.defaultStyle(),
|
||||||
|
shortcutEvents: const [],
|
||||||
|
customBuilders: const {},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -283,6 +289,8 @@ final editorState = EditorState(
|
|||||||
);
|
);
|
||||||
return AppFlowyEditor(
|
return AppFlowyEditor(
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
|
editorStyle: EditorStyle.defaultStyle(),
|
||||||
|
shortcutEvents: const [],
|
||||||
customBuilders: {
|
customBuilders: {
|
||||||
'network_image': NetworkImageNodeWidgetBuilder(),
|
'network_image': NetworkImageNodeWidgetBuilder(),
|
||||||
},
|
},
|
||||||
@ -292,3 +300,95 @@ return AppFlowyEditor(
|
|||||||

|

|
||||||
|
|
||||||
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.
|
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 ...
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
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 {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
Binary file not shown.
After Width: | Height: | Size: 300 KiB |
Binary file not shown.
After Width: | Height: | Size: 343 KiB |
@ -56,7 +56,7 @@
|
|||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": { "subtype": "quote" },
|
"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": [] },
|
{ "type": "text", "delta": [] },
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,8 @@ import 'dart:io';
|
|||||||
import 'package:example/plugin/underscore_to_italic_key_event_handler.dart';
|
import 'package:example/plugin/underscore_to_italic_key_event_handler.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.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';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
@ -22,6 +24,9 @@ class MyApp extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
AppFlowyEditorLocalizations.delegate,
|
AppFlowyEditorLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: AppFlowyEditorLocalizations.delegate.supportedLocales,
|
supportedLocales: AppFlowyEditorLocalizations.delegate.supportedLocales,
|
||||||
@ -149,11 +154,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
icon: const Icon(Icons.color_lens),
|
icon: const Icon(Icons.color_lens),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_editorStyle = _editorStyle.copyWith(
|
_editorStyle =
|
||||||
textStyle: darkMode
|
darkMode ? EditorStyle.defaultStyle() : _customizedStyle();
|
||||||
? BuiltInTextStyle.builtIn()
|
|
||||||
: BuiltInTextStyle.builtInDarkMode(),
|
|
||||||
);
|
|
||||||
darkMode = !darkMode;
|
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,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,10 @@ dependencies:
|
|||||||
url_launcher: ^6.1.5
|
url_launcher: ^6.1.5
|
||||||
video_player: ^2.4.5
|
video_player: ^2.4.5
|
||||||
pod_player: 0.0.8
|
pod_player: 0.0.8
|
||||||
flutter_inappwebview: ^5.4.3+7
|
|
||||||
path_provider: ^2.0.11
|
path_provider: ^2.0.11
|
||||||
|
google_fonts: ^3.0.1
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -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/render/selection/selectable.dart';
|
||||||
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
|
||||||
|
|
||||||
class BulletedListTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
class BulletedListTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
||||||
@override
|
@override
|
||||||
@ -77,6 +78,10 @@ class _BulletedListTextNodeWidgetState extends State<BulletedListTextNodeWidget>
|
|||||||
child: FlowyRichText(
|
child: FlowyRichText(
|
||||||
key: _richTextKey,
|
key: _richTextKey,
|
||||||
placeholderText: 'List',
|
placeholderText: 'List',
|
||||||
|
textSpanDecorator: (textSpan) =>
|
||||||
|
textSpan.updateTextStyle(textStyle),
|
||||||
|
placeholderTextSpanDecorator: (textSpan) =>
|
||||||
|
textSpan.updateTextStyle(textStyle),
|
||||||
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
||||||
textNode: widget.textNode,
|
textNode: widget.textNode,
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
|
@ -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/render/selection/selectable.dart';
|
||||||
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
|
||||||
|
|
||||||
class QuotedTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
class QuotedTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
||||||
@override
|
@override
|
||||||
@ -77,6 +78,10 @@ class _QuotedTextNodeWidgetState extends State<QuotedTextNodeWidget>
|
|||||||
key: _richTextKey,
|
key: _richTextKey,
|
||||||
placeholderText: 'Quote',
|
placeholderText: 'Quote',
|
||||||
textNode: widget.textNode,
|
textNode: widget.textNode,
|
||||||
|
textSpanDecorator: (textSpan) =>
|
||||||
|
textSpan.updateTextStyle(textStyle),
|
||||||
|
placeholderTextSpanDecorator: (textSpan) =>
|
||||||
|
textSpan.updateTextStyle(textStyle),
|
||||||
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
),
|
),
|
||||||
|
@ -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/render/selection/selectable.dart';
|
||||||
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
import 'package:appflowy_editor/src/service/render_plugin_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:appflowy_editor/src/extensions/text_style_extension.dart';
|
||||||
|
|
||||||
class RichTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
class RichTextNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
||||||
@override
|
@override
|
||||||
@ -64,6 +65,9 @@ class _RichTextNodeWidgetState extends State<RichTextNodeWidget>
|
|||||||
child: FlowyRichText(
|
child: FlowyRichText(
|
||||||
key: _richTextKey,
|
key: _richTextKey,
|
||||||
textNode: widget.textNode,
|
textNode: widget.textNode,
|
||||||
|
textSpanDecorator: (textSpan) => textSpan.updateTextStyle(textStyle),
|
||||||
|
placeholderTextSpanDecorator: (textSpan) =>
|
||||||
|
textSpan.updateTextStyle(textStyle),
|
||||||
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
lineHeight: widget.editorState.editorStyle.textStyle.lineHeight,
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: appflowy_editor
|
name: appflowy_editor
|
||||||
description: A highly customizable rich-text editor for Flutter
|
description: A highly customizable rich-text editor for Flutter
|
||||||
version: 0.0.4
|
version: 0.0.5
|
||||||
homepage: https://github.com/AppFlowy-IO/AppFlowy
|
homepage: https://github.com/AppFlowy-IO/AppFlowy
|
||||||
|
|
||||||
platforms:
|
platforms:
|
||||||
@ -23,15 +23,14 @@ dependencies:
|
|||||||
url_launcher: ^6.1.5
|
url_launcher: ^6.1.5
|
||||||
logging: ^1.0.2
|
logging: ^1.0.2
|
||||||
intl_utils: ^2.7.0
|
intl_utils: ^2.7.0
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
network_image_mock: ^2.1.1
|
network_image_mock: ^2.1.1
|
||||||
flutter_localizations:
|
|
||||||
sdk: flutter
|
|
||||||
|
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
Loading…
x
Reference in New Issue
Block a user