From d8e83b56a4a1d8add70875535c201bf6a096357a Mon Sep 17 00:00:00 2001 From: Ellet Date: Sun, 25 Aug 2024 01:38:09 +0300 Subject: [PATCH] chore!: move spell checker to example (#2145) --- README.md | 62 ++------------ doc/spell_checker.md | 79 ++++++++++++++++++ example/lib/screens/quill/quill_screen.dart | 11 +-- .../simple_spell_checker_service.dart | 65 +++++++++++++++ example/lib/spell_checker/spell_checker.dart | 27 ++++++ example/pubspec.yaml | 1 + .../lib/flutter_quill_extensions.dart | 31 +++---- .../simple_spell_checker_service.dart | 83 +++++++++---------- flutter_quill_extensions/pubspec.yaml | 1 - 9 files changed, 230 insertions(+), 130 deletions(-) create mode 100644 doc/spell_checker.md create mode 100644 example/lib/spell_checker/simple_spell_checker_service.dart create mode 100644 example/lib/spell_checker/spell_checker.dart diff --git a/README.md b/README.md index 8740c0426..57f2e1b5d 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ You can join our [Slack Group] for discussion. - [๐Ÿ› ๏ธ Using the embed blocks from `flutter_quill_extensions`](#๏ธ-using-the-embed-blocks-from-flutter_quill_extensions) - [๐Ÿ”— Links](#-links-2) - [๐Ÿ”„ Conversion to HTML](#-conversion-to-html) - - [๐Ÿ“ Spelling checker](#-Spelling-checker) + - [๐Ÿ“ Spelling checker](#-spelling-checker) - [๐ŸŒ Translation](#-translation) - [๐Ÿงช Testing](#-testing) - [๐Ÿ‘ฅ Contributors](#-contributors) @@ -208,7 +208,7 @@ _controller.document = Document.fromJson(json); ## โš™๏ธ Configurations -The `QuillToolbar` and `QuillEditor` widgets let you customize a lot of things +The `QuillSimpleToolbar` and `QuillEditor` widgets are both customizable. [Sample Page] provides sample code for advanced usage and configuration. ### ๐Ÿ”— Links @@ -285,63 +285,11 @@ The following packages can be used: ## ๐Ÿ“ Spelling checker -A spell checker is a software tool or feature integrated into various text processing applications that automatically identifies and corrects spelling errors in a written document. It works by comparing the words in the text against a built-in dictionary. If a word isn't found in the dictionary or doesn't match any known word patterns, the spell checker highlights it as a potential error. +While spell-checking is not a feature that's implemented into the project, it can be used using external dependencies. -#### Benefits of a spell checker include: +It's implemented using the package `simple_spell_checker` in the [Example](./example/). -* Improved Accuracy: It helps writers avoid common spelling mistakes, ensuring that the text is free of errors. -* Time-Saving: Automatically detecting errors reduces the time needed for manual proofreading. -* Enhanced Professionalism: Correctly spelled words contribute to the overall professionalism of documents, which is crucial in academic, business, and formal writing. -* Multilingual Support: Many spell checkers support multiple languages, making it easier for users to write accurately in different languages. - -> [!IMPORTANT] -> The spell checker usually does not work as expected in most cases. **Many translations are not supported** such as: `Chinese`, `Japanese`, `Korean`, `Hebrew`, `Arabic`, `Russian`, etc. For now it is a purely **experimental** feature that may have **code that will be modified** in future versions. - -#### The translations supported so far are: - -* **German** - `de` (may contain errors or missing words) -* **English** - `en` (currently adding missing translations) -* **Spanish** - `es` (currently adding missing translations) -* **French** - `fr` (may contain errors or missing words) -* **Italian** - `it` (currently adding missing translations) -* **Norwegian** - `no` (may contain errors or missing words) -* **Portuguese** - `pt` (may contain errors or missing words) -* **Swedish** - `sv` (may contain errors or missing words) - -_**Note**: If you have knowledge about any of these available languages or the unsupported ones, you can make a pull request to add support or add words that are not currently in [simple_spell_checker](https://github.com/CatHood0/simple_spell_checker)_. - -In order to activate this functionality you can use the following code: - -```dart -// you can use the language of your preference or directly select the language of the operating system -final language = 'en'; // or Localizations.localeOf(context).languageCode -FlutterQuillExtensions.useSpellCheckerService(language); -``` - -When you no longer need to have the Spell checker activated you can simply use `dispose()` of the `SpellCheckerServiceProvider` class: - -```dart -// dispose all service and it cannot be used after this -SpellCheckerServiceProvider.dispose(); -``` - -If what we want is to **close the StreamControllers** without deleting the values that are already stored in it, we can set `onlyPartial` to `true`. - -```dart -// it can be still used by the editor -SpellCheckerServiceProvider.dispose(onlyPartial: true); -``` - -One use of this would be having the opportunity to **activate and deactivate** the service when we want, we can see this in the example that we have in this package, in which you can see that on each screen, we have a button that dynamically activates and deactivates the service. To do this is pretty simple: - -```dart - SpellCheckerServiceProvider.toggleState(); - // use isServiceActive to get the state of the service - SpellCheckerServiceProvider.isServiceActive(); - setState(() {}); -``` - -Open this [page](https://pub.dev/packages/simple_spell_checker) for more information. +Take a look at [Spelling Checker](./doc/spell_checker.md) page for more info. ## ๐ŸŒ Translation diff --git a/doc/spell_checker.md b/doc/spell_checker.md new file mode 100644 index 000000000..5fc3e56b5 --- /dev/null +++ b/doc/spell_checker.md @@ -0,0 +1,79 @@ +# ๐Ÿ“ Spelling checker + +A spell checker is a software tool or feature integrated into various text processing applications that automatically identifies and corrects spelling errors in a written document. It works by comparing the words in the text against a built-in dictionary. If a word isn't found in the dictionary or doesn't match any known word patterns, the spell checker highlights it as a potential error. + +While spell-checking is not a feature that's implemented into the project, it can be used using external dependencies. + +It's implemented using the package `simple_spell_checker` in the [Example](../example/). + +> [!NOTE] +> [`simple_spell_checker`](https://pub.dev/packages/simple_spell_checker) is a client-side dependency that works without an internet connection, so, it could weigh more than expected due to each of the dictionaries. As mentioned below, it supports a very wide variety of languages which can have a file of up to 300.000 words (this being just one language). + +### Benefits of a spell checker include: + +* Improved Accuracy: It helps writers avoid common spelling mistakes, ensuring that the text is free of errors. +* Time-Saving: Automatically detecting errors reduces the time needed for manual proofreading. +* Enhanced Professionalism: Correctly spelled words contribute to the overall professionalism of documents, which is crucial in academic, business, and formal writing. +* Multilingual Support: Many spell checkers support multiple languages, making it easier for users to write accurately in different languages. + +> [!IMPORTANT] +> The spell checker usually does not work as expected in most cases. For now it is a purely **experimental** feature that may have **code that will be modified** in future versions. + +### The translations supported so far are: + +* German - `de`, `de-ch` +* English - `en`, `en-gb` +* Spanish - `es` +* Catalan - `ca` +* Arabic - `ar` +* Danish - `da` +* French - `fr` +* Bulgarian - `bg` +* Dutch - `nl` +* Korean - `ko` +* Estonian - `et` +* Hebrew - `he` +* Slovak - `sk` +* Italian - `it` +* Norwegian - `no` +* Portuguese - `pt` +* Swedish - `sv` +* Russian - `ru` + +_**Note**: If you have knowledge about any of these available languages or the unsupported ones, you can make a pull request to add support or add words that are not currently in [simple_spell_checker](https://github.com/CatHood0/simple_spell_checker)_. + +In order to activate this functionality you can use the following code: + +```dart +// you can use the language of your preference or directly select the language of the operating system +final language = 'en'; // or Localizations.localeOf(context).languageCode +SpellChecker.useSpellCheckerService(language); +``` + +> [!NOTE] +> The class `SpellChecker` is not available as part of the project API. Instead, you will have to implement it manually. Take a look at the example [Spell Checker](../example/lib/spell_checker/spell_checker.dart) class. + +When you no longer need to have the Spell checker activated you can simply use `dispose()` of the `SpellCheckerServiceProvider` class: + +```dart +// dispose all service and it cannot be used after this +SpellCheckerServiceProvider.dispose(); +``` + +If what we want is to **close the StreamControllers** without deleting the values that are already stored in it, we can set `onlyPartial` to `true`. + +```dart +// it can be still used by the editor +SpellCheckerServiceProvider.dispose(onlyPartial: true); +``` + +One use of this would be having the opportunity to **activate and deactivate** the service when we want, we can see this in the example that we have in this package, in which you can see that on each screen, we have a button that dynamically activates and deactivates the service. To do this is pretty simple: + +```dart + SpellCheckerServiceProvider.toggleState(); + // use isServiceActive to get the state of the service + SpellCheckerServiceProvider.isServiceActive(); + setState(() {}); +``` + +Open this [page](https://pub.dev/packages/simple_spell_checker) for more information. \ No newline at end of file diff --git a/example/lib/screens/quill/quill_screen.dart b/example/lib/screens/quill/quill_screen.dart index db59e5396..11e0a1279 100644 --- a/example/lib/screens/quill/quill_screen.dart +++ b/example/lib/screens/quill/quill_screen.dart @@ -3,19 +3,15 @@ import 'dart:convert' show jsonEncode; import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart' - show - FlutterQuillEmbeds, - FlutterQuillExtensions, - QuillSharedExtensionsConfigurations; + show FlutterQuillEmbeds, QuillSharedExtensionsConfigurations; import 'package:share_plus/share_plus.dart' show Share; import '../../extensions/scaffold_messenger.dart'; +import '../../spell_checker/spell_checker.dart'; import '../shared/widgets/home_screen_button.dart'; import 'my_quill_editor.dart'; import 'my_quill_toolbar.dart'; -var _isSpellcheckerActive = false; - @immutable class QuillScreenArgs { const QuillScreenArgs({required this.document}); @@ -43,6 +39,7 @@ class _QuillScreenState extends State { final _editorFocusNode = FocusNode(); final _editorScrollController = ScrollController(); var _isReadOnly = false; + var _isSpellcheckerActive = false; @override void initState() { @@ -63,7 +60,7 @@ class _QuillScreenState extends State { _controller.readOnly = _isReadOnly; if (!_isSpellcheckerActive) { _isSpellcheckerActive = true; - FlutterQuillExtensions.useSpellCheckerService( + SpellChecker.useSpellCheckerService( Localizations.localeOf(context).languageCode); } return Scaffold( diff --git a/example/lib/spell_checker/simple_spell_checker_service.dart b/example/lib/spell_checker/simple_spell_checker_service.dart new file mode 100644 index 000000000..c804a8d19 --- /dev/null +++ b/example/lib/spell_checker/simple_spell_checker_service.dart @@ -0,0 +1,65 @@ +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 toggleChecker() => checker.toggleChecker(); + + @override + bool isServiceActive() => checker.isCheckerActive(); + + @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/example/lib/spell_checker/spell_checker.dart b/example/lib/spell_checker/spell_checker.dart new file mode 100644 index 000000000..08238ce17 --- /dev/null +++ b/example/lib/spell_checker/spell_checker.dart @@ -0,0 +1,27 @@ +import 'package:flutter_quill/flutter_quill.dart'; + +import 'simple_spell_checker_service.dart'; + +class SpellChecker { + SpellChecker._(); + + /// 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), + ); + } +} diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 29b1b65ca..6078401ce 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: equatable: ^2.0.5 cross_file: ^0.3.4 cached_network_image: ^3.3.1 + simple_spell_checker: ^1.2.1 # Bloc libraries bloc: ^8.1.4 diff --git a/flutter_quill_extensions/lib/flutter_quill_extensions.dart b/flutter_quill_extensions/lib/flutter_quill_extensions.dart index b5a703dd4..e437b98cb 100644 --- a/flutter_quill_extensions/lib/flutter_quill_extensions.dart +++ b/flutter_quill_extensions/lib/flutter_quill_extensions.dart @@ -1,12 +1,9 @@ library flutter_quill_extensions; -// ignore: implementation_imports -import 'package:flutter_quill/src/editor/spellchecker/spellchecker_service_provider.dart'; // ignore: implementation_imports 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'; @@ -16,6 +13,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'; +// TODO: Remove Simple Spell Checker Service 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'; @@ -43,23 +41,18 @@ 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); - ///``` + @Deprecated( + ''' + Spell checker feature has been removed from the package to make it optional and + reduce bundle size. See issue https://github.com/singerdmx/flutter-quill/issues/2142 + for more details. + + Calling this function will no longer activate the feature. + ''', + ) static void useSpellCheckerService(String language) { - SpellCheckerServiceProvider.setNewCheckerService( - SimpleSpellCheckerService(language: language)); + // This feature has been removed from the package. + // See https://github.com/singerdmx/flutter-quill/issues/2142 } /// Override default implementation of [ClipboardServiceProvider.instance] 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 index c804a8d19..c6fbb7807 100644 --- 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 @@ -1,65 +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; +@Deprecated( + ''' + Spell checker feature has been removed from the package to make it optional and + reduce bundle size. See issue https://github.com/singerdmx/flutter-quill/issues/2142 + for more details. + + Calling this function will not activate the feature. + + This class will be removed in future releases. + ''', +) +class SimpleSpellCheckerService extends SpellCheckerService { + SimpleSpellCheckerService({required super.language}); + + void _featureNoLongerAvailable() => throw UnimplementedError( + ''' + The spell checker feature has been removed from the package and is now optional. + See https://github.com/singerdmx/flutter-quill/issues/2142 for more details. + ''', + ); @override - List? checkSpelling( - String text, { - LongPressGestureRecognizer Function(String word)? - customLongPressRecognizerOnWrongSpan, - }) { - return checker.check( - text, - customLongPressRecognizerOnWrongSpan: - customLongPressRecognizerOnWrongSpan, - ); - } + void addCustomLanguage({required Object? languageIdentifier}) => + _featureNoLongerAvailable(); @override - void toggleChecker() => checker.toggleChecker(); + List? checkSpelling(String text, + {LongPressGestureRecognizer Function(String p1)? + customLongPressRecognizerOnWrongSpan}) { + _featureNoLongerAvailable(); + throw UnimplementedError(); + } @override - bool isServiceActive() => checker.isCheckerActive(); + void dispose({bool onlyPartial = false}) => _featureNoLongerAvailable(); @override - void dispose({bool onlyPartial = false}) { - if (onlyPartial) { - checker.disposeControllers(); - return; - } - checker.dispose(); + bool isServiceActive() { + _featureNoLongerAvailable(); + throw UnimplementedError(); } @override - void addCustomLanguage({required languageIdentifier}) { - checker - ..registerLanguage(languageIdentifier.language) - ..addCustomLanguage(languageIdentifier); - } + void setNewLanguageState({required String language}) => + _featureNoLongerAvailable(); @override - void setNewLanguageState({required String language}) { - checker.setNewLanguageToState(language); - } + void toggleChecker() => _featureNoLongerAvailable(); @override - void updateCustomLanguageIfExist({required languageIdentifier}) { - checker.updateCustomLanguageIfExist(languageIdentifier); - } + void updateCustomLanguageIfExist({required Object? languageIdentifier}) => + _featureNoLongerAvailable(); } diff --git a/flutter_quill_extensions/pubspec.yaml b/flutter_quill_extensions/pubspec.yaml index 9733b3e5b..c78f01677 100644 --- a/flutter_quill_extensions/pubspec.yaml +++ b/flutter_quill_extensions/pubspec.yaml @@ -41,7 +41,6 @@ dependencies: # Plugins video_player: ^2.8.1 - simple_spell_checker: ^1.2.1 youtube_player_flutter: ^9.0.1 url_launcher: ^6.2.1 super_clipboard: ^0.8.15