Skip to content

Commit caec8dc

Browse files
Merge pull request #93 from andrew-bekhiet-solid/allow-providing-custom-lang-tool-service
feat: allow overriding languageCheckService
2 parents 4c24bda + 8290948 commit caec8dc

File tree

9 files changed

+147
-103
lines changed

9 files changed

+147
-103
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
- BREAKING: require flutter 3.27.0 or higher
44
- BREAKING: require dart 3.0.0 or higher
55
- BREAKING: rename autoFocus to autofocus to match `TextField`'s naming
6+
- potentially BREAKING: remove `delayType` and `delay` fields from `LanguageToolController`
7+
- potentially BREAKING: hide baseService and debouncing/throttling from Debouncing and Throttling LanguageService wrappers
8+
- potentially BREAKING: rename `DebounceLanguageToolService` to `DebounceLanguageCheckService`
9+
- potentially BREAKING: rename `ThrottleLanguageToolService` to `ThrottleLanguageCheckService`
10+
- Allow overriding `languageCheckService`
611
- Add `isEnabled` to toggle spell check
712
- Add missing properties from flutter's `TextField`
813
- autofillHints

lib/languagetool_textfield.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export 'src/domain/highlight_style.dart';
1212
export 'src/domain/language_check_service.dart';
1313
export 'src/domain/mistake.dart';
1414
export 'src/domain/writing_mistake.dart';
15-
export 'src/implementations/debounce_lang_tool_service.dart';
16-
export 'src/implementations/lang_tool_service.dart';
17-
export 'src/implementations/throttling_lang_tool_service.dart';
15+
export 'src/language_check_services/language_tool_service.dart';
1816
export 'src/presentation/language_tool_text_field.dart';
1917
export 'src/utils/mistake_popup.dart';
2018
export 'src/utils/popup_overlay_renderer.dart';
19+
export 'src/wrappers/debounce_language_check_service.dart';
20+
export 'src/wrappers/throttling_language_check_service.dart';

lib/src/core/controllers/language_tool_controller.dart

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,10 @@ import 'dart:math';
33
import 'package:collection/collection.dart';
44
import 'package:flutter/gestures.dart';
55
import 'package:flutter/material.dart';
6-
import 'package:languagetool_textfield/src/client/language_tool_client.dart';
7-
import 'package:languagetool_textfield/src/core/enums/delay_type.dart';
6+
import 'package:languagetool_textfield/languagetool_textfield.dart';
87
import 'package:languagetool_textfield/src/core/enums/mistake_type.dart';
9-
import 'package:languagetool_textfield/src/domain/highlight_style.dart';
10-
import 'package:languagetool_textfield/src/domain/language_check_service.dart';
11-
import 'package:languagetool_textfield/src/domain/mistake.dart';
12-
import 'package:languagetool_textfield/src/implementations/debounce_lang_tool_service.dart';
13-
import 'package:languagetool_textfield/src/implementations/lang_tool_service.dart';
14-
import 'package:languagetool_textfield/src/implementations/throttling_lang_tool_service.dart';
158
import 'package:languagetool_textfield/src/utils/closed_range.dart';
169
import 'package:languagetool_textfield/src/utils/keep_latest_response_service.dart';
17-
import 'package:languagetool_textfield/src/utils/mistake_popup.dart';
1810

1911
/// A TextEditingController with overrides buildTextSpan for building
2012
/// marked TextSpans with tap recognizer
@@ -24,23 +16,6 @@ class LanguageToolController extends TextEditingController {
2416
/// Color scheme to highlight mistakes
2517
final HighlightStyle highlightStyle;
2618

27-
/// Represents the type of delay for language checking.
28-
///
29-
/// [DelayType.debouncing] - Calls a function when a user hasn't carried out
30-
/// the event in a specific amount of time.
31-
///
32-
/// [DelayType.throttling] - Calls a function at intervals of a specified
33-
/// amount of time while the user is carrying out the event.
34-
final DelayType delayType;
35-
36-
/// Represents the duration of the delay for language checking.
37-
///
38-
/// If the delay is [Duration.zero], no delaying is applied.
39-
final Duration delay;
40-
41-
/// Create an instance of [LanguageToolClient] instance
42-
final _languageToolClient = LanguageToolClient();
43-
4419
/// Create an instance of [KeepLatestResponseService]
4520
/// to handle asynchronous operations
4621
final _latestResponseService = KeepLatestResponseService();
@@ -69,10 +44,10 @@ class LanguageToolController extends TextEditingController {
6944
///
7045
/// A language code like en-US, de-DE, fr, or auto to guess
7146
/// the language automatically.
72-
String get language => _languageToolClient.language;
47+
String get language => _languageCheckService?.language ?? 'auto';
7348

7449
set language(String language) {
75-
_languageToolClient.language = language;
50+
_languageCheckService?.language = language;
7651
}
7752

7853
/// Indicates whether spell checking is enabled
@@ -108,26 +83,51 @@ class LanguageToolController extends TextEditingController {
10883
super.value = newValue;
10984
}
11085

111-
/// Controller constructor
86+
/// Controller constructor.
87+
///
88+
/// [highlightStyle] - Color scheme to highlight mistakes.
89+
///
90+
/// [delayType] - Represents the type of delay for language checking.
91+
/// [DelayType.debouncing] - Calls a function when a user hasn't carried out
92+
/// the event in a specific amount of time.
93+
/// [DelayType.throttling] - Calls a function at intervals of a specified
94+
/// amount of time while the user is carrying out the event.
95+
///
96+
/// [delay] - Represents the duration of the delay for language checking.
97+
/// If the delay is [Duration.zero], no delaying is applied.
98+
///
99+
/// You can optionally provide a custom [languageCheckService] to fully control
100+
/// how text is analyzed and processed. When provided, [delayType] and [delay]
101+
/// are ignored.
112102
LanguageToolController({
113103
bool isEnabled = true,
114104
this.highlightStyle = const HighlightStyle(),
115-
this.delay = Duration.zero,
116-
this.delayType = DelayType.debouncing,
105+
DelayType delayType = DelayType.debouncing,
106+
Duration delay = Duration.zero,
107+
LanguageCheckService? languageCheckService,
117108
}) : _isEnabled = isEnabled {
118-
_languageCheckService = _getLanguageCheckService();
109+
_languageCheckService = languageCheckService ??
110+
_getLanguageCheckService(
111+
delayType: delayType,
112+
delay: delay,
113+
languageToolClient: LanguageToolClient(),
114+
);
119115
}
120116

121-
LanguageCheckService _getLanguageCheckService() {
122-
final languageToolService = LangToolService(_languageToolClient);
117+
static LanguageCheckService _getLanguageCheckService({
118+
required DelayType delayType,
119+
required Duration delay,
120+
required LanguageToolClient languageToolClient,
121+
}) {
122+
final languageToolService = LanguageToolService(languageToolClient);
123123

124124
if (delay == Duration.zero) return languageToolService;
125125

126126
switch (delayType) {
127127
case DelayType.debouncing:
128-
return DebounceLangToolService(languageToolService, delay);
128+
return DebounceLanguageCheckService(languageToolService, delay);
129129
case DelayType.throttling:
130-
return ThrottlingLangToolService(languageToolService, delay);
130+
return ThrottlingLanguageCheckService(languageToolService, delay);
131131
}
132132
}
133133

lib/src/domain/language_check_service.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ import 'package:languagetool_textfield/src/utils/result.dart';
33

44
/// A base language check service.
55
abstract class LanguageCheckService {
6+
/// Gets the current language code used for language checking.
7+
///
8+
/// Returns a string representing the language code (e.g., 'en-US', 'de-DE').
9+
String get language;
10+
11+
/// Sets the language code to be used for language checking.
12+
///
13+
/// [language] A string representing the language code (e.g., 'en-US', 'de-DE').
14+
/// This determines which language rules will be applied during text analysis.
15+
set language(String language);
16+
617
/// Creates a new instance of the [LanguageCheckService] class.
718
const LanguageCheckService();
819

lib/src/implementations/debounce_lang_tool_service.dart

Lines changed: 0 additions & 30 deletions
This file was deleted.

lib/src/implementations/throttling_lang_tool_service.dart

Lines changed: 0 additions & 31 deletions
This file was deleted.

lib/src/implementations/lang_tool_service.dart renamed to lib/src/language_check_services/language_tool_service.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import 'package:languagetool_textfield/src/domain/writing_mistake.dart';
55
import 'package:languagetool_textfield/src/utils/result.dart';
66

77
/// An implementation of language check service with language tool service.
8-
class LangToolService extends LanguageCheckService {
8+
class LanguageToolService extends LanguageCheckService {
99
/// An instance of this class that is used to interact with LanguageTool API.
1010
final LanguageToolClient languageTool;
1111

12-
/// Creates a new instance of the [LangToolService].
13-
LangToolService(this.languageTool);
12+
@override
13+
String get language => languageTool.language;
14+
15+
@override
16+
set language(String language) {
17+
languageTool.language = language;
18+
}
19+
20+
/// Creates a new instance of the [LanguageToolService].
21+
LanguageToolService(this.languageTool);
1422

1523
@override
1624
Future<Result<List<Mistake>>> findMistakes(String text) async {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'package:languagetool_textfield/src/domain/language_check_service.dart';
2+
import 'package:languagetool_textfield/src/domain/mistake.dart';
3+
import 'package:languagetool_textfield/src/utils/result.dart';
4+
import 'package:throttling/throttling.dart';
5+
6+
/// A language check service with debouncing.
7+
class DebounceLanguageCheckService extends LanguageCheckService {
8+
/// A base language check service.
9+
final LanguageCheckService _languageCheckService;
10+
11+
/// A debouncing used to debounce the API calls.
12+
final Debouncing<Future<Result<List<Mistake>>?>> _debouncing;
13+
14+
@override
15+
String get language => _languageCheckService.language;
16+
17+
@override
18+
set language(String language) {
19+
_languageCheckService.language = language;
20+
}
21+
22+
/// Creates a new instance of the [DebounceLanguageCheckService] class.
23+
DebounceLanguageCheckService(
24+
this._languageCheckService,
25+
Duration debouncingDuration,
26+
) : _debouncing = Debouncing(duration: debouncingDuration);
27+
28+
@override
29+
Future<Result<List<Mistake>>?> findMistakes(String text) async {
30+
return await _debouncing
31+
.debounce(() => _languageCheckService.findMistakes(text));
32+
}
33+
34+
// ignore: proper_super_calls
35+
@override
36+
Future<void> dispose() async {
37+
_debouncing.close();
38+
await _languageCheckService.dispose();
39+
}
40+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import 'package:languagetool_textfield/src/domain/language_check_service.dart';
2+
import 'package:languagetool_textfield/src/domain/mistake.dart';
3+
import 'package:languagetool_textfield/src/utils/result.dart';
4+
import 'package:throttling/throttling.dart';
5+
6+
/// A language check service with debouncing.
7+
class ThrottlingLanguageCheckService extends LanguageCheckService {
8+
/// A base language check service that is used to interact
9+
/// with the language check API.
10+
final LanguageCheckService _languageCheckService;
11+
12+
/// A throttling used to throttle the API calls.
13+
final Throttling<Future<Result<List<Mistake>>?>> _throttling;
14+
15+
@override
16+
String get language => _languageCheckService.language;
17+
18+
@override
19+
set language(String language) {
20+
_languageCheckService.language = language;
21+
}
22+
23+
/// Creates a new instance of the [ThrottlingLanguageCheckService] class.
24+
ThrottlingLanguageCheckService(
25+
this._languageCheckService,
26+
Duration throttlingDuration,
27+
) : _throttling = Throttling(duration: throttlingDuration);
28+
29+
@override
30+
Future<Result<List<Mistake>>?> findMistakes(String text) async {
31+
return await _throttling
32+
.throttle(() => _languageCheckService.findMistakes(text));
33+
}
34+
35+
// ignore: proper_super_calls
36+
@override
37+
Future<void> dispose() async {
38+
_throttling.close();
39+
await _languageCheckService.dispose();
40+
}
41+
}

0 commit comments

Comments
 (0)