Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI

on:
pull_request:
push:
branches: [master]

jobs:
test:
runs-on: macos-latest
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '21'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6

- name: Run tests
run: ./gradlew :signaturepad:allTests
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
run: ./gradlew :signaturepad:build

- name: Publish release
run: ./gradlew publishToMavenCentral --no-configuration-cache
run: ./gradlew :signaturepad:publishToMavenCentral --no-configuration-cache
if: success()
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
Expand Down
9 changes: 9 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension

plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
Expand All @@ -13,6 +16,12 @@ tasks.wrapper {
gradleVersion = "9.5.1"
}

// kotlin-js-store/yarn.lock resolves to slightly different contents across platforms (e.g. CI
// macOS vs a Linux dev machine), so don't fail the build on a mismatch — warn instead.
plugins.withType<YarnPlugin> {
the<YarnRootExtension>().yarnLockMismatchReport = YarnLockMismatchReport.WARNING
}

allprojects {
// Credentials must be added to ~/.gradle/gradle.properties per
// https://vanniktech.github.io/gradle-maven-publish-plugin/central/#secrets
Expand Down
17 changes: 16 additions & 1 deletion signaturepad/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@file:OptIn(ExperimentalWasmDsl::class)
@file:OptIn(ExperimentalWasmDsl::class, KotlinNativeCacheApi::class)

import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.plugin.mpp.DisableCacheInKotlinVersion
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCacheApi
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
alias(libs.plugins.android.kotlin.multiplatform.library)
Expand Down Expand Up @@ -30,6 +33,18 @@ kotlin {
iosArm64()
iosSimulatorArm64()

// The Kotlin/Native compiler cache holds Compose ui-uikit objects that hard-reference newer
// UIKit symbols (e.g. UIViewLayoutRegion), which fail to link the iOS test binary. Disable the
// cache for the native targets so those symbols resolve correctly.
targets.withType<KotlinNativeTarget>().configureEach {
binaries.all {
disableNativeCache(
version = DisableCacheInKotlinVersion.`2_4_0`,
reason = "Compose ui-uikit cache references newer UIKit symbols that fail to link",
)
}
}

explicitApi()

jvmToolchain(17)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class SignaturePadDrawingTest {
@Test
fun clear_removesPreviouslyDrawnStrokes() {
val state = SignaturePadStateImpl()
state.setSize(100, 100) // points outside the bounds are ignored, so give the pad a size
state.gestureStarted(Offset(0f, 0f))
listOf(Offset(10f, 10f), Offset(20f, 0f), Offset(30f, 10f)).forEach { state.gestureMoved(it) }
assertTrue(drawTo(state).drawnStrokes.isNotEmpty(), "precondition: signature has strokes")
Expand All @@ -36,6 +37,7 @@ class SignaturePadDrawingTest {
@Test
fun gesture_needsFourPointsBeforeFirstCurve() {
val state = SignaturePadStateImpl()
state.setSize(100, 100)
// gestureStarted seeds two points; one move gives three — not enough for a cubic bezier.
state.gestureStarted(Offset(0f, 0f))
state.gestureMoved(Offset(10f, 10f))
Expand All @@ -46,6 +48,7 @@ class SignaturePadDrawingTest {
@Test
fun gesture_producesOneCurvePerMoveAfterTheFirst() {
val state = SignaturePadStateImpl()
state.setSize(100, 100)
state.gestureStarted(Offset(0f, 0f))
// Well-separated points so each curve has a non-zero length and is actually drawn.
val moves = listOf(Offset(10f, 10f), Offset(20f, 0f), Offset(30f, 10f), Offset(40f, 0f))
Expand Down