Skip to content

Commit 861456d

Browse files
committed
Add code theme customization
1 parent e3f7ebb commit 861456d

File tree

7 files changed

+446
-10
lines changed

7 files changed

+446
-10
lines changed

lib/pages/home_page.dart

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import 'package:analyzer/dart/ast/syntactic_entity.dart';
44
import 'package:analyzer/error/error.dart' show AnalysisError;
55
import 'package:analyzer/source/line_info.dart' show LineInfo;
66
import 'package:flutter/material.dart';
7+
import 'package:flutter_riverpod/flutter_riverpod.dart';
78
import 'package:lucide_icons_flutter/lucide_icons.dart';
89
import 'package:re_editor/re_editor.dart';
910

1011
import '../models/tree_node.dart';
12+
import '../providers/code_theme.dart';
1113
import '../utils/utils.dart';
1214
import '../widgets/about_button.dart';
1315
import '../widgets/analysis_error_list_view.dart';
@@ -17,6 +19,7 @@ import '../widgets/ast_node_tree_view.dart';
1719
import '../widgets/code_field.dart';
1820
import '../widgets/github_link_button.dart';
1921
import '../widgets/select_ast_node_dialog.dart';
22+
import '../widgets/select_code_theme_button.dart';
2023
import '../widgets/toggle_theme_mode_button.dart';
2124

2225
class HomePage extends StatefulWidget {
@@ -132,6 +135,7 @@ class _HomePageState extends State<HomePage> {
132135
actions: [
133136
const AboutButton(),
134137
const GithubLinkButton(),
138+
const SelectCodeThemeButton(),
135139
const ToggleThemeModeButton(),
136140
IconButton(
137141
tooltip: 'Ast Nodes',
@@ -148,10 +152,7 @@ class _HomePageState extends State<HomePage> {
148152
return Row(
149153
children: [
150154
Expanded(
151-
child: CodeField(
152-
controller: _controller,
153-
onContentChanged: _onContentChanged,
154-
),
155+
child: _buildCodeField(theme),
155156
),
156157
const SizedBox(width: 8.0),
157158
Expanded(
@@ -171,10 +172,7 @@ class _HomePageState extends State<HomePage> {
171172
children: [
172173
Expanded(
173174
flex: 2,
174-
child: CodeField(
175-
controller: _controller,
176-
onContentChanged: _onContentChanged,
177-
),
175+
child: _buildCodeField(theme),
178176
),
179177
const SizedBox(width: 8.0),
180178
Expanded(
@@ -193,6 +191,20 @@ class _HomePageState extends State<HomePage> {
193191
);
194192
}
195193

194+
Consumer _buildCodeField(ThemeData theme) {
195+
return Consumer(
196+
builder: (context, ref, child) {
197+
final lightCodeTheme = ref.watch(currentLightCodeThemeProvider);
198+
final darkCodeTheme = ref.watch(currentDarkCodeThemeProvider);
199+
return CodeField(
200+
controller: _controller,
201+
theme: theme.brightness == Brightness.light ? lightCodeTheme.value : darkCodeTheme.value,
202+
onContentChanged: _onContentChanged,
203+
);
204+
},
205+
);
206+
}
207+
196208
Widget _buildTreeView() {
197209
return _parsedResult.errors.isEmpty
198210
? AstNodeTreeView(

lib/providers/code_theme.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import 'package:riverpod_annotation/riverpod_annotation.dart';
2+
3+
import '../themes/code_theme.dart';
4+
import 'prefs.dart';
5+
6+
part 'code_theme.g.dart';
7+
8+
@riverpod
9+
class CurrentLightCodeTheme extends _$CurrentLightCodeTheme {
10+
@override
11+
LightCodeTheme build() {
12+
final prefs = ref.watch(sharedPrefsProvider).requireValue;
13+
final cachedTheme = prefs.getString('lightCodeTheme');
14+
15+
if (cachedTheme == null) {
16+
return LightCodeTheme.defaultTheme;
17+
}
18+
19+
return LightCodeTheme.values.firstWhere(
20+
(e) => e.name == cachedTheme,
21+
orElse: () => LightCodeTheme.defaultTheme,
22+
);
23+
}
24+
25+
void set(LightCodeTheme theme) {
26+
final prefs = ref.watch(sharedPrefsProvider).requireValue;
27+
prefs.setString('lightCodeTheme', theme.name);
28+
state = theme;
29+
}
30+
}
31+
32+
@riverpod
33+
class CurrentDarkCodeTheme extends _$CurrentDarkCodeTheme {
34+
@override
35+
DarkCodeTheme build() {
36+
final prefs = ref.watch(sharedPrefsProvider).requireValue;
37+
final cachedTheme = prefs.getString('darkCodeTheme');
38+
39+
if (cachedTheme == null) {
40+
return DarkCodeTheme.defaultTheme;
41+
}
42+
43+
return DarkCodeTheme.values.firstWhere(
44+
(e) => e.name == cachedTheme,
45+
orElse: () => DarkCodeTheme.defaultTheme,
46+
);
47+
}
48+
49+
void set(DarkCodeTheme theme) {
50+
final prefs = ref.watch(sharedPrefsProvider).requireValue;
51+
prefs.setString('darkCodeTheme', theme.name);
52+
state = theme;
53+
}
54+
}

lib/providers/code_theme.g.dart

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/themes/code_theme.dart

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import 'package:flutter/painting.dart' show TextStyle;
2+
import 'package:re_highlight/styles/a11y-dark.dart';
3+
import 'package:re_highlight/styles/a11y-light.dart';
4+
import 'package:re_highlight/styles/agate.dart';
5+
import 'package:re_highlight/styles/an-old-hope.dart';
6+
import 'package:re_highlight/styles/androidstudio.dart';
7+
import 'package:re_highlight/styles/arduino-light.dart';
8+
import 'package:re_highlight/styles/arta.dart';
9+
import 'package:re_highlight/styles/ascetic.dart';
10+
import 'package:re_highlight/styles/atom-one-dark-reasonable.dart';
11+
import 'package:re_highlight/styles/atom-one-dark.dart';
12+
import 'package:re_highlight/styles/atom-one-light.dart';
13+
import 'package:re_highlight/styles/brown-paper.dart';
14+
import 'package:re_highlight/styles/codepen-embed.dart';
15+
import 'package:re_highlight/styles/color-brewer.dart';
16+
import 'package:re_highlight/styles/dark.dart';
17+
import 'package:re_highlight/styles/devibeans.dart';
18+
import 'package:re_highlight/styles/docco.dart';
19+
import 'package:re_highlight/styles/far.dart';
20+
import 'package:re_highlight/styles/felipec.dart';
21+
import 'package:re_highlight/styles/foundation.dart';
22+
import 'package:re_highlight/styles/github-dark-dimmed.dart';
23+
import 'package:re_highlight/styles/github-dark.dart';
24+
import 'package:re_highlight/styles/github.dart';
25+
import 'package:re_highlight/styles/gml.dart';
26+
import 'package:re_highlight/styles/googlecode.dart';
27+
import 'package:re_highlight/styles/gradient-dark.dart';
28+
import 'package:re_highlight/styles/gradient-light.dart';
29+
import 'package:re_highlight/styles/grayscale.dart';
30+
import 'package:re_highlight/styles/hybrid.dart';
31+
import 'package:re_highlight/styles/idea.dart';
32+
import 'package:re_highlight/styles/intellij-light.dart';
33+
import 'package:re_highlight/styles/ir-black.dart';
34+
import 'package:re_highlight/styles/isbl-editor-dark.dart';
35+
import 'package:re_highlight/styles/isbl-editor-light.dart';
36+
import 'package:re_highlight/styles/kimbie-dark.dart';
37+
import 'package:re_highlight/styles/kimbie-light.dart';
38+
import 'package:re_highlight/styles/lightfair.dart';
39+
import 'package:re_highlight/styles/lioshi.dart';
40+
import 'package:re_highlight/styles/magula.dart';
41+
import 'package:re_highlight/styles/mono-blue.dart';
42+
import 'package:re_highlight/styles/monokai-sublime.dart';
43+
import 'package:re_highlight/styles/monokai.dart';
44+
import 'package:re_highlight/styles/night-owl.dart';
45+
import 'package:re_highlight/styles/nnfx-dark.dart';
46+
import 'package:re_highlight/styles/nnfx-light.dart';
47+
import 'package:re_highlight/styles/nord.dart';
48+
import 'package:re_highlight/styles/obsidian.dart';
49+
import 'package:re_highlight/styles/panda-syntax-dark.dart';
50+
import 'package:re_highlight/styles/panda-syntax-light.dart';
51+
import 'package:re_highlight/styles/paraiso-dark.dart';
52+
import 'package:re_highlight/styles/paraiso-light.dart';
53+
import 'package:re_highlight/styles/pojoaque.dart';
54+
import 'package:re_highlight/styles/purebasic.dart';
55+
import 'package:re_highlight/styles/qtcreator-dark.dart';
56+
import 'package:re_highlight/styles/qtcreator-light.dart';
57+
import 'package:re_highlight/styles/rainbow.dart';
58+
import 'package:re_highlight/styles/routeros.dart';
59+
import 'package:re_highlight/styles/school-book.dart';
60+
import 'package:re_highlight/styles/shades-of-purple.dart';
61+
import 'package:re_highlight/styles/srcery.dart';
62+
import 'package:re_highlight/styles/stackoverflow-dark.dart';
63+
import 'package:re_highlight/styles/stackoverflow-light.dart';
64+
import 'package:re_highlight/styles/sunburst.dart';
65+
import 'package:re_highlight/styles/tokyo-night-dark.dart';
66+
import 'package:re_highlight/styles/tokyo-night-light.dart';
67+
import 'package:re_highlight/styles/tomorrow-night-blue.dart';
68+
import 'package:re_highlight/styles/tomorrow-night-bright.dart';
69+
import 'package:re_highlight/styles/vs.dart';
70+
import 'package:re_highlight/styles/vs2015.dart';
71+
import 'package:re_highlight/styles/xcode.dart';
72+
import 'package:re_highlight/styles/xt256.dart';
73+
74+
enum LightCodeTheme {
75+
a11yLight('a11y-light', a11YLightTheme),
76+
arduinoLight('arduino-light', arduinoLightTheme),
77+
ascetic('ascetic', asceticTheme),
78+
atomOneLight('atom-one-light', atomOneLightTheme),
79+
github('github', githubTheme),
80+
gradientLight('gradient-light', gradientLightTheme),
81+
intellijLight('intellij-light', intellijLightTheme),
82+
isblEditorLight('isbl-editor-light', isblEditorLightTheme),
83+
kimbieLight('kimbie-light', kimbieLightTheme),
84+
lightfair('lightfair', lightfairTheme),
85+
monoBlue('mono-blue', monoBlueTheme),
86+
nnfxLight('nnfx-light', nnfxLightTheme),
87+
pandaSyntaxLight('panda-syntax-light', pandaSyntaxLightTheme),
88+
paraisoLight('paraiso-light', paraisoLightTheme),
89+
qtcreatorLight('qtcreator-light', qtcreatorLightTheme),
90+
stackoverflowLight('stackoverflow-light', stackoverflowLightTheme),
91+
tokyoNightLight('tokyo-night-light', tokyoNightLightTheme),
92+
vs('vs', vsTheme),
93+
xcode('xcode', xcodeTheme),
94+
;
95+
96+
final String label;
97+
final Map<String, TextStyle> value;
98+
99+
const LightCodeTheme(this.label, this.value);
100+
101+
static const LightCodeTheme defaultTheme = LightCodeTheme.github;
102+
}
103+
104+
enum DarkCodeTheme {
105+
a11YDark('a11y-dark', a11YDarkTheme),
106+
agate('agate', agateTheme),
107+
anOldHope('an-old-hope', anOldHopeTheme),
108+
androidstudio('androidstudio', androidstudioTheme),
109+
arta('arta', artaTheme),
110+
atomOneDarkReasonable('atom-one-dark-reasonable', atomOneDarkReasonableTheme),
111+
atomOneDark('atom-one-dark', atomOneDarkTheme),
112+
brownPaper('brown-paper', brownPaperTheme),
113+
codepenEmbed('codepen-embed', codepenEmbedTheme),
114+
colorBrewer('color-brewer', colorBrewerTheme),
115+
dark('dark', darkTheme),
116+
devibeans('devibeans', devibeansTheme),
117+
docco('docco', doccoTheme),
118+
far('far', farTheme),
119+
felipec('felipec', felipecTheme),
120+
foundation('foundation', foundationTheme),
121+
githubDarkDimmed('github-dark-dimmed', githubDarkDimmedTheme),
122+
githubDark('github-dark', githubDarkTheme),
123+
gml('gml', gmlTheme),
124+
googlecode('googlecode', googlecodeTheme),
125+
gradientDark('gradient-dark', gradientDarkTheme),
126+
grayscale('grayscale', grayscaleTheme),
127+
hybrid('hybrid', hybridTheme),
128+
idea('idea', ideaTheme),
129+
irBlack('ir-black', irBlackTheme),
130+
isblEditorDark('isbl-editor-dark', isblEditorDarkTheme),
131+
kimbieDark('kimbie-dark', kimbieDarkTheme),
132+
lioshi('lioshi', lioshiTheme),
133+
magula('magula', magulaTheme),
134+
monokaiSublime('monokai-sublime', monokaiSublimeTheme),
135+
monokai('monokai', monokaiTheme),
136+
nightOwl('night-owl', nightOwlTheme),
137+
nnfxDark('nnfx-dark', nnfxDarkTheme),
138+
nord('nord', nordTheme),
139+
obsidian('obsidian', obsidianTheme),
140+
pandaSyntaxDark('panda-syntax-dark', pandaSyntaxDarkTheme),
141+
paraisoDark('paraiso-dark', paraisoDarkTheme),
142+
pojoaque('pojoaque', pojoaqueTheme),
143+
purebasic('purebasic', purebasicTheme),
144+
qtcreatorDark('qtcreator-dark', qtcreatorDarkTheme),
145+
rainbow('rainbow', rainbowTheme),
146+
routeros('routeros', routerosTheme),
147+
schoolBook('school-book', schoolBookTheme),
148+
shadesOfPurple('shades-of-purple', shadesOfPurpleTheme),
149+
srcery('srcery', srceryTheme),
150+
stackoverflowDark('stackoverflow-dark', stackoverflowDarkTheme),
151+
sunburst('sunburst', sunburstTheme),
152+
tokyoNightDark('tokyo-night-dark', tokyoNightDarkTheme),
153+
tomorrowNightBlue('tomorrow-night-blue', tomorrowNightBlueTheme),
154+
tomorrowNightBright('tomorrow-night-bright', tomorrowNightBrightTheme),
155+
vs2015('vs2015', vs2015Theme),
156+
xt256('xt256', xt256Theme),
157+
;
158+
159+
final String label;
160+
final Map<String, TextStyle> value;
161+
162+
const DarkCodeTheme(this.label, this.value);
163+
164+
static const DarkCodeTheme defaultTheme = DarkCodeTheme.githubDark;
165+
}

lib/widgets/code_field.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:re_editor/re_editor.dart';
33
import 'package:re_highlight/languages/dart.dart';
4-
import 'package:re_highlight/styles/monokai-sublime.dart';
54

65
import 'app_decorated_box.dart';
76

@@ -12,12 +11,14 @@ class CodeField extends StatefulWidget {
1211
this.wordWrap = false,
1312
this.controller,
1413
this.onContentChanged,
14+
required this.theme,
1515
});
1616

1717
final bool readOnly;
1818
final bool wordWrap;
1919
final CodeLineEditingController? controller;
2020
final ValueChanged<String>? onContentChanged;
21+
final Map<String, TextStyle> theme;
2122

2223
@override
2324
State<CodeField> createState() => _CodeFieldState();
@@ -67,7 +68,7 @@ class _CodeFieldState extends State<CodeField> {
6768
fontFamily: 'JetBrainsMono',
6869
codeTheme: CodeHighlightTheme(
6970
languages: {'dart': CodeHighlightThemeMode(mode: langDart)},
70-
theme: monokaiSublimeTheme,
71+
theme: widget.theme,
7172
),
7273
),
7374
indicatorBuilder: (context, editingController, chunkController, notifier) {

0 commit comments

Comments
 (0)