-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 클라이언트단 카카오 로그인 구현 #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
f70cb6c
42c0b77
87a15dc
b5612c1
948373d
a669f2d
425c71d
a8c7bd1
622b3de
2b06391
6289001
fe38e41
ee826c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,4 +18,20 @@ | |
|
|
||
| # If you keep the line number information, uncomment this to | ||
| # hide the original source file name. | ||
| #-renamesourcefileattribute SourceFile | ||
| #-renamesourcefileattribute SourceFile | ||
|
|
||
| # Kakao Login | ||
| -keep class com.kakao.sdk.**.model.* { <fields>; } | ||
|
|
||
| # https://github.com/square/okhttp/pull/6792 | ||
| -dontwarn org.bouncycastle.jsse.** | ||
| -dontwarn org.conscrypt.* | ||
| -dontwarn org.openjsse.** | ||
|
|
||
| # refrofit2 (with r8 full mode) | ||
| -if interface * { @retrofit2.http.* <methods>; } | ||
| -keep,allowobfuscation interface <1> | ||
| -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation | ||
| -if interface * { @retrofit2.http.* public *** *(...); } | ||
| -keep,allowoptimization,allowshrinking,allowobfuscation class <3> | ||
| -keep,allowobfuscation,allowshrinking class retrofit2.Response | ||
|
Comment on lines
+31
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Retrofit2 R8 룰 문법 오류 -# Retrofit2 (with R8 full mode)
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
-keep,allowobfuscation,allowshrinking class retrofit2.Response
+# Retrofit2 (with R8 full mode)
+# Retrofit HTTP 인터페이스 및 응답 타입 보존
+keep class retrofit2.** { *; }
+keep interface retrofit2.http.** { *; }
+keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package com.ninecraft.booket.initializer | ||
|
|
||
| import android.content.Context | ||
| import androidx.startup.Initializer | ||
| import com.kakao.sdk.common.KakaoSdk | ||
| import com.ninecraft.booket.BuildConfig | ||
|
|
||
| class KakaoSdkInitializer : Initializer<Unit> { | ||
|
|
||
| override fun create(context: Context) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @easyhooon 제가 잘 몰라서 그러는데, (init 불리는 시점이나 성능 차이..?) Androidx Startup 나온지 꽤 됐는데 아직 한 번도 제대로 본 적이 없네요 😭
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jisungbin InitializationProvider 코드를 보면 startup 라이브러리가 ContentProvider 추상클래스를 상속하여, ContentProvider를 기반으로 구현되어있음을 알 수 있습니다 ContentProvider는 그외에도 답변을 드리다가 문득 생각이 든게, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하!!! 제 핑거프린세스 질문에도 자세한 답변 감사합니다. 그러면 현재 시나리오에서는
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
음 말씀하신것처럼 반드시 이른 시점에 진행하지 않아도 되는 것은 맞지만, 저는 onCreate()보다 빠른 초기화를 할 수 있다는 점에서 메리트가 있다고 생각하여 채택했습니다! 벤치마크를 통해 직접 어느정도 이득을 볼 수 있는지 측정해보진 않았지만, Jetpack에서 지원하는 라이브러리이고, 사용하면 장점이 있다고 공식문서에서도 안내를 하기 때문에(사용한다고 trade off가 있는 것도 아닌걸로 판단됨) Intializer로 구현을 결정하였습니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 모두 공감됩니다. |
||
| KakaoSdk.init(context, BuildConfig.KAKAO_NATIVE_APP_KEY) | ||
| } | ||
|
|
||
| override fun dependencies(): List<Class<out Initializer<*>>> { | ||
| return emptyList() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| <resources> | ||
| <string name="app_name">Booket</string> | ||
| <string name="network_error_message">네트워크 연결이 불안해요.\n잠시후 다시 이용해주세요.</string> | ||
| <string name="server_error_message">이용에 불편을 드려 죄송합니다.\n잠시후 다시 이용해주세요.</string> | ||
| <string name="unknown_error_message">알 수 없는 오류가 발생하였습니다.</string> | ||
| </resources> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /build |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| @file:Suppress("INLINE_FROM_HIGHER_PLATFORM") | ||
|
|
||
| plugins { | ||
| alias(libs.plugins.booket.android.library) | ||
| alias(libs.plugins.booket.android.library.compose) | ||
| } | ||
|
|
||
| android { | ||
| namespace = "com.ninecraft.booket.core.ui" | ||
| } | ||
|
|
||
| dependencies { | ||
| implementations( | ||
| projects.core.designsystem, | ||
|
|
||
| libs.logger, | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package com.ninecraft.booket.core.ui.component | ||
|
|
||
| import androidx.compose.foundation.layout.Box | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.foundation.layout.sizeIn | ||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||
| import androidx.compose.material.icons.Icons | ||
| import androidx.compose.material.icons.filled.Check | ||
| import androidx.compose.material3.Button | ||
| import androidx.compose.material3.ButtonDefaults | ||
| import androidx.compose.material3.Icon | ||
| import androidx.compose.material3.MaterialTheme | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Color | ||
| import androidx.compose.ui.unit.dp | ||
| import com.ninecraft.booket.core.designsystem.ComponentPreview | ||
| import com.ninecraft.booket.core.designsystem.theme.BooketTheme | ||
|
|
||
| @Composable | ||
| fun BooketButton( | ||
| onClick: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| enabled: Boolean = true, | ||
| containerColor: Color = MaterialTheme.colorScheme.primaryContainer, | ||
| contentColor: Color = MaterialTheme.colorScheme.onPrimaryContainer, | ||
| disabledContainerColor: Color = MaterialTheme.colorScheme.tertiaryContainer, | ||
| disabledContentColor: Color = MaterialTheme.colorScheme.onTertiaryContainer, | ||
| text: @Composable () -> Unit, | ||
| leadingIcon: @Composable (() -> Unit)? = null, | ||
| ) { | ||
| Button( | ||
| onClick = onClick, | ||
| modifier = modifier, | ||
| enabled = enabled, | ||
| shape = RoundedCornerShape(12.dp), | ||
| colors = ButtonDefaults.buttonColors( | ||
| containerColor = containerColor, | ||
| contentColor = contentColor, | ||
| disabledContainerColor = disabledContainerColor, | ||
| disabledContentColor = disabledContentColor, | ||
| ), | ||
| contentPadding = if (leadingIcon != null) { | ||
| ButtonDefaults.ButtonWithIconContentPadding | ||
| } else { | ||
| ButtonDefaults.ContentPadding | ||
| }, | ||
| ) { | ||
| TogetherButtonContent( | ||
| text = text, | ||
| leadingIcon = leadingIcon, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| private fun TogetherButtonContent( | ||
| text: @Composable () -> Unit, | ||
| leadingIcon: @Composable (() -> Unit)? = null, | ||
| ) { | ||
| if (leadingIcon != null) { | ||
| Box(Modifier.sizeIn(maxHeight = ButtonDefaults.IconSize)) { | ||
| leadingIcon() | ||
| } | ||
| } | ||
| Box( | ||
| Modifier.padding( | ||
| start = if (leadingIcon != null) { | ||
| ButtonDefaults.IconSpacing | ||
| } else { | ||
| 0.dp | ||
| }, | ||
| ), | ||
| ) { | ||
| text() | ||
| } | ||
| } | ||
|
|
||
| @ComponentPreview | ||
| @Composable | ||
| private fun TogetherButtonPreview() { | ||
| BooketTheme { | ||
| BooketButton( | ||
| onClick = {}, | ||
| text = { | ||
| Text(text = "Button") | ||
| }, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @ComponentPreview | ||
| @Composable | ||
| private fun TogetherButtonWithLeadingIconPreview() { | ||
| BooketTheme { | ||
| BooketButton( | ||
| onClick = {}, | ||
| text = { | ||
| Text("Check Button") | ||
| }, | ||
| leadingIcon = { | ||
| Icon( | ||
| imageVector = Icons.Default.Check, | ||
| contentDescription = "Check icon", | ||
| tint = Color.White, | ||
| ) | ||
| }, | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /build |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| @file:Suppress("INLINE_FROM_HIGHER_PLATFORM") | ||
|
|
||
| plugins { | ||
| alias(libs.plugins.booket.android.feature) | ||
| alias(libs.plugins.kotlin.serialization) | ||
| alias(libs.plugins.kotlin.parcelize) | ||
| } | ||
|
|
||
| android { | ||
| namespace = "com.ninecraft.booket.feature.login" | ||
|
|
||
| buildFeatures { | ||
| buildConfig = true | ||
| } | ||
| } | ||
|
|
||
| ksp { | ||
| arg("circuit.codegen.mode", "hilt") | ||
| } | ||
|
|
||
| dependencies { | ||
| implementations( | ||
| projects.feature.home, | ||
|
|
||
| libs.logger, | ||
| libs.kakao.auth, | ||
| ) | ||
| } | ||
|
easyhooon marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.ninecraft.booket.feature.login | ||
|
|
||
| import android.widget.Toast | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.LaunchedEffect | ||
| import androidx.compose.runtime.remember | ||
| import androidx.compose.ui.platform.LocalContext | ||
|
|
||
| @Composable | ||
| internal fun HandleLoginEffects( | ||
| state: LoginScreen.State, | ||
| eventSink: (LoginScreen.Event) -> Unit, | ||
| ) { | ||
| val context = LocalContext.current | ||
| val kakaoAuthClient = remember { KakaoAuthClient() } | ||
|
|
||
| LaunchedEffect(state.sideEffect) { | ||
| when (state.sideEffect) { | ||
| is LoginScreen.SideEffect.KakaoLogin -> { | ||
| kakaoAuthClient.loginWithKakao( | ||
| context = context, | ||
| onSuccess = { token -> | ||
| eventSink(LoginScreen.Event.LoginSuccess(token)) | ||
| }, | ||
| onFailure = { errorMessage -> | ||
| eventSink(LoginScreen.Event.LoginFailure(errorMessage)) | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| is LoginScreen.SideEffect.ShowToast -> { | ||
| Toast.makeText(context, state.sideEffect.message, Toast.LENGTH_SHORT).show() | ||
| } | ||
|
|
||
| null -> {} | ||
| } | ||
| } | ||
|
|
||
| if (state.sideEffect != null) { | ||
| eventSink(LoginScreen.Event.InitSideEffect) | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| } | ||

Uh oh!
There was an error while loading. Please reload this page.