diff --git a/flutter_quill_extensions/lib/flutter_quill_extensions.dart b/flutter_quill_extensions/lib/flutter_quill_extensions.dart index 3817f97d..dba74bd3 100644 --- a/flutter_quill_extensions/lib/flutter_quill_extensions.dart +++ b/flutter_quill_extensions/lib/flutter_quill_extensions.dart @@ -1,9 +1,11 @@ library flutter_quill_extensions; // ignore: implementation_imports +import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/src/editor_toolbar_controller_shared/clipboard/clipboard_service_provider.dart'; import 'package:meta/meta.dart' show immutable; +import 'src/editor/spell_checker/simple_spell_checker_service.dart'; import 'src/editor_toolbar_controller_shared/clipboard/super_clipboard_service.dart'; export 'src/common/extensions/controller_ext.dart'; @@ -13,6 +15,7 @@ export 'src/editor/image/image_embed_types.dart'; export 'src/editor/image/image_web_embed.dart'; export 'src/editor/image/models/image_configurations.dart'; export 'src/editor/image/models/image_web_configurations.dart'; +export 'src/editor/spell_checker/simple_spell_checker_service.dart'; export 'src/editor/table/table_cell_embed.dart'; export 'src/editor/table/table_embed.dart'; export 'src/editor/table/table_models.dart'; @@ -39,6 +42,24 @@ export 'src/toolbar/video/video_button.dart'; class FlutterQuillExtensions { const FlutterQuillExtensions._(); + /// override the default implementation of [SpellCheckerServiceProvider] + /// to allow a `flutter quill` support a better check spelling + /// + /// # !WARNING + /// To avoid memory leaks, ensure to use [dispose()] method to + /// close stream controllers that used by this custom implementation + /// when them no longer needed + /// + /// Example: + /// + ///```dart + ///// set partial true if you only need to close the controllers + ///SpellCheckerServiceProvider.dispose(onlyPartial: false); + ///``` + static void useSpellCheckerService(String language) { + SpellCheckerServiceProvider.setNewCheckerService(SimpleSpellCheckerService(language: language)); + } + /// Override default implementation of [ClipboardServiceProvider.instance] /// to allow `flutter_quill` package to use `super_clipboard` plugin /// to support rich text features, gif and images. diff --git a/flutter_quill_extensions/lib/src/editor/spell_checker/simple_spell_checker_service.dart b/flutter_quill_extensions/lib/src/editor/spell_checker/simple_spell_checker_service.dart new file mode 100644 index 00000000..70dccfc0 --- /dev/null +++ b/flutter_quill_extensions/lib/src/editor/spell_checker/simple_spell_checker_service.dart @@ -0,0 +1,56 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; +import 'package:simple_spell_checker/simple_spell_checker.dart'; + +/// SimpleSpellChecker is a simple spell checker for get +/// all words divide on different objects if them are wrong or not +class SimpleSpellCheckerService extends SpellCheckerService { + SimpleSpellCheckerService({required super.language}) + : checker = SimpleSpellChecker( + language: language, + safeDictionaryLoad: true, + ); + + /// [SimpleSpellChecker] comes from the package [simple_spell_checker] + /// that give us all necessary methods for get our spans with highlighting + /// where needed + final SimpleSpellChecker checker; + + @override + List? checkSpelling( + String text, { + LongPressGestureRecognizer Function(String word)? customLongPressRecognizerOnWrongSpan, + }) { + return checker.check( + text, + customLongPressRecognizerOnWrongSpan: customLongPressRecognizerOnWrongSpan, + ); + } + + @override + void dispose({bool onlyPartial = false}) { + if (onlyPartial) { + checker.disposeControllers(); + return; + } + checker.dispose(); + } + + @override + void addCustomLanguage({required languageIdentifier}) { + checker + ..registerLanguage(languageIdentifier.language) + ..addCustomLanguage(languageIdentifier); + } + + @override + void setNewLanguageState({required String language}) { + checker.setNewLanguageToState(language); + } + + @override + void updateCustomLanguageIfExist({required languageIdentifier}) { + checker.updateCustomLanguageIfExist(languageIdentifier); + } +} diff --git a/flutter_quill_extensions/pubspec.yaml b/flutter_quill_extensions/pubspec.yaml index 186ffcac..4ea6468f 100644 --- a/flutter_quill_extensions/pubspec.yaml +++ b/flutter_quill_extensions/pubspec.yaml @@ -35,12 +35,13 @@ dependencies: universal_html: ^2.2.4 cross_file: ^0.3.3+6 - flutter_quill: ^10.0.0 + flutter_quill: ^10.3.0 photo_view: ^0.15.0 youtube_explode_dart: ^2.2.1 # Plugins video_player: ^2.8.1 + simple_spell_checker: ^1.0.9 youtube_player_flutter: ^9.0.1 url_launcher: ^6.2.1 super_clipboard: ^0.8.15 diff --git a/lib/flutter_quill.dart b/lib/flutter_quill.dart index 349ca110..ded85364 100644 --- a/lib/flutter_quill.dart +++ b/lib/flutter_quill.dart @@ -24,7 +24,6 @@ export 'src/editor/raw_editor/config/raw_editor_configurations.dart'; export 'src/editor/raw_editor/quill_single_child_scroll_view.dart'; export 'src/editor/raw_editor/raw_editor.dart'; export 'src/editor/raw_editor/raw_editor_state.dart'; -export 'src/editor/spellchecker/simple_spellchecker_impl.dart'; export 'src/editor/spellchecker/spellchecker_service.dart'; export 'src/editor/spellchecker/spellchecker_service_provider.dart'; export 'src/editor/style_widgets/style_widgets.dart'; diff --git a/lib/src/editor/spellchecker/default_spellchecker_service.dart b/lib/src/editor/spellchecker/default_spellchecker_service.dart index 95e457d8..7dcb3a25 100644 --- a/lib/src/editor/spellchecker/default_spellchecker_service.dart +++ b/lib/src/editor/spellchecker/default_spellchecker_service.dart @@ -1,20 +1,30 @@ import 'package:flutter/gestures.dart' show LongPressGestureRecognizer; import 'package:flutter/material.dart' show TextSpan; -import 'spellchecker_service.dart' show SpellcheckerService; +import 'spellchecker_service.dart' show SpellCheckerService; /// A default implementation of the [SpellcheckerService] /// that always will return null since Spell checking /// is not a standard feature -class DefaultSpellcheckerService extends SpellcheckerService { - DefaultSpellcheckerService() : super(language: 'en'); +class DefaultSpellCheckerService extends SpellCheckerService { + DefaultSpellCheckerService() : super(language: 'en'); @override void dispose({bool onlyPartial = false}) {} @override - List? fetchSpellchecker(String text, - {LongPressGestureRecognizer Function(String p1)? - customLongPressRecognizerOnWrongSpan}) { + List? checkSpelling( + String text, { + LongPressGestureRecognizer Function(String p1)? customLongPressRecognizerOnWrongSpan, + }) { return null; } + + @override + void addCustomLanguage({languageIdentifier}) {} + + @override + void setNewLanguageState({required String language}) {} + + @override + void updateCustomLanguageIfExist({languageIdentifier}) {} } diff --git a/lib/src/editor/spellchecker/simple_spellchecker_impl.dart b/lib/src/editor/spellchecker/simple_spellchecker_impl.dart deleted file mode 100644 index 117ec2be..00000000 --- a/lib/src/editor/spellchecker/simple_spellchecker_impl.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:simple_spell_checker/simple_spell_checker.dart'; - -import 'spellchecker_service.dart'; - -/// SimpleSpellCheckerImpl is a simple spell checker for get -/// all words divide on different objects if them are wrong or not -class SimpleSpellCheckerImpl extends SpellcheckerService { - SimpleSpellCheckerImpl({required super.language}) - : checker = SimpleSpellChecker( - language: language, - safeDictionaryLoad: true, - ); - - /// [SimpleSpellChecker] comes from the package [simple_spell_checker] - /// that give us all necessary methods for get our spans with highlighting - /// where needed - final SimpleSpellChecker checker; - - @override - List? fetchSpellchecker( - String text, { - LongPressGestureRecognizer Function(String word)? - customLongPressRecognizerOnWrongSpan, - }) { - return checker.check( - text, - customLongPressRecognizerOnWrongSpan: - customLongPressRecognizerOnWrongSpan, - ); - } - - @override - void dispose({bool onlyPartial = false}) { - if (onlyPartial) { - checker.disposeControllers(); - return; - } - checker.dispose(closeDirectionary: true); - } -} diff --git a/lib/src/editor/spellchecker/spellchecker_service.dart b/lib/src/editor/spellchecker/spellchecker_service.dart index 495a28dd..b8331420 100644 --- a/lib/src/editor/spellchecker/spellchecker_service.dart +++ b/lib/src/editor/spellchecker/spellchecker_service.dart @@ -2,8 +2,8 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; /// A representation a custom SpellCheckService. -abstract class SpellcheckerService { - SpellcheckerService({required this.language}); +abstract class SpellCheckerService { + SpellCheckerService({required this.language}); final String language; @@ -15,10 +15,19 @@ abstract class SpellcheckerService { /// if [onlyPartial] is false dispose all resources void dispose({bool onlyPartial = false}); + /// set a new language state used for SpellcheckerService + void setNewLanguageState({required String language}); + + /// set a new language state used for SpellcheckerService + void updateCustomLanguageIfExist({required T languageIdentifier}); + + /// set a new custom language for SpellcheckerService + void addCustomLanguage({required T languageIdentifier}); + /// Facilitates a spell check request. /// /// Returns a [List] with all misspelled words divide from the right words. - List? fetchSpellchecker(String text, + List? checkSpelling(String text, {LongPressGestureRecognizer Function(String)? customLongPressRecognizerOnWrongSpan}); } diff --git a/lib/src/editor/spellchecker/spellchecker_service_provider.dart b/lib/src/editor/spellchecker/spellchecker_service_provider.dart index 2e4eb2f0..47bd4771 100644 --- a/lib/src/editor/spellchecker/spellchecker_service_provider.dart +++ b/lib/src/editor/spellchecker/spellchecker_service_provider.dart @@ -3,17 +3,26 @@ import 'default_spellchecker_service.dart'; import 'spellchecker_service.dart'; @immutable -class SpellcheckerServiceProvider { - const SpellcheckerServiceProvider._(); - static SpellcheckerService _instance = DefaultSpellcheckerService(); +class SpellCheckerServiceProvider { + const SpellCheckerServiceProvider._(); + static SpellCheckerService _instance = DefaultSpellCheckerService(); - static SpellcheckerService get instance => _instance; + static SpellCheckerService get instance => _instance; - static void setInstance(SpellcheckerService service) { + static void setNewCheckerService(SpellCheckerService service) { _instance = service; } - static void setInstanceToDefault() { - _instance = DefaultSpellcheckerService(); + static void dispose({bool onlyPartial = false}){ + _instance.dispose(onlyPartial: onlyPartial); + } + + static void setNewLanguageState({required String language}){ + assert(language.isNotEmpty); + _instance.setNewLanguageState(language: language); + } + + static void turnOffService() { + _instance = DefaultSpellCheckerService(); } }