Add Sign in with Apple for iOS

Kotlin Shared Layer:
- Add AppleSignInRequest and AppleSignInResponse models
- Add appleSignIn method to AuthApi and APILayer
- Add appleSignInState and appleSignIn() to AuthViewModel

iOS App:
- Create AppleSignInManager for AuthenticationServices integration
- Create AppleSignInViewModel to coordinate Apple auth flow
- Update LoginView with "Sign in with Apple" button
- Add Sign in with Apple entitlement
- Add accessibility identifier for UI testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-29 01:17:38 -06:00
parent 4b905ad5fe
commit 5a1a87fe8d
10 changed files with 529 additions and 0 deletions

View File

@@ -2,6 +2,8 @@ package com.example.casera.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.casera.models.AppleSignInRequest
import com.example.casera.models.AppleSignInResponse
import com.example.casera.models.AuthResponse
import com.example.casera.models.ForgotPasswordRequest
import com.example.casera.models.ForgotPasswordResponse
@@ -48,6 +50,9 @@ class AuthViewModel : ViewModel() {
private val _resetPasswordState = MutableStateFlow<ApiResult<ResetPasswordResponse>>(ApiResult.Idle)
val resetPasswordState: StateFlow<ApiResult<ResetPasswordResponse>> = _resetPasswordState
private val _appleSignInState = MutableStateFlow<ApiResult<AppleSignInResponse>>(ApiResult.Idle)
val appleSignInState: StateFlow<ApiResult<AppleSignInResponse>> = _appleSignInState
fun login(username: String, password: String) {
viewModelScope.launch {
_loginState.value = ApiResult.Loading
@@ -207,6 +212,36 @@ class AuthViewModel : ViewModel() {
_resetPasswordState.value = ApiResult.Idle
}
fun appleSignIn(
idToken: String,
userId: String,
email: String?,
firstName: String?,
lastName: String?
) {
viewModelScope.launch {
_appleSignInState.value = ApiResult.Loading
val result = APILayer.appleSignIn(
AppleSignInRequest(
idToken = idToken,
userId = userId,
email = email,
firstName = firstName,
lastName = lastName
)
)
_appleSignInState.value = when (result) {
is ApiResult.Success -> ApiResult.Success(result.data)
is ApiResult.Error -> result
else -> ApiResult.Error("Unknown error")
}
}
}
fun resetAppleSignInState() {
_appleSignInState.value = ApiResult.Idle
}
fun logout() {
viewModelScope.launch {
APILayer.logout()