Jisho-Study-Tool/lib/models/history/search.dart

121 lines
3.3 KiB
Dart

import 'package:get_it/get_it.dart';
import 'package:sembast/sembast.dart';
import './kanji_query.dart';
import './word_query.dart';
export 'package:get_it/get_it.dart';
export 'package:sembast/sembast.dart';
class Search {
final WordQuery? wordQuery;
final KanjiQuery? kanjiQuery;
final List<DateTime> timestamps;
Search.fromKanjiQuery({
required KanjiQuery this.kanjiQuery,
List<DateTime>? timestamps,
}) : wordQuery = null,
timestamps = timestamps ?? [DateTime.now()];
Search.fromWordQuery({
required WordQuery this.wordQuery,
List<DateTime>? timestamps,
}) : kanjiQuery = null,
timestamps = timestamps ?? [DateTime.now()];
bool get isKanji => wordQuery == null;
DateTime get timestamp => timestamps.last;
Map<String, Object?> toJson() => {
'timestamps': [for (final ts in timestamps) ts.millisecondsSinceEpoch],
'lastTimestamp': timestamps.last.millisecondsSinceEpoch,
'wordQuery': wordQuery?.toJson(),
'kanjiQuery': kanjiQuery?.toJson(),
};
factory Search.fromJson(Map<String, dynamic> json) {
final List<DateTime> timestamps = [
for (final ts in json['timestamps'] as List<dynamic>)
DateTime.fromMillisecondsSinceEpoch(ts as int)
];
return json['wordQuery'] != null
? Search.fromWordQuery(
wordQuery: WordQuery.fromJson(json['wordQuery']),
timestamps: timestamps,
)
: Search.fromKanjiQuery(
kanjiQuery: KanjiQuery.fromJson(json['kanjiQuery']),
timestamps: timestamps,
);
}
static StoreRef<int, Object?> get store => intMapStoreFactory.store('search');
}
Future<void> addSearchToDatabase({
required String searchTerm,
required bool isKanji,
}) async {
final DateTime now = DateTime.now();
final db = GetIt.instance.get<Database>();
final Filter filter = Filter.equals(
isKanji ? 'kanjiQuery.kanji' : 'wordQuery.query',
searchTerm,
);
final RecordSnapshot<int, Object?>? previousSearch =
await Search.store.findFirst(db, finder: Finder(filter: filter));
if (previousSearch != null) {
final search =
Search.fromJson(previousSearch.value! as Map<String, Object?>);
search.timestamps.add(now);
Search.store.record(previousSearch.key).put(db, search.toJson());
return;
}
Search.store.add(
db,
isKanji
? Search.fromKanjiQuery(kanjiQuery: KanjiQuery(kanji: searchTerm))
.toJson()
: Search.fromWordQuery(wordQuery: WordQuery(query: searchTerm))
.toJson(),
);
}
List<Search> mergeSearches(List<Search> a, List<Search> b) {
final List<Search> result = [...a];
for (final Search search in b) {
late final Iterable<Search> matchingEntry;
if (search.isKanji) {
matchingEntry =
result.where((e) => e.kanjiQuery?.kanji == search.kanjiQuery!.kanji);
} else {
matchingEntry =
result.where((e) => e.wordQuery?.query == search.wordQuery!.query);
}
if (matchingEntry.isEmpty) {
result.add(search);
continue;
}
final timestamps = [...matchingEntry.first.timestamps];
matchingEntry.first.timestamps.clear();
matchingEntry.first.timestamps.addAll(
(timestamps
..addAll(search.timestamps)
..sort())
.toSet()
.toList(),
);
}
return result;
}