-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Set the classes to use the
ApiRequestService
to remove the dependency on the `language_tool` package; Enabled changing the spellcheck language on the fly in the `ColoredTextEditingController`. Implementing #25.
- Loading branch information
Showing
10 changed files
with
185 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import 'package:language_tool/language_tool.dart'; | ||
import 'package:languagetool_textfield/core/dataclasses/language/supported_language.dart'; | ||
|
||
/// A language fetch service interface. | ||
abstract class LanguageFetchService { | ||
/// Creates a new [LanguageFetchService]. | ||
const LanguageFetchService(); | ||
|
||
/// Returns a Future List of [Language]s that are supported by the API. | ||
Future<List<Language>> fetchLanguages(); | ||
/// Returns a Future List of APIs [SupportedLanguage]s. | ||
Future<List<SupportedLanguage>> fetchLanguages(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 22 additions & 32 deletions
54
lib/implementations/lang_fetch_service/lang_fetch_service.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,39 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:http/http.dart' as http; | ||
import 'package:language_tool/language_tool.dart'; | ||
import 'package:languagetool_textfield/domain/api_request_service.dart'; | ||
import 'package:languagetool_textfield/domain/language_fetch_service.dart'; | ||
|
||
import '../../core/dataclasses/language/supported_language.dart'; | ||
|
||
/// A class that provide the functionality to fetch the supported language list | ||
/// from the langtoolplus API and handles the errors occurred. | ||
class LangFetchService implements LanguageFetchService { | ||
static const String _uri = 'api.languagetoolplus.com'; | ||
static const String _path = 'v2/languages'; | ||
static final Map<String, String> _headers = { | ||
HttpHeaders.acceptHeader: ContentType.json.value, | ||
}; | ||
|
||
final ApiRequestService<List<SupportedLanguage>> _fetchService; | ||
|
||
/// Creates a new [LangFetchService]. | ||
const LangFetchService(); | ||
const LangFetchService([ | ||
this._fetchService = | ||
const ApiRequestService(_languagesResponseConverter, []), | ||
]); | ||
|
||
// todo change to using ErrorWrapper when merged | ||
@override | ||
Future<List<Language>> fetchLanguages() async { | ||
final uri = Uri.https(_uri, _path); | ||
Object? error; | ||
|
||
http.Response? response; | ||
try { | ||
response = await http.get(uri, headers: _headers); | ||
} on http.ClientException catch (err) { | ||
error = err; | ||
} | ||
|
||
if (error == null && response?.statusCode != HttpStatus.ok) { | ||
error = http.ClientException( | ||
response?.reasonPhrase ?? 'Could not request', | ||
uri, | ||
); | ||
} | ||
|
||
if (response == null || response.bodyBytes.isEmpty) { | ||
return []; | ||
} | ||
|
||
final decoded = | ||
jsonDecode(utf8.decode(response.bodyBytes)) as List<dynamic>; | ||
|
||
return decoded.cast<Map<String, dynamic>>().map(Language.fromJson).toList(); | ||
Future<List<SupportedLanguage>> fetchLanguages() async { | ||
final uri = Uri.https(ApiRequestService.apiLink, _path); | ||
|
||
return _fetchService.get(uri, headers: _headers); | ||
} | ||
} | ||
|
||
List<SupportedLanguage> _languagesResponseConverter(dynamic json) { | ||
final list = json as List<dynamic>; | ||
|
||
return list | ||
.cast<Map<String, dynamic>>() | ||
.map(SupportedLanguage.fromJson) | ||
.toList(growable: false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 74 additions & 35 deletions
109
lib/implementations/lang_tool_service/lang_tool_service.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,89 @@ | ||
import 'package:language_tool/language_tool.dart'; | ||
import 'package:languagetool_textfield/core/enums/mistake_type.dart'; | ||
import 'dart:io'; | ||
|
||
import 'package:languagetool_textfield/core/dataclasses/mistake_match.dart'; | ||
import 'package:languagetool_textfield/domain/api_request_service.dart'; | ||
import 'package:languagetool_textfield/domain/language_check_service.dart'; | ||
import 'package:languagetool_textfield/domain/mistake.dart'; | ||
|
||
/// An implementation of language check service with language tool service. | ||
/// A basic implementation of a [LanguageCheckService]. | ||
class LangToolService extends LanguageCheckService { | ||
/// An instance of this class that is used to interact with LanguageTool API. | ||
final LanguageTool languageTool; | ||
static const String _path = 'v2/check'; | ||
static final Map<String, String> _headers = { | ||
HttpHeaders.acceptHeader: ContentType.json.value, | ||
HttpHeaders.contentTypeHeader: | ||
ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8') | ||
.value, | ||
}; | ||
|
||
final ApiRequestService<List<MistakeMatch>> _fetchService; | ||
|
||
/// Creates a new instance of the [LangToolService]. | ||
const LangToolService(this.languageTool); | ||
const LangToolService([ | ||
this._fetchService = | ||
const ApiRequestService(_mistakesResponseConverter, []), | ||
]); | ||
|
||
@override | ||
Future<List<Mistake>> findMistakes(String text) async { | ||
final writingMistakes = await languageTool.check(text); | ||
final mistakes = writingMistakes.map( | ||
(m) => Mistake( | ||
message: m.message, | ||
type: _stringToMistakeType( | ||
m.issueType, | ||
), | ||
offset: m.offset, | ||
length: m.length, | ||
replacements: m.replacements, | ||
), | ||
Future<List<Mistake>> findMistakes( | ||
String text, { | ||
String checkLanguage = 'auto', | ||
bool isPicky = false, | ||
}) async { | ||
final uri = Uri.https( | ||
ApiRequestService.apiLink, | ||
_path, | ||
); | ||
|
||
final body = _encodeFormData( | ||
text, | ||
language: checkLanguage, | ||
isPicky: isPicky, | ||
); | ||
|
||
final writingMistakes = await _fetchService.post( | ||
uri, | ||
headers: _headers, | ||
body: body, | ||
); | ||
|
||
final mistakes = writingMistakes.map(Mistake.fromMatch); | ||
|
||
return mistakes.toList(); | ||
} | ||
|
||
MistakeType _stringToMistakeType(String issueType) { | ||
switch (issueType.toLowerCase()) { | ||
case 'misspelling': | ||
return MistakeType.misspelling; | ||
case 'typographical': | ||
return MistakeType.typographical; | ||
case 'grammar': | ||
return MistakeType.grammar; | ||
case 'uncategorized': | ||
return MistakeType.uncategorized; | ||
case 'non-conformance': | ||
return MistakeType.nonConformance; | ||
case 'style': | ||
return MistakeType.style; | ||
default: | ||
return MistakeType.other; | ||
} | ||
String _encodeFormData( | ||
String text, { | ||
required String language, | ||
required bool isPicky, | ||
}) { | ||
final escapedText = Uri.encodeFull(text); | ||
final formData = '&language=$language' | ||
'&enabledOnly=false' | ||
'&level=${isPicky ? 'picky' : 'default'}' | ||
'&text=$escapedText'; | ||
|
||
return formData; | ||
} | ||
} | ||
|
||
/// expected json structure: | ||
/// ```json | ||
/// { | ||
/// ... | ||
/// matches: [ | ||
/// {MistakeMatch}, | ||
/// {MistakeMatch}, | ||
/// ... | ||
/// ] | ||
/// ... | ||
/// } | ||
/// ``` | ||
List<MistakeMatch> _mistakesResponseConverter(dynamic json) { | ||
final checkJson = json as Map<String, dynamic>; | ||
final matchesJson = checkJson['matches'] as List<dynamic>; | ||
|
||
return matchesJson | ||
.cast<Map<String, dynamic>>() | ||
.map(MistakeMatch.fromJson) | ||
.toList(growable: false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.