# Quick Start — Tera Beauty SDK (15 minutes)

Integrate the on-device Beauty Editor into an existing app: **one repository, one dependency,
one Activity call.**

---

## Step 1 — Repository + credentials (the step people get wrong)

The dependency line is trivial; wiring the **Artifactory repo with credentials** is what trips most
consumers. In your **`settings.gradle.kts`**:

```kotlin
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
        maven {
            url = uri("https://artifactory.apero.vn/artifactory/gradle-release/")
            credentials {
                username = providers.gradleProperty("artifactoryUser").orNull
                    ?: System.getenv("ARTIFACTORY_USER")
                password = providers.gradleProperty("artifactoryPassword").orNull
                    ?: System.getenv("ARTIFACTORY_PASSWORD")
            }
        }
    }
}
```

Put the credentials in **`~/.gradle/gradle.properties`** (never commit them):

```properties
artifactoryUser=<your-user>
artifactoryPassword=<your-token>
```

> Contact the Apero team for credentials.

---

## Step 2 — One dependency

In your app module's **`build.gradle.kts`**:

```kotlin
dependencies {
    implementation("tera-soft:tera-sdk-beauty:1.1.0-alpha01")
}
```

That's the only `tera-soft:*` line you need — the 8 engine artifacts
(`beauty-core`, `beauty-renderer`, `beauty-detection`, `beauty-face`, `beauty-body`,
`beauty-adjust`, `beauty-retouch`, `beauty-sdk`) resolve transitively.

Requirements: **minSdk 24**, compileSdk 36, Java 11.

---

## Step 3 — Launch the editor and read the result

The API mirrors ML Kit: `getClient(options)` → build an `IntentSender` → launch it with
`StartIntentSenderForResult` → parse the result.

```kotlin
class MainActivity : AppCompatActivity() {

    // 1) Launcher that receives the edited image (null Intent = user cancelled).
    private val editorLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            val edited = BeautyEditingResult.fromActivityResultIntent(result.data) ?: return@registerForActivityResult
            // edited.imageUri / edited.imagePath — the saved result
            binding.preview.setImageURI(edited.imageUri)
        }

    private fun launchEditor(input: BeautyInput) {
        // 2) Configure
        val options = BeautyEditorOptions.Builder()
            .setEnabledTools(Tool.CROP, Tool.ADJUST, Tool.FACE_EDIT, Tool.BODY, Tool.MAKEUP, Tool.AUTO_RETOUCH)
            .setOutputFormat(OutputFormat.JPEG)
            .setOutputQuality(95)
            .setThemeMode(ThemeMode.DARK)   // DARK (default) / LIGHT / SYSTEM — see Step 4
            .build()

        // 3) Build the intent and launch
        BeautyEditing.getClient(options)
            .getStartEditingIntent(this, input)
            .addOnSuccessListener { editorLauncher.launch(IntentSenderRequest.Builder(it).build()) }
            .addOnFailureListener { e -> Log.e("Beauty", "Failed to build editor intent", e) }
    }
}
```

### Passing the input image — `BeautyInput`

The input is a `BeautyInput`. Build it with the factory matching your source:

```kotlin
BeautyInput.fromUri(uri)        // content:// , file:// or a path — used as-is (no copy)
BeautyInput.fromFile(file)      // a File on disk — used as-is
BeautyInput.fromBitmap(bitmap)  // in-memory bitmap (e.g. an AI-generated image) — encoded to PNG
BeautyInput.fromByteArray(bytes)// encoded image bytes (e.g. a network/AI response) — written verbatim
```

The editor is a **separate Activity** that must survive process death, so in-memory inputs
(`fromBitmap` / `fromByteArray`) are **materialized to a private cache file by the SDK for you** —
you no longer copy anything by hand. `fromUri` / `fromFile` pass through untouched.

```kotlin
// System picker → content:// . Hand it straight to the editor:
launchEditor(BeautyInput.fromUri(pickedContentUri))

// Already have a generated Bitmap? No cache dance needed:
launchEditor(BeautyInput.fromBitmap(generatedBitmap))
```

> For a `content://` from **another app**, make sure it is still readable when the editor launches
> (a short-lived picker grant can expire). If in doubt, copy into your cache and use
> `BeautyInput.fromFile(...)`. A legacy `getStartEditingIntent(activity, inputUri)` overload is also
> kept for backward compatibility.

---

## Step 4 (optional) — Open straight into one tool

To wire a Home-screen "Makeup" button directly to the Makeup tool, keep all tools enabled and set
the initial tool:

```kotlin
val options = BeautyEditorOptions.Builder()
    .setInitialTool(Tool.MAKEUP)   // opens on Makeup; closing it returns to the full tool bar
    .build()
```

`null` (the default) opens on the full tool bar.

---

## Step 5 (optional) — Light / Dark theme

The editor ships both palettes; pick which one renders with `setThemeMode(...)`:

```kotlin
val options = BeautyEditorOptions.Builder()
    .setThemeMode(ThemeMode.SYSTEM)   // follow the device's day/night setting
    .build()
```

| Mode | Behaviour |
|---|---|
| `ThemeMode.DARK` | Always dark — the SDK's original look. **Default** (existing integrations unchanged). |
| `ThemeMode.LIGHT` | Always light. |
| `ThemeMode.SYSTEM` | Follows the device's dark/light setting. |

The mode is chosen at runtime — not by the device unless you pass `SYSTEM`. To recolor either palette
to your brand, see **[theming-guide.md](https://md2link.com/d/444hpghpsvnh)** (`values/` = light, `values-night/` = dark).

---
