[versions] kotlin = "2.4.10" agp = "9.3.0" openapiGenerator = "7.25.0" okhttp = "4.12.0" kotlinxSerializationJson = "1.7.3" kotlinxCoroutines = "1.11.0" composeBom = "2026.08.00" androidxActivityCompose = "1.13.0" androidxNavigationCompose = "2.10.0" androidxLifecycleCompose = "2.11.0" androidxCoreKtx = "1.19.0" junit = "4.13.2" robolectric = "4.16.1" androidxTestCore = "1.7.0" androidxTestRunner = "1.7.0" androidxTestExtJunit = "1.3.0" androidxTestRules = "1.7.0" androidxTestUiautomator = "2.4.0" coil = "2.7.0" # WhatsApp video/audio playback; exoplayer, ui and datasource-okhttp share this version. media3 = "1.11.0" # Group io.github.rosemoe. Do not use the old io.github.Rosemoe.sora-editor group (frozen at 0.23.6). soraEditor = "0.24.4" # Pinned to the io.gitlab.arturbosch.detekt group: BffOnlyNetworkClientRule # relies on its type-resolution API, which differs in the newer dev.detekt 2.x. detekt = "1.23.8" compileSdk = "37" targetSdk = "36" # The whole device fleet runs Android 14+, so a lower floor buys nothing. Settled decision. minSdk = "34" # NDK r27d. Zig and the pinned Ghostty commit live in # android/terminal-engine/toolchain.properties (catalogs cannot express them). ndk = "27.3.13750724" # minSdk 34 has the framework Credential Manager provider, so # credentials-play-services-auth is not needed. androidxCredentials = "1.6.0" # Pairing QR scanner uses CameraX plus pure-JVM zxing instead of ML Kit, to avoid Play Services. cameraX = "1.6.2" zxingCore = "3.5.4" # EncryptedSharedPreferences for ServerConfigStore, so the server address is # protected as well as the credentials sent to it. securityCrypto = "1.1.0" # WorkManager for resumable downloads/uploads that survive process death. androidxWork = "2.11.2" androidxGlance = "1.1.1" # FCM data messages. No google-services plugin or google-services.json yet, so # FirebaseMessaging.getInstance() has no default FirebaseApp until the Firebase # project is provisioned (or FirebaseApp.initializeApp is called explicitly). firebaseBom = "34.4.0" # GetStream's maintained build of Google's WebRTC (org.webrtc.*), not the # unofficial JitPack artifact. Only the -ktx variant is consumed so far. streamWebrtc = "1.3.10" # Terminal font size preference (local only). datastore = "1.2.1" # App lock. Stay on stable: this gates access to the app, so no alpha releases. biometric = "1.1.0" [libraries] kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" } compose-runtime = { module = "androidx.compose.runtime:runtime" } compose-ui = { module = "androidx.compose.ui:ui" } compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } compose-foundation = { module = "androidx.compose.foundation:foundation" } compose-material3 = { module = "androidx.compose.material3:material3" } # Core icon set only (823 KB); material-icons-extended is 35.7 MB. Missing # glyphs are drawn in :design-system from the official Material paths (PanelIcons.kt). # No version.ref on purpose: the version comes from compose-bom. compose-material-icons-core = { module = "androidx.compose.material:material-icons-core" } compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" } androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidxActivityCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidxNavigationCompose" } androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycleCompose" } androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycleCompose" } androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidxLifecycleCompose" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCoreKtx" } junit = { module = "junit:junit", version.ref = "junit" } robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } androidx-test-core = { module = "androidx.test:core", version.ref = "androidxTestCore" } androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidxTestRunner" } androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidxTestExtJunit" } # GrantPermissionRule, so on-device tests pass the real CAMERA/RECORD_AUDIO checks deterministically. androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidxTestRules" } # UiDevice.sleep()/wakeUp(): the only way to simulate screen off/on in a test # (ACTION_SCREEN_OFF is a protected broadcast). androidx-test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version.ref = "androidxTestUiautomator" } coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } # Used only by :data for the authenticated ImageLoader's VideoFrameDecoder; pulls coil-base without Compose. coil-video = { module = "io.coil-kt:coil-video", version.ref = "coil" } media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" } media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3" } # Referenced only by :data (dev.servercontrolpanel.data.media). media3-datasource-okhttp = { module = "androidx.media3:media3-datasource-okhttp", version.ref = "media3" } sora-editor-bom = { group = "io.github.rosemoe", name = "editor-bom", version.ref = "soraEditor" } sora-editor = { group = "io.github.rosemoe", name = "editor" } sora-editor-language-textmate = { group = "io.github.rosemoe", name = "language-textmate" } androidx-credentials = { module = "androidx.credentials:credentials", version.ref = "androidxCredentials" } androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraX" } androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraX" } androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraX" } androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraX" } zxing-core = { module = "com.google.zxing:core", version.ref = "zxingCore" } androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "securityCrypto" } androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "androidxWork" } # Glance: the home screen widget, written in Compose instead of hand-built RemoteViews. androidx-glance-appwidget = { module = "androidx.glance:glance-appwidget", version.ref = "androidxGlance" } androidx-glance-material3 = { module = "androidx.glance:glance-material3", version.ref = "androidxGlance" } # WorkManagerTestInitHelper for Robolectric; without it WorkManager.getInstance() throws in tests. androidx-work-testing = { module = "androidx.work:work-testing", version.ref = "androidxWork" } firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" } firebase-messaging = { module = "com.google.firebase:firebase-messaging" } stream-webrtc-android = { module = "io.getstream:stream-webrtc-android", version.ref = "streamWebrtc" } stream-webrtc-android-ktx = { module = "io.getstream:stream-webrtc-android-ktx", version.ref = "streamWebrtc" } # Declared but not used by any module yet. stream-webrtc-android-compose = { module = "io.getstream:stream-webrtc-android-compose", version.ref = "streamWebrtc" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx-biometric = { module = "androidx.biometric:biometric", version.ref = "biometric" } androidx-fragment = { module = "androidx.fragment:fragment", version = "1.3.6" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } openapi-generator = { id = "org.openapi.generator", version.ref = "openapiGenerator" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }