lib/search/word_search: pagination

This commit is contained in:
2025-05-16 17:06:00 +02:00
parent 2db99e76f0
commit 6c580e95e2

View File

@@ -13,6 +13,7 @@ import 'package:jadb/models/word_search/word_search_sense_language_source.dart';
import 'package:jadb/models/word_search/word_search_sources.dart';
import 'package:jadb/models/word_search/word_search_xref_entry.dart';
import 'package:jadb/util/sqlite_utils.dart';
import 'package:jadb/util/text_filtering.dart';
import 'package:sqflite_common/sqlite_api.dart';
// TODO: Support globs
@@ -23,21 +24,61 @@ import 'package:sqflite_common/sqlite_api.dart';
// TODO: Support mixing kana and romaji
Future<List<WordSearchResult>?> searchWordWithDbConnection(
DatabaseExecutor connection,
String word, {
bool isKana = true,
}) async {
if (word.isEmpty) {
return null;
enum SearchMode {
Auto,
English,
Kanji,
MixedKanji,
Kana,
MixedKana,
}
SearchMode _determineSearchMode(String word) {
final bool containsKanji = kanjiRegex.hasMatch(word);
final bool containsAscii = RegExp(r'[A-Za-z]').hasMatch(word);
if (containsKanji && containsAscii) {
return SearchMode.MixedKanji;
} else if (containsKanji) {
return SearchMode.Kanji;
} else if (containsAscii) {
return SearchMode.English;
} else if (word.contains(hiraganaRegex) || word.contains(katakanaRegex)) {
return SearchMode.Kana;
} else {
return SearchMode.MixedKana;
}
}
Future<List<int>> _fetchEntryIds(DatabaseExecutor connection, String word,
SearchMode searchMode, int pageSize, int? offset) async {
assert(
searchMode != SearchMode.Auto,
'Search mode should not be auto when fetching entry IDs',
);
assert(
word.isNotEmpty,
'Word should not be empty when fetching entry IDs',
);
late final List<int> entryIds;
if (isKana) {
if (searchMode == SearchMode.Kanji) {
entryIds = (await connection.query(
'JMdict_EntryByKanji',
where: 'kanji LIKE ?',
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
} else if (searchMode == SearchMode.Kana) {
entryIds = (await connection.query(
'JMdict_EntryByKana',
where: 'kana LIKE ?',
whereArgs: ['$word%'],
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
@@ -45,12 +86,42 @@ Future<List<WordSearchResult>?> searchWordWithDbConnection(
entryIds = (await connection.query(
'JMdict_EntryByEnglish',
where: 'english LIKE ?',
whereArgs: ['$word%'],
whereArgs: ['%$word%'],
limit: pageSize,
offset: offset,
))
.map((row) => row['entryId'] as int)
.toList();
}
return entryIds;
}
Future<List<WordSearchResult>?> searchWordWithDbConnection(
DatabaseExecutor connection,
String word, {
SearchMode searchMode = SearchMode.Auto,
int page = 0,
int pageSize = 10,
}) async {
if (word.isEmpty) {
return null;
}
if (searchMode == SearchMode.Auto) {
searchMode = _determineSearchMode(word);
}
final offset = page * pageSize;
final List<int> entryIds = await _fetchEntryIds(
connection,
word,
searchMode,
pageSize,
offset,
);
if (entryIds.isEmpty) {
return [];
}
@@ -270,7 +341,7 @@ Future<List<WordSearchResult>?> searchWordWithDbConnection(
kanjiElementInfos_query.then((value) => kanjiElementInfos = value),
]);
return _regroupWordSearchResults(
final result = _regroupWordSearchResults(
entryIds: entryIds,
readingElements: readingElements,
kanjiElements: kanjiElements,
@@ -293,6 +364,8 @@ Future<List<WordSearchResult>?> searchWordWithDbConnection(
readingElementRestrictions: readingElementRestrictions,
kanjiElementInfos: kanjiElementInfos,
);
return result;
}
List<WordSearchResult> _regroupWordSearchResults({