Skip to content

Commit ceb309a

Browse files
committed
feat: adapt dark mode
1 parent cc6bf3c commit ceb309a

35 files changed

+921
-534
lines changed

frontend/app_flowy/lib/plugins/doc/document_page.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,20 @@ class _DocumentPageState extends State<DocumentPage> {
9393
}
9494

9595
Widget _renderAppFlowyEditor(EditorState editorState) {
96+
final theme = Theme.of(context);
9697
final editor = AppFlowyEditor(
9798
editorState: editorState,
98-
editorStyle: customEditorStyle(context),
9999
customBuilders: {
100100
'horizontal_rule': HorizontalRuleWidgetBuilder(),
101101
},
102102
shortcutEvents: [
103103
insertHorizontalRule,
104104
],
105+
themeData: theme.copyWith(extensions: [
106+
...theme.extensions.values,
107+
customEditorTheme(context),
108+
...customPluginTheme(context),
109+
]),
105110
);
106111
return Expanded(
107112
child: SizedBox.expand(

frontend/app_flowy/lib/plugins/doc/editor_styles.dart

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,63 @@ import 'package:flowy_infra/theme.dart';
33
import 'package:flutter/material.dart';
44
import 'package:provider/provider.dart';
55

6-
EditorStyle customEditorStyle(BuildContext context) {
6+
const _baseFontSize = 14.0;
7+
8+
EditorStyle customEditorTheme(BuildContext context) {
79
final theme = context.watch<AppTheme>();
8-
const baseFontSize = 14.0;
9-
const basePadding = 12.0;
10-
var textStyle = theme.isDark
11-
? BuiltInTextStyle.builtInDarkMode()
12-
: BuiltInTextStyle.builtIn();
13-
textStyle = textStyle.copyWith(
14-
defaultTextStyle: textStyle.defaultTextStyle.copyWith(
10+
11+
var editorStyle = theme.isDark ? EditorStyle.dark : EditorStyle.light;
12+
editorStyle = editorStyle.copyWith(
13+
textStyle: editorStyle.textStyle?.copyWith(
14+
fontFamily: 'poppins',
15+
fontSize: _baseFontSize,
16+
),
17+
placeholderTextStyle: editorStyle.placeholderTextStyle?.copyWith(
1518
fontFamily: 'poppins',
16-
fontSize: baseFontSize,
19+
fontSize: _baseFontSize,
1720
),
18-
bold: textStyle.bold.copyWith(
21+
bold: editorStyle.bold?.copyWith(
1922
fontWeight: FontWeight.w500,
2023
),
2124
);
22-
return EditorStyle.defaultStyle().copyWith(
23-
padding: const EdgeInsets.symmetric(horizontal: 80),
24-
textStyle: textStyle,
25-
pluginStyles: {
26-
'text/heading': builtInPluginStyle
27-
..update(
28-
'textStyle',
29-
(_) => (EditorState editorState, Node node) {
30-
final headingToFontSize = {
31-
'h1': baseFontSize + 12,
32-
'h2': baseFontSize + 8,
33-
'h3': baseFontSize + 4,
34-
'h4': baseFontSize,
35-
'h5': baseFontSize,
36-
'h6': baseFontSize,
37-
};
38-
final fontSize =
39-
headingToFontSize[node.attributes.heading] ?? baseFontSize;
40-
return TextStyle(fontSize: fontSize, fontWeight: FontWeight.w600);
41-
},
42-
)
43-
..update(
44-
'padding',
45-
(_) => (EditorState editorState, Node node) {
46-
final headingToPadding = {
47-
'h1': basePadding + 6,
48-
'h2': basePadding + 4,
49-
'h3': basePadding + 2,
50-
'h4': basePadding,
51-
'h5': basePadding,
52-
'h6': basePadding,
53-
};
54-
final padding =
55-
headingToPadding[node.attributes.heading] ?? basePadding;
56-
return EdgeInsets.only(bottom: padding);
57-
},
58-
)
25+
return editorStyle;
26+
}
27+
28+
Iterable<ThemeExtension<dynamic>> customPluginTheme(BuildContext context) {
29+
final theme = context.watch<AppTheme>();
30+
const basePadding = 12.0;
31+
var headingPluginStyle =
32+
theme.isDark ? HeadingPluginStyle.dark : HeadingPluginStyle.light;
33+
headingPluginStyle = headingPluginStyle.copyWith(
34+
textStyle: (EditorState editorState, Node node) {
35+
final headingToFontSize = {
36+
'h1': _baseFontSize + 12,
37+
'h2': _baseFontSize + 8,
38+
'h3': _baseFontSize + 4,
39+
'h4': _baseFontSize,
40+
'h5': _baseFontSize,
41+
'h6': _baseFontSize,
42+
};
43+
final fontSize =
44+
headingToFontSize[node.attributes.heading] ?? _baseFontSize;
45+
return TextStyle(fontSize: fontSize, fontWeight: FontWeight.w600);
46+
},
47+
padding: (EditorState editorState, Node node) {
48+
final headingToPadding = {
49+
'h1': basePadding + 6,
50+
'h2': basePadding + 4,
51+
'h3': basePadding + 2,
52+
'h4': basePadding,
53+
'h5': basePadding,
54+
'h6': basePadding,
55+
};
56+
final padding = headingToPadding[node.attributes.heading] ?? basePadding;
57+
return EdgeInsets.only(bottom: padding);
5958
},
6059
);
60+
final pluginTheme =
61+
theme.isDark ? darkPlguinStyleExtension : lightPlguinStyleExtension;
62+
return pluginTheme.toList()
63+
..removeWhere((element) => element is HeadingPluginStyle)
64+
..add(headingPluginStyle);
6165
}

frontend/app_flowy/lib/plugins/doc/presentation/plugins/horizontal_rule_node_widget.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ ShortcutEventHandler _insertHorzaontalRule = (editorState, event) {
3838

3939
SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem(
4040
name: () => 'Horizontal rule',
41-
icon: const Icon(
41+
icon: (editorState, onSelected) => Icon(
4242
Icons.horizontal_rule,
43-
color: Colors.black,
43+
color: onSelected
44+
? editorState.editorStyle.selectionMenuItemSelectedIconColor
45+
: editorState.editorStyle.selectionMenuItemIconColor,
4446
size: 18.0,
4547
),
4648
keywords: ['horizontal rule'],

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

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:flutter/services.dart';
1010

1111
import 'package:file_picker/file_picker.dart';
1212
import 'package:flutter_localizations/flutter_localizations.dart';
13-
import 'package:google_fonts/google_fonts.dart';
1413
import 'package:path_provider/path_provider.dart';
1514
import 'package:universal_html/html.dart' as html;
1615

@@ -38,7 +37,10 @@ class MyApp extends StatelessWidget {
3837
debugShowCheckedModeBanner: false,
3938
theme: ThemeData(
4039
primarySwatch: Colors.blue,
40+
// extensions: [HeadingPluginStyle.light],
4141
),
42+
darkTheme: ThemeData.dark(),
43+
themeMode: ThemeMode.dark,
4244
home: const MyHomePage(title: 'AppFlowyEditor Example'),
4345
);
4446
}
@@ -56,7 +58,6 @@ class _MyHomePageState extends State<MyHomePage> {
5658
int _pageIndex = 0;
5759
EditorState? _editorState;
5860
bool darkMode = false;
59-
EditorStyle _editorStyle = EditorStyle.defaultStyle();
6061
Future<String>? _jsonString;
6162

6263
@override
@@ -125,12 +126,31 @@ class _MyHomePageState extends State<MyHomePage> {
125126
_editorState!.transactionStream.listen((event) {
126127
debugPrint('Transaction: ${event.toJson()}');
127128
});
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+
);
128148
return Container(
129149
color: darkMode ? Colors.black : Colors.white,
130150
width: MediaQuery.of(context).size.width,
131151
child: AppFlowyEditor(
132152
editorState: _editorState!,
133-
editorStyle: _editorStyle,
153+
themeData: themeData,
134154
editable: true,
135155
customBuilders: {
136156
'text/code_block': CodeBlockNodeWidgetBuilder(),
@@ -186,8 +206,6 @@ class _MyHomePageState extends State<MyHomePage> {
186206
icon: const Icon(Icons.color_lens),
187207
onPressed: () {
188208
setState(() {
189-
_editorStyle =
190-
darkMode ? EditorStyle.defaultStyle() : _customizedStyle();
191209
darkMode = !darkMode;
192210
});
193211
},
@@ -256,44 +274,4 @@ class _MyHomePageState extends State<MyHomePage> {
256274
});
257275
}
258276
}
259-
260-
EditorStyle _customizedStyle() {
261-
final editorStyle = EditorStyle.defaultStyle();
262-
return editorStyle.copyWith(
263-
cursorColor: Colors.white,
264-
selectionColor: Colors.blue.withOpacity(0.3),
265-
textStyle: editorStyle.textStyle.copyWith(
266-
defaultTextStyle: GoogleFonts.poppins().copyWith(
267-
color: Colors.white,
268-
fontSize: 14.0,
269-
),
270-
defaultPlaceholderTextStyle: GoogleFonts.poppins().copyWith(
271-
color: Colors.white.withOpacity(0.5),
272-
fontSize: 14.0,
273-
),
274-
bold: const TextStyle(fontWeight: FontWeight.w900),
275-
code: TextStyle(
276-
fontStyle: FontStyle.italic,
277-
color: Colors.red[300],
278-
backgroundColor: Colors.grey.withOpacity(0.3),
279-
),
280-
highlightColorHex: '0x6FFFEB3B',
281-
),
282-
pluginStyles: {
283-
'text/quote': builtInPluginStyle
284-
..update(
285-
'textStyle',
286-
(_) {
287-
return (EditorState editorState, Node node) {
288-
return TextStyle(
289-
color: Colors.blue[200],
290-
fontStyle: FontStyle.italic,
291-
fontSize: 12.0,
292-
);
293-
};
294-
},
295-
),
296-
},
297-
);
298-
}
299277
}

frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ ShortcutEventHandler _ignorekHandler = (editorState, event) {
4646

4747
SelectionMenuItem codeBlockMenuItem = SelectionMenuItem(
4848
name: () => 'Code Block',
49-
icon: const Icon(
49+
icon: (_, __) => const Icon(
5050
Icons.abc,
5151
color: Colors.black,
5252
size: 18.0,
@@ -167,7 +167,7 @@ class __CodeBlockNodeWidgeState extends State<_CodeBlockNodeWidge>
167167
textNode: widget.textNode,
168168
editorState: widget.editorState,
169169
textSpanDecorator: (textSpan) => TextSpan(
170-
style: widget.editorState.editorStyle.textStyle.defaultTextStyle,
170+
style: widget.editorState.editorStyle.textStyle,
171171
children: codeTextSpan,
172172
),
173173
),

frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ShortcutEventHandler _insertHorzaontalRule = (editorState, event) {
3838

3939
SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem(
4040
name: () => 'Horizontal rule',
41-
icon: const Icon(
41+
icon: (_, __) => const Icon(
4242
Icons.horizontal_rule,
4343
color: Colors.black,
4444
size: 18.0,

frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:flutter_math_fork/flutter_math.dart';
66

77
SelectionMenuItem teXBlockMenuItem = SelectionMenuItem(
88
name: () => 'Tex',
9-
icon: const Icon(
9+
icon: (_, __) => const Icon(
1010
Icons.text_fields_rounded,
1111
color: Colors.black,
1212
size: 18.0,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ export 'src/render/rich_text/default_selectable.dart';
3131
export 'src/render/rich_text/flowy_rich_text.dart';
3232
export 'src/render/selection_menu/selection_menu_widget.dart';
3333
export 'src/l10n/l10n.dart';
34+
export 'src/render/style/plugin_styles.dart';
35+
export 'src/render/style/editor_style.dart';

frontend/app_flowy/packages/appflowy_editor/lib/src/editor_state.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@ class EditorState {
5959
/// Stores the selection menu items.
6060
List<SelectionMenuItem> selectionMenuItems = [];
6161

62-
/// Stores the editor style.
63-
EditorStyle editorStyle = EditorStyle.defaultStyle();
64-
6562
/// Operation stream.
6663
Stream<Transaction> get transactionStream => _observer.stream;
6764
final StreamController<Transaction> _observer = StreamController.broadcast();
6865

66+
late ThemeData themeData;
67+
EditorStyle get editorStyle =>
68+
themeData.extension<EditorStyle>() ?? EditorStyle.light;
69+
6970
final UndoManager undoManager = UndoManager();
7071
Selection? _cursorSelection;
7172

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'package:flutter/material.dart';
2+
3+
extension ThemeExtension on ThemeData {
4+
T? extensionOrNull<T>() {
5+
if (extensions.containsKey(T)) {
6+
return extensions[T] as T;
7+
}
8+
return null;
9+
}
10+
}

0 commit comments

Comments
 (0)