Files
amethyst/.claude/skills/quartz-integration/references/gradle-setup.md
T
Vitor PamplonaandClaude Opus 5 cb49caae69 chore(release): bump to 1.15.2
app 1.15.1 -> 1.15.2, appCode 459 -> 460. That single edit drives Android's
versionName/versionCode, Desktop and CLI packageVersion, quartz's Maven version
and geode's RelayInfo.VERSION.

Three substantive PRs since v1.15.1, plus Crowdin translations and the packaging
syncs the bump workflows opened after the last tag:

- #4092 media previews: an extension match now requires a real dot, so a player
  page whose path merely ends in the letters `_mp3` stops going to the video
  player, and `og:audio`/`og:video` are read and played with the page's
  `og:image` as poster. A declaration whose type is `text/html` -- YouTube's --
  is refused.
- #4095 nested NIP-22 replies: engagement subscriptions asked only for the
  lowercase `e`/`a` tags, so a comment two or more levels deep was invisible
  until ThreadScreen opened its own subscription. Each relay gets a second,
  root-scoped filter on `E`/`A`. Kind 1619 moves there too -- NIP-34 gives PR
  updates only an uppercase `E`, so it had been in a filter it could never match.
- #4096 Health Connect: a rationale screen Play requires, reachable from the
  composer, from Health Connect's permission screen and standalone without an
  account; reads moved off the UI thread; source names memoized; and the workout
  form is replaced rather than merged when a second suggestion is picked.

Verified on a Pixel 9 emulator before cutting, since two of the three are only
observable on device: the og:audio track plays in a thread with real transport
controls (00:30 / 05:00) where it used to buffer forever, and the Health Connect
rationale opens from all three routes -- including the one that matters for
review, where Health Connect's own permission screen launches our
ViewPermissionUsageActivity through the START_VIEW_PERMISSION_USAGE-guarded
filter.

RELEASE_NOTES_ID deliberately stays on the v1.15.0 note: RELEASE_OPS has it
repointed on x.y.0 only.

Left alone deliberately: everything under */packaging/ and translators.json's
tag, which the bump workflows and the Crowdin job write after the tag exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VgVDQQXAg4cmzsWHoJj61k
2026-09-12 10:28:52 -04:00

3.3 KiB

Quartz Gradle Dependency Setup

Current version

com.vitorpamplona.quartz:quartz:1.15.2

Check latest: https://central.sonatype.com/artifact/com.vitorpamplona.quartz/quartz


KMP Project Setup

gradle/libs.versions.toml

[versions]
quartz = "1.15.2"

[libraries]
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }

build.gradle.kts (library/app module)

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidKotlinMultiplatformLibrary) // or androidLibrary/androidApplication
}

kotlin {
    jvm()
    androidLibrary {
        namespace = "com.example.myapp"
        compileSdk = 35
        minSdk = 21
    }
    // optional: iOS targets

    sourceSets {
        commonMain.dependencies {
            implementation(libs.quartz)
        }
        // No platform-specific deps needed — Quartz provides them transitively
    }
}

Android-only Project

// build.gradle.kts (app module)
dependencies {
    implementation("com.vitorpamplona.quartz:quartz:1.15.2")
}

JVM (Desktop) standalone

// build.gradle.kts
plugins {
    kotlin("jvm")
}

dependencies {
    implementation("com.vitorpamplona.quartz:quartz:1.15.2")
    // JNA needed for libsodium (NIP-44) on JVM
    implementation("net.java.dev.jna:jna:5.18.1")
}

Transitive Dependencies (what you get automatically)

All platforms (commonMain)

  • org.jetbrains.kotlin:kotlin-stdlib
  • org.jetbrains.kotlinx:kotlinx-coroutines-core
  • org.jetbrains.kotlinx:kotlinx-collections-immutable
  • org.jetbrains.kotlinx:kotlinx-serialization-json
  • androidx.collection:collection (LruCache)
  • androidx.compose.runtime:runtime-annotation (@Immutable/@Stable)
  • fr.acinq.secp256k1:secp256k1-kmp (Schnorr crypto — common)

JVM + Android (jvmAndroid)

  • com.github.anthonynsimon:rfc3986-normalizer (URL normalization)
  • com.fasterxml.jackson.module:jackson-module-kotlin (JSON)
  • com.squareup.okhttp3:okhttp (WebSocket)
  • ru.gildor.coroutines:kotlin-coroutines-okhttp
  • nl.bommber:kchesslib (NIP-64 chess, version pinned to 1.0.0)

JVM only

  • fr.acinq.secp256k1:secp256k1-kmp-jni-jvm
  • com.goterl:lazysodium-java (NIP-44 encryption)
  • net.java.dev.jna:jna

Android only

  • fr.acinq.secp256k1:secp256k1-kmp-jni-android
  • com.goterl:lazysodium-android
  • net.java.dev.jna:jna (aar)
  • androidx.core:core-ktx

Packaging / ProGuard

Quartz ships consumer ProGuard rules automatically (publish = true in the library). You don't need to add manual keep rules for Quartz classes in your app.

For Android release builds, these classes are preserved:

  • All com.vitorpamplona.quartz.** event and model classes
  • Jackson serialization annotations

Common Build Errors

Duplicate class kotlin.collections.jdk8

Add to gradle.properties:

android.useFullClasspathForDexingTransform=true

Could not find lazysodium-java on JVM

Ensure JNA is on the classpath:

implementation("net.java.dev.jna:jna:5.18.1")

iOS: Framework not found quartz-kmpKit

Build the XCFramework first:

./gradlew :quartz:assembleQuartz-kmpKitReleaseXCFramework

Then drag quartz/build/XCFrameworks/release/quartz-kmpKit.xcframework into Xcode.