diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d43d18..c345970 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ - BREAKING: require flutter 3.27.0 or higher - BREAKING: require dart 3.0.0 or higher - BREAKING: rename autoFocus to autofocus to match `TextField`'s naming +- potentially BREAKING: remove `delayType` and `delay` fields from `LanguageToolController` +- potentially BREAKING: hide baseService and debouncing/throttling from Debouncing and Throttling LanguageService wrappers +- potentially BREAKING: rename `DebounceLanguageToolService` to `DebounceLanguageCheckService` +- potentially BREAKING: rename `ThrottleLanguageToolService` to `ThrottleLanguageCheckService` +- Allow overriding `languageCheckService` - Add `isEnabled` to toggle spell check - Add missing properties from flutter's `TextField` - autofillHints diff --git a/lib/languagetool_textfield.dart b/lib/languagetool_textfield.dart index 6379dc5..fa751af 100644 --- a/lib/languagetool_textfield.dart +++ b/lib/languagetool_textfield.dart @@ -12,9 +12,9 @@ export 'src/domain/highlight_style.dart'; export 'src/domain/language_check_service.dart'; export 'src/domain/mistake.dart'; export 'src/domain/writing_mistake.dart'; -export 'src/implementations/debounce_lang_tool_service.dart'; -export 'src/implementations/lang_tool_service.dart'; -export 'src/implementations/throttling_lang_tool_service.dart'; +export 'src/language_check_services/language_tool_service.dart'; export 'src/presentation/language_tool_text_field.dart'; export 'src/utils/mistake_popup.dart'; export 'src/utils/popup_overlay_renderer.dart'; +export 'src/wrappers/debounce_language_check_service.dart'; +export 'src/wrappers/throttling_language_check_service.dart'; diff --git a/lib/src/core/controllers/language_tool_controller.dart b/lib/src/core/controllers/language_tool_controller.dart index eb39c0e..40867a4 100644 --- a/lib/src/core/controllers/language_tool_controller.dart +++ b/lib/src/core/controllers/language_tool_controller.dart @@ -3,18 +3,10 @@ import 'dart:math'; import 'package:collection/collection.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:languagetool_textfield/src/client/language_tool_client.dart'; -import 'package:languagetool_textfield/src/core/enums/delay_type.dart'; +import 'package:languagetool_textfield/languagetool_textfield.dart'; import 'package:languagetool_textfield/src/core/enums/mistake_type.dart'; -import 'package:languagetool_textfield/src/domain/highlight_style.dart'; -import 'package:languagetool_textfield/src/domain/language_check_service.dart'; -import 'package:languagetool_textfield/src/domain/mistake.dart'; -import 'package:languagetool_textfield/src/implementations/debounce_lang_tool_service.dart'; -import 'package:languagetool_textfield/src/implementations/lang_tool_service.dart'; -import 'package:languagetool_textfield/src/implementations/throttling_lang_tool_service.dart'; import 'package:languagetool_textfield/src/utils/closed_range.dart'; import 'package:languagetool_textfield/src/utils/keep_latest_response_service.dart'; -import 'package:languagetool_textfield/src/utils/mistake_popup.dart'; /// A TextEditingController with overrides buildTextSpan for building /// marked TextSpans with tap recognizer @@ -24,23 +16,6 @@ class LanguageToolController extends TextEditingController { /// Color scheme to highlight mistakes final HighlightStyle highlightStyle; - /// Represents the type of delay for language checking. - /// - /// [DelayType.debouncing] - Calls a function when a user hasn't carried out - /// the event in a specific amount of time. - /// - /// [DelayType.throttling] - Calls a function at intervals of a specified - /// amount of time while the user is carrying out the event. - final DelayType delayType; - - /// Represents the duration of the delay for language checking. - /// - /// If the delay is [Duration.zero], no delaying is applied. - final Duration delay; - - /// Create an instance of [LanguageToolClient] instance - final _languageToolClient = LanguageToolClient(); - /// Create an instance of [KeepLatestResponseService] /// to handle asynchronous operations final _latestResponseService = KeepLatestResponseService(); @@ -69,10 +44,10 @@ class LanguageToolController extends TextEditingController { /// /// A language code like en-US, de-DE, fr, or auto to guess /// the language automatically. - String get language => _languageToolClient.language; + String get language => _languageCheckService?.language ?? 'auto'; set language(String language) { - _languageToolClient.language = language; + _languageCheckService?.language = language; } /// Indicates whether spell checking is enabled @@ -108,26 +83,51 @@ class LanguageToolController extends TextEditingController { super.value = newValue; } - /// Controller constructor + /// Controller constructor. + /// + /// [highlightStyle] - Color scheme to highlight mistakes. + /// + /// [delayType] - Represents the type of delay for language checking. + /// [DelayType.debouncing] - Calls a function when a user hasn't carried out + /// the event in a specific amount of time. + /// [DelayType.throttling] - Calls a function at intervals of a specified + /// amount of time while the user is carrying out the event. + /// + /// [delay] - Represents the duration of the delay for language checking. + /// If the delay is [Duration.zero], no delaying is applied. + /// + /// You can optionally provide a custom [languageCheckService] to fully control + /// how text is analyzed and processed. When provided, [delayType] and [delay] + /// are ignored. LanguageToolController({ bool isEnabled = true, this.highlightStyle = const HighlightStyle(), - this.delay = Duration.zero, - this.delayType = DelayType.debouncing, + DelayType delayType = DelayType.debouncing, + Duration delay = Duration.zero, + LanguageCheckService? languageCheckService, }) : _isEnabled = isEnabled { - _languageCheckService = _getLanguageCheckService(); + _languageCheckService = languageCheckService ?? + _getLanguageCheckService( + delayType: delayType, + delay: delay, + languageToolClient: LanguageToolClient(), + ); } - LanguageCheckService _getLanguageCheckService() { - final languageToolService = LangToolService(_languageToolClient); + static LanguageCheckService _getLanguageCheckService({ + required DelayType delayType, + required Duration delay, + required LanguageToolClient languageToolClient, + }) { + final languageToolService = LanguageToolService(languageToolClient); if (delay == Duration.zero) return languageToolService; switch (delayType) { case DelayType.debouncing: - return DebounceLangToolService(languageToolService, delay); + return DebounceLanguageCheckService(languageToolService, delay); case DelayType.throttling: - return ThrottlingLangToolService(languageToolService, delay); + return ThrottlingLanguageCheckService(languageToolService, delay); } } diff --git a/lib/src/domain/language_check_service.dart b/lib/src/domain/language_check_service.dart index 6bb796c..1ccd56f 100644 --- a/lib/src/domain/language_check_service.dart +++ b/lib/src/domain/language_check_service.dart @@ -3,6 +3,17 @@ import 'package:languagetool_textfield/src/utils/result.dart'; /// A base language check service. abstract class LanguageCheckService { + /// Gets the current language code used for language checking. + /// + /// Returns a string representing the language code (e.g., 'en-US', 'de-DE'). + String get language; + + /// Sets the language code to be used for language checking. + /// + /// [language] A string representing the language code (e.g., 'en-US', 'de-DE'). + /// This determines which language rules will be applied during text analysis. + set language(String language); + /// Creates a new instance of the [LanguageCheckService] class. const LanguageCheckService(); diff --git a/lib/src/implementations/debounce_lang_tool_service.dart b/lib/src/implementations/debounce_lang_tool_service.dart deleted file mode 100644 index e7fc013..0000000 --- a/lib/src/implementations/debounce_lang_tool_service.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:languagetool_textfield/src/domain/language_check_service.dart'; -import 'package:languagetool_textfield/src/domain/mistake.dart'; -import 'package:languagetool_textfield/src/utils/result.dart'; -import 'package:throttling/throttling.dart'; - -/// A language check service with debouncing. -class DebounceLangToolService extends LanguageCheckService { - /// A base language check service. - final LanguageCheckService baseService; - - /// A debouncing used to debounce the API calls. - final Debouncing>?>> debouncing; - - /// Creates a new instance of the [DebounceLangToolService] class. - DebounceLangToolService( - this.baseService, - Duration debouncingDuration, - ) : debouncing = Debouncing(duration: debouncingDuration); - - @override - Future>?> findMistakes(String text) async => - await debouncing.debounce(() => baseService.findMistakes(text)); - - // ignore: proper_super_calls - @override - Future dispose() async { - debouncing.close(); - await baseService.dispose(); - } -} diff --git a/lib/src/implementations/throttling_lang_tool_service.dart b/lib/src/implementations/throttling_lang_tool_service.dart deleted file mode 100644 index dfa6868..0000000 --- a/lib/src/implementations/throttling_lang_tool_service.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:languagetool_textfield/src/domain/language_check_service.dart'; -import 'package:languagetool_textfield/src/domain/mistake.dart'; -import 'package:languagetool_textfield/src/utils/result.dart'; -import 'package:throttling/throttling.dart'; - -/// A language check service with debouncing. -class ThrottlingLangToolService extends LanguageCheckService { - /// A base language check service that is used to interact - /// with the language check API. - final LanguageCheckService baseService; - - /// A throttling used to throttle the API calls. - final Throttling>?>> throttling; - - /// Creates a new instance of the [ThrottlingLangToolService] class. - ThrottlingLangToolService( - this.baseService, - Duration throttlingDuration, - ) : throttling = Throttling(duration: throttlingDuration); - - @override - Future>?> findMistakes(String text) async => - throttling.throttle(() => baseService.findMistakes(text)); - - // ignore: proper_super_calls - @override - Future dispose() async { - throttling.close(); - await baseService.dispose(); - } -} diff --git a/lib/src/implementations/lang_tool_service.dart b/lib/src/language_check_services/language_tool_service.dart similarity index 80% rename from lib/src/implementations/lang_tool_service.dart rename to lib/src/language_check_services/language_tool_service.dart index 9cd9e9c..344a8fd 100644 --- a/lib/src/implementations/lang_tool_service.dart +++ b/lib/src/language_check_services/language_tool_service.dart @@ -5,12 +5,20 @@ import 'package:languagetool_textfield/src/domain/writing_mistake.dart'; import 'package:languagetool_textfield/src/utils/result.dart'; /// An implementation of language check service with language tool service. -class LangToolService extends LanguageCheckService { +class LanguageToolService extends LanguageCheckService { /// An instance of this class that is used to interact with LanguageTool API. final LanguageToolClient languageTool; - /// Creates a new instance of the [LangToolService]. - LangToolService(this.languageTool); + @override + String get language => languageTool.language; + + @override + set language(String language) { + languageTool.language = language; + } + + /// Creates a new instance of the [LanguageToolService]. + LanguageToolService(this.languageTool); @override Future>> findMistakes(String text) async { diff --git a/lib/src/wrappers/debounce_language_check_service.dart b/lib/src/wrappers/debounce_language_check_service.dart new file mode 100644 index 0000000..3660f04 --- /dev/null +++ b/lib/src/wrappers/debounce_language_check_service.dart @@ -0,0 +1,40 @@ +import 'package:languagetool_textfield/src/domain/language_check_service.dart'; +import 'package:languagetool_textfield/src/domain/mistake.dart'; +import 'package:languagetool_textfield/src/utils/result.dart'; +import 'package:throttling/throttling.dart'; + +/// A language check service with debouncing. +class DebounceLanguageCheckService extends LanguageCheckService { + /// A base language check service. + final LanguageCheckService _languageCheckService; + + /// A debouncing used to debounce the API calls. + final Debouncing>?>> _debouncing; + + @override + String get language => _languageCheckService.language; + + @override + set language(String language) { + _languageCheckService.language = language; + } + + /// Creates a new instance of the [DebounceLanguageCheckService] class. + DebounceLanguageCheckService( + this._languageCheckService, + Duration debouncingDuration, + ) : _debouncing = Debouncing(duration: debouncingDuration); + + @override + Future>?> findMistakes(String text) async { + return await _debouncing + .debounce(() => _languageCheckService.findMistakes(text)); + } + + // ignore: proper_super_calls + @override + Future dispose() async { + _debouncing.close(); + await _languageCheckService.dispose(); + } +} diff --git a/lib/src/wrappers/throttling_language_check_service.dart b/lib/src/wrappers/throttling_language_check_service.dart new file mode 100644 index 0000000..2d637db --- /dev/null +++ b/lib/src/wrappers/throttling_language_check_service.dart @@ -0,0 +1,41 @@ +import 'package:languagetool_textfield/src/domain/language_check_service.dart'; +import 'package:languagetool_textfield/src/domain/mistake.dart'; +import 'package:languagetool_textfield/src/utils/result.dart'; +import 'package:throttling/throttling.dart'; + +/// A language check service with debouncing. +class ThrottlingLanguageCheckService extends LanguageCheckService { + /// A base language check service that is used to interact + /// with the language check API. + final LanguageCheckService _languageCheckService; + + /// A throttling used to throttle the API calls. + final Throttling>?>> _throttling; + + @override + String get language => _languageCheckService.language; + + @override + set language(String language) { + _languageCheckService.language = language; + } + + /// Creates a new instance of the [ThrottlingLanguageCheckService] class. + ThrottlingLanguageCheckService( + this._languageCheckService, + Duration throttlingDuration, + ) : _throttling = Throttling(duration: throttlingDuration); + + @override + Future>?> findMistakes(String text) async { + return await _throttling + .throttle(() => _languageCheckService.findMistakes(text)); + } + + // ignore: proper_super_calls + @override + Future dispose() async { + _throttling.close(); + await _languageCheckService.dispose(); + } +}