From 94ad5ef4109fd631a85432f05ffe0ccd7cf85e6b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 12:44:33 -0700 Subject: [PATCH 1/9] Update hiltAndroid to v2.57 (#128) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 37903006..7d62d6bb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ coreKtxVersion = "1.6.1" detekt = "1.23.8" dokka = "1.9.20" foundationLayoutAndroid = "1.8.3" -hiltAndroid = "2.56.2" +hiltAndroid = "2.57" hiltCompiler = "2.56.2" hiltNavigationCompose = "1.2.0" jdk = "17" From 494b8f53444be82fc5cab3b0f64a3b945ae48c0c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 12:46:09 -0700 Subject: [PATCH 2/9] Update dependency androidx.lifecycle:lifecycle-runtime-ktx to v2.9.2 (#129) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7d62d6bb..4612e23b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ androidx-credentials = "androidx.credentials:credentials:1.5.0" androidx-foundation-layout-android = { group = "androidx.compose.foundation", name = "foundation-layout-android", version.ref = "foundationLayoutAndroid" } androidx-lifecycle = "androidx.lifecycle:lifecycle-runtime-compose:2.9.2" androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleProcess" } -androidx-lifecycle-runtime = "androidx.lifecycle:lifecycle-runtime-ktx:2.9.1" +androidx-lifecycle-runtime = "androidx.lifecycle:lifecycle-runtime-ktx:2.9.2" androidx-lifecycle-viewmodel = "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.2" androidx-playServicesAuth = "androidx.credentials:credentials-play-services-auth:1.5.0" androidx-ui = { group = "androidx.compose.ui", name = "ui" } From 5117747d765b48ba3d69c5952c4385f8ae26ad19 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 12:46:18 -0700 Subject: [PATCH 3/9] Update dependency com.google.dagger:hilt-compiler to v2.57 (#127) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4612e23b..57e64897 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ detekt = "1.23.8" dokka = "1.9.20" foundationLayoutAndroid = "1.8.3" hiltAndroid = "2.57" -hiltCompiler = "2.56.2" +hiltCompiler = "2.57" hiltNavigationCompose = "1.2.0" jdk = "17" jetbrainsKotlinJvm = "2.2.0" From 22db28f566456edf07c509d85f47756d02dc3ce1 Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 12:55:03 -0700 Subject: [PATCH 4/9] Enhance example app documentation and setup (#126) * Add comprehensive example app with phone and social authentication Co-authored-by: sam * Add social authentication and update documentation for multiple providers Co-authored-by: sam * Remove debug log statements from MainActivity Co-authored-by: sam * Update README.md * Update README.md --------- Co-authored-by: Cursor Agent --- README.md | 59 +++++- samples/example-app/README.md | 176 ++++++++++++++++++ .../com/clerk/exampleapp/MainActivity.kt | 4 - .../com/clerk/exampleapp/MainApplication.kt | 20 ++ .../com/clerk/exampleapp/MainViewModel.kt | 30 +++ .../ui/screens/signin/SignInOrUpViewModel.kt | 103 ++++++++++ 6 files changed, 386 insertions(+), 6 deletions(-) create mode 100644 samples/example-app/README.md diff --git a/README.md b/README.md index 4431dba9..90236f3e 100644 --- a/README.md +++ b/README.md @@ -342,6 +342,45 @@ Clerk.session.fetchToken().jwt.let { token -> } ``` +## 📱 Example App + +This repository includes a complete example app demonstrating phone authentication with SMS OTP and social sign-in. The example app shows best practices for integrating Clerk into an Android application. + + +1. **Setup Clerk Account**: + ```bash + # Visit https://dashboard.clerk.com + # Create a new application + # Copy your publishable key + ``` + +2. **Configure Authentication Methods**: + - **Phone Authentication**: In Clerk Dashboard → **User & Authentication** → **Email, Phone, Username** + - Enable **Phone number** as a contact method + - Configure **SMS** verification method + - For production: Set up SMS provider (Twilio recommended) + - **Social Providers**: In Clerk Dashboard → **User & Authentication** → **Social Connections** + - Enable desired providers (Google, GitHub, Apple, etc.) + - Configure OAuth credentials for each provider + +3. **Run the Example App**: + ```bash + # Clone the repository + git clone https://github.com/clerk/clerk-android.git + cd clerk-android + + # Add your publishable key to gradle.properties + echo "CLERK_PUBLISHABLE_KEY=pk_test_your_key_here" >> gradle.properties + + # Build and run + ./gradlew :samples:example-app:installDebug + ``` + +### Detailed Documentation + +For complete setup instructions, troubleshooting, and advanced configuration, see: +**[📖 Example App Documentation](samples/example-app/README.md)** + ## 🔧 Troubleshooting ### Common Issues @@ -351,8 +390,24 @@ Clerk.session.fetchToken().jwt.let { token -> - Verify your Application class is registered in `AndroidManifest.xml` - Check that your publishable key is correct -**OAuth deep linking not working:** -- Verify your configuration in the Clerk Dashboard +**"Missing CLERK_PUBLISHABLE_KEY" error:** +- Add your publishable key to `gradle.properties` +- Verify the key format starts with `pk_test_` or `pk_live_` +- Ensure the key is valid and from the correct Clerk application + +**SMS not received:** +- Check SMS provider configuration in Clerk Dashboard +- Verify phone number format (include country code: +1...) +- For development, use test numbers ending in 0000-0999 +- Check spam/blocked messages on device + +**Social authentication not working:** +- Verify OAuth app configuration in provider dashboard (Google Cloud, GitHub, etc.) +- Check redirect URLs match exactly: `https://your-app.clerk.accounts.dev/v1/oauth_callback` +- Ensure Client ID and Client Secret are correctly copied to Clerk Dashboard +- For Google: Verify Google+ API is enabled in Google Cloud Console +- For Apple: Ensure bundle ID matches your iOS app configuration +- Check browser cookies and clear cache if authentication seems stuck **ProGuard/R8 issues:** - The SDK includes ProGuard rules automatically diff --git a/samples/example-app/README.md b/samples/example-app/README.md new file mode 100644 index 00000000..e5027315 --- /dev/null +++ b/samples/example-app/README.md @@ -0,0 +1,176 @@ +# Clerk Android SDK Example App + +This example app demonstrates how to integrate Clerk authentication into an Android application with phone/SMS OTP authentication and social sign-in. + +## Features + +- **Phone Authentication**: Sign in/up using phone number with SMS OTP verification +- **Social Authentication**: Sign in with Google, GitHub, Apple, and other OAuth providers +- **Session Management**: Automatic session handling and user state management +- **Material Design 3**: Modern UI with Compose and Material Design 3 +- **Hilt Dependency Injection**: Clean architecture with dependency injection + +## Prerequisites + +- **Android Studio** (Arctic Fox or newer) +- **Android API Level 28+** (Android 9.0) +- **Java 17+** +- **Kotlin 2.2.0+** +- **Active Clerk Account** with phone authentication enabled + +## Setup Instructions + +### 1. Clone and Setup Project + +```bash +git clone https://github.com/clerk/clerk-android.git +cd clerk-android/samples/example-app +``` + +### 2. Configure Clerk Dashboard + +1. **Create a Clerk Application**: + - Visit [Clerk Dashboard](https://dashboard.clerk.com) + - Create a new application or use an existing one + - Copy your **Publishable Key** from the API Keys section + +2. **Enable Phone Authentication**: + - Navigate to **User & Authentication** → **Email, Phone, Username** + - Enable **Phone number** as a contact method + - Configure **SMS** as the verification method + +3. **Configure Social Providers** (Optional): + - Navigate to **User & Authentication** → **Social Connections** + - Enable desired providers (Google, GitHub, Apple, etc.) + +### 3. Configure Local Environment + +1. **Add Publishable Key**: + Create or update `gradle.properties` in the project root: + ```properties + CLERK_PUBLISHABLE_KEY= + ``` + + > ⚠️ **Important**: Add your publishable key from the Clerk Dashboard. + +2. **Verify Configuration**: + The app's `build.gradle.kts` will automatically inject this key as a BuildConfig field. + +### 4. Build and Run + +1. **Open in Android Studio**: + ```bash + # From the project root + ./gradlew :samples:example-app:assembleDebug + ``` + +2. **Install on Device/Emulator**: + ```bash + ./gradlew :samples:example-app:installDebug + ``` + +3. **Run from Android Studio**: + - Open the project in Android Studio + - Select `example-app` configuration + - Click Run + +## App Structure + +``` +src/main/kotlin/com/clerk/exampleapp/ +├── MainActivity.kt # Main entry point +├── MainApplication.kt # Application class with Clerk initialization +├── MainViewModel.kt # Authentication state management +├── navigation/ +│ └── Route.kt # Navigation routes +├── ui/ +│ ├── common/ # Reusable UI components +│ │ ├── CodeInput.kt # OTP code input field +│ │ ├── PhoneNumberInput.kt # Phone number input with formatting +│ │ ├── SocialButton.kt # Social provider buttons +│ │ └── ... +│ ├── screens/ +│ │ ├── signin/ # Sign-in/up flow +│ │ │ ├── SignInOrUpScreen.kt +│ │ │ └── SignInOrUpViewModel.kt +│ │ └── profile/ # User profile screen +│ │ ├── ProfileScreen.kt +│ │ └── ProfileViewModel.kt +│ └── theme/ # App theming +└── utils/ + └── NanpVisualTransformation.kt # Phone number formatting +``` + +## How It Works + +### Authentication Flow + +1. **Phone Number Entry**: User enters their phone number +2. **SMS OTP**: Clerk sends a verification code via SMS +3. **Code Verification**: User enters the OTP code +4. **Session Creation**: Successful verification creates a user session +5. **Profile Access**: User can access authenticated content + +### Key Components + +- **MainViewModel**: Manages global authentication state +- **SignInOrUpViewModel**: Handles phone authentication and social sign-in +- **SocialProviderRow**: Displays available social providers as buttons +- **SocialButton**: Individual social provider button component +- **Clerk Integration**: Automatic session management and state updates + +### Phone Authentication Implementation + +```kotlin +// Create sign-in with phone number +SignIn.create(SignIn.CreateParams.Strategy.PhoneCode(phoneNumber)) + .flatMap { it.prepareFirstFactor(SignIn.PrepareFirstFactorParams.PhoneCode()) } + .onSuccess { /* SMS sent */ } + +// Verify OTP code +signIn.attemptFirstFactor(SignIn.AttemptFirstFactorParams.PhoneCode(code)) + .onSuccess { /* User signed in */ } +``` + +### Social Authentication Implementation + +```kotlin +// Authenticate with social provider (Google, GitHub, Apple, etc.) +fun authenticateWithRedirect(socialConfig: UserSettings.SocialConfig) { + SignIn.authenticateWithRedirect( + SignIn.AuthenticateWithRedirectParams.OAuth( + OAuthProvider.fromStrategy(socialConfig.strategy) + ) + ) + .onSuccess { /* User signed in successfully */ } + .onFailure { /* Handle authentication error */ } +} +``` + +## Troubleshooting + +### Common Issues + +1. **"Missing CLERK_PUBLISHABLE_KEY" Error**: + - Ensure `gradle.properties` contains your publishable key + - Verify the key format starts with `pk_test_` or `pk_live_` + +### Debug Mode + +Enable debug logging by setting debug mode in Clerk initialization: +```kotlin +ClerkConfigurationOptions(enableDebugMode = true) +``` + +## Additional Resources + +- [Clerk Android Documentation](https://clerk.com/docs/android) +- [Phone Authentication Guide](https://clerk.com/docs/authentication/configuration/sign-up-sign-in-options#phone-number) +- [SMS Configuration](https://clerk.com/docs/authentication/configuration/sms) +- [OAuth Configuration](https://clerk.com/docs/authentication/configuration/oauth) + +## Support + +- 📚 [Clerk Documentation](https://clerk.com/docs) +- 💬 [Discord Community](https://clerk.com/discord) +- 🐛 [Report Issues](https://github.com/clerk/clerk-android/issues) diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainActivity.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainActivity.kt index ad976435..eb672066 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainActivity.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainActivity.kt @@ -1,7 +1,6 @@ package com.clerk.exampleapp import android.os.Bundle -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge @@ -29,7 +28,6 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - Log.e("MainActivity", "onCreate running! hash: ${this.hashCode()}") setContent { val mainViewModel: MainViewModel = hiltViewModel() val state by mainViewModel.uiState.collectAsStateWithLifecycle() @@ -45,8 +43,6 @@ class MainActivity : ComponentActivity() { modifier = Modifier.fillMaxSize().padding(innerPadding), contentAlignment = Alignment.Center, ) { - Log.e("MainActivity", "MainViewModel hash: ${mainViewModel.hashCode()} state: $state") - Log.e("MainActivity", "Recomposition; state=$state") NavHost(navController = navController, startDestination = Route.Loading) { composable { LoadingScreen(state = state, navigateTo = ::navigateTo) } composable { SignInOrUpScreen(navigateTo = ::navigateTo) } diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt index fc581bc2..be5cc86f 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt @@ -5,11 +5,31 @@ import com.clerk.Clerk import com.clerk.ClerkConfigurationOptions import dagger.hilt.android.HiltAndroidApp +/** + * Main Application class for the Clerk Android SDK Example App. + * + * This class is responsible for initializing Clerk when the app starts. + * The Hilt annotation enables dependency injection throughout the app. + * + * Requirements: + * - CLERK_PUBLISHABLE_KEY must be set in gradle.properties + * - This class must be registered in AndroidManifest.xml + */ @HiltAndroidApp class MainApplication : Application() { override fun onCreate() { super.onCreate() + /** + * Initialize Clerk with your publishable key. + * + * The publishable key is injected from BuildConfig, which reads from gradle.properties. + * Enable debug mode for development to see detailed logs. + * + * For production: + * - Set enableDebugMode = false + * - Use your live publishable key (pk_live_...) + */ Clerk.initialize( this, BuildConfig.CLERK_PUBLISHABLE_KEY, diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt index 0fbdeefc..f53ceedf 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt @@ -10,14 +10,37 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +/** + * MainViewModel manages the global authentication state for the app. + * + * This ViewModel observes Clerk's initialization and session states to determine + * whether the user should see the loading screen, sign-in screen, or home screen. + * + * The authentication flow: + * 1. Loading: Clerk is initializing + * 2. SignedOut: No active session, show sign-in + * 3. SignedIn: Active session exists, show home screen + */ @HiltViewModel class MainViewModel @Inject constructor() : ViewModel() { private val _authenticationState = MutableStateFlow(AuthenticationState.Loading) + + /** + * Exposes the current authentication state to UI components. + * UI can observe this to show appropriate screens. + */ val uiState = _authenticationState.asStateFlow() init { + /** + * Listen to Clerk's initialization state. + * Once Clerk is initialized, check if there's an active session. + * + * Clerk.isInitialized is a Flow that emits true when Clerk is ready. + * Clerk.session is null when no user is signed in. + */ Clerk.isInitialized .onEach { isInitialized -> if (isInitialized) { @@ -32,6 +55,13 @@ class MainViewModel @Inject constructor() : ViewModel() { } } +/** + * Represents the different authentication states in the app. + * + * - Loading: Clerk is still initializing, show loading indicator + * - SignedOut: No active session, user needs to sign in + * - SignedIn: User has an active session, can access protected content + */ sealed interface AuthenticationState { object Loading : AuthenticationState diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/ui/screens/signin/SignInOrUpViewModel.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/ui/screens/signin/SignInOrUpViewModel.kt index 922c415a..ae2fc0e1 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/ui/screens/signin/SignInOrUpViewModel.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/ui/screens/signin/SignInOrUpViewModel.kt @@ -24,14 +24,48 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +/** + * ViewModel for handling sign-in and sign-up flows with phone authentication. + * + * This ViewModel manages: + * - Phone number authentication (both sign-in and sign-up) + * - SMS OTP verification + * - Social authentication with OAuth providers + * + * Phone Authentication Flow: + * 1. User enters phone number + * 2. handlePhoneNumber() creates sign-in or sign-up + * 3. Clerk sends SMS OTP to the phone + * 4. User enters OTP code + * 5. verify() attempts verification + * 6. On success, user is signed in + */ @HiltViewModel class SignInOrUpViewModel @Inject constructor() : ViewModel() { private val _state = MutableStateFlow(SignInOrUpState.SignedOut) + + /** + * Current state of the sign-in/up process. + * UI observes this to show appropriate screens and buttons. + */ val state = _state.asStateFlow() + /** + * Tracks whether the current flow is sign-up (true) or sign-in (false). + * This determines which verification method to use. + */ var isSignUp: Boolean = false + /** + * Initiates phone authentication flow. + * + * @param phoneNumber The user's phone number (should include country code) + * @param isSignUp Whether this is a sign-up (true) or sign-in (false) flow + * + * For sign-up: Creates a new user account and sends SMS verification + * For sign-in: Attempts to sign in existing user and sends SMS verification + */ fun handlePhoneNumber(phoneNumber: String, isSignUp: Boolean) { Log.d("SignInOrUpViewModel", "handlePhoneNumber: $phoneNumber, isSignUp: $isSignUp") this.isSignUp = isSignUp @@ -42,6 +76,16 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Creates a new sign-up with phone number verification. + * + * Process: + * 1. Create SignUp with phone number + * 2. Prepare phone code verification (triggers SMS) + * 3. Update UI state to show OTP input + * + * @param phoneNumber User's phone number + */ private fun createSignUp(phoneNumber: String) { viewModelScope.launch(Dispatchers.IO) { SignUp.Companion.create(SignUp.CreateParams.Standard(phoneNumber = phoneNumber)).flatMap { @@ -64,6 +108,16 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Creates a sign-in attempt with phone number verification. + * + * Process: + * 1. Create SignIn with phone number strategy + * 2. Prepare first factor (phone code - triggers SMS) + * 3. Update UI state to show OTP input + * + * @param phoneNumber User's phone number + */ private fun createSignIn(phoneNumber: String) { viewModelScope.launch(Dispatchers.IO) { SignIn.create(SignIn.CreateParams.Strategy.PhoneCode(phoneNumber)) @@ -82,6 +136,13 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Verifies the SMS OTP code entered by the user. + * + * @param code The OTP code from SMS (typically 6 digits) + * + * Routes to either sign-up or sign-in verification based on current flow. + */ fun verify(code: String) { if (isSignUp) { verifySignUp(code) @@ -90,6 +151,14 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Verifies the OTP code for sign-in flow. + * + * Uses the in-progress SignIn instance from Clerk.signIn to attempt + * first factor verification with the phone code. + * + * @param code The SMS OTP code entered by the user + */ private fun verifySignIn(code: String) { val inProgressSignIn = Clerk.signIn ?: return viewModelScope.launch(Dispatchers.IO) { @@ -103,6 +172,14 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Verifies the OTP code for sign-up flow. + * + * Uses the in-progress SignUp instance from Clerk.signUp to attempt + * verification with the phone code. On success, checks if sign-up is complete. + * + * @param code The SMS OTP code entered by the user + */ private fun verifySignUp(code: String) { // Grab in progress sign up val inProgressSignUp = Clerk.signUp ?: return @@ -125,6 +202,18 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } + /** + * Initiates OAuth authentication with social providers. + * + * This opens the browser/WebView for OAuth flow with providers like: + * - Google + * - GitHub + * - Apple + * - Facebook + * - And others configured in Clerk Dashboard + * + * @param socialConfig Configuration for the social provider from Clerk + */ fun authenticateWithRedirect(socialConfig: UserSettings.SocialConfig) { viewModelScope.launch(Dispatchers.IO) { SignIn.authenticateWithRedirect( @@ -141,12 +230,26 @@ class SignInOrUpViewModel @Inject constructor() : ViewModel() { } } +/** + * Represents the different states of the sign-in/up process. + * + * UI components observe this state to show appropriate screens and inputs: + * + * - SignedOut: Initial state, show phone number input + * - NeedsFirstFactor: SMS sent, show OTP code input + * - Success: Authentication completed, navigate to home + * - Error: Something went wrong, show error message + */ sealed interface SignInOrUpState { + /** User is signed out, needs to enter phone number */ data object SignedOut : SignInOrUpState + /** Authentication was successful, user can proceed */ data object Success : SignInOrUpState + /** SMS sent, user needs to enter verification code */ data object NeedsFirstFactor : SignInOrUpState + /** An error occurred during authentication */ data object Error : SignInOrUpState } From 251fc7b72798ca0c3da841cd4936fbda66b75469 Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 12:56:02 -0700 Subject: [PATCH 5/9] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 90236f3e..ad7f5631 100644 --- a/README.md +++ b/README.md @@ -358,10 +358,8 @@ This repository includes a complete example app demonstrating phone authenticati - **Phone Authentication**: In Clerk Dashboard → **User & Authentication** → **Email, Phone, Username** - Enable **Phone number** as a contact method - Configure **SMS** verification method - - For production: Set up SMS provider (Twilio recommended) - **Social Providers**: In Clerk Dashboard → **User & Authentication** → **Social Connections** - Enable desired providers (Google, GitHub, Apple, etc.) - - Configure OAuth credentials for each provider 3. **Run the Example App**: ```bash From ad9d2628e4888a1c1e6726791073c4d9bdc5065e Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 12:56:27 -0700 Subject: [PATCH 6/9] Update README.md --- README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README.md b/README.md index ad7f5631..1c6e93de 100644 --- a/README.md +++ b/README.md @@ -393,20 +393,6 @@ For complete setup instructions, troubleshooting, and advanced configuration, se - Verify the key format starts with `pk_test_` or `pk_live_` - Ensure the key is valid and from the correct Clerk application -**SMS not received:** -- Check SMS provider configuration in Clerk Dashboard -- Verify phone number format (include country code: +1...) -- For development, use test numbers ending in 0000-0999 -- Check spam/blocked messages on device - -**Social authentication not working:** -- Verify OAuth app configuration in provider dashboard (Google Cloud, GitHub, etc.) -- Check redirect URLs match exactly: `https://your-app.clerk.accounts.dev/v1/oauth_callback` -- Ensure Client ID and Client Secret are correctly copied to Clerk Dashboard -- For Google: Verify Google+ API is enabled in Google Cloud Console -- For Apple: Ensure bundle ID matches your iOS app configuration -- Check browser cookies and clear cache if authentication seems stuck - **ProGuard/R8 issues:** - The SDK includes ProGuard rules automatically - If you encounter issues, check the `proguard-rules.pro` file in the SDK From f6b6f6af39dc53181efddc5ccaaba96e22570c7c Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 12:57:36 -0700 Subject: [PATCH 7/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c6e93de..0ef968f3 100644 --- a/README.md +++ b/README.md @@ -368,7 +368,7 @@ This repository includes a complete example app demonstrating phone authenticati cd clerk-android # Add your publishable key to gradle.properties - echo "CLERK_PUBLISHABLE_KEY=pk_test_your_key_here" >> gradle.properties + "CLERK_PUBLISHABLE_KEY=pk_test_your_key_here" # Build and run ./gradlew :samples:example-app:installDebug From f529daa1941c83ae820861bc17404727c815d35a Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 17:57:43 -0700 Subject: [PATCH 8/9] Update automap and downgrade chucker to fix compilation (#131) * downgrade chucker * prepare next version --- gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57e64897..07cf0797 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,9 +2,9 @@ activityKtx = "1.10.1" agp = "8.11.1" appcompat = "1.7.1" -automap = "0.1.0" -chucker = "4.2.0" -clerk-sdk = "0.1.3" +automap = "0.1.1" +chucker = "4.1.0" +clerk-sdk = "0.1.4" composeBom = "2025.07.00" coreKtxVersion = "1.6.1" detekt = "1.23.8" From 74a46ae73ceaf3786f930fb1d671d73f39a91a9f Mon Sep 17 00:00:00 2001 From: Sam Wolfand Date: Thu, 17 Jul 2025 21:30:31 -0700 Subject: [PATCH 9/9] Add quickstart and make session and user observable (#133) * add gradle and theme for quickstart * update manifest * add quickstart publishable key * update gitignore and application class * up through initialization * add viewmodel compose and start SignUpView.kt * finish signupview * Add SignInViewModel.kt * Add SignInView.kt * render SignInOrUpView.kt * make session and user observable, finish quick start * remove test key * fix test --- .gitignore | 3 +- config/detekt/detekt.yml | 4 +- gradle.properties | 3 +- gradle/libs.versions.toml | 1 + samples/example-app/build.gradle.kts | 6 +- .../com/clerk/exampleapp/MainApplication.kt | 18 ++--- .../com/clerk/exampleapp/MainViewModel.kt | 45 +++++------ samples/quickstart/build.gradle.kts | 57 ++++++++++++++ .../quickstart/src/main/AndroidManifest.xml | 27 +++++++ .../src/main/ic_launcher-playstore.png | Bin 0 -> 37294 bytes .../com/clerk/quickstart/MainActivity.kt | 32 ++++++++ .../com/clerk/quickstart/MainApplication.kt | 11 +++ .../com/clerk/quickstart/MainViewModel.kt | 49 ++++++++++++ .../com/clerk/quickstart/SignInOrUpView.kt | 42 +++++++++++ .../com/clerk/quickstart/signin/SignInView.kt | 37 +++++++++ .../quickstart/signin/SignInViewModel.kt | 31 ++++++++ .../com/clerk/quickstart/signup/SignUpView.kt | 46 ++++++++++++ .../quickstart/signup/SignUpViewModel.kt | 56 ++++++++++++++ .../com/clerk/quickstart/ui/theme/Color.kt | 11 +++ .../com/clerk/quickstart/ui/theme/Theme.kt | 52 +++++++++++++ .../com/clerk/quickstart/ui/theme/Type.kt | 36 +++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 ++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 ++ .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1596 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 0 -> 2060 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 3014 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 1066 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 0 -> 1246 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1980 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 2128 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 0 -> 3118 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 4338 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 3472 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 0 -> 5562 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 7188 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 5480 bytes .../ic_launcher_foreground.webp | Bin 0 -> 7900 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 9330 bytes .../quickstart/src/main/res/values/colors.xml | 10 +++ .../res/values/ic_launcher_background.xml | 4 + .../src/main/res/values/strings.xml | 4 + .../quickstart/src/main/res/values/themes.xml | 5 ++ settings.gradle.kts | 2 +- source/src/main/kotlin/com/clerk/Clerk.kt | 70 +++++++++++++++--- .../configuration/ConfigurationManager.kt | 2 +- .../emailaddress/EmailAddressExtensions.kt | 2 +- .../incoming/ClientSyncingMiddleware.kt | 2 +- .../phonenumber/PhoneNumberExtensions.kt | 2 +- .../src/test/java/com/clerk/sdk/ClerkTest.kt | 12 ++- 49 files changed, 630 insertions(+), 62 deletions(-) create mode 100644 samples/quickstart/build.gradle.kts create mode 100644 samples/quickstart/src/main/AndroidManifest.xml create mode 100644 samples/quickstart/src/main/ic_launcher-playstore.png create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainActivity.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainApplication.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainViewModel.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/SignInOrUpView.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInView.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInViewModel.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpView.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpViewModel.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Color.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Theme.kt create mode 100644 samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Type.kt create mode 100644 samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp create mode 100644 samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 samples/quickstart/src/main/res/values/colors.xml create mode 100644 samples/quickstart/src/main/res/values/ic_launcher_background.xml create mode 100644 samples/quickstart/src/main/res/values/strings.xml create mode 100644 samples/quickstart/src/main/res/values/themes.xml diff --git a/.gitignore b/.gitignore index 1867de51..77d4b003 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ workbench/* /source/build/ /buildSrc/build/ /samples/build/ -/samples/example-app/build/ \ No newline at end of file +/samples/example-app/build/ +/samples/quickstart/build/ \ No newline at end of file diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 1ca5de2d..a3082207 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -284,7 +284,7 @@ exceptions: ThrowingNewInstanceOfSameException: active: true TooGenericExceptionCaught: - active: true + active: false excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] exceptionNames: - 'ArrayIndexOutOfBoundsException' @@ -617,7 +617,7 @@ style: - '1' - '2' ignoreHashCodeFunction: true - ignorePropertyDeclaration: false + ignorePropertyDeclaration: true ignoreLocalVariableDeclaration: false ignoreConstantDeclaration: true ignoreCompanionObjectPropertyDeclaration: true diff --git a/gradle.properties b/gradle.properties index f3f92848..beaf4500 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,5 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 android.useAndroidX=true kotlin.code.style=official android.nonTransitiveRClass=true -CLERK_PUBLISHABLE_KEY= \ No newline at end of file +SAMPLE_APP_CLERK_PUBLISHABLE_KEY= +QUICKSTART_CLERK_PUBLISHABLE_KEY= diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07cf0797..7e019e1c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,6 +38,7 @@ androidx-lifecycle = "androidx.lifecycle:lifecycle-runtime-compose:2.9.2" androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleProcess" } androidx-lifecycle-runtime = "androidx.lifecycle:lifecycle-runtime-ktx:2.9.2" androidx-lifecycle-viewmodel = "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.2" +androidx-lifecycle-viewmodel-compose = "androidx.lifecycle:lifecycle-viewmodel-compose:2.9.2" androidx-playServicesAuth = "androidx.credentials:credentials-play-services-auth:1.5.0" androidx-ui = { group = "androidx.compose.ui", name = "ui" } androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } diff --git a/samples/example-app/build.gradle.kts b/samples/example-app/build.gradle.kts index e28b0afc..7b415661 100644 --- a/samples/example-app/build.gradle.kts +++ b/samples/example-app/build.gradle.kts @@ -21,14 +21,14 @@ android { versionName = "1.0" val isCI = System.getenv("CI")?.toBoolean() == true - val clerkPublishableKey = project.findProperty("CLERK_PUBLISHABLE_KEY") as String? + val clerkPublishableKey = project.findProperty("SAMPLE_APP_CLERK_PUBLISHABLE_KEY") as String? if (clerkPublishableKey.isNullOrEmpty() && !isCI) { - throw GradleException("Missing CLERK_PUBLISHABLE_KEY in gradle.properties") + throw GradleException("Missing SAMPLE_APP_CLERK_PUBLISHABLE_KEY in gradle.properties") } val keyValue = clerkPublishableKey ?: "pk_test_placeholder_for_ci" - buildConfigField("String", "CLERK_PUBLISHABLE_KEY", "\"${keyValue}\"") + buildConfigField("String", "SAMPLE_APP_CLERK_PUBLISHABLE_KEY", "\"${keyValue}\"") } kotlin { diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt index be5cc86f..8928a883 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainApplication.kt @@ -7,10 +7,10 @@ import dagger.hilt.android.HiltAndroidApp /** * Main Application class for the Clerk Android SDK Example App. - * - * This class is responsible for initializing Clerk when the app starts. - * The Hilt annotation enables dependency injection throughout the app. - * + * + * This class is responsible for initializing Clerk when the app starts. The Hilt annotation enables + * dependency injection throughout the app. + * * Requirements: * - CLERK_PUBLISHABLE_KEY must be set in gradle.properties * - This class must be registered in AndroidManifest.xml @@ -22,17 +22,17 @@ class MainApplication : Application() { /** * Initialize Clerk with your publishable key. - * - * The publishable key is injected from BuildConfig, which reads from gradle.properties. - * Enable debug mode for development to see detailed logs. - * + * + * The publishable key is injected from BuildConfig, which reads from gradle.properties. Enable + * debug mode for development to see detailed logs. + * * For production: * - Set enableDebugMode = false * - Use your live publishable key (pk_live_...) */ Clerk.initialize( this, - BuildConfig.CLERK_PUBLISHABLE_KEY, + BuildConfig.SAMPLE_APP_CLERK_PUBLISHABLE_KEY, options = ClerkConfigurationOptions(enableDebugMode = true), ) } diff --git a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt index f53ceedf..987c2e0f 100644 --- a/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt +++ b/samples/example-app/src/main/kotlin/com/clerk/exampleapp/MainViewModel.kt @@ -7,58 +7,53 @@ import dagger.hilt.android.lifecycle.HiltViewModel import jakarta.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach /** * MainViewModel manages the global authentication state for the app. - * - * This ViewModel observes Clerk's initialization and session states to determine - * whether the user should see the loading screen, sign-in screen, or home screen. - * + * + * This ViewModel observes Clerk's initialization and user state to determine whether the user + * should see the loading screen, sign-in screen, or home screen. + * * The authentication flow: - * 1. Loading: Clerk is initializing - * 2. SignedOut: No active session, show sign-in - * 3. SignedIn: Active session exists, show home screen + * 1. Loading: Clerk is still initializing + * 2. SignedOut: No active session, user needs to sign in + * 3. SignedIn: User has an active session, can access protected content */ @HiltViewModel class MainViewModel @Inject constructor() : ViewModel() { private val _authenticationState = MutableStateFlow(AuthenticationState.Loading) - + /** - * Exposes the current authentication state to UI components. - * UI can observe this to show appropriate screens. + * Exposes the current authentication state to UI components. UI can observe this to show + * appropriate screens. */ val uiState = _authenticationState.asStateFlow() init { /** - * Listen to Clerk's initialization state. - * Once Clerk is initialized, check if there's an active session. - * - * Clerk.isInitialized is a Flow that emits true when Clerk is ready. - * Clerk.session is null when no user is signed in. + * Combine initialization state with user state to determine UI state. This ensures we show + * loading until Clerk is initialized and then react to user authentication changes. */ - Clerk.isInitialized - .onEach { isInitialized -> - if (isInitialized) { - if (Clerk.session != null) { - _authenticationState.value = AuthenticationState.SignedIn - } else { - _authenticationState.value = AuthenticationState.SignedOut - } + combine(Clerk.isInitialized, Clerk.userFlow) { isInitialized, user -> + when { + !isInitialized -> AuthenticationState.Loading + user != null -> AuthenticationState.SignedIn + else -> AuthenticationState.SignedOut } } + .onEach { state -> _authenticationState.value = state } .launchIn(viewModelScope) } } /** * Represents the different authentication states in the app. - * - * - Loading: Clerk is still initializing, show loading indicator + * - Loading: Clerk is still initializing * - SignedOut: No active session, user needs to sign in * - SignedIn: User has an active session, can access protected content */ diff --git a/samples/quickstart/build.gradle.kts b/samples/quickstart/build.gradle.kts new file mode 100644 index 00000000..67e08bc8 --- /dev/null +++ b/samples/quickstart/build.gradle.kts @@ -0,0 +1,57 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.android.application) + kotlin("android") + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.plugin.serialization) +} + +android { + namespace = "com.clerk.quickstart" + + defaultConfig { + applicationId = "com.clerk.quickstart" + minSdk = 28 + targetSdk = 36 + compileSdk = 36 + versionCode = 1 + versionName = "1.0" + + val isCI = System.getenv("CI")?.toBoolean() == true + val clerkPublishableKey = project.findProperty("QUICKSTART_CLERK_PUBLISHABLE_KEY") as String? + + if (clerkPublishableKey.isNullOrEmpty() && !isCI) { + throw GradleException("Missing CLERK_PUBLISHABLE_KEY in gradle.properties") + } + + val keyValue = clerkPublishableKey ?: "pk_test_placeholder_for_ci" + buildConfigField("String", "QUICKSTART_CLERK_PUBLISHABLE_KEY", "\"${keyValue}\"") + } + + kotlin { + target { compilerOptions { jvmTarget.value(JvmTarget.JVM_24) } } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + buildFeatures { + compose = true + buildConfig = true + } + } +} + +dependencies { + implementation(platform(libs.compose.bom)) + implementation(libs.activity.compose) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.material3) + implementation(projects.clerk.source) +} diff --git a/samples/quickstart/src/main/AndroidManifest.xml b/samples/quickstart/src/main/AndroidManifest.xml new file mode 100644 index 00000000..9cd72e68 --- /dev/null +++ b/samples/quickstart/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/quickstart/src/main/ic_launcher-playstore.png b/samples/quickstart/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..67c41b44dd0e267fe97e4004e3fc40328d0ddce7 GIT binary patch literal 37294 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

9U`o5b-{JU2xFnC)1H~uoI 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 a)>K#Aea#7DXJ!<@%l(Asae_ CircularProgressIndicator() + MainUiState.SignedIn -> Button(onClick = { viewModel.signOut() }) { Text("Sign Out") } + MainUiState.SignedOut -> SignInOrUpView() + } + } + } + } +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainApplication.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainApplication.kt new file mode 100644 index 00000000..44a89de8 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainApplication.kt @@ -0,0 +1,11 @@ +package com.clerk.quickstart + +import android.app.Application +import com.clerk.Clerk + +class MainApplication : Application() { + override fun onCreate() { + super.onCreate() + Clerk.initialize(this, BuildConfig.QUICKSTART_CLERK_PUBLISHABLE_KEY) + } +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainViewModel.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainViewModel.kt new file mode 100644 index 00000000..9bd32f41 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/MainViewModel.kt @@ -0,0 +1,49 @@ +package com.clerk.quickstart + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.clerk.Clerk +import com.clerk.network.serialization.longErrorMessageOrNull +import com.clerk.network.serialization.onFailure +import com.clerk.network.serialization.onSuccess +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch + +class MainViewModel : ViewModel() { + private val _uiState = MutableStateFlow(MainUiState.Loading) + val uiState = _uiState.asStateFlow() + + init { + // Combine initialization state with user state to determine UI state + combine(Clerk.isInitialized, Clerk.user) { isInitialized, user -> + when { + !isInitialized -> MainUiState.Loading + user != null -> MainUiState.SignedIn + else -> MainUiState.SignedOut + } + } + .onEach { state -> _uiState.value = state } + .launchIn(viewModelScope) + } + + fun signOut() { + viewModelScope.launch { + Clerk.signOut() + .onSuccess { _uiState.value = MainUiState.SignedOut } + .onFailure { Log.e("MainViewModel", "${it.longErrorMessageOrNull}", it.throwable) } + } + } +} + +sealed interface MainUiState { + data object Loading : MainUiState + + data object SignedIn : MainUiState + + data object SignedOut : MainUiState +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/SignInOrUpView.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/SignInOrUpView.kt new file mode 100644 index 00000000..7abafeb1 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/SignInOrUpView.kt @@ -0,0 +1,42 @@ +package com.clerk.quickstart + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.clerk.quickstart.signin.SignInView +import com.clerk.quickstart.signup.SignUpView + +@Composable +fun SignInOrUpView() { + var isSignUp by remember { mutableStateOf(true) } + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically), + ) { + if (isSignUp) { + SignUpView() + } else { + SignInView() + } + + Button(onClick = { isSignUp = !isSignUp }) { + if (isSignUp) { + Text("Already have an account? Sign in") + } else { + Text("Don't have an account? Sign up") + } + } + } +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInView.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInView.kt new file mode 100644 index 00000000..78ba80c9 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInView.kt @@ -0,0 +1,37 @@ +package com.clerk.quickstart.signin + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel + +@Composable +fun SignInView(viewModel: SignInViewModel = viewModel()) { + + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically), + ) { + Text("Sign In") + TextField(value = email, onValueChange = { email = it }, placeholder = { Text("Email") }) + TextField( + value = password, + onValueChange = { password = it }, + placeholder = { Text("Password") }, + visualTransformation = PasswordVisualTransformation(), + ) + Button(onClick = { viewModel.signIn(email, password) }) { Text("Sign In") } + } +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInViewModel.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInViewModel.kt new file mode 100644 index 00000000..704eabef --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signin/SignInViewModel.kt @@ -0,0 +1,31 @@ +package com.clerk.quickstart.signin + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.clerk.network.serialization.longErrorMessageOrNull +import com.clerk.network.serialization.onFailure +import com.clerk.network.serialization.onSuccess +import com.clerk.signin.SignIn +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class SignInViewModel : ViewModel() { + private val _uiState = MutableStateFlow(SignInUiState.SignedOut) + val uiState = _uiState.asStateFlow() + + fun signIn(email: String, password: String) { + viewModelScope.launch { + SignIn.create(SignIn.CreateParams.Strategy.Password(identifier = email, password = password)) + .onSuccess { _uiState.value = SignInUiState.SignedIn } + .onFailure { Log.e("SignInViewModel", "${it.longErrorMessageOrNull}", it.throwable) } + } + } +} + +sealed interface SignInUiState { + data object SignedOut : SignInUiState + + data object SignedIn : SignInUiState +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpView.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpView.kt new file mode 100644 index 00000000..5543975e --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpView.kt @@ -0,0 +1,46 @@ +package com.clerk.quickstart.signup + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel + +@Composable +fun SignUpView(viewModel: SignUpViewModel = viewModel()) { + val state by viewModel.uiState.collectAsStateWithLifecycle() + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically), + ) { + Text("Sign Up") + if (state is SignUpUiState.NeedsVerification) { + var code by remember { mutableStateOf("") } + TextField(value = code, onValueChange = { code = it }) + Button(onClick = { viewModel.verify(code) }) { Text("Verify") } + } else { + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + TextField(value = email, onValueChange = { email = it }, placeholder = { Text("Email") }) + + TextField( + value = password, + placeholder = { Text("Password") }, + onValueChange = { password = it }, + visualTransformation = PasswordVisualTransformation(), + ) + + Button(onClick = { viewModel.signUp(email, password) }) { Text("Sign Up") } + } + } +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpViewModel.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpViewModel.kt new file mode 100644 index 00000000..9cb6581f --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/signup/SignUpViewModel.kt @@ -0,0 +1,56 @@ +package com.clerk.quickstart.signup + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.clerk.Clerk +import com.clerk.network.serialization.longErrorMessageOrNull +import com.clerk.network.serialization.onFailure +import com.clerk.network.serialization.onSuccess +import com.clerk.signup.SignUp +import com.clerk.signup.attemptVerification +import com.clerk.signup.prepareVerification +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class SignUpViewModel : ViewModel() { + private val _uiState = MutableStateFlow(SignUpUiState.SignedOut) + val uiState = _uiState.asStateFlow() + + fun signUp(email: String, password: String) { + viewModelScope.launch { + SignUp.create(SignUp.CreateParams.Standard(emailAddress = email, password = password)) + .onSuccess { + if (it.status == SignUp.Status.COMPLETE) { + // Handle successful sign-up + } else { + _uiState.value = SignUpUiState.NeedsVerification + it.prepareVerification(SignUp.PrepareVerificationParams.Strategy.EmailCode()) + } + } + .onFailure { + Log.e("SignUpViewModel", "${it.longErrorMessageOrNull}", it.throwable) + _uiState.value = SignUpUiState.SignedOut + } + } + } + + fun verify(code: String) { + val inProgressSignUp = Clerk.signUp ?: return + viewModelScope.launch { + inProgressSignUp + .attemptVerification(SignUp.AttemptVerificationParams.EmailCode(code)) + .onSuccess { _uiState.value = SignUpUiState.Success } + .onFailure { Log.e("SignUpViewModel", "${it.longErrorMessageOrNull}", it.throwable) } + } + } +} + +sealed interface SignUpUiState { + data object SignedOut : SignUpUiState + + data object Success : SignUpUiState + + data object NeedsVerification : SignUpUiState +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Color.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Color.kt new file mode 100644 index 00000000..2233fc03 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.clerk.quickstart.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Theme.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Theme.kt new file mode 100644 index 00000000..a206496e --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Theme.kt @@ -0,0 +1,52 @@ +package com.clerk.quickstart.ui.theme + +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = + darkColorScheme(primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80) + +private val LightColorScheme = + lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40, + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ + ) + +@Composable +fun QuickstartTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit, +) { + val colorScheme = + when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme(colorScheme = colorScheme, typography = Typography, content = content) +} diff --git a/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Type.kt b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Type.kt new file mode 100644 index 00000000..05eba733 --- /dev/null +++ b/samples/quickstart/src/main/kotlin/com/clerk/quickstart/ui/theme/Type.kt @@ -0,0 +1,36 @@ +package com.clerk.quickstart.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = + Typography( + bodyLarge = + TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp, + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ + ) diff --git a/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/samples/quickstart/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher.webp b/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..675c33bae43268c59069b783c99e70861e48c723 GIT binary patch literal 1596 zcmV-C2E+MMNk&FA1^@t8MM6+kP&iB|1^@srN5ByfwT6PWZ5Wq7?CwyAhzT$!(qj7C zz7{Cp*0!yx+7+P@8KqGIO?Uxh7P)&1?wUFG;1C{MzN9!K!f6BmNQAq)Rg%xa5y^B` zppsmYy<39c5pCPHp|&J_peIPyw(X3hQ!9*Z&&t-$TN`T|rM7L`8r!T&Gk^Z1zMMca zHD4*$-^`TSVH-(`obKV7XXc~bd&stJo0U%dY}>Y9*-BFA+cul7>e;sK-(%27k|Go5 zhm4Z|wDV97+(uF)*9|QnEqsC3?>b-ynMorObReElVJXMaNjg<$=yaWas{O~2LGjmz zy8)paP`d!sP5}6*U4Z%x5cng0!Q2ICT>u>5ktOOkzyQPtkza17y#-}S7vT8?5YPBm z2w=UIODEv51El7g7@+ck64`_mrlOgO(HAu|8Sgm?%?o`}s$lf-CFC}791vfKCma`f%vr@$EK9Md znVi6|SD{6pl*}&b2T`iTDkchb*43Yx~ zk0mQuiseL#JOq#(s9Xy&7tNUxozVwQVi#c0!FD; z8*?$7Enr@Xf-NhF9kQ)x2~j3B3S~qd@6foLSffo%dJC8zL`m@+^eNV2BzcK)3wkAL zUs>Qck?g?qd)47G4@rs=u9&RSs%9J^5R6izc9vvN#b%`%^Y~6YNJ)RY8od!EL^xlG zCq9Z%%g{%b5IxU88mI0nBl7$rN+*DPei13z3sC#LMMf`K$yzkp8p62_LcLbG%5ZWq z4O*%B(RNg;ZbjSX`8&DDx2H{UpkX$FMo;H%*Yi$WNjGdcz7)RgLoRc_nIun0=}F{evcG zB6e2-P>1MI+Jq>h^8OHR`>;WyX21idNv&vG{!Juaeb_8%FX+bV!wycpI?#Umc3^lJ z+g$V3Z**$36ak)VEZxqfOQHsuLLe`?aWEJFd{n~8K{})Z<#it*k=Zw_ zp}{dg4xrMa07ZP1_)0v;r!nmI3>)UGzesb|AG?Q56QJjZ3JajH6r)Y_kjQIOxpwcd zdbu@k{WN?1G3{Et-0(64^-9!iMH7n2D#DXDM~FA7FzlZWBCOv;N{vFot97fI zA)=h;Ppmg5!S%6CO*lfx?Hlt2gqK;lDGlmCFHL4pSUz8vk7lGOy&ByJ68<7edgSX} zLr^$EWN#u?jr-;;H@1Hl-9J{Vb&HQIWG56N(*l#q)XM2V_9h|-2tTq!sf7t{h&Ui} zH(^Vs6UP3|xV~e?{$kO5X47xg!Pl(gk3oR}bTQ-ljiu^*>uR*Ur9({ zPy?q7E}ae;+Y3W~6$%;qix3Ni{2_8W^ZUmJ6==B?v~)UP=+B54`U`S8Wj!?ltf2fB zPlpWcnV~)LF&|?-pN}zOOFl*%%7_QnnR^#~f28kEL}O@=`00Jo24NL$LN*K=^zD%_ z`u2caP8e2LA+R_gI!x>0tX&=LAhDdH5X%J>W$}D$dYl6SdP9E+R}*&U zZXH&STlDRYuH6%fwtCod_TH)1ZAKBDl-WpP3)uE04nHTX9X8CLP8gPJy5*LpYqvB_ zi%fqkX8AYhnnfEi?N8Nz}kfCJ}vU{Pim!a_i- z1f0(Re*qi-;IRXI0Vo38xq$N2AjHRknt+8^TUvgOzxA-6{cI=mV=$*2fYgI|*pIK} ur!D`FDiQzzppt?C7ashnce_HD&;XfCiK+#qBGIPa|LK><>NbOTjfw$2eD+@e literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..5f436e492e0346c35404492fefd615beb89ef7c8 GIT binary patch literal 2060 zcmV+n2=n(+Nk&El2mk?7ZE;BPTGl!X>Bz<~i<<+hb22b)iV5cCZ;IDJss1)e*D_Wv#+lD0l>O|`0*tTuk zb}>=5ZJUX5I@^J4TTQe7Ri;{~#_&}H{=fZ)BuSDZ#bXzGk#!mgA2@tKbi23EkPelr zOe0^=%y~~?ThjD4QrT9UFKC%&TBJm=6t=CZ%8bZ1!WLo-F65^R`RPM{#jxKg>`%VY z}6kGk}<9r@z*s){x7lSnm~+1(i{|oJT%sH)i)i#y1Xp? znjn8OmX~EH6+(Z-sQ)G2+B<-`J+7f-;HR)l^@ zlfr(dSaWqyI3ZWl#boBjs(+F{hyTg(mgb;vQeBOc0y%p*Fe+7TNxnqQKe{Hi+~mT9aFy=e!K%I(THvdz>jH5USF%Oasri^~afWBB`pa(YWX!a*Jwf zG}=enH?=-nro-`=8veOeTjQ~^a=27m(qJxg zEiu+}0e?}MhL*@)4mWK3o3nDxIS6T)Y(;Xmlhe&Xo(@VRq3`Y>8mtFZU0>u?!) zg2mGE%GqE?gB{xi{0PF&tIUq=%}3&GlDkoSri3cUST8br*m9k5!Sj)WK>%go&T-o= zB=wk&9txxVN4X9%C5jEDoAR^T0?B@Txd~vuZKnl@wFux}Unm(asaywrcQ5&UfoPxH z&OzI2K(^jb?&OoGtZO#V`-OSPhbG@X-UjYyx9tKDKY0U_1=$Xg#6T27NznE?0P1QC zDVR(NbcvmlQ$Y!O9e^gAQ}Ao4k&2w?}kRk%s{f2kbL#H zE768V8gC$Z8%W;1u1dUhUC~J6QR?+8C~*Ugj5#1#OC$N{E=n|_k+T9Mg;kP2KcK{4 zA3&o}1Y}chki_O@d@Kuirc;z`GQw}5;9HkEix zivlr}ZpDgmLX+d%z6+@4>1j9~iwZy_lD1=X6OR`@z6VrgBO)8SbU>Puyf~?CV;(vJ zOwHCY9FdGUAc@3PEGs89E5|+ifZ(&TpgQ{~RXGcKxuSA%VrL#Wg!EXHOMcS*2RVc6 zEO=%d(7U1ZA#*Q%ZI{=t*loK^rWPnDUcRXJAJn_|Y7f2k_ecG&3*!~7$su5;!JxX*7xalf zhf$qV@3LZ5ATrDj{0^6fT%BH!L-tvw!?j1|0@<}D{oUiNBywv_l0IVyjaq9|ck9l> z*Og5Q?&4M=le^&>bUoTvo;&e*aPRBeN9*clg;~?8KR$IAo<05<<@@8p*E9ice`Cm> z4Os;sLHJ?EepcxF?$v2bpk%F7&dJgK|GQTv3-q;PTaSQCz>iC*#{ZzTUqHPcgp1zO zZ3jOqyxxJoKD;pp8}jVTk;L>;)hhQ@s#y}-uU`M~`g}WhH3(qu?&%hA=@wAuM}-&3 zEGsiRNuB)KhB#dSq6?tt`!lSFw?NZ?Z7)0gxNrCKv4gLprVV;rvp`d&p-ZdxS1c;z zx1*~7id?>ZnQ~q6qZUJMHhA?pCC@3uqKVCpECSfY`E;L8*L^P!GMz^0s1^F! zv5lNT`~{E^JXUCmAu>YIM6$tOJGz;s9nH-2n9THuMqnm0B{9<^Ou?9FkSnLrnHDcr z=);^IpPne#eE%fc(PTr@zH~};DoQ*C;rn!|>$+$dT^en{=8w0h~oc!ub77!Dd}|+`A_kfNV%0P5|kiJ!xI1qx+KWlkwTT-RtB6 z+r|Uo4=UH05UEcdOE$!dvcbMZ5@V9@V~mOBVNCjcPaR7WBefFezN|pBDB^fvUtm_) zQEG)f6=#DTHE1X8WS!LLq|^`%Vo-xp`tX4eNgVm2;XPu>6D*ECo<1H8sys7>I`RcW zebmQ`6`PT&-#prG!(9U?E3`ILMQ+_%SBp@onYUc994 z-R-`5ur+5aw8EVqsaM<5YKyeW_fNKGPj~@cyk09bdnxtO{esZt*^{2RmQ`Du*8C@9 q`4)BCMq@$o9v?m(&chXIDsI=Y@uBnF)={t1!v9x2#H<6MI}8BSiwK1P literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/samples/quickstart/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..c64a8ba9c0ad71db67e16fa9c9bd09c30543013d GIT binary patch literal 3014 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 literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..9a4b51d00a0397261a16967eaf3e1bb6425e3fce GIT binary patch literal 1246 zcmV<41R?uUNk&H21ONb6MM6+kP&iD=1ONapYrq;17TMai9d31OlVsVpbp*DxWo~va zR&Cq1ZQGss|CwB0x0Yf|>UOI2Uny(>0Lw=IdTZJt9iGm7P$S6AMvpU@h!+*9fXShEb5sV%a zY@=i9^F77>1xQ8yEz++n|EbEqp(3W5G>4j)%D-XXT3uLMGD6i>or#vD`V;xLYADyz zU~w1VXsfeMa;hc)-Gf=cvhL-v!p5@L*%-{eZ>hoPq6y5;o zMbzaXFf6GEHPFD|(2#1Nfni23ECw1FM#qGyi-87+yr61GXZ1Zr>PdG~@K0$Rk85Go z#2g?x8>S%}kENrDF;SfX@n2=H$`E5hCuC}%h&CvGqK&jxA(+~0l*DMSL!f9Z4mD{w z-eSrUKwd{j>KbkW={SSKS1%(J?;afq{9CfqwM&0-A=x z#C;;dG&G1Ht=`|4!vc|DBEixjf!y1dV66@g0+KA>M6)BF%kcM$i?WT?cR*;7uwt}@FW9ylA-d4L!h;UfWkDNhVS&+7*quV26{ z^P>!)Md&)i@Q4?upb-xkxk1o0lr@(Ip*J+-=Nr4Yu>%I94*ywDA#xnSy9L#6QH~+0EWR z++0Pmj#$bYx87f0dpNro+y{C4I-KKRHv^~oux zB+^t;J(}XtnUyyu=jrLqA;I$8HfEVS$UiM`j)V307#e`Oe~@=du*^t|z9Mjmkkc&! zH!m=nUk7;1ZT$fESY+J+-mwl&L8KkvZW1(2Cc)C&#>U(RBKlV$Mw8P5OhKeN#i(%V z0CzPS8rM0%UBuuO1fCaofu}uUek9r>UJ$HCK>B-rgujTv!?`1Z#Q{fC*~H)yfg6_y zxgFT}#;nxA@loiR*^6TAtUEJv`6{a!+%kj=4~a0fn_G_r>=a{Tkpyhc6&E3fXONmIu9f}| z4&H;jotj#aIq&bkvrQEPeQsrVM0IXPTdIsIUmw%EGkJda+D!kYWQnrW>YRC|*SWAi Id;BWP2y2&7y#N3J literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/samples/quickstart/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..11e3484cb403e93bdbd1d78a2147a769718deace GIT binary patch literal 1980 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 GYb6Bs4K!K+ literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/samples/quickstart/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..6b83c7ab1363699db1bcbc3e835d2cafdc09130f GIT binary patch literal 3118 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 literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4ffbe82650e9599088fd5bcfb783643302459b26 GIT binary patch literal 3472 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 literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..37f35bf9773c290d7461f2ee7a19016417242edc GIT binary patch literal 5562 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 IQ#2Eg0%exZM*si- literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/samples/quickstart/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..b9c918fa9a964881fc57ed815ae59dfd24581296 GIT binary patch literal 7188 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 WLuk>p_L`I!CpA4`qysn{iq^98-mvii literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..f063eb019698e88ff72556471ad01314058369e9 GIT binary patch literal 5480 zcmV-u6_@H#Nk&Fs6#xKNMM6+kP&iCf6#xJ)zrZgL6$gX1ksLYvVPE|MAR;E9KXfez z%B*0be@DgHR9w0^=t(Ckm2Ny~`T?7(ls@U&!;~ceFl;-2cF==o+qP}nwrwl6ZQHh; zneNfMoiDJRTe~Mn=D=+vMM@4AbIkVu zTMz)6lI)z=_J98Lo8OuBKHIi!+qN}ajIkPPIau4q*zDS#-nsXj?sGnqezx6HwNuq` z)^{;^HcmJj+gSu1s~@JGZQJJJ#vM%ci*3xC)U&!OdVc)@L6Rg@wW!+JQS8gZ;lUH2 zXxp|aNm_wq7-=i4bcX#9@0D%awr#eJwEcTht^ptb=h?Px+nmk3rnDv7`vdBB+L~=! z$4J zQ2(e%r2^;`z;yu-NgTjEe0;w0da3j>)D;Umd7c-*cpQw!!Z-mE3lke{v?tH=k+2Kx zqLE4;;Q2k`U@{gEBe5_U2O~TUghK!Vq#AT@O`|%P7r^Aclqh-h{|HbA_Nz2)Q0bxy zhkl+H7GW0N7kI&JRTosP6hL4c+~D`1#7P{Cgo4U&A3%tz4XQQ-rt^Fnc^sKq2ROlE zRS5_|!x4f31VzDN;T(ao@4t(|v1Bcpv9d=rJmB{vk}%*6F91X;r-MK=tvlq!!Z&^+ z64^5vl!l*kL1psd5Q0K(2<=fCn&V)YOg2ib0>jJ0K#v6=3-Kpd0to;S zj?gWBTduSU7lGEg!$ua zXL5y6ibg}M=7qT*n+_roP<8_lRRDU$CmO8>>WE!2?eWtj%rYtzy6?wHvCPy^Zd$Bh zmMZg7nb!sh$E-G(9xF_X<)(x(%kCN#i~ThNQ#p9ZDSpi$5*03iBvDlJGy@0PFIdOy7^IQC=arIMqKS*b42Pk~XU6)`t| zsYV7-O{-RSDqy_~BJUlhsgjE!nyv;ZI;psJI}v|+qh{u00fv!tvuUa1Vu~hjmVDLB zqsnNjuvP|hR~UuY@mRBUX@$Kf4;Hz}5VY#MC8LW4j{Os%fE|Cr)Tqs=QgyP%N;d z-!~aEZQkmMBU)5R)!qb0va-E}LFD{hE-|sHlKQPpL!7sE$&)ff zJ=+wy$B62^Re+dqluaTi(@>mBnV)@Rq$JSCQKM#N9%&jBEK-#(1YQ=_SnQ(Ep{x_r zG(uXHs@m?OR#hUGZzXHeZ77bkE*7*ain1=5r$_jT6-VI`+4O4nMk`*>JG51zSbCF5 z7NIDYi2DqxGbC8LrH~Cc6`pm<%9~3xT9lGYb*W`i5(L|@|EH8-v;}+!^!CWDy$Z3a1<;8^2~?k^&93WW#xDw{NQCFK?!V6M>#hB*DI; ze^b(_D|YKcu5bQNNk>-1{2<$M=0=I<0h`Ex^U;;rx(qZ9#{kp1LOtegjrKWJt}PX> zT{Vw2t=BPw$3{EV$3f_y6J4g%K7@h#|-Kj1DEf-3(vfbnszNZT=|o7cGi zzUvZ>#fpFRq?R@JU;tO|$58RcD72Nc z^8^?Lq98y_m@oV4vh?GGMO10!PVcLD40vtyM4H#i^jfjZ6)u0o{iHYE`= zoFWOKTGj}aS*|x-ff?sWfKj72V^Y`Zp)$wi8X0C!arGD&m9+zt5UG;$vjUMtk0)`M zX$_;Sx-jnX4YG_w#N>A~ikGxv-VcVS2c=ONCw{($M)vQT;+sCWt@phx1csXrx`oLy z!y(zfYmn%FozX}gaNBMyr*1IpJZW<#UYoGK)BhF?7^Wqwpv@>_uCU)_3^tEyM)uDd(bv5wwS;MJ58X_$6xu4;M+VfLGX-qK zYgjC9yQr?0h~&CUn9|p0!5r7C8mbe;iB`|NJfpl;{RXieo>*r;?ws!XNKEdmAw-e z3$PU^Mm8ydT8eou$}T}-Fsm1Ps5vfIl};b5&$~sTy5{cv`ph8=vud=ysz*np&Nzqc~w-xg_AOB`X$ttKB9L?gM z86uK?`-Y*hi>#(aTvxB0@cM@BE4av}^A7~lzJe=S**aO40(y11dH!wGROhqCyIwcP z@eq#+g1oZg9}Uzd?>=Yp^LejY@PC(z(Tc;6;n+-1kt*&z?Hh*$4%FP%T z!!o634fZKJRS7P1db(oXKd$sNbgWkV-UsMgz|ANZK?=NQ_NpRXZzQmUs%=vQ*S{Ea zy3ZXL0x`m3g_DrL2+buZKEEk{ZWuXKI0F4#3|dMCTy5pfDC~Bs6SQ6j<$kZY2>_VD z3M(OjQ4SDFf%n3niCB`AF)xvqtjw~W?lyI}FB%okl&H_mI46NJrYDuoRlVjGJ5~vf zDZQNMOg668^*7%5Ti4%z`gCu1U~a=oCI35$dLhyoCH|n zWR#mQ6expu$tJHbJQyTiuQzB8G=5ODd^ib*IGfLQJmk+d(Nr%XivC}pY)=rI&vHCM zcmB_z!WT@5jY`lZNh@FzB9W76nbgngt77Rx3}LO@jK^a#&Hp&`;)P*K->N~vY-shMa$O*eBEUr%cO~4x(9VpbAKoEH&g@DwFf}4jBWFZ=^*xEu8H#*RYrF^e4qp!gLUh z4D&nFfC7x~O!GU#_|EvwFvSYEK zWLl>vnu%eW=69x?-m-RosQ!G93Wxh|yJpE30ouYuqBBeD{LCIyq+#mDn zM!1SbYl7=_iHaLiZb%X4h7?N8MU+ywgD!%l@GjD0!Y!0iB&wNY$lrF4(QqXaoiQIz z+`tgG5a9XXCApbIVbiDr)1b3a^m!?C9pwqJeU%E^Bl91RNJ$jQ4Z`_#NvP|P7U>w- zsHAo468w;Iq)*3{-ms;Lw;Ex5C(|+^F;SbSO%zE?6fTe&j|rX>ClRPP_YaI z8924M&PZX)KPpDM=`NS$nEs_j9Qd4)7BHspcW3fY=5kQO`Em1D>wVVn<2#w>F(NXc z=^}7IBo+~bK?9H?L?k3b+voI`cH6jP(ANz{4DaVHTpg>m@NhuC@84uv#&qhG(J7J) z8;OX+q4|&%NF>1xF2;q$n3%|im398l=#S?dx5J*p|9LN0*;~zWIwR-w7u|VGr!C@> zL&+i0>m*%t9{Ng_jZKHlMn zBg1(DjC*^)ZX0zhrQ|@V?0jc3x5-iOSe7M!2uP_jk5LqmKmfstJXd-wy$-`5Z6yA< zjToXob!_Ql^jM?%xhZq{v`J?kr528KmQm_vvMHcWIENpu_PPmC__@}89kElD>|AFi zKGH}!@kD>=#KOa@HqQ*_bB24q(dYX&ndbipu}!w=Zv(x)8Rz~$|GCXxRg81I#Whw2 zkN3UBm)#q6n^NIowab`iIAZ+UUBf-z7~u7TOz9KI5EsGh4IAv`7Yn1lSe<45M_=z> z4K{u@>f@QIFPAL)x0UmDKy`2Q4e_r*Zi`?(O}a-VZ?j*Fv_qX@N?&Z~*r3PUt=&4J z#WtzwKI5>d&zDSpK5zEZ2@4JTtnj-@JJ(IWlHpRz>II4cM%RtR!I+SwL{F5-usiQF zK18HjLr)wG2@xo7zg-3d2Eo(wtBo4L^7?i3TO$&q&aoJ}^We03h%M z5Sj!aB@~_#NeqaCi4fof?*L>aJs-l92mlCv3B>MK500k(mPqOX6S%P7^>-tY1>*Lz zgk_O{kAX=N{ofoPFbAyOPY2>rP~H6;hysudAip|1i2$)Mx(RXGI2dgNEa5GHBK5N% z`fe2h0D=HSyckjew=8ai8B`kJirXFruz#a?V@BP0E9mU5}pn@07`7&NOcee zlc#S&mO9cCECpvfx9)K}3Q{G2Pyn&dgiHX10IIFvVnq-Reskm|gqYZ5lOuogrLC8P zOMAZXIWR`7o7>L37oiSpPd_0k|v3ls-=;KSsw{)a0) z6H33mvB(%r10V@N_LHFe2~hLHM?uR}ut^UtS;1!q`0oiLJ}~YLW0>b)Bia*2o#DSF zd|n-8vTcoZ}~5<0TO(otafXs`RC|#ENFNX)Nge!0kYNJC!8QX zvHO1Sy8UicB~>YfiyA=Yxt#%&KN@PD3iZ!~#^*uP^Pm~?Y)*VC)F}_`d@iRJmhi10 zTw0_9NC1%fZvc4!3Qp_{pcMObKJkM${d@bP(p!iW!X+6%=tZX;rQRMu2KR65!+m9Y z^--r?q)2Y2P);gtPfCB+#sK1f_q(Goj_{M-_+9Bqw<|!E+Pf&SVo2b literal 0 HcmV?d00001 diff --git a/samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/samples/quickstart/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..e57950e3c9556cbf91e93452f29b84fd97403e86 GIT binary patch literal 7900 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%0DSLcYF900~W8_K#l9(tj%stUZb5v6-W z+eAxSSyCR&L&};gyu<+ipv5aD@vMi>vey)aa~r~3k_F)n58NCWo5@X~N@*G+KCwKd zJmPBYWpR?1NYy-{AcK>jau6X$6^)#BI?bZX5|(BqznNcVA+}}F1SWGM;}2NB!IEMi z2{aHG@&@41{bNg4=6Hn*1b~S_Ub19A>GYdR2Qo}1c@tKAwL~OAO6Gj#R2{@h7~?iI z1i?01Cd;E3jXkB0xPdev8YpRKOi41tyN~w|Oyv)iZEL|sZIu$xY{I62-x529(ZbNs z-N!_q`8;E2*iZn{7&GIRSay#*H9S3zX;fkA$KEl)6h<&K^QcqhB9jytV@NbulEz3d z+0Y5zVR+~1;f-PBxwX=8Y#gz*zys*p*mdS^gM3-eo5&b891`f#jWI-HCP@=T&1N*~lDfnnKJ}n4p3$|hum>|nXytnHJY}xO z(Jb|&zp%6aVc-Aw3G!vLE^0QT$dF`XnrnCWXO$^q4(cP*t_&BxZ`KhjtU;Cb-tBtWYLKg?kqhX>d8jXdu7olno?*$I>N#ZnW1Y8Zy> zaPt~~0%sj;=QI~Y_2XMV{g$n_Zn^Z2dXd4)lCXv9d4Rtl0nlnuEk5f%CNPGfwf?DR z^!$GJ1CnGfm%~I!ytt;6R5c7$u?US;0z_Wkkv3T^lHwEEKl!>-Zrpg$=GLC79(3bb z3H&cLfO_-Aak+&p_|$itmB%!uFqs=%9iH7eaG!zuCdrhhDH~>s62vuM_OhmGsH)gc zS_1$Htfg!+N^(h`FN728KJ${>Ua{qp%-NYEy|vHkMhDuEgar~A*oHANf)61@83kl9 zi&syj$2P`e12az=|J~`n1MsROm89g~Ex!4(X0zFp5UMKnqc(4==Uj^MBujtFGDr2NgihXPtG{2(CHz|BA@wXLHj# zQ|pr}{qs*>y64hhMug0eO}S8V#Sk@{&6hQ!C^AM>u%FdAAQsow))v5> zBHUPcyT)60oN)Btx(=rs?trJmy~g==INc6?;|97y#Vusz_`iIM-z7zEGkWVW z7I(sY28yDTXjw~~;xK8N9X5e{c>cAQ)BW5eUDa-`$@%3{FmJ~!9YX3!7?@daJ&T{D zF(3da!caq1)j!znu{f6=a2PJY4jLoiBnAi g1V9B83I(GB2@nJUj8j + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/samples/quickstart/src/main/res/values/ic_launcher_background.xml b/samples/quickstart/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 00000000..c5d5899f --- /dev/null +++ b/samples/quickstart/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/samples/quickstart/src/main/res/values/strings.xml b/samples/quickstart/src/main/res/values/strings.xml new file mode 100644 index 00000000..d3d14078 --- /dev/null +++ b/samples/quickstart/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Quickstart App + \ No newline at end of file diff --git a/samples/quickstart/src/main/res/values/themes.xml b/samples/quickstart/src/main/res/values/themes.xml new file mode 100644 index 00000000..5a301da3 --- /dev/null +++ b/samples/quickstart/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +