@@ -3,44 +3,76 @@ import 'dart:math';
33import 'package:collection/collection.dart' ;
44import 'package:flutter/gestures.dart' ;
55import 'package:flutter/material.dart' ;
6+ import 'package:languagetool_textfield/client/language_tool_client.dart' ;
7+ import 'package:languagetool_textfield/core/enums/delay_type.dart' ;
68import 'package:languagetool_textfield/core/enums/mistake_type.dart' ;
79import 'package:languagetool_textfield/domain/highlight_style.dart' ;
810import 'package:languagetool_textfield/domain/language_check_service.dart' ;
911import 'package:languagetool_textfield/domain/mistake.dart' ;
12+ import 'package:languagetool_textfield/implementations/debounce_lang_tool_service.dart' ;
13+ import 'package:languagetool_textfield/implementations/lang_tool_service.dart' ;
14+ import 'package:languagetool_textfield/implementations/throttling_lang_tool_service.dart' ;
1015import 'package:languagetool_textfield/utils/closed_range.dart' ;
1116import 'package:languagetool_textfield/utils/keep_latest_response_service.dart' ;
1217import 'package:languagetool_textfield/utils/mistake_popup.dart' ;
1318
1419/// A TextEditingController with overrides buildTextSpan for building
1520/// marked TextSpans with tap recognizer
16- class ColoredTextEditingController extends TextEditingController {
21+ class LanguageToolController extends TextEditingController {
1722 /// Color scheme to highlight mistakes
1823 final HighlightStyle highlightStyle;
1924
20- /// Language tool API index
21- final LanguageCheckService languageCheckService;
25+ /// Represents the type of delay for language checking.
26+ ///
27+ /// [DelayType.debouncing] - Calls a function when a user hasn't carried out
28+ /// the event in a specific amount of time.
29+ ///
30+ /// [DelayType.throttling] - Calls a function at intervals of a specified
31+ /// amount of time while the user is carrying out the event.
32+ final DelayType delayType;
2233
23- /// Create an instance of [KeepLatestResponseService]
24- /// to handle asynchronous operations
25- final latestResponseService = KeepLatestResponseService ();
34+ /// Represents the duration of the delay for language checking.
35+ ///
36+ /// If the delay is [Duration.zero] , no delaying is applied.
37+ final Duration delay;
2638
27- /// List which contains Mistake objects spans are built from
28- List <Mistake > _mistakes = [];
39+ /// Create an instance of [LanguageToolClient] instance
40+ final _languageToolClient = LanguageToolClient ();
41+
42+ /// Create an instance of [KeepLatestResponseService]
43+ /// to handle asynchronous operations
44+ final _latestResponseService = KeepLatestResponseService ();
2945
3046 /// List of that is used to dispose recognizers after mistakes rebuilt
3147 final List <TapGestureRecognizer > _recognizers = [];
3248
33- /// Reference to the popup widget
34- MistakePopup ? popupWidget ;
49+ /// Language tool API index
50+ LanguageCheckService ? _languageCheckService ;
3551
3652 /// Reference to the focus of the LanguageTool TextField
3753 FocusNode ? focusNode;
3854
55+ /// List which contains Mistake objects spans are built from
56+ List <Mistake > _mistakes = [];
57+
58+ /// Reference to the popup widget
59+ MistakePopup ? popupWidget;
60+
3961 /// Represents the scroll offset value of the LanguageTool TextField.
4062 double ? scrollOffset;
4163
4264 Object ? _fetchError;
4365
66+ /// The language used for spellchecking in the text field.
67+ ///
68+ /// A language code like en-US, de-DE, fr, or auto to guess
69+ /// the language automatically.
70+ String get language => _languageToolClient.language;
71+
72+ set language (String language) {
73+ _languageToolClient.language = language;
74+ }
75+
4476 /// An error that may have occurred during the API fetch.
4577 Object ? get fetchError => _fetchError;
4678
@@ -51,10 +83,26 @@ class ColoredTextEditingController extends TextEditingController {
5183 }
5284
5385 /// Controller constructor
54- ColoredTextEditingController ({
55- required this .languageCheckService,
86+ LanguageToolController ({
5687 this .highlightStyle = const HighlightStyle (),
57- });
88+ this .delay = Duration .zero,
89+ this .delayType = DelayType .debouncing,
90+ }) {
91+ _languageCheckService = _getLanguageCheckService ();
92+ }
93+
94+ LanguageCheckService _getLanguageCheckService () {
95+ final languageToolService = LangToolService (_languageToolClient);
96+
97+ if (delay == Duration .zero) return languageToolService;
98+
99+ switch (delayType) {
100+ case DelayType .debouncing:
101+ return DebounceLangToolService (languageToolService, delay);
102+ case DelayType .throttling:
103+ return ThrottlingLangToolService (languageToolService, delay);
104+ }
105+ }
58106
59107 /// Close the popup widget
60108 void _closePopup () => popupWidget? .popupRenderer.dismiss ();
@@ -78,7 +126,7 @@ class ColoredTextEditingController extends TextEditingController {
78126
79127 @override
80128 void dispose () {
81- languageCheckService .dispose ();
129+ _languageCheckService ? .dispose ();
82130 super .dispose ();
83131 }
84132
@@ -114,8 +162,8 @@ class ColoredTextEditingController extends TextEditingController {
114162 }
115163 _recognizers.clear ();
116164
117- final mistakesWrapper = await latestResponseService .processLatestOperation (
118- () => languageCheckService .findMistakes (newText),
165+ final mistakesWrapper = await _latestResponseService .processLatestOperation (
166+ () => _languageCheckService ? .findMistakes (newText) ?? Future (() => null ),
119167 );
120168 final mistakes = mistakesWrapper? .result ();
121169 _fetchError = mistakesWrapper? .error;
0 commit comments