Skip to content

Commit 9c24597

Browse files
authored
Merge pull request #1380 from LucasXu0/appflowy_editor_0_0_7
appflowy editor 0.0.7
2 parents ea46272 + ac36d76 commit 9c24597

File tree

10 files changed

+164
-105
lines changed

10 files changed

+164
-105
lines changed

frontend/app_flowy/packages/appflowy_editor/documentation/customizing.md

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ Widget build(BuildContext context) {
1616
alignment: Alignment.topCenter,
1717
child: AppFlowyEditor(
1818
editorState: EditorState.empty(),
19-
editorStyle: EditorStyle.defaultStyle(),
2019
shortcutEvents: const [],
2120
customBuilders: const {},
2221
),
@@ -93,7 +92,7 @@ ShortcutEventHandler _underscoreToItalicHandler = (editorState, event) {
9392
// Delete the previous 'underscore',
9493
// update the style of the text surrounded by the two underscores to 'italic',
9594
// and update the cursor position.
96-
TransactionBuilder(editorState)
95+
final transaction = editorState.transaction
9796
..deleteText(textNode, firstUnderscore, 1)
9897
..formatText(
9998
textNode,
@@ -108,8 +107,8 @@ ShortcutEventHandler _underscoreToItalicHandler = (editorState, event) {
108107
path: textNode.path,
109108
offset: selection.end.offset - 1,
110109
),
111-
)
112-
..commit();
110+
);
111+
editorState.apply(transaction);
113112
114113
return KeyEventResult.handled;
115114
};
@@ -125,7 +124,6 @@ Widget build(BuildContext context) {
125124
alignment: Alignment.topCenter,
126125
child: AppFlowyEditor(
127126
editorState: EditorState.empty(),
128-
editorStyle: EditorStyle.defaultStyle(),
129127
customBuilders: const {},
130128
shortcutEvents: [
131129
underscoreToItalic,
@@ -138,7 +136,7 @@ Widget build(BuildContext context) {
138136

139137
![After](./images/customize_a_shortcut_event_after.gif)
140138

141-
Check out the [complete code](https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/underscore_to_italic.dart) file of this example.
139+
Check out the [complete code](https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text.dart) file of this example.
142140

143141

144142
## Customizing a Component
@@ -156,7 +154,6 @@ Widget build(BuildContext context) {
156154
alignment: Alignment.topCenter,
157155
child: AppFlowyEditor(
158156
editorState: EditorState.empty(),
159-
editorStyle: EditorStyle.defaultStyle(),
160157
shortcutEvents: const [],
161158
customBuilders: const {},
162159
),
@@ -180,7 +177,7 @@ We'll use `network_image` in this case. And we add `network_image_src` to the `a
180177

181178
Then, we create a class that inherits [NodeWidgetBuilder](../lib/src/service/render_plugin_service.dart). As shown in the autoprompt, we need to implement two functions:
182179
1. one returns a widget
183-
2. the other verifies the correctness of the [Node](../lib/src/document/node.dart).
180+
2. the other verifies the correctness of the [Node](../lib/src/core/document/node.dart).
184181

185182

186183
```dart
@@ -308,7 +305,7 @@ return AppFlowyEditor(
308305

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

311-
## Customizing a Theme (New Feature in 0.0.5, Alpha)
308+
## Customizing a Theme (New Feature in 0.0.7)
312309

313310
We will use a simple example to illustrate how to quickly customize a theme.
314311

@@ -322,7 +319,6 @@ Widget build(BuildContext context) {
322319
alignment: Alignment.topCenter,
323320
child: AppFlowyEditor(
324321
editorState: EditorState.empty(),
325-
editorStyle: EditorStyle.defaultStyle(),
326322
shortcutEvents: const [],
327323
customBuilders: const {},
328324
),
@@ -338,44 +334,41 @@ At this point, the editor looks like ...
338334
Next, we will customize the `EditorStyle`.
339335

340336
```dart
341-
EditorStyle _customizedStyle() {
342-
final editorStyle = EditorStyle.defaultStyle();
343-
return editorStyle.copyWith(
344-
cursorColor: Colors.white,
345-
selectionColor: Colors.blue.withOpacity(0.3),
346-
textStyle: editorStyle.textStyle.copyWith(
347-
defaultTextStyle: GoogleFonts.poppins().copyWith(
348-
color: Colors.white,
349-
fontSize: 14.0,
350-
),
351-
defaultPlaceholderTextStyle: GoogleFonts.poppins().copyWith(
352-
color: Colors.white.withOpacity(0.5),
353-
fontSize: 14.0,
354-
),
355-
bold: const TextStyle(fontWeight: FontWeight.w900),
356-
code: TextStyle(
357-
fontStyle: FontStyle.italic,
358-
color: Colors.red[300],
359-
backgroundColor: Colors.grey.withOpacity(0.3),
360-
),
361-
highlightColorHex: '0x6FFFEB3B',
337+
ThemeData customizeEditorTheme(BuildContext context) {
338+
final dark = EditorStyle.dark;
339+
final editorStyle = dark.copyWith(
340+
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 150),
341+
cursorColor: Colors.red.shade600,
342+
selectionColor: Colors.yellow.shade600.withOpacity(0.5),
343+
textStyle: GoogleFonts.poppins().copyWith(
344+
fontSize: 14,
345+
color: Colors.white,
346+
),
347+
placeholderTextStyle: GoogleFonts.poppins().copyWith(
348+
fontSize: 14,
349+
color: Colors.grey.shade400,
362350
),
363-
pluginStyles: {
364-
'text/quote': builtInPluginStyle
365-
..update(
366-
'textStyle',
367-
(_) {
368-
return (EditorState editorState, Node node) {
369-
return TextStyle(
370-
color: Colors.blue[200],
371-
fontStyle: FontStyle.italic,
372-
fontSize: 12.0,
373-
);
374-
};
375-
},
376-
),
377-
},
351+
code: dark.code?.copyWith(
352+
backgroundColor: Colors.lightBlue.shade200,
353+
fontStyle: FontStyle.italic,
354+
),
355+
highlightColorHex: '0x60FF0000', // red
378356
);
357+
358+
final quote = QuotedTextPluginStyle.dark.copyWith(
359+
textStyle: (_, __) => GoogleFonts.poppins().copyWith(
360+
fontSize: 14,
361+
color: Colors.blue.shade400,
362+
fontStyle: FontStyle.italic,
363+
fontWeight: FontWeight.w700,
364+
),
365+
);
366+
367+
return Theme.of(context).copyWith(extensions: [
368+
editorStyle,
369+
...darkPlguinStyleExtension,
370+
quote,
371+
]);
379372
}
380373
```
381374

@@ -389,7 +382,7 @@ Widget build(BuildContext context) {
389382
alignment: Alignment.topCenter,
390383
child: AppFlowyEditor(
391384
editorState: EditorState.empty(),
392-
editorStyle: _customizedStyle(),
385+
themeData: customizeEditorTheme(context),
393386
shortcutEvents: const [],
394387
customBuilders: const {},
395388
),
228 KB
Loading
800 KB
Loading

frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import 'dart:convert';
22
import 'dart:io';
33

4-
import 'package:example/plugin/code_block_node_widget.dart';
5-
import 'package:example/plugin/horizontal_rule_node_widget.dart';
6-
import 'package:example/plugin/tex_block_node_widget.dart';
4+
import 'package:example/plugin/editor_theme.dart';
75
import 'package:flutter/foundation.dart';
86
import 'package:flutter/material.dart';
97
import 'package:flutter/services.dart';
108

9+
import 'package:example/plugin/code_block_node_widget.dart';
10+
import 'package:example/plugin/horizontal_rule_node_widget.dart';
11+
import 'package:example/plugin/tex_block_node_widget.dart';
1112
import 'package:file_picker/file_picker.dart';
1213
import 'package:flutter_localizations/flutter_localizations.dart';
1314
import 'package:path_provider/path_provider.dart';
@@ -26,22 +27,16 @@ class MyApp extends StatelessWidget {
2627

2728
@override
2829
Widget build(BuildContext context) {
29-
return MaterialApp(
30-
localizationsDelegates: const [
30+
return const MaterialApp(
31+
localizationsDelegates: [
3132
GlobalMaterialLocalizations.delegate,
3233
GlobalCupertinoLocalizations.delegate,
3334
GlobalWidgetsLocalizations.delegate,
3435
AppFlowyEditorLocalizations.delegate,
3536
],
36-
supportedLocales: const [Locale('en', 'US')],
37+
supportedLocales: [Locale('en', 'US')],
3738
debugShowCheckedModeBanner: false,
38-
theme: ThemeData(
39-
primarySwatch: Colors.blue,
40-
// extensions: [HeadingPluginStyle.light],
41-
),
42-
darkTheme: ThemeData.dark(),
43-
themeMode: ThemeMode.dark,
44-
home: const MyHomePage(title: 'AppFlowyEditor Example'),
39+
home: MyHomePage(title: 'AppFlowyEditor Example'),
4540
);
4641
}
4742
}
@@ -60,25 +55,13 @@ class _MyHomePageState extends State<MyHomePage> {
6055
bool darkMode = false;
6156
Future<String>? _jsonString;
6257

58+
ThemeData? _editorThemeData;
59+
6360
@override
6461
Widget build(BuildContext context) {
6562
return Scaffold(
6663
extendBodyBehindAppBar: true,
6764
body: _buildEditor(context),
68-
// body: Center(
69-
// child: ContextMenu(editorState: EditorState.empty(), items: [
70-
// [
71-
// ContextMenuItem(name: 'ABCDEFGHIJKLM', onPressed: (editorState) {}),
72-
// ContextMenuItem(name: 'A', onPressed: (editorState) {}),
73-
// ContextMenuItem(name: 'A', onPressed: (editorState) {})
74-
// ],
75-
// [
76-
// ContextMenuItem(name: 'B', onPressed: (editorState) {}),
77-
// ContextMenuItem(name: 'B', onPressed: (editorState) {}),
78-
// ContextMenuItem(name: 'B', onPressed: (editorState) {})
79-
// ]
80-
// ]),
81-
// ),
8265
floatingActionButton: _buildExpandableFab(),
8366
);
8467
}
@@ -92,10 +75,6 @@ class _MyHomePageState extends State<MyHomePage> {
9275
rootBundle.loadString('assets/example.json'),
9376
);
9477
} else if (_pageIndex == 1) {
95-
return _buildEditorWithJsonString(
96-
rootBundle.loadString('assets/big_document.json'),
97-
);
98-
} else if (_pageIndex == 2) {
9978
return _buildEditorWithJsonString(
10079
Future.value(
10180
jsonEncode(EditorState.empty().document.toJson()),
@@ -126,32 +105,19 @@ class _MyHomePageState extends State<MyHomePage> {
126105
_editorState!.transactionStream.listen((event) {
127106
debugPrint('Transaction: ${event.toJson()}');
128107
});
129-
final themeData = darkMode
130-
? ThemeData.dark().copyWith(extensions: [
131-
HeadingPluginStyle.dark,
132-
CheckboxPluginStyle.dark,
133-
NumberListPluginStyle.dark,
134-
QuotedTextPluginStyle.dark,
135-
BulletedListPluginStyle.dark,
136-
EditorStyle.dark,
137-
])
138-
: ThemeData.light().copyWith(
139-
extensions: [
140-
HeadingPluginStyle.light,
141-
CheckboxPluginStyle.light,
142-
NumberListPluginStyle.light,
143-
QuotedTextPluginStyle.light,
144-
BulletedListPluginStyle.light,
145-
EditorStyle.light,
146-
],
147-
);
108+
_editorThemeData ??= Theme.of(context).copyWith(extensions: [
109+
if (darkMode) ...darkEditorStyleExtension,
110+
if (darkMode) ...darkPlguinStyleExtension,
111+
if (!darkMode) ...lightEditorStyleExtension,
112+
if (!darkMode) ...lightPlguinStyleExtension,
113+
]);
148114
return Container(
149115
color: darkMode ? Colors.black : Colors.white,
150116
width: MediaQuery.of(context).size.width,
151117
child: AppFlowyEditor(
152118
editorState: _editorState!,
153-
themeData: themeData,
154119
editable: true,
120+
themeData: _editorThemeData,
155121
customBuilders: {
156122
'text/code_block': CodeBlockNodeWidgetBuilder(),
157123
'tex': TeXBlockNodeWidgetBuidler(),
@@ -190,10 +156,6 @@ class _MyHomePageState extends State<MyHomePage> {
190156
icon: const Icon(Icons.abc),
191157
onPressed: () => _switchToPage(1),
192158
),
193-
ActionButton(
194-
icon: const Icon(Icons.abc),
195-
onPressed: () => _switchToPage(2),
196-
),
197159
ActionButton(
198160
icon: const Icon(Icons.print),
199161
onPressed: () => _exportDocument(_editorState!),
@@ -203,13 +165,22 @@ class _MyHomePageState extends State<MyHomePage> {
203165
onPressed: () async => await _importDocument(),
204166
),
205167
ActionButton(
206-
icon: const Icon(Icons.color_lens),
168+
icon: const Icon(Icons.dark_mode),
207169
onPressed: () {
208170
setState(() {
209171
darkMode = !darkMode;
210172
});
211173
},
212174
),
175+
ActionButton(
176+
icon: const Icon(Icons.color_lens),
177+
onPressed: () {
178+
setState(() {
179+
_editorThemeData = customizeEditorTheme(context);
180+
darkMode = true;
181+
});
182+
},
183+
),
213184
],
214185
);
215186
}
@@ -269,6 +240,7 @@ class _MyHomePageState extends State<MyHomePage> {
269240
void _switchToPage(int pageIndex) {
270241
if (pageIndex != _pageIndex) {
271242
setState(() {
243+
_editorThemeData = null;
272244
_editorState = null;
273245
_pageIndex = pageIndex;
274246
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'package:appflowy_editor/appflowy_editor.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:google_fonts/google_fonts.dart';
4+
5+
ThemeData customizeEditorTheme(BuildContext context) {
6+
final dark = EditorStyle.dark;
7+
final editorStyle = dark.copyWith(
8+
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 150),
9+
cursorColor: Colors.red.shade600,
10+
selectionColor: Colors.yellow.shade600.withOpacity(0.5),
11+
textStyle: GoogleFonts.poppins().copyWith(
12+
fontSize: 14,
13+
color: Colors.white,
14+
),
15+
placeholderTextStyle: GoogleFonts.poppins().copyWith(
16+
fontSize: 14,
17+
color: Colors.grey.shade400,
18+
),
19+
code: dark.code?.copyWith(
20+
backgroundColor: Colors.lightBlue.shade200,
21+
fontStyle: FontStyle.italic,
22+
),
23+
highlightColorHex: '0x60FF0000', // red
24+
);
25+
26+
final quote = QuotedTextPluginStyle.dark.copyWith(
27+
textStyle: (_, __) => GoogleFonts.poppins().copyWith(
28+
fontSize: 14,
29+
color: Colors.blue.shade400,
30+
fontStyle: FontStyle.italic,
31+
fontWeight: FontWeight.w700,
32+
),
33+
);
34+
35+
return Theme.of(context).copyWith(extensions: [
36+
editorStyle,
37+
...darkPlguinStyleExtension,
38+
quote,
39+
]);
40+
}

frontend/app_flowy/packages/appflowy_editor/lib/src/l10n/intl/messages_all.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:intl/intl.dart';
1515
import 'package:intl/message_lookup_by_library.dart';
1616
import 'package:intl/src/intl_helpers.dart';
1717

18+
import 'messages_bn_BN.dart' as messages_bn_bn;
1819
import 'messages_ca.dart' as messages_ca;
1920
import 'messages_cs-CZ.dart' as messages_cs_cz;
2021
import 'messages_de-DE.dart' as messages_de_de;
@@ -39,6 +40,7 @@ import 'messages_zh-TW.dart' as messages_zh_tw;
3940

4041
typedef Future<dynamic> LibraryLoader();
4142
Map<String, LibraryLoader> _deferredLibraries = {
43+
'bn_BN': () => new Future.value(null),
4244
'ca': () => new Future.value(null),
4345
'cs_CZ': () => new Future.value(null),
4446
'de_DE': () => new Future.value(null),
@@ -64,6 +66,8 @@ Map<String, LibraryLoader> _deferredLibraries = {
6466

6567
MessageLookupByLibrary? _findExact(String localeName) {
6668
switch (localeName) {
69+
case 'bn_BN':
70+
return messages_bn_bn.messages;
6771
case 'ca':
6872
return messages_ca.messages;
6973
case 'cs_CZ':

0 commit comments

Comments
 (0)