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
|
||||
* Support more shortcut events.
|
||||
* Fix some bugs.
|
||||
|
@ -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,
|
||||
],
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -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)
|
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",
|
||||
"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": [] },
|
||||
{
|
||||
|
@ -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,
|
||||
);
|
||||
};
|
||||
},
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user