diff --git a/app/build.gradle b/app/build.gradle index edd84e4..c7c7985 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,8 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'org.jetbrains.kotlin.plugin.compose' + id 'org.jetbrains.kotlin.plugin.serialization' } android { @@ -60,10 +62,10 @@ dependencies { implementation "androidx.compose.material:material-icons-extended:$compose_version" implementation 'androidx.compose.material3:material3:1.2.1' implementation 'androidx.navigation:navigation-compose:2.7.7' - implementation 'com.beust:klaxon:5.5' + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'androidx.test.ext:junit:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" diff --git a/app/src/main/java/org/jyutping/jyutping/ui/cantonese/ConfusionScreen.kt b/app/src/main/java/org/jyutping/jyutping/ui/cantonese/ConfusionScreen.kt index b51e525..b42fefe 100644 --- a/app/src/main/java/org/jyutping/jyutping/ui/cantonese/ConfusionScreen.kt +++ b/app/src/main/java/org/jyutping/jyutping/ui/cantonese/ConfusionScreen.kt @@ -23,10 +23,11 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController -import com.beust.klaxon.Klaxon import java.io.BufferedReader import java.io.IOException import java.io.InputStreamReader +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json @Throws(IOException::class) private fun fetchConfusionJsonContent(navController: NavHostController): String? { @@ -50,10 +51,10 @@ private fun fetchConfusionJsonContent(navController: NavHostController): String? @Composable fun ConfusionScreen(navController: NavHostController) { - val entries = remember { mutableStateOf>(listOf()) } + val entries = remember { mutableStateOf>(listOf()) } LaunchedEffect(Unit) { val fetched = fetchConfusionJsonContent(navController) - val parsed = fetched?.let { Klaxon().parseArray(it) } + val parsed = fetched?.let { Json.decodeFromString>(it) } parsed?.let { entries.value = it } } LazyColumn( @@ -62,7 +63,7 @@ fun ConfusionScreen(navController: NavHostController) { ) { if (entries.value.isNotEmpty()) { items(entries.value) { - ConfusionView(confusion = it) + ConfusionElementView(it) } } else { item { @@ -73,7 +74,7 @@ fun ConfusionScreen(navController: NavHostController) { } @Composable -private fun ConfusionView(confusion: Confusion) { +private fun ConfusionElementView(element: ConfusionElement) { Row( modifier = Modifier .clip(shape = RoundedCornerShape(size = 8.dp)) @@ -82,9 +83,9 @@ private fun ConfusionView(confusion: Confusion) { horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically ) { - Text(text = confusion.simplified) + Text(text = element.simplified) Column { - confusion.traditional.map { + element.traditional.map { Row { Box { Row( @@ -111,10 +112,13 @@ private fun ConfusionView(confusion: Confusion) { } } -private data class Confusion ( +@Serializable +private data class ConfusionElement ( val simplified: String, val traditional: List ) + +@Serializable private data class ConfusionTraditional ( val character: String, val romanization: String, diff --git a/app/src/main/java/org/jyutping/jyutping/utilities/DatabasePreparer.kt b/app/src/main/java/org/jyutping/jyutping/utilities/DatabasePreparer.kt index 8071a4e..b432876 100644 --- a/app/src/main/java/org/jyutping/jyutping/utilities/DatabasePreparer.kt +++ b/app/src/main/java/org/jyutping/jyutping/utilities/DatabasePreparer.kt @@ -10,11 +10,12 @@ import java.io.OutputStream import org.jyutping.jyutping.BuildConfig object DatabasePreparer { - private const val SOURCE_DATABASE_NAME = "appdb.sqlite3" private val oldDatabaseNames: List = listOf( "tmpdb.sqlite3", - "tmpdb.sqlite3-journal" + "tmpdb.sqlite3-journal", + "appdb-v0.1.0-tmp.sqlite3", + "appdb-v0.1.0-tmp.sqlite3-journal", ) val databaseName: String = run { val version = BuildConfig.VERSION_NAME @@ -24,23 +25,31 @@ object DatabasePreparer { fun prepare(context: Context) { deleteOldDatabases(context) - if (!doesDatabaseExists(context)) { + val shouldCopyDatabase: Boolean = !(doesDatabaseExists(context)) + if (shouldCopyDatabase) { copyDatabase(context) } } + + @Throws(SecurityException::class) private fun deleteOldDatabases(context: Context) { oldDatabaseNames.map { - val path = context.applicationInfo.dataDir + DATABASES_DIR + it - val file = File(path) - if (file.exists()) { - try { - file.delete() - } catch (e: Exception) { - Log.e("DeleteDatabase", "Error deleting file: $path", e) + try { + val dbFile = context.getDatabasePath(it) + if (dbFile.exists() && dbFile.isFile) { + dbFile.delete() } + val path = context.applicationInfo.dataDir + DATABASES_DIR + it + val file = File(path) + if (file.exists() && file.isFile) { + file.delete() + } else { } + } catch (e: SecurityException) { + Log.e("DeleteDatabase", "Error deleting file: $it", e) } } } + private fun doesDatabaseExists(context: Context): Boolean { val dbFile = context.getDatabasePath(databaseName) val path = context.applicationInfo.dataDir + DATABASES_DIR + databaseName diff --git a/build.gradle b/build.gradle index 8c5bdce..b3cfcd7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ buildscript { } plugins { id 'com.android.application' version '8.5.0' apply false - id 'com.android.library' version '8.5.0' apply false id 'org.jetbrains.kotlin.android' version '1.9.23' apply false + id 'org.jetbrains.kotlin.plugin.compose' version '2.0.0' apply false + id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0' apply false }