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
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Release

on:
push:
tags:
- 'v*'

jobs:
release:
runs-on: macos-13
permissions:
contents: write

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

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

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

- name: Build Android
run: ./gradlew :uxcam-kmp-shared:compileReleaseKotlinAndroid :uxcam-kmp-shared:bundleReleaseAar --no-daemon

- name: Publish to Maven Central
run: ./gradlew :uxcam-kmp-shared:publishAndReleaseToMavenCentral --no-configuration-cache --no-daemon
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
body_path: CHANGELOG.md
55 changes: 55 additions & 0 deletions .github/workflows/test-secrets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Test Secrets

on:
workflow_dispatch:

jobs:
test-secrets:
runs-on: ubuntu-latest
steps:
- name: Check MAVEN_CENTRAL_USERNAME
run: |
if [ -z "${{ secrets.MAVEN_CENTRAL_USERNAME }}" ]; then
echo "::error::MAVEN_CENTRAL_USERNAME is not set"
exit 1
else
echo "MAVEN_CENTRAL_USERNAME is set (length: ${#MAVEN_CENTRAL_USERNAME})"
fi
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}

- name: Check MAVEN_CENTRAL_PASSWORD
run: |
if [ -z "${{ secrets.MAVEN_CENTRAL_PASSWORD }}" ]; then
echo "::error::MAVEN_CENTRAL_PASSWORD is not set"
exit 1
else
echo "MAVEN_CENTRAL_PASSWORD is set (length: ${#MAVEN_CENTRAL_PASSWORD})"
fi
env:
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}

- name: Check SIGNING_KEY
run: |
if [ -z "${{ secrets.SIGNING_KEY }}" ]; then
echo "::error::SIGNING_KEY is not set"
exit 1
else
echo "SIGNING_KEY is set (length: ${#SIGNING_KEY})"
fi
env:
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}

- name: Check SIGNING_PASSWORD
run: |
if [ -z "${{ secrets.SIGNING_PASSWORD }}" ]; then
echo "::error::SIGNING_PASSWORD is not set"
exit 1
else
echo "SIGNING_PASSWORD is set (length: ${#SIGNING_PASSWORD})"
fi
env:
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: All secrets configured
run: echo "All required secrets are configured correctly!"
14 changes: 6 additions & 8 deletions .github/workflows/validate-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ name: Validate PR
on:
pull_request:
branches:
- 'master'
- 'main'
jobs:
build_project:
# if: startsWith(github.head_ref, 'renovate')
runs-on: macos-latest
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4

- name: Setup java
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Build
run: |
./gradlew :uxcam-kmp-shared:build --no-daemon
- name: Build Android
run: ./gradlew :uxcam-kmp-shared:compileReleaseKotlinAndroid :uxcam-kmp-shared:bundleReleaseAar --no-daemon
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] - 2026-01-12

### Added

- Initial release of UXCam-KMP
- Unified Kotlin API for UXCam SDK (Android & iOS)
- Session recording controls (pause/resume)
- User identification with `setUserIdentity()`
- Custom user properties with `setUserProperty()`
- Event logging with `logEvent()` and optional properties
- Screen privacy controls with `addScreenNameToIgnore()`
- Session management (`startNewSession()`, `stopSessionAndUploadData()`, `cancelCurrentSession()`)
- Session URL retrieval with `urlForCurrentSession()`
- Configuration options:
- `enableAutomaticScreenNameTagging`
- `enableImprovedScreenCapture` (Android only)
- `enableCrashHandling`

### Platform Support

- Android: minSdk 23, compileSdk 33
- iOS: 12.0+
- Kotlin: 1.9.21+

### Dependencies

- UXCam Android SDK: 3.6.12
- UXCam iOS SDK: via CocoaPods
- Napier: 2.7.1 (logging)
38 changes: 38 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to a positive environment:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior:

- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting

## Enforcement Responsibilities

Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers. All complaints will be reviewed and investigated promptly and fairly.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ A Kotlin Multiplatform wrapper library for [UXCam](https://uxcam.com/) session r

## Installation

### Kotlin Multiplatform

Add the repository to your `settings.gradle.kts`:

```kotlin
dependencyResolutionManagement {
repositories {
maven { url = uri("https://sdk.uxcam.com/android/") }
}
}
```

Add the dependency to your shared module's `build.gradle.kts`:

```kotlin
kotlin {
sourceSets {
commonMain.dependencies {
implementation("dev.onexeor:uxcam-kmp-shared:<version>")
}
}
}
```

### Android (Gradle)

Add the repository to your `settings.gradle.kts`:
Expand Down
4 changes: 3 additions & 1 deletion UXCamExample/androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ plugins {
kotlin("android")
}

val libraryVersion: String = project.findProperty("VERSION_NAME")?.toString() ?: "1.0.0"

android {
namespace = "dev.onexeor.uxcam.uxcamexample.android"
compileSdk = 33
Expand All @@ -11,7 +13,7 @@ android {
minSdk = 23
targetSdk = 33
versionCode = 1
versionName = "1.0"
versionName = libraryVersion
}
buildFeatures {
compose = true
Expand Down
4 changes: 3 additions & 1 deletion UXCamExample/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ plugins {
id("com.android.library")
}

val libraryVersion: String = project.findProperty("VERSION_NAME")?.toString() ?: "1.0.0"

@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default()
Expand All @@ -22,7 +24,7 @@ kotlin {
cocoapods {
summary = "UXCam for KMP example"
homepage = "onexeor.dev"
version = "1.0"
version = libraryVersion
ios.deploymentTarget = "12.0"
podfile = project.file("../iosApp/Podfile")
framework {
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
// trick: for the same plugin versions in all sub-modules
id("com.android.library").version("8.1.1").apply(false)
kotlin("multiplatform").version("1.9.21").apply(false)
id("com.vanniktech.maven.publish").version("0.30.0").apply(false)
}

tasks.register("clean", Delete::class) {
Expand Down
19 changes: 18 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,21 @@ android.nonTransitiveRClass=true

#MPP
kotlin.mpp.enableCInteropCommonization=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.mpp.androidSourceSetLayoutVersion=2

# Library Version
VERSION_NAME=1.0.0

# Maven Central Publishing (Sonatype Central Portal)
GROUP=dev.onexeor
POM_ARTIFACT_ID=uxcam-kmp-shared
POM_NAME=UXCam KMP
POM_DESCRIPTION=Kotlin Multiplatform wrapper for UXCam SDK
POM_URL=https://github.com/OneXeor/UXCam-KMP
POM_SCM_URL=https://github.com/OneXeor/UXCam-KMP
POM_SCM_CONNECTION=scm:git:git://github.com/OneXeor/UXCam-KMP.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/OneXeor/UXCam-KMP.git
POM_LICENCE_NAME=MIT License
POM_LICENCE_URL=https://opensource.org/licenses/MIT
POM_DEVELOPER_ID=onexeor
POM_DEVELOPER_NAME=OneXeor
19 changes: 17 additions & 2 deletions uxcam-kmp-shared/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import com.vanniktech.maven.publish.SonatypeHost

plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("com.vanniktech.maven.publish")
}

val libraryVersion: String = project.findProperty("VERSION_NAME")?.toString() ?: "1.0.0"

@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default()
Expand All @@ -14,12 +19,13 @@ kotlin {
jvmTarget = "1.8"
}
}
publishLibraryVariants("release")
}

ios()
iosSimulatorArm64()
cocoapods {
version = "1.0"
version = libraryVersion
ios.deploymentTarget = "12.0"
framework {
baseName = "uxcam-kmp-shared"
Expand All @@ -29,7 +35,11 @@ kotlin {
}

sourceSets {
val commonMain by getting
val commonMain by getting {
dependencies {
implementation("io.github.aakira:napier:2.7.1")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
Expand All @@ -49,3 +59,8 @@ android {
implementation("com.uxcam:uxcam:3.6.12")
}
}

mavenPublishing {
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
signAllPublications()
}
Loading