Compare commits

...

4 Commits

7 changed files with 127 additions and 15 deletions

View File

@@ -5,6 +5,7 @@ import 'dart:io';
import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart';
import 'package:jadb/search.dart';
import 'package:mugiten/models/verify_tables.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
@@ -119,10 +120,12 @@ Future<Database> openAndMigrateDatabase(
},
onOpen: (db) async {
log('Verifying jadb tables...');
db.jadbVerifyTables();
log('jadb opened successfully');
log('Verifying jadb tables...');
verifyMugitenTablesWithDbConnection(db);
log('Database tables verified successfully');
},
);
return database;

View File

@@ -31,4 +31,12 @@ abstract class HistoryTableNames {
/// - language CHAR(1)?
static const String historyEntryOrderedByTimestamp =
'Mugiten_HistoryEntry_orderedByTimestamp';
static Set<String> get allTables => {
historyEntry,
historyEntryKanji,
historyEntryTimestamp,
historyEntryWord,
historyEntryOrderedByTimestamp,
};
}

View File

@@ -20,4 +20,10 @@ abstract class LibraryListTableNames {
/// Attributes:
/// - name TEXT
static const String libraryListOrdered = 'Mugiten_LibraryList_Ordered';
static Set<String> get allTables => {
libraryList,
libraryListEntry,
libraryListOrdered,
};
}

View File

@@ -1,6 +1,7 @@
import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:get_it/get_it.dart';
import 'package:mugiten/database/library_list/table_names.dart';
import '../../database/database.dart';
@@ -10,9 +11,9 @@ import 'library_entry.dart';
class LibraryList {
final String name;
const LibraryList._byName(this.name);
const LibraryList.byName(this.name);
static const LibraryList favourites = LibraryList._byName('favourites');
static const LibraryList favourites = LibraryList.byName('favourites');
/// Get all entries within the library, in their custom order
Future<List<LibraryEntry>> get entries async {
@@ -48,7 +49,7 @@ class LibraryList {
static Future<List<LibraryList>> get allLibraries async {
final query = await db().query(LibraryListTableNames.libraryListOrdered);
return query
.map((lib) => LibraryList._byName(lib['name']! as String))
.map((lib) => LibraryList.byName(lib['name']! as String))
.toList();
}
@@ -83,7 +84,7 @@ class LibraryList {
return Map.fromEntries(
query.map(
(lib) => MapEntry(
LibraryList._byName(lib['name']! as String),
LibraryList.byName(lib['name']! as String),
lib['exists']! as int == 1,
),
),
@@ -249,6 +250,32 @@ class LibraryList {
});
}
Future<void> insertJsonEntries(
List<Map<String, Object?>> jsonEntries,
) async {
List<LibraryEntry> entries =
jsonEntries.map((e) => LibraryEntry.fromJson(e)).toList();
// TODO: batch
for (final entry in entries) {
if (entry.kanji != null) {
await insertEntry(
kanji: entry.kanji,
jmdictEntryId: null,
position: null,
lastModified: entry.lastModified,
);
} else if (entry.jmdictEntryId != null) {
await insertEntry(
jmdictEntryId: entry.jmdictEntryId,
kanji: null,
position: null,
lastModified: entry.lastModified,
);
}
}
}
/// Deletes an entry within a list
/// Will throw an exception if the entry is not in the library
Future<void> deleteEntry({
@@ -418,7 +445,7 @@ class LibraryList {
'name': libraryName,
'prevList': prevList.name,
});
return LibraryList._byName(libraryName);
return LibraryList.byName(libraryName);
}
/// Delete this library from the database

View File

@@ -0,0 +1,35 @@
import 'package:mugiten/database/history/table_names.dart';
import 'package:mugiten/database/library_list/table_names.dart';
import 'package:sqflite/sqflite.dart';
Future<void> verifyMugitenTablesWithDbConnection(DatabaseExecutor db) async {
final Set<String> tables = await db
.query(
'sqlite_master',
columns: ['name'],
where: 'type = ?',
whereArgs: ['table'],
)
.then((result) {
return result.map((row) => row['name'] as String).toSet();
});
final Set<String> expectedTables = {
...HistoryTableNames.allTables,
...LibraryListTableNames.allTables,
};
final missingTables = expectedTables.difference(tables);
if (missingTables.isNotEmpty) {
throw Exception([
'Missing tables:',
missingTables.map((table) => ' - $table').join('\n'),
'',
'Found tables:\n',
tables.map((table) => ' - $table').join('\n'),
'',
'Please ensure the database is correctly set up.',
].join('\n'));
}
}

View File

@@ -1,4 +1,5 @@
import 'dart:io';
import 'dart:developer';
import 'package:confirm_dialog/confirm_dialog.dart';
import 'package:file_picker/file_picker.dart';
@@ -80,16 +81,20 @@ class _SettingsViewState extends State<SettingsView> {
}
Future<void> clearAll(context) async {
final historyCount = await HistoryEntry.amountOfEntries();
final libraryCount = await LibraryList.libraryCount();
if (!context.mounted) return;
int? historyCount;
int? libraryCount;
try {
historyCount = await HistoryEntry.amountOfEntries();
libraryCount = await LibraryList.libraryCount();
} catch (e) {
log('Error getting counts: $e');
}
final bool userIsSure = await confirm(
context,
content: Text(
'Are you sure you want to delete $historyCount history entries '
'and $libraryCount libraries?',
'Are you sure you want to delete ${historyCount ?? '?'} history entries '
'and ${libraryCount ?? '?'} libraries?',
),
);

View File

@@ -25,7 +25,7 @@ Future<Directory> tmpdir() async =>
Future<Directory> unpackZipToTempDir(String zipFilePath) async {
final outputDir = await tmpdir();
extractFileToDisk(
await extractFileToDisk(
zipFilePath,
outputDir.path,
);
@@ -148,5 +148,33 @@ Future<void> exportLibraryListsTo(
// TODO: how do we handle lists that already exist? There seems to be no good way to merge them?
Future<void> importLibraryListsFrom(Directory libraryListsDir) async {
print('TODO: Implement importLibraryLists');
for (final file in libraryListsDir.listSync()) {
if (file is! File) continue;
assert(file.path.endsWith('.json'));
final libraryName =
file.uri.pathSegments.last.replaceFirst(RegExp(r'\.json$'), '');
if (await LibraryList.exists(libraryName)) {
if ((await LibraryList.byName(libraryName).length) > 0) {
print(
'Library list "$libraryName" already exists and is not empty. Skipping import.');
continue;
} else {
print('Library list "$libraryName" already exists but is empty. '
'Importing entries from file ${file.path}.');
}
} else {
LibraryList.insert(libraryName);
}
final content = await file.readAsString();
final List<Map<String, Object?>> jsonEntries = (jsonDecode(content) as List)
.map((e) => e as Map<String, Object?>)
.toList();
final libraryList = LibraryList.byName(libraryName);
await libraryList.insertJsonEntries(jsonEntries);
}
}