Add Phase 5 Kotlin desktop app: Compose Multiplatform with gRPC client

Kotlin/Compose Desktop application under desktop/ with:
- Gradle build: Kotlin 2.1, Compose 1.8, gRPC/Protobuf codegen, detekt
- ExoClient: gRPC client for both ArtifactService and KnowledgeGraphService
- Obsidian-style layout: collapsible tree sidebar, contextual main panel
- Five view modes: artifact detail, note editor, search results, catalog,
  graph (stub)
- Unified search bar with selector prefix support
- Command palette (Ctrl+Shift+A) for quick actions
- Menu bar with keyboard shortcuts (Ctrl+I/L/F/Q)
- Dark Material 3 theme
- Detekt lint config with Compose/test naming exceptions
- Unit tests for AppState and model types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 11:44:45 -07:00
parent 051a85d846
commit fa21dbaf98
18 changed files with 1342 additions and 2 deletions

97
desktop/build.gradle.kts Normal file
View File

@@ -0,0 +1,97 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins {
kotlin("jvm") version "2.1.20"
id("org.jetbrains.compose") version "1.8.0-alpha02"
id("org.jetbrains.kotlin.plugin.compose") version "2.1.20"
id("com.google.protobuf") version "0.9.4"
id("io.gitlab.arturbosch.detekt") version "1.23.7"
}
group = "dev.wntrmute.exo"
version = "0.1.0"
repositories {
google()
mavenCentral()
}
val grpcVersion = "1.68.0"
val grpcKotlinVersion = "1.4.1"
val protobufVersion = "4.28.2"
dependencies {
// Compose Desktop
implementation(compose.desktop.currentOs)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
// gRPC
implementation("io.grpc:grpc-netty-shaded:$grpcVersion")
implementation("io.grpc:grpc-protobuf:$grpcVersion")
implementation("io.grpc:grpc-kotlin-stub:$grpcKotlinVersion")
implementation("com.google.protobuf:protobuf-kotlin:$protobufVersion")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.9.0")
// Testing
testImplementation(kotlin("test"))
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
}
// Protobuf code generation
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobufVersion"
}
plugins {
create("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion"
}
create("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpcKotlinVersion:jdk8@jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
create("grpc")
create("grpckt")
}
it.builtins {
create("kotlin")
}
}
}
}
// Detekt static analysis
detekt {
buildUponDefaultConfig = true
config.setFrom(files("detekt.yml"))
parallel = true
}
compose.desktop {
application {
mainClass = "dev.wntrmute.exo.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Deb, TargetFormat.Rpm)
packageName = "exo-desktop"
packageVersion = "0.1.0"
description = "kExocortex Desktop Application"
vendor = "wntrmute.dev"
}
}
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(21)
}