11import 'package:flutter/material.dart' ;
22import 'package:highlights_plugin/highlights_plugin.dart' ;
3+ import 'package:highlights_plugin/model/phrase_location.dart' ;
34
5+ // TODO Test code
6+ // TODO Add changelog
47void main () {
58 runApp (const MyApp ());
69}
@@ -19,6 +22,12 @@ class _MyAppState extends State<MyApp> {
1922 String ? _language;
2023 String ? _theme;
2124 List <String > _highlights = [];
25+ final List <PhraseLocation > _emphasis = [];
26+
27+ Future <void > _updateDarkMode (bool isDark) async {
28+ _highlightsPlugin.setDarkMode (isDark);
29+ _updateHighlights (_code ?? '' );
30+ }
2231
2332 void _updateLanguage (String language) {
2433 setState (() {
@@ -35,19 +44,29 @@ class _MyAppState extends State<MyApp> {
3544 }
3645
3746 Future <void > _updateHighlights (String code) async {
47+ print ('Updating highlights $code ' );
3848 _code = code;
39- final highlightList = await _highlightsPlugin.getHighlights (
49+ _highlightsPlugin
50+ .getHighlights (
4051 _code ?? '' ,
41- _language ?? '' ,
42- _theme ?? '' ,
43- [],
44- );
45- setState (() {
46- _highlights =
47- highlightList.map ((highlight) => highlight.toString ()).toList ();
52+ _language,
53+ _theme,
54+ _emphasis,
55+ )
56+ .then ((value) {
57+ print ('Flutter Highlights $value ' );
58+ setState (() {
59+ value.sort ((a, b) => a.location.start.compareTo (b.location.start));
60+ _highlights = value.map ((highlight) => highlight.toString ()).toList ();
61+ });
4862 });
4963 }
5064
65+ void _addEmphasis (PhraseLocation location) {
66+ _emphasis.add (location);
67+ _updateHighlights (_code ?? '' );
68+ }
69+
5170 @override
5271 Widget build (BuildContext context) {
5372 return MaterialApp (
@@ -59,13 +78,11 @@ class _MyAppState extends State<MyApp> {
5978 crossAxisAlignment: CrossAxisAlignment .stretch,
6079 children: [
6180 Expanded (
62- child: TextField (
63- onChanged: _updateHighlights,
64- maxLines: 20 ,
65- keyboardType: TextInputType .multiline,
66- decoration: const InputDecoration (
67- border: OutlineInputBorder (),
68- ),
81+ child: _EditableTextField (
82+ onChange: (code) => _updateHighlights (code),
83+ onBold: (location) {
84+ _addEmphasis (location);
85+ },
6986 ),
7087 ),
7188 Expanded (
@@ -79,13 +96,15 @@ class _MyAppState extends State<MyApp> {
7996 )
8097 ],
8198 ),
82- // TODO Add theme switcher
8399 bottomNavigationBar: Padding (
84100 padding: const EdgeInsets .all (16 ),
85101 child: Column (
86102 mainAxisSize: MainAxisSize .min,
87103 crossAxisAlignment: CrossAxisAlignment .stretch,
88104 children: < Widget > [
105+ _ThemeSwitchRow (
106+ onChange: (isDark) => _updateDarkMode (isDark),
107+ ),
89108 FutureDropdown (
90109 selected: _language,
91110 future: _highlightsPlugin.getLanguages (),
@@ -105,6 +124,83 @@ class _MyAppState extends State<MyApp> {
105124 }
106125}
107126
127+ class _EditableTextField extends StatelessWidget {
128+ const _EditableTextField ({
129+ required this .onChange,
130+ required this .onBold,
131+ });
132+
133+ final void Function (String ) onChange;
134+ final void Function (PhraseLocation ) onBold;
135+
136+ @override
137+ Widget build (BuildContext context) {
138+ return TextField (
139+ onChanged: onChange,
140+ maxLines: 20 ,
141+ keyboardType: TextInputType .multiline,
142+ decoration: const InputDecoration (
143+ border: OutlineInputBorder (),
144+ ),
145+ contextMenuBuilder: (context, state) {
146+ final TextEditingValue value = state.textEditingValue;
147+ final List <ContextMenuButtonItem > buttonItems =
148+ state.contextMenuButtonItems;
149+ buttonItems.insert (
150+ 0 ,
151+ ContextMenuButtonItem (
152+ label: 'Bold' ,
153+ onPressed: () {
154+ ContextMenuController .removeAny ();
155+ final range = value.selection;
156+ onBold (PhraseLocation (start: range.start, end: range.end));
157+ },
158+ ),
159+ );
160+ return AdaptiveTextSelectionToolbar .buttonItems (
161+ anchors: state.contextMenuAnchors,
162+ buttonItems: buttonItems,
163+ );
164+ },
165+ );
166+ }
167+ }
168+
169+ class _ThemeSwitchRow extends StatefulWidget {
170+ const _ThemeSwitchRow ({required this .onChange});
171+
172+ final void Function (bool ) onChange;
173+
174+ @override
175+ State <_ThemeSwitchRow > createState () => _ThemeSwitchRowState ();
176+ }
177+
178+ class _ThemeSwitchRowState extends State <_ThemeSwitchRow > {
179+ var isDark = false ;
180+
181+ @override
182+ Widget build (BuildContext context) {
183+ void onChanged (bool value) {
184+ widget.onChange (value);
185+ setState (() {
186+ isDark = value;
187+ });
188+ }
189+
190+ return Row (
191+ mainAxisAlignment: MainAxisAlignment .spaceEvenly,
192+ children: [
193+ const Icon (Icons .brightness_4),
194+ Switch (
195+ value: isDark,
196+ onChanged: (isDark) => onChanged (isDark),
197+ ),
198+ const Icon (Icons .brightness_2),
199+ ],
200+ );
201+ }
202+ }
203+
108204class FutureDropdown <T > extends StatelessWidget {
109205 const FutureDropdown ({
110206 required this .selected,
0 commit comments