diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc876a3c..a2c8a9fd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -75,6 +75,17 @@ android:scheme="https"/> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/easyhz/noffice/NofficeApplication.kt b/app/src/main/java/com/easyhz/noffice/NofficeApplication.kt index d7c61bd0..b1f1444c 100644 --- a/app/src/main/java/com/easyhz/noffice/NofficeApplication.kt +++ b/app/src/main/java/com/easyhz/noffice/NofficeApplication.kt @@ -6,6 +6,7 @@ import android.app.NotificationManager import android.content.Context import android.os.Build import com.easyhz.noffice.data.notification.service.NotificationService +import com.kakao.sdk.common.KakaoSdk import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp @@ -13,7 +14,9 @@ class NofficeApplication: Application() { override fun onCreate() { super.onCreate() createNotificationChannel() + initKakao() } + private fun createNotificationChannel() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( @@ -26,4 +29,8 @@ class NofficeApplication: Application() { notificationManager.createNotificationChannel(channel) } } + + private fun initKakao() { + KakaoSdk.init(this, BuildConfig.KAKAO_NATIVE_APP_KEY) + } } \ No newline at end of file diff --git a/core/design-system/src/main/java/com/easyhz/noffice/core/design_system/theme/Color.kt b/core/design-system/src/main/java/com/easyhz/noffice/core/design_system/theme/Color.kt index b0f94894..5b6911bc 100644 --- a/core/design-system/src/main/java/com/easyhz/noffice/core/design_system/theme/Color.kt +++ b/core/design-system/src/main/java/com/easyhz/noffice/core/design_system/theme/Color.kt @@ -89,4 +89,9 @@ val DimColor = Color(0xFF121212).copy(alpha = 0.5f) @Stable val Red100 = Color(0xFFFFF0EF) @Stable -val Red = Color(0xFFFF3F3F) \ No newline at end of file +val Red = Color(0xFFFF3F3F) + +@Stable +val KakaoYellow = Color(0xFFFEE500) +@Stable +val KakaoBlack = Color(0xFF000000) \ No newline at end of file diff --git a/core/design-system/src/main/res/drawable/ic_logo_kakao.xml b/core/design-system/src/main/res/drawable/ic_logo_kakao.xml new file mode 100644 index 00000000..e45d8b6b --- /dev/null +++ b/core/design-system/src/main/res/drawable/ic_logo_kakao.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/core/design-system/src/main/res/values/strings.xml b/core/design-system/src/main/res/values/strings.xml index 035f7b8c..23d5115a 100644 --- a/core/design-system/src/main/res/values/strings.xml +++ b/core/design-system/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ - Google로 로그인 + Google로 시작하기 + Kakao로 시작하기 약속된 날짜가 없어요 약속된 장소가 없어요 diff --git a/data/auth/src/main/java/com/easyhz/noffice/data/auth/di/strategy/LoginStrategyModule.kt b/data/auth/src/main/java/com/easyhz/noffice/data/auth/di/strategy/LoginStrategyModule.kt index 991f55fa..42563846 100644 --- a/data/auth/src/main/java/com/easyhz/noffice/data/auth/di/strategy/LoginStrategyModule.kt +++ b/data/auth/src/main/java/com/easyhz/noffice/data/auth/di/strategy/LoginStrategyModule.kt @@ -2,7 +2,9 @@ package com.easyhz.noffice.data.auth.di.strategy import com.easyhz.noffice.data.auth.strategy.BaseStrategy import com.easyhz.noffice.data.auth.strategy.GoogleStrategy +import com.easyhz.noffice.data.auth.strategy.KakaoStrategy import com.easyhz.noffice.data.auth.util.google +import com.easyhz.noffice.data.auth.util.kakao import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -18,4 +20,9 @@ object LoginStrategyModule { @IntoMap @StringKey(google) fun provideGoogleStrategy(googleStrategy: GoogleStrategy): BaseStrategy = googleStrategy + + @Provides + @IntoMap + @StringKey(kakao) + fun provideKakaoStrategy(kakaoStrategy: KakaoStrategy): BaseStrategy = kakaoStrategy } \ No newline at end of file diff --git a/data/auth/src/main/java/com/easyhz/noffice/data/auth/strategy/KakaoStrategy.kt b/data/auth/src/main/java/com/easyhz/noffice/data/auth/strategy/KakaoStrategy.kt new file mode 100644 index 00000000..9f898770 --- /dev/null +++ b/data/auth/src/main/java/com/easyhz/noffice/data/auth/strategy/KakaoStrategy.kt @@ -0,0 +1,67 @@ +package com.easyhz.noffice.data.auth.strategy + +import android.content.Context +import android.util.Log +import com.kakao.sdk.auth.model.OAuthToken +import com.kakao.sdk.common.model.ClientError +import com.kakao.sdk.common.model.ClientErrorCause +import com.kakao.sdk.user.UserApiClient +import kotlinx.coroutines.suspendCancellableCoroutine +import javax.inject.Inject +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException + +class KakaoStrategy @Inject constructor() : BaseStrategy() { + private val tag = this.javaClass.name + override suspend fun login(context: Context): Result = runCatching { + val token = loginWithKakaoTalk(context) + Log.d(tag, "카카오톡으로 로그인 성공 ${token.accessToken}") + token.accessToken + }.recoverCatching { error -> + Log.d(tag, "카카오톡으로 로그인 실패 : $error") + + if (error is ClientError && error.reason == ClientErrorCause.Cancelled) throw error // 의도적인 로그인 취소 + + val token = loginWithKakaoAccount(context) + Log.d(tag, "카카오 계정으로 로그인 성공 ${token.accessToken}") + token.accessToken + } + + override suspend fun logout(context: Context): Result { + TODO("Not yet implemented") + } + + /** + * 카카오톡으로 로그인 + * + * @param context Context + * @return [OAuthToken] 로그인 성공 시 발급되는 토큰 + */ + private suspend fun loginWithKakaoTalk(context: Context): OAuthToken = suspendCancellableCoroutine { continuation -> + UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> + when { + error != null -> continuation.resumeWithException(error) + token != null -> continuation.resume(token) + else -> continuation.resumeWithException(IllegalStateException("Unexpected error during KakaoTalk login")) + } + } + } + + /** + * 카카오 계정으로 로그인 + * + * * 카카오톡에 연결된 카카오 계정이 없을 경우 카카오 계정 로그인 시도 + * + * @param context Context + * @return [OAuthToken] 로그인 성공 시 발급되는 토큰 + */ + private suspend fun loginWithKakaoAccount(context: Context): OAuthToken = suspendCancellableCoroutine { continuation -> + UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> + when { + error != null -> continuation.resumeWithException(error) + token != null -> continuation.resume(token) + else -> continuation.resumeWithException(IllegalStateException("Unexpected error during KakaoAccount login")) + } + } + } +} \ No newline at end of file diff --git a/data/auth/src/main/java/com/easyhz/noffice/data/auth/util/Provider.kt b/data/auth/src/main/java/com/easyhz/noffice/data/auth/util/Provider.kt index 16fc2bee..e43662de 100644 --- a/data/auth/src/main/java/com/easyhz/noffice/data/auth/util/Provider.kt +++ b/data/auth/src/main/java/com/easyhz/noffice/data/auth/util/Provider.kt @@ -3,11 +3,13 @@ package com.easyhz.noffice.data.auth.util import com.easyhz.noffice.core.network.model.request.sign.LoginRequest const val google = "GOOGLE" +const val kakao = "KAKAO" enum class Provider( val type: String ) { - GOOGLE(type = google); + GOOGLE(type = google), + KAKAO(type = kakao); fun getLoginRequest(code: String) = LoginRequest( code = code, diff --git a/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/component/login/SocialLoginButton.kt b/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/component/login/SocialLoginButton.kt index f7be82a3..9234d7cd 100644 --- a/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/component/login/SocialLoginButton.kt +++ b/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/component/login/SocialLoginButton.kt @@ -38,6 +38,10 @@ internal fun LoginView( socialLoginType = SocialLoginType.GOOGLE, onClick = onClick ) + SocialLoginButton( + socialLoginType = SocialLoginType.KAKAO, + onClick = onClick + ) } } diff --git a/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/util/login/SocialLoginType.kt b/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/util/login/SocialLoginType.kt index 07e9b62c..482214fd 100644 --- a/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/util/login/SocialLoginType.kt +++ b/feature/sign/src/main/java/com/easyhz/noffice/feature/sign/util/login/SocialLoginType.kt @@ -6,6 +6,8 @@ import androidx.compose.ui.graphics.Color import com.easyhz.noffice.core.design_system.R import com.easyhz.noffice.core.design_system.theme.Grey50 import com.easyhz.noffice.core.design_system.theme.Grey800 +import com.easyhz.noffice.core.design_system.theme.KakaoBlack +import com.easyhz.noffice.core.design_system.theme.KakaoYellow enum class SocialLoginType( @StringRes val stringId: Int, @@ -18,5 +20,10 @@ enum class SocialLoginType( iconId = R.drawable.ic_logo_google, containerColor = Grey50, contentColor = Grey800, + ), KAKAO( + stringId = R.string.social_login_kakao, + iconId = R.drawable.ic_logo_kakao, + containerColor = KakaoYellow, + contentColor = KakaoBlack, ); } \ No newline at end of file