searchForSentences method
- {required BuildContext context,
- required AppModel appModel,
- required String searchTerm}
Search the Massif API for example sentences and return a list of results.
Implementation
Future<List<MassifResult>> searchForSentences({
required BuildContext context,
required AppModel appModel,
required String searchTerm,
}) async {
if (searchTerm.trim().isEmpty) {
return [];
}
if (_massifCache[searchTerm] != null) {
return _massifCache[searchTerm]!;
}
List<MassifResult> results = [];
late http.Response response;
try {
/// Query the Massif API for results.
response = await _client.get(Uri.parse(
'https://massif.la/ja/search?&fmt=json&q=${Uri.encodeComponent(searchTerm)}'));
Map<String, dynamic> json = jsonDecode(utf8.decode(response.bodyBytes));
/// For each response, create a [MassifResult] that can be used to display
/// the widget as well as hold the sentence and source data.
List<Map<String, dynamic>> queryResponses =
List<Map<String, dynamic>>.from(json['results']);
for (Map<String, dynamic> queryResponse in queryResponses) {
Map<String, String> sampleSource =
Map<String, String>.from(queryResponse['sample_source']);
String source = sampleSource['title']!;
String text = queryResponse['text'];
List<InlineSpan> spans = [];
String highlightedText = queryResponse['highlighted_html'];
List<String> splitWithDelims =
highlightedText.splitWithDelim(RegExp(r'<em>(.*?)<\/em>'));
final buffer = StringBuffer();
TextRange range = TextRange.empty;
bool firstFound = false;
bool consecutiveFlag = false;
int? start;
int? end;
for (String splitWithDelim in splitWithDelims) {
if (splitWithDelim.startsWith('<em>') &&
splitWithDelim.endsWith('</em>')) {
String text =
splitWithDelim.replaceAll('<em>', '').replaceAll('</em>', '');
if (!firstFound) {
consecutiveFlag = true;
firstFound = true;
start = buffer.length;
end = buffer.length + text.length;
}
if (firstFound && consecutiveFlag) {
end = buffer.length + text.length;
}
buffer.write(text);
spans.add(
TextSpan(
text: text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
fontSize: Theme.of(context).textTheme.titleMedium?.fontSize,
),
),
);
} else {
if (splitWithDelim.trim().isNotEmpty) {
consecutiveFlag = false;
}
buffer.write(splitWithDelim);
spans.add(
TextSpan(
text: splitWithDelim,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: Theme.of(context).textTheme.titleMedium?.fontSize,
),
),
);
}
}
if (start != null && end != null) {
range = TextRange(
start: start,
end: end,
);
}
MassifResult result = MassifResult(
text: text,
range: range,
source: source,
spans: spans,
);
results.add(result);
}
/// Save this into cache.
_massifCache[searchTerm] = results;
return results;
} catch (e) {
/// Used to log if this third-party service is down or changes domains.
appModel.showFailedToCommunicateMessage();
throw Exception(
'Failed to communicate with Massif: ${response.reasonPhrase}',
);
}
}