spotube/AGENTS.md

4.8 KiB

AGENTS

Repo shape (KMP + modules)

  • Gradle multi-module: :composeApp (main app), :plugin_interfaces (plugin API contracts), :js_plugin_example (Zipline JS plugin template).
  • :composeApp uses custom KMP source sets (mobileMain, androidJvmMain) with explicit dependsOn; Gradle prints "Default Kotlin Hierarchy Template Not Applied Correctly" warning. Treat as known/expected.

Real app entrypoints

  • Desktop/JVM: composeApp/src/jvmMain/kotlin/dev/krtirtho/spotube/main.kt (mainClass = dev.krtirtho.spotube.MainKt).
  • Android: composeApp/src/androidMain/kotlin/dev/krtirtho/spotube/MainActivity.kt.
  • iOS bridge: composeApp/src/iosMain/kotlin/dev/krtirtho/spotube/MainViewController.kt and iosApp/iosApp/ContentView.swift.

High-value commands

  • Use Gradle wrapper (./gradlew or ./gradlew.bat) only.
  • Run desktop: :composeApp:run
  • Build Android debug: :composeApp:assembleDebug
  • Module checks: :composeApp:check, :plugin_interfaces:check, :js_plugin_example:check
  • Focused tests: :composeApp:jvmTest, :composeApp:iosSimulatorArm64Test, :plugin_interfaces:jvmTest, :plugin_interfaces:jsTest, :js_plugin_example:jsTest
  • No lint/typecheck/formatter tasks are configured; :composeApp:check is the only aggregated check.

Dependencies

  • gradle/libs.versions.toml is the single source of truth for all version pins and library declarations.
  • Kotlin: 2.3.0, JVM target: 11 (compile/target compatibility in both composeApp/build.gradle.kts and plugin_interfaces/build.gradle.kts).

Codegen and plugin packaging

  • JS plugin bundles: :js_plugin_example:packageDevelopmentPlugin and :js_plugin_example:packageProductionPlugin. Output is .smplug files in js_plugin_example/build/distributions/.
  • Zipline plugin entrypoint: mainFunction = "dev.krtirtho.js_plugin_example.main" in js_plugin_example/build.gradle.kts. Plugin metadata from js_plugin_example/plugin.json.

Plugin architecture

  • plugin_interfaces exports zipline.core and semver as API. composeApp depends on it for the plugin system.
  • plugin_interfaces also has a JS target (browser()), used by the plugin system.

UI component patterns

  • AdaptiveDropdownBottomSheet (commonMain/.../core/ui/component/AdaptiveDropdownBottomSheet.kt): switches between DropdownMenu (large screen) and ModalBottomSheet (small screen) via currentWindowAdaptiveInfo(). Do NOT use expect/actual — all adaptive components that rely ONLY on Compose/Material3 APIs belong in commonMain.
  • AdaptiveDialogBottomSheet (commonMain/.../core/ui/component/AdaptiveDialogBottomSheet.kt): switches between ThemedDialog (large screen) and ModalBottomSheet (small screen) via currentWindowAdaptiveInfo(). Same rule — keep in commonMain unless platform-specific APIs are required.
  • Use expect/actual only when the component MUST use platform-specific APIs (e.g. WindowState for desktop window controls, native scrollbars). Pure Compose/Material3 adaptivity stays in commonMain.
  • JavaFX is required; --add-opens flags in compose.desktop.application.jvmArgs must be preserved: javafx.graphics/javafx.scene, javafx.graphics/com.sun.javafx.sg.prism, javafx.graphics/com.sun.javafx.scene, javafx.web/com.sun.webkit, javafx.media/com.sun.media.jfxmedia, javafx.media/com.sun.media.jfxmedia.events.
  • JavaFX dependencies are loaded from OpenJFX with platform classifiers (win/mac/linux) resolved at configuration time via System.getProperty("os.name").

Tooling

  • Gradle config cache enabled (gradle.properties); prefer module-scoped tasks.
  • Gradle daemon JVM pinned to JetBrains JDK 21 via gradle/gradle-daemon-jvm.properties.
  • Gradle 8.14.3 (from gradle/wrapper/gradle-wrapper.properties).
  • Foojay toolchain resolver in use (plugins { id("org.gradle.toolchains.foojay-resolver-convention") }).

Current testing reality

  • No committed *Test*.kt files; test tasks may run zero tests unless new tests are added.

Release workflow (.github/workflows/release.yml)

  • Triggered by workflow_dispatch with a release_type choice input (stable | nightly).
  • prepare-deps job checks out & publishes to mavenLocal:
    • kdroidFilter/ComposeNativeWebview (compose-webview)
    • team-spotube/gradle-plugin (spotubeGradle + vlcjBundler plugins)
  • Build jobs per platform (Android, Linux, Windows, macOS), all needs: prepare-deps.
  • Stable: reads versionName from composeApp/build.gradle.kts, tag = v{version}, draft release.
  • Nightly: builds with -PversionName=nightly, tag = nightly (updates existing), prerelease.
  • Android signing: decodes secrets.KEYSTORE (base64) → composeApp/upload-keystore.jks, writes signing config into local.properties from secrets.
  • create-release job (depends on all builds) uses softprops/action-gh-release@v2 to create the GitHub release with all artifacts attached.