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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ktlint_code_style = ktlint_official
ktlint_function_naming_ignore_when_annotated_with = Composable

# For Migration and AutoMigration classes
[core/src/main/kotlin/xyz/sevive/arcaeaoffline/core/database/migrations/*Migration*.kt]
[shared/src/commonMain/kotlin/xyz/sevive/arcaeaoffline/core/database/migrations/*Migration*.kt]
# The class name were directly copied from Google's documentation
ktlint_standard_class-naming = disabled
# Auto generated SQL lines can be very long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import org.koin.android.ext.koin.androidLogger
import org.koin.androidx.workmanager.koin.workManagerFactory
import org.koin.core.context.startKoin
import org.koin.mp.KoinPlatform.getKoin
import xyz.sevive.arcaeaoffline.core.database.ArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.core.database.getArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.core.ocr.device.DeviceOcrOnnxHelper
import xyz.sevive.arcaeaoffline.data.maintenance.AppDataMaintenanceManager
import xyz.sevive.arcaeaoffline.data.notification.Notifications
Expand Down Expand Up @@ -89,7 +89,7 @@ class ArcaeaOfflineApplication : Application() {
try {
val databases =
listOf(
ArcaeaOfflineDatabase.getDatabase(this),
getArcaeaOfflineDatabase(this),
OcrQueueDatabase.getDatabase(this),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import xyz.sevive.arcaeaoffline.BuildConfig
import xyz.sevive.arcaeaoffline.core.database.ArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.core.database.getArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.data.OcrDependencyPaths
import xyz.sevive.arcaeaoffline.database.AppDatabase
import xyz.sevive.arcaeaoffline.database.OcrQueueDatabase
Expand Down Expand Up @@ -231,7 +232,7 @@ class DiagnosticsCollector(
databaseInfo(
dbFile = File(context.getDatabasePath(ArcaeaOfflineDatabase.DATABASE_FILENAME).path),
) {
ArcaeaOfflineDatabase.getDatabase(context)
getArcaeaOfflineDatabase(context)
},
appData =
databaseInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import kotlinx.io.buffered
import kotlinx.io.files.SystemFileSystem
import xyz.sevive.arcaeaoffline.R
import xyz.sevive.arcaeaoffline.core.database.ArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.core.database.getArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.data.OcrDependencyPaths
import xyz.sevive.arcaeaoffline.database.OcrQueueDatabase
import xyz.sevive.arcaeaoffline.database.daos.OcrQueueTaskDao
Expand Down Expand Up @@ -358,7 +359,7 @@ class EmergencyModeActivityViewModel(
) {
// Merge WAL into the main database file, so that copying it alone
// produces a complete backup.
val database = ArcaeaOfflineDatabase.getDatabase(appContext)
val database = getArcaeaOfflineDatabase(appContext)
database.useWriterConnection { connection ->
connection.executeSQL("PRAGMA wal_checkpoint(TRUNCATE)")
}
Expand Down
17 changes: 0 additions & 17 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.plugin.serialization)
alias(libs.plugins.koin.compiler)

alias(androidx.plugins.room3)
}

room3 {
schemaDirectory("$projectDir/schemas")
}

kotlin {
Expand Down Expand Up @@ -46,10 +40,6 @@ android {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
// Adds exported schema location as test app assets.
getByName("androidTest").assets.directories += setOf("$projectDir/schemas")
}
}

dependencies {
Expand All @@ -69,10 +59,6 @@ dependencies {

implementation(androidx.core.ktx)

api(androidx.room3.runtime)
ksp(androidx.room3.compiler)
implementation(androidx.sqlite.bundled)

// 3rd party
implementation(libs.kermit)

Expand All @@ -83,8 +69,5 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.junit)
androidTestImplementation(androidx.test.ext.junit)
testImplementation(androidx.room3.testing)
testImplementation(androidx.sqlite.bundled.jvm)
androidTestImplementation(androidx.test.runner)
androidTestImplementation(androidx.room3.testing)
}
1 change: 0 additions & 1 deletion core/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@
#-renamesourcefileattribute SourceFile

-keep public class org.opencv.core.CvException { *; }
-keep class * extends androidx.room3.RoomDatabase { <init>(); }
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import xyz.sevive.arcaeaoffline.core.database.daos.PropertyDao
import xyz.sevive.arcaeaoffline.core.database.daos.R30EntryDao
import xyz.sevive.arcaeaoffline.core.database.daos.SongDao
import xyz.sevive.arcaeaoffline.core.database.daos.SongLocalizedDao
import xyz.sevive.arcaeaoffline.core.database.getArcaeaOfflineDatabase
import xyz.sevive.arcaeaoffline.core.database.repositories.ChartInfoRepository
import xyz.sevive.arcaeaoffline.core.database.repositories.ChartInfoRepositoryImpl
import xyz.sevive.arcaeaoffline.core.database.repositories.DifficultyLocalizedRepository
Expand Down Expand Up @@ -50,7 +51,7 @@ import xyz.sevive.arcaeaoffline.core.database.repositories.SongLocalizedReposito
import xyz.sevive.arcaeaoffline.core.database.repositories.SongRepository
import xyz.sevive.arcaeaoffline.core.database.repositories.SongRepositoryImpl

internal fun createArcaeaOfflineDatabase(context: Context) = ArcaeaOfflineDatabase.getDatabase(context)
internal fun createArcaeaOfflineDatabase(context: Context) = getArcaeaOfflineDatabase(context)

internal fun metaDao(db: ArcaeaOfflineDatabase) = db.metaDao()

Expand Down
1 change: 1 addition & 0 deletions desktopApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
implementation(libs.compose.ui)
implementation(libs.compose.foundation)
implementation(libs.compose.components.resources)
implementation(libs.filekit.core)
}

compose.desktop {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import io.github.vinceglb.filekit.FileKit
import org.jetbrains.compose.resources.stringResource
import xyz.sevive.arcaeaoffline.core.ArcaeaPartnerModifiers
import xyz.sevive.arcaeaoffline.core.calculators.calculatePlayRating
Expand All @@ -30,7 +31,9 @@ import xyz.sevive.arcaeaoffline.ui.components.rememberArcaeaConstantStepperTextF
import xyz.sevive.arcaeaoffline.ui.theme.ArcaeaOfflineTheme
import xyz.sevive.arcaeaoffline.ui.theme.spacing

fun main() =
fun main() {
FileKit.init("ArcaeaOffline")

application {
Window(onCloseRequest = ::exitApplication, title = "Arcaea Offline (Proof-of-Concept Prototype)") {
ArcaeaOfflineTheme {
Expand All @@ -40,6 +43,7 @@ fun main() =
}
}
}
}

@Composable
fun CalculatorScreen() {
Expand Down
1 change: 0 additions & 1 deletion gradle/androidx.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ room3-runtime = { module = "androidx.room3:room3-runtime", version.ref = "room3"
room3-compiler = { module = "androidx.room3:room3-compiler", version.ref = "room3" }
room3-testing = { module = "androidx.room3:room3-testing", version.ref = "room3" }
sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
sqlite-bundled-jvm = { module = "androidx.sqlite:sqlite-bundled-jvm", version.ref = "sqlite" }

datastore-core = { module = "androidx.datastore:datastore-core", version.ref = "datastore" }
datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" }
Expand Down
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ github-cheonjaeung-gridlayout = "2.7.4"
aboutlibraries = "14.2.1"
kermit = "2.1.0"
filekit = "0.14.2"
jSystemThemeDetector = "3.9.1"
kotlinx-io = "0.9.0"
ktor = "3.5.2"
bignum = "0.3.10"
Expand Down Expand Up @@ -67,7 +68,7 @@ materialkolor-color-utilities = { module = "com.materialkolor:material-color-uti

opencv = { module = "org.opencv:opencv", version.ref = "opencv" }
apache-commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "apache-commons-compress" }
jSystemThemeDetector = { module = "com.github.Dansoftowner:jSystemThemeDetector", version = "3.9.1" }
jSystemThemeDetector = { module = "com.github.Dansoftowner:jSystemThemeDetector", version.ref = "jSystemThemeDetector" }
io-sentry-sentryAndroid = { module = "io.sentry:sentry-android", version.ref = "io-sentry-sentryAndroid" }

onnxruntime-android = { module = "com.microsoft.onnxruntime:onnxruntime-android", version = "1.26.0" }
Expand Down
33 changes: 32 additions & 1 deletion shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.kotlin.multiplatform.library)
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.ksp)

alias(libs.plugins.compose.compiler)
alias(libs.plugins.jetbrains.compose)

alias(libs.plugins.kotlin.plugin.serialization)

alias(androidx.plugins.room3)
}

room3 {
schemaDirectory("$projectDir/schemas")
}

compose {
Expand All @@ -27,6 +34,11 @@ tasks.withType<Test>().configureEach {
}

kotlin {
compilerOptions {
// Room3 compiler opt out
freeCompilerArgs.add("-Xexpect-actual-classes")
}

jvm()

android {
Expand Down Expand Up @@ -65,20 +77,33 @@ kotlin {
implementation(libs.compose.ui.tooling)

implementation(libs.kotlinx.serialization)
implementation(libs.kotlinx.datetime)

implementation(libs.bignum)
implementation(libs.kermit)

implementation(libs.ktor.client.core)

api(androidx.room3.runtime)
implementation(androidx.sqlite.bundled)
}

androidMain.dependencies {
implementation(libs.ktor.client.okhttp)
}

jvmMain.dependencies {
implementation(libs.jSystemThemeDetector)
// jSystemThemeDetector pulls in jfa, whose POM pins jna with a non-existent
// "jpms" classfier, breaking jvm configuration with "jna-<version>-jpms.jar"
// not found.
//
// filekit-core depends on jna-platform which introduces plain jna, so excluding
// this does not affect compilation.
implementation("com.github.Dansoftowner:jSystemThemeDetector:${libs.versions.jSystemThemeDetector.get()}") {
exclude(group = "net.java.dev.jna", module = "jna")
}
implementation(libs.ktor.client.cio)
implementation(libs.filekit.core)
}

commonTest.dependencies {
Expand All @@ -91,6 +116,12 @@ kotlin {

jvmTest.dependencies {
implementation(compose.desktop.currentOs)
implementation(androidx.room3.testing)
}
}
}

dependencies {
add("kspAndroid", androidx.room3.compiler)
add("kspJvm", androidx.room3.compiler)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package xyz.sevive.arcaeaoffline.core.database

import android.content.Context
import androidx.room3.Room
import androidx.room3.RoomDatabase

@Volatile
private var instance: ArcaeaOfflineDatabase? = null

private val instanceLock = Any()

fun getArcaeaOfflineDatabaseBuilder(context: Context): RoomDatabase.Builder<ArcaeaOfflineDatabase> {
val appContext = context.applicationContext
val dbFile = appContext.getDatabasePath(ArcaeaOfflineDatabase.DATABASE_FILENAME)
return Room.databaseBuilder<ArcaeaOfflineDatabase>(
context = appContext,
name = dbFile.absolutePath,
)
}

fun getArcaeaOfflineDatabase(context: Context): ArcaeaOfflineDatabase {
// If the instance is not null, return it, otherwise create a new database instance.
return instance ?: synchronized(instanceLock) {
getArcaeaOfflineDatabase(getArcaeaOfflineDatabaseBuilder(context)).also { instance = it }
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package xyz.sevive.arcaeaoffline.core.database

import android.content.Context
import androidx.room3.AutoMigration
import androidx.room3.ColumnTypeConverters
import androidx.room3.ConstructedBy
import androidx.room3.Database
import androidx.room3.Room
import androidx.room3.RoomDatabase
import androidx.room3.RoomDatabaseConstructor
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import kotlinx.coroutines.Dispatchers
import xyz.sevive.arcaeaoffline.core.database.converters.ArcaeaLanguageConverters
Expand Down Expand Up @@ -43,6 +43,7 @@ import xyz.sevive.arcaeaoffline.core.database.migrations.Migration_15_16
import xyz.sevive.arcaeaoffline.core.database.migrations.Migration_6_7
import xyz.sevive.arcaeaoffline.core.database.migrations.Migration_7_8

@ConstructedBy(ArcaeaOfflineDatabaseConstructor::class)
@Database(
entities = [
Property::class,
Expand Down Expand Up @@ -107,33 +108,20 @@ abstract class ArcaeaOfflineDatabase : RoomDatabase() {

companion object {
const val DATABASE_FILENAME = "arcaea_offline.db"

@Volatile
private var instance: ArcaeaOfflineDatabase? = null

private fun getDatabaseBuilder(context: Context): Builder<ArcaeaOfflineDatabase> {
val appContext = context.applicationContext
val dbFile = appContext.getDatabasePath(DATABASE_FILENAME)
return Room.databaseBuilder<ArcaeaOfflineDatabase>(
context = appContext,
name = dbFile.absolutePath,
)
}

fun getDatabase(context: Context): ArcaeaOfflineDatabase {
// If the instance is not null, return it, otherwise create a new database instance.
return instance ?: synchronized(this) {
getDatabaseBuilder(context)
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.addCallback(ScoringModeCreateCallback)
.addMigrations(
Migration_6_7,
Migration_7_8,
Migration_15_16,
).build()
.also { instance = it }
}
}
}
}

expect object ArcaeaOfflineDatabaseConstructor : RoomDatabaseConstructor<ArcaeaOfflineDatabase> {
override fun initialize(): ArcaeaOfflineDatabase
}

fun getArcaeaOfflineDatabase(builder: RoomDatabase.Builder<ArcaeaOfflineDatabase>): ArcaeaOfflineDatabase =
builder
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.addCallback(ScoringModeCreateCallback)
.addMigrations(
Migration_6_7,
Migration_7_8,
Migration_15_16,
).build()
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package xyz.sevive.arcaeaoffline.core.database

import androidx.room3.Room
import androidx.room3.RoomDatabase
import io.github.vinceglb.filekit.FileKit
import io.github.vinceglb.filekit.absolutePath
import io.github.vinceglb.filekit.databasesDir
import io.github.vinceglb.filekit.div

fun getArcaeaOfflineDatabaseBuilder(): RoomDatabase.Builder<ArcaeaOfflineDatabase> =
Room.databaseBuilder<ArcaeaOfflineDatabase>(
name = (FileKit.databasesDir / ArcaeaOfflineDatabase.DATABASE_FILENAME).absolutePath(),
)
Loading
Loading