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 timestamps; Search.fromKanjiQuery({ required KanjiQuery this.kanjiQuery, List? timestamps, }) : wordQuery = null, timestamps = timestamps ?? [DateTime.now()]; Search.fromWordQuery({ required WordQuery this.wordQuery, List? timestamps, }) : kanjiQuery = null, timestamps = timestamps ?? [DateTime.now()]; bool get isKanji => wordQuery == null; DateTime get timestamp => timestamps.last; Map toJson() => { 'timestamps': [for (final ts in timestamps) ts.millisecondsSinceEpoch], 'word': wordQuery?.toJson(), 'kanji': kanjiQuery?.toJson(), }; factory Search.fromJson(Map json) { final List timestamps = [ for (final ts in json['timestamps'] as List) DateTime.fromMillisecondsSinceEpoch(ts as int) ]; return json['word'] != null ? Search.fromWordQuery( wordQuery: WordQuery.fromJson(json['word']), timestamps: timestamps, ) : Search.fromKanjiQuery( kanjiQuery: KanjiQuery.fromJson(json['kanji']), timestamps: timestamps, ); } static StoreRef get store => intMapStoreFactory.store('search'); } Future addSearchToDatabase({ required String searchTerm, required bool isKanji, }) async { final DateTime now = DateTime.now(); final db = GetIt.instance.get(); final Filter filter = Filter.equals( isKanji ? 'kanjiQuery.kanji' : 'wordQuery.query', searchTerm, ); final RecordSnapshot? previousSearch = await Search.store.findFirst(db, finder: Finder(filter: filter)); if (previousSearch != null) { final search = Search.fromJson(previousSearch.value! as Map); 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 mergeSearches(List a, List b) { final List result = [...a]; for (final Search search in b) { late final Iterable 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; }