Standalone Shonar Desktop: vendor portable sources + local engine; decouple from ~/Projects/Shonar

- shared/ = portable Android-origin sources vendored from deferred/desktop-server
  (app/build.gradle.kts srcDir repointed; PlaybackController.kt excluded as Android-only)
- backend/ = bundled-lite engine (SQLite + inline queue); .venv symlinked from the
  old checkout, PYTHONPATH pins THIS backend's code over any editable install
- repoRoot() resolves this project dir (env SHONAR_REPO still wins); desktop-dev.sh
  watches shared/ + backend/
- Verified: :app:compileKotlin + :app:test green (23 tests); engine boots on :8010,
  self-migrates, /healthz ok
This commit is contained in:
avi 2026-09-14 17:14:54 -05:00
commit 76c867fca4
136 changed files with 21099 additions and 0 deletions

99
app/build.gradle.kts Normal file
View file

@ -0,0 +1,99 @@
plugins {
kotlin("jvm") version "2.0.21"
id("org.jetbrains.kotlin.plugin.compose") version "2.0.21"
id("org.jetbrains.compose") version "1.7.3"
}
group = "com.shonar"
version = "0.1.0"
repositories {
mavenCentral()
google()
}
kotlin {
jvmToolchain(17)
}
sourceSets {
main {
kotlin {
// Portable shared sources vendored into this project (formerly
// compiled in place from the sibling Android repo). Android-only
// files excluded below.
srcDir("../shared")
exclude(
"com/shonar/ShonarApplication.kt",
"com/shonar/MainActivity.kt",
// settings store impls are Android (DataStore/Keystore);
// desktop provides its own (desktopSettingsStore.kt).
"com/shonar/settings/SettingsStore.kt",
// recording: only AiContent.kt is portable.
"com/shonar/recording/MigrationRunner.kt",
"com/shonar/recording/RecordingDao.kt",
"com/shonar/recording/RecordingEntity.kt",
"com/shonar/recording/RecordingNotificationHelper.kt",
"com/shonar/recording/PlaybackController.kt",
"com/shonar/recording/RecordingPermissionHelper.kt",
"com/shonar/recording/RecordingRepository.kt",
"com/shonar/recording/RecordingService.kt",
"com/shonar/recording/RecordingStateStore.kt",
"com/shonar/recording/ShonarDatabase.kt",
"com/shonar/recording/SyncDrain.kt",
"com/shonar/recording/SyncSlots.kt",
"com/shonar/recording/SyncStateConverter.kt",
"com/shonar/recording/SyncWorker.kt",
// widget + rename-after-save UI: Android-only (AppWidget,
// ShonarApplication references).
"com/shonar/widget/**",
"com/shonar/ui/rename/**",
// ui: only ui/folder/FolderList.kt is portable.
"com/shonar/ui/detail/**",
"com/shonar/ui/home/**",
"com/shonar/ui/provider/**",
"com/shonar/ui/settings/**",
"com/shonar/ui/theme/**",
"com/shonar/ui/folder/FolderBrowserScreen.kt",
)
srcDir("src/main/kotlin")
}
}
test {
kotlin {
srcDir("src/test/kotlin")
}
}
}
dependencies {
implementation(compose.desktop.currentOs)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Real org.json for JVM (Android stubs throw "not mocked").
implementation("org.json:json:20240303")
testImplementation("junit:junit:4.13.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
testImplementation("com.squareup.okhttp3:mockwebserver:4.12.0")
}
compose.desktop {
application {
mainClass = "com.shonar.desktop.MainKt"
nativeDistributions {
targetFormats(org.jetbrains.compose.desktop.application.dsl.TargetFormat.Dmg)
targetFormats(org.jetbrains.compose.desktop.application.dsl.TargetFormat.Msi)
targetFormats(org.jetbrains.compose.desktop.application.dsl.TargetFormat.Deb)
packageName = "shonar-desktop"
packageVersion = "0.1.0"
}
}
}
tasks.withType<Test> {
useJUnit()
}