Skip to content

Commit

Permalink
chore!: move spell checker to example (#2145)
Browse files Browse the repository at this point in the history
  • Loading branch information
EchoEllet authored Aug 24, 2024
1 parent b37f31d commit d8e83b5
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 130 deletions.
62 changes: 5 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
79 changes: 79 additions & 0 deletions doc/spell_checker.md
Original file line number Diff line number Diff line change
@@ -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.
11 changes: 4 additions & 7 deletions example/lib/screens/quill/quill_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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});
Expand Down Expand Up @@ -43,6 +39,7 @@ class _QuillScreenState extends State<QuillScreen> {
final _editorFocusNode = FocusNode();
final _editorScrollController = ScrollController();
var _isReadOnly = false;
var _isSpellcheckerActive = false;

@override
void initState() {
Expand All @@ -63,7 +60,7 @@ class _QuillScreenState extends State<QuillScreen> {
_controller.readOnly = _isReadOnly;
if (!_isSpellcheckerActive) {
_isSpellcheckerActive = true;
FlutterQuillExtensions.useSpellCheckerService(
SpellChecker.useSpellCheckerService(
Localizations.localeOf(context).languageCode);
}
return Scaffold(
Expand Down
65 changes: 65 additions & 0 deletions example/lib/spell_checker/simple_spell_checker_service.dart
Original file line number Diff line number Diff line change
@@ -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<LanguageIdentifier> {
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<TextSpan>? 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);
}
}
27 changes: 27 additions & 0 deletions example/lib/spell_checker/spell_checker.dart
Original file line number Diff line number Diff line change
@@ -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),
);
}
}
1 change: 1 addition & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 12 additions & 19 deletions flutter_quill_extensions/lib/flutter_quill_extensions.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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]
Expand Down
Loading

0 comments on commit d8e83b5

Please sign in to comment.