Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions lib/src/dao/flashcard_sets_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ class FlashcardSetsDao extends DatabaseAccessor<AppDatabase>
}

Future<void> deleteFlashcardSet(FlashcardSet flashcardSet) async {
await deleteFlashcardSetReports(flashcardSet);
await db.transaction(() async {
await deleteFlashcardSetReports(flashcardSet);

await (db.delete(db.flashcardSets)
..where((set) => set.id.equals(flashcardSet.id)))
.go();
await (db.delete(db.flashcardSets)
..where((set) => set.id.equals(flashcardSet.id)))
.go();
});
}

Future<List<FlashcardSet>> getAll() async {
Expand Down Expand Up @@ -152,7 +154,9 @@ class FlashcardSetsDao extends DatabaseAccessor<AppDatabase>
}

Future<void> deleteAll() async {
await db.delete(db.flashcardSets).go();
await db.delete(db.flashcardSetReports).go();
await db.transaction(() async {
await db.delete(db.flashcardSets).go();
await db.delete(db.flashcardSetReports).go();
});
}
}
48 changes: 31 additions & 17 deletions lib/src/dao/grammars_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,37 @@ class GrammarsDao extends DatabaseAccessor<AppDatabase>
final baseQuery = db.select(db.grammars)
..where((grammars) => grammars.id.isIn(idList));

if (frontType == null) return baseQuery.get();

final query = baseQuery.join([
leftOuterJoin(
db.spacedRepetitionDatas,
Expression.and([
db.spacedRepetitionDatas.itemId.equalsExp(db.grammars.id),
db.spacedRepetitionDatas.itemType
.equals(DictionaryItemType.grammar.index),
db.spacedRepetitionDatas.frontType.equals(frontType.index),
]))
]).map(
(row) => row.readTable(db.grammars)
..spacedRepetitionData = row.readTableOrNull(db.spacedRepetitionDatas),
);

return query.get();
final List<Grammar> grammars;
if (frontType == null) {
grammars = await baseQuery.get();
} else {
final query = baseQuery.join([
leftOuterJoin(
db.spacedRepetitionDatas,
Expression.and([
db.spacedRepetitionDatas.itemId.equalsExp(db.grammars.id),
db.spacedRepetitionDatas.itemType
.equals(DictionaryItemType.grammar.index),
db.spacedRepetitionDatas.frontType.equals(frontType.index),
]))
]).map(
(row) => row.readTable(db.grammars)
..spacedRepetitionData =
row.readTableOrNull(db.spacedRepetitionDatas),
);

grammars = await query.get();
}

// Put the results in the same order as the input
final grammarMap = {for (var grammar in grammars) grammar.id: grammar};
List<Grammar> grammarList = [];
for (final id in idList) {
final grammar = grammarMap[id];
if (grammar != null) grammarList.add(grammar);
}

return grammarList;
}

Future<List<Grammar>> validateAll(List<int> idList) async {
Expand Down
163 changes: 53 additions & 110 deletions lib/src/dao/kanjis_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:sagase_dictionary/src/datamodels/kanji/kanji_notes.dart';
import 'package:sagase_dictionary/src/datamodels/kanji_component_connections.dart';
import 'package:sagase_dictionary/src/datamodels/kanjis.dart';
import 'package:sagase_dictionary/src/datamodels/spaced_repetition_datas.dart';
import 'package:sagase_dictionary/src/utils/dao_utils.dart';
import 'package:sagase_dictionary/src/utils/enums.dart';
import 'package:sagase_dictionary/src/utils/string_utils.dart';

Expand Down Expand Up @@ -51,15 +52,23 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {

if (kanji == null) return null;

List<KanjiReading> onReadings = [];
List<KanjiReading> kunReadings = [];
List<KanjiReading> nanori = [];

final readings = await (db.select(db.kanjiReadings)
..where((reading) => reading.kanjiId.equals(kanji!.id))
..orderBy([(reading) => OrderingTerm.asc(reading.id)]))
.get();

_setReadings(kanji, readings);

final note = await getNote(kanji.id);

return kanji..note = note?.note;
}

void _setReadings(Kanji kanji, List<KanjiReading> readings) {
List<KanjiReading> onReadings = [];
List<KanjiReading> kunReadings = [];
List<KanjiReading> nanori = [];

for (final reading in readings) {
switch (reading.type) {
case KanjiReadingType.on:
Expand All @@ -74,13 +83,10 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
}
}

final note = await getNote(kanji.id);

return kanji
kanji
..onReadings = onReadings.isEmpty ? null : onReadings
..kunReadings = kunReadings.isEmpty ? null : kunReadings
..nanori = nanori.isEmpty ? null : nanori
..note = note?.note;
..nanori = nanori.isEmpty ? null : nanori;
}

Future<Kanji?> getKanji(String kanji, {FrontType? frontType}) async {
Expand All @@ -92,7 +98,7 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {

final baseQuery = db.select(db.kanjis)..where((row) => row.id.isIn(idList));

late Map<int, Kanji> kanjiMap = {};
final Map<int, Kanji> kanjiMap;
if (frontType == null) {
// Get kanji only
kanjiMap = {for (var kanji in (await baseQuery.get())) kanji.id: kanji};
Expand Down Expand Up @@ -121,47 +127,16 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
..orderBy([(reading) => OrderingTerm.asc(reading.id)]))
.get();

if (readings.isNotEmpty) {
int currentKanjiId = readings[0].kanjiId;
List<KanjiReading> onReadings = [];
List<KanjiReading> kunReadings = [];
List<KanjiReading> nanori = [];
for (final reading in readings) {
// If id does not match got to new kanji, add current readings and clear lists
if (reading.kanjiId != currentKanjiId) {
kanjiMap[currentKanjiId]!
..onReadings = onReadings.isEmpty ? null : onReadings
..kunReadings = kunReadings.isEmpty ? null : kunReadings
..nanori = nanori.isEmpty ? null : nanori;
currentKanjiId = reading.kanjiId;
onReadings = [];
kunReadings = [];
nanori = [];
}
switch (reading.type) {
case KanjiReadingType.on:
onReadings.add(reading);
break;
case KanjiReadingType.kun:
kunReadings.add(reading);
break;
case KanjiReadingType.nanori:
nanori.add(reading);
break;
}
}
// Add remaining readings
kanjiMap[currentKanjiId]!
..onReadings = onReadings.isEmpty ? null : onReadings
..kunReadings = kunReadings.isEmpty ? null : kunReadings
..nanori = nanori.isEmpty ? null : nanori;
}
groupRowsById(readings, (reading) => reading.kanjiId, (id, rows) {
final kanji = kanjiMap[id];
if (kanji != null) _setReadings(kanji, rows);
});

final notes = await (db.select(db.kanjiNotes)
..where((note) => note.id.isIn(idList)))
.get();
for (final note in notes) {
kanjiMap[note.id]!.note = note.note;
kanjiMap[note.id]?.note = note.note;
}

// Put the results in the same order as the input
Expand All @@ -184,41 +159,9 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
..orderBy([(reading) => OrderingTerm.asc(reading.id)]))
.get();

if (readings.isNotEmpty) {
int currentKanjiId = readings[0].kanjiId;
List<KanjiReading> onReadings = [];
List<KanjiReading> kunReadings = [];
List<KanjiReading> nanori = [];
for (final reading in readings) {
// If id does not match got to new kanji, add current readings and clear lists
if (reading.kanjiId != currentKanjiId) {
kanjiMap[currentKanjiId]!
..onReadings = onReadings.isEmpty ? null : onReadings
..kunReadings = kunReadings.isEmpty ? null : kunReadings
..nanori = nanori.isEmpty ? null : nanori;
currentKanjiId = reading.kanjiId;
onReadings = [];
kunReadings = [];
nanori = [];
}
switch (reading.type) {
case KanjiReadingType.on:
onReadings.add(reading);
break;
case KanjiReadingType.kun:
kunReadings.add(reading);
break;
case KanjiReadingType.nanori:
nanori.add(reading);
break;
}
}
// Add remaining readings
kanjiMap[currentKanjiId]!
..onReadings = onReadings.isEmpty ? null : onReadings
..kunReadings = kunReadings.isEmpty ? null : kunReadings
..nanori = nanori.isEmpty ? null : nanori;
}
groupRowsById(readings, (reading) => reading.kanjiId, (id, rows) {
_setReadings(kanjiMap[id]!, rows);
});

final notes = await (db.select(db.kanjiNotes)
..where((note) => note.id.isIn(kanjiMap.keys)))
Expand Down Expand Up @@ -270,32 +213,6 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
final selectedCodePoints =
components.map((c) => c.kanjiCodePoint()).toSet();

final kanji = await (db.select(db.kanjis).join([
innerJoin(
db.kanjiComponentConnections,
db.kanjiComponentConnections.kanjiCodePoint.equalsExp(db.kanjis.id),
useColumns: false,
),
])
..where(db.kanjiComponentConnections.componentCodePoint
.isIn(selectedCodePoints))
..groupBy(
[db.kanjis.id],
having: db.kanjiComponentConnections.componentCodePoint
.count(distinct: true)
.equals(selectedCodePoints.length),
)
..orderBy([
OrderingTerm.asc(db.kanjis.strokeCount),
OrderingTerm.asc(db.kanjis.frequency, nulls: NullsOrder.last),
]))
.map((row) => row.readTable(db.kanjis).kanji)
.get();

if (kanji.isEmpty) {
return (kanji: const <String>[], validComponents: const <String>[]);
}

final matchingIds = db.selectOnly(db.kanjiComponentConnections)
..addColumns([db.kanjiComponentConnections.kanjiCodePoint])
..where(db.kanjiComponentConnections.componentCodePoint
Expand All @@ -307,6 +224,20 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
.equals(selectedCodePoints.length),
);

final kanji = await (db.select(db.kanjis)
..where((kanji) => kanji.id.isInQuery(matchingIds))
..orderBy([
(kanji) => OrderingTerm.asc(kanji.strokeCount),
(kanji) =>
OrderingTerm.asc(kanji.frequency, nulls: NullsOrder.last),
]))
.map((kanji) => kanji.kanji)
.get();

if (kanji.isEmpty) {
return (kanji: const <String>[], validComponents: const <String>[]);
}

final validComponents = await (db.selectOnly(db.kanjiComponentConnections,
distinct: true)
..addColumns([db.kanjiComponentConnections.componentCodePoint])
Expand All @@ -323,11 +254,16 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
}

Future<List<Kanji>> search(String text) async {
final cleanedText = RegExp.escape(text).toLowerCase().removeDiacritics();
final cleanedText = text
.replaceAll('_', '')
.replaceAll('%', '')
.toLowerCase()
.removeDiacritics()
.trim();
if (cleanedText.isEmpty) return [];

// If given a single kanji character return only that
if (cleanedText.length == 1 && _kanaKit.isKanji(cleanedText)) {
if (cleanedText.runes.length == 1 && cleanedText.isKanji()) {
final kanji = await getKanji(cleanedText);
if (kanji != null) return [kanji];
}
Expand Down Expand Up @@ -539,7 +475,10 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
.get();

// Sort exact matches of the search string to the top
final regExp = RegExp(r'\b' + cleanedText, caseSensitive: false);
final regExp = RegExp(
r'\b' + RegExp.escape(cleanedText),
caseSensitive: false,
);

final List<Kanji> exactMatchKanjiList = [];
for (int i = 0; i < unsortedKanjiList.length; i++) {
Expand Down Expand Up @@ -580,6 +519,10 @@ class KanjisDao extends DatabaseAccessor<AppDatabase> with _$KanjisDaoMixin {
.go();
}

Future<void> deleteAllNotes() async {
await db.delete(db.kanjiNotes).go();
}

// Inverse of String.kanjiCodePoint()
String _kanjiFromCodePoint(int codePoint) {
if (codePoint <= 0xFFFF) return String.fromCharCode(codePoint);
Expand Down
Loading
Loading