Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/android-pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Create local.properties with base.url
run: echo "base.url=https://ci-placeholder.local" >> local.properties
- name: Create local.properties with base.url and kakao.native.key
run: |
echo "base.url=https://ci-placeholder.local" >> local.properties
echo "kakao.native.key=${{ secrets.KAKAO_NATIVE_KEY }}" >> local.properties

- name: Run ktlint
run: ./gradlew ktlintCheck
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ dependencies {
implementation(projects.remote)
implementation(projects.domain)
implementation(projects.feature.main)

implementation(libs.kakao.login)
}
14 changes: 14 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,19 @@
android:usesCleartextTraffic="true"
tools:targetApi="31">

<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="oauth"
android:scheme="kakao${KAKAO_NATIVE_KEY}" />
</intent-filter>
</activity>
</application>
</manifest>
4 changes: 4 additions & 0 deletions app/src/main/java/com/teamsolply/solply/SolplyApplication.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.teamsolply.solply

import android.app.Application
import com.kakao.sdk.common.KakaoSdk
import com.teamsolply.solply.buildconfig.BuildConfig.KAKAO_NATIVE_KEY
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class SolplyApplication : Application() {
override fun onCreate() {
super.onCreate()

KakaoSdk.init(this, KAKAO_NATIVE_KEY)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.teamsolply.solply.convention.configureAndroidCompose
import com.teamsolply.solply.convention.configureKotlinAndroid
import com.teamsolply.solply.convention.extension.getLibrary
Expand All @@ -24,6 +25,7 @@ internal class AndroidApplicationPlugin : Plugin<Project> {
targetSdk = libs.getVersion("targetSdk").requiredVersion.toInt()
versionCode = libs.getVersion("versionCode").requiredVersion.toInt()
versionName = libs.getVersion("versionName").requiredVersion
manifestPlaceholders["KAKAO_NATIVE_KEY"] = gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key").replace("\"", "")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ internal fun Project.configureBuildConfig(
"BASE_URL",
gradleLocalProperties(rootDir, providers).getProperty("base.url")
)
buildConfigField(
"String",
"KAKAO_NATIVE_KEY",
gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key")
)
Comment on lines +17 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ› ๏ธ Refactor suggestion

์นด์นด์˜ค ๋„ค์ดํ‹ฐ๋ธŒ ํ‚ค ๋นŒ๋“œ ์„ค์ •์— null ์•ˆ์ „์„ฑ ๊ณ ๋ ค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋กœ์ปฌ properties์—์„œ "kakao.native.key" ์†์„ฑ์„ ์ฝ์–ด์˜ค๋Š”๋ฐ, ํ•ด๋‹น ์†์„ฑ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋นŒ๋“œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”:

            buildConfigField(
                "String",
                "KAKAO_NATIVE_KEY",
-               gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key")
+               "\"${gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key") ?: ""}\""
            )
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
buildConfigField(
"String",
"KAKAO_NATIVE_KEY",
gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key")
)
buildConfigField(
"String",
"KAKAO_NATIVE_KEY",
- gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key")
+ "\"${gradleLocalProperties(rootDir, providers).getProperty("kakao.native.key") ?: ""}\""
)
๐Ÿค– Prompt for AI Agents
In
build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt
around lines 17 to 21, the code reads the "kakao.native.key" property without
null safety, which can cause build errors if the property is missing. Modify the
code to provide a default value when the property is not found, ensuring null
safety and preventing build failures. Use a safe call or an Elvis operator to
supply a fallback string like an empty string or a placeholder.

}

buildFeatures {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.teamsolply.solply.buildconfig.impl

import com.teamsolply.solply.buildconfig.BuildConfig
import com.teamsolply.solply.buildconfig.BuildConfig.BASE_URL
import com.teamsolply.solply.buildconfig.BuildConfig.KAKAO_NATIVE_KEY
import com.teamsolply.solply.common.buildconfig.BuildConfigFieldProvider
import com.teamsolply.solply.common.buildconfig.BuildConfigFields
import javax.inject.Inject

class BuildConfigFieldsProviderImpl @Inject constructor() : BuildConfigFieldProvider {
override fun get(): BuildConfigFields =
BuildConfigFields(
baseUrl = BuildConfig.BASE_URL,
baseUrl = BASE_URL,
kakaoNativeKey = KAKAO_NATIVE_KEY,
isDebug = true
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package com.teamsolply.solply.common.buildconfig

data class BuildConfigFields(
val baseUrl: String,
val kakaoNativeKey: String,
val isDebug: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.teamsolply.solply.ui.lifecycle

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.CoroutineScope

@Composable
fun LaunchedEffectWithLifecycle(
key1: Any? = Unit,
key2: Any? = Unit,
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
action: suspend CoroutineScope.() -> Unit = {}
) {
LaunchedEffect(key1 = key1, key2 = key2) {
lifecycleOwner.lifecycle.repeatOnLifecycle(minActiveState) {
action()
}
}
}
1 change: 1 addition & 0 deletions feature/main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ android {
}

dependencies {
implementation(projects.feature.oauth)
implementation(projects.feature.home)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.teamsolply.solply.home.navigation.Home
import com.teamsolply.solply.home.navigation.navigateHome
import com.teamsolply.solply.oauth.navigation.Oauth

internal class MainNavigator(
val navController: NavHostController
Expand All @@ -19,7 +19,7 @@ internal class MainNavigator(
@Composable get() = navController
.currentBackStackEntryAsState().value?.destination

val startDestination = Home
val startDestination = Oauth

val currentTab: MainNavTab?
@Composable get() = MainNavTab.find { tab ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.navigation.compose.NavHost
import com.teamsolply.solply.designsystem.theme.SolplyTheme
import com.teamsolply.solply.home.navigation.homeNavGraph
import com.teamsolply.solply.main.component.MainBottomBar
import com.teamsolply.solply.oauth.navigation.oauthNavGraph
import kotlinx.collections.immutable.toPersistentList

@Composable
Expand All @@ -33,6 +34,7 @@ internal fun MainScreen(
.background(color = SolplyTheme.colors.white)
.fillMaxSize()
) {
oauthNavGraph(paddingValues = innerPadding)
homeNavGraph(paddingValues = innerPadding)
}
},
Expand Down
1 change: 1 addition & 0 deletions feature/oauth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
11 changes: 11 additions & 0 deletions feature/oauth/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
alias(libs.plugins.solply.feature)
}

android {
namespace = "com.teamsolply.solply.oauth"
}

dependencies {
implementation(libs.kakao.login)
}
4 changes: 4 additions & 0 deletions feature/oauth/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.teamsolply.solply.oauth.navigation

import androidx.compose.foundation.layout.PaddingValues
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.teamsolply.solply.navigation.Route
import com.teamsolply.solply.oauth.presentation.OauthRoute
import kotlinx.serialization.Serializable

fun NavController.navigateOauth(
navOptions: NavOptions
) {
navigate(Oauth, navOptions)
}

fun NavGraphBuilder.oauthNavGraph(
paddingValues: PaddingValues
) {
composable<Oauth> {
OauthRoute(
paddingValues = paddingValues
)
}
}

@Serializable
data object Oauth : Route
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.teamsolply.solply.oauth.presentation

import com.teamsolply.solply.ui.base.SideEffect
import com.teamsolply.solply.ui.base.UiIntent
import com.teamsolply.solply.ui.base.UiState

data class OauthState(
val g: String = ""
) : UiState
Comment on lines +7 to +9
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ› ๏ธ Refactor suggestion

ํ”Œ๋ ˆ์ด์Šคํ™€๋” ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝํ•˜์„ธ์š”.

OauthState์˜ g ํ”„๋กœํผํ‹ฐ๋Š” ์˜๋ฏธ๊ฐ€ ๋ถˆ๋ถ„๋ช…ํ•˜๋ฉฐ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ถˆํ•„์š”ํ•œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ์‹ค์ œ ํ•„์š”ํ•œ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 data class OauthState(
-    val g: String = ""
+    // ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์˜๋ฏธ์žˆ๋Š” ์ƒํƒœ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€
 ) : UiState
๐Ÿค– Prompt for AI Agents
In
feature/oauth/src/main/java/com/teamsolply/solply/oauth/presentation/OauthContract.kt
around lines 7 to 9, the OauthState data class has a property named 'g' which is
unclear and likely unused. Remove this placeholder property if it is
unnecessary, or rename it to a meaningful name that accurately represents the
state it holds to improve code clarity and maintainability.


sealed interface OauthIntent : UiIntent {
data object KakaoLoginClick : OauthIntent
}

sealed interface OauthSideEffect : SideEffect {
data object StartKakaoLogin : OauthSideEffect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.teamsolply.solply.oauth.presentation

import android.app.Activity
import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kakao.sdk.common.model.ClientError
import com.kakao.sdk.common.model.ClientErrorCause
import com.kakao.sdk.user.UserApiClient
import com.teamsolply.solply.ui.extension.customClickable
import com.teamsolply.solply.ui.lifecycle.LaunchedEffectWithLifecycle
import kotlinx.coroutines.flow.collectLatest

@Composable
fun OauthRoute(
paddingValues: PaddingValues,
viewModel: OauthViewModel = hiltViewModel()
) {
val context = LocalContext.current
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

LaunchedEffectWithLifecycle {
viewModel.sideEffect.collectLatest { sideEffect ->
when (sideEffect) {
OauthSideEffect.StartKakaoLogin -> startKakaoLogin(
context = context,
onSuccess = { accessToken, refreshToken ->
Toast.makeText(context, "๋กœ๊ทธ์ธ ์„ฑ๊ณต", Toast.LENGTH_SHORT).show()
Log.d(
"asdasdasd",
"accessToken: ${accessToken}\n refreshToken: $refreshToken"
)
},
onFailure = { error ->
Log.d("asdasdasd", error.toString())
}
Comment on lines +41 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ› ๏ธ Refactor suggestion

๋””๋ฒ„๊ทธ ๋กœ๊ทธ ํƒœ๊ทธ๋ฅผ ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝํ•˜์„ธ์š”.

"asdasdasd" ๊ฐ™์€ ์ž„์‹œ ๋กœ๊ทธ ํƒœ๊ทธ๋Š” ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ์— ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜๋ฏธ์žˆ๋Š” ํƒœ๊ทธ๋ช…์„ ์‚ฌ์šฉํ•˜๊ณ , ๋ฏผ๊ฐํ•œ ํ† ํฐ ์ •๋ณด ๋กœ๊น…์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

                        Log.d(
-                            "asdasdasd",
+                            "OAUTH_LOGIN",
                            "accessToken: ${accessToken}\n refreshToken: $refreshToken"
                        )
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Log.d(
"asdasdasd",
"accessToken: ${accessToken}\n refreshToken: $refreshToken"
)
},
onFailure = { error ->
Log.d("asdasdasd", error.toString())
}
Log.d(
"OAUTH_LOGIN",
"accessToken: ${accessToken}\n refreshToken: $refreshToken"
)
},
onFailure = { error ->
Log.d("asdasdasd", error.toString())
}
๐Ÿค– Prompt for AI Agents
In
feature/oauth/src/main/java/com/teamsolply/solply/oauth/presentation/OauthScreen.kt
around lines 40 to 47, replace the placeholder log tag "asdasdasd" with a
meaningful and descriptive tag relevant to the OAuth screen or authentication
process. Additionally, remove or mask sensitive token information like
accessToken and refreshToken from the logs to avoid exposing confidential data.

)
}
}
}

OauthScreen(
kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) }
)
}

@Composable
fun OauthScreen(
kakaoLoginClick: () -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Oauth",
modifier = Modifier.customClickable(
onClick = kakaoLoginClick
)
)
}
}

fun startKakaoLogin(
context: Context,
onSuccess: (accessToken: String, refreshToken: String?) -> Unit = { _, _ -> },
onFailure: (Throwable) -> Unit = {}
) {
val activity = context as? Activity ?: return

if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
UserApiClient.instance.loginWithKakaoTalk(activity) { token, error ->
if (error != null) {
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
Toast.makeText(context, "๋กœ๊ทธ์ธ ์ทจ์†Œ", Toast.LENGTH_SHORT).show()
return@loginWithKakaoTalk
}
UserApiClient.instance.loginWithKakaoAccount(context) { accountToken, accountError ->
if (accountError != null) {
onFailure(accountError)
Toast.makeText(
context,
"๋กœ๊ทธ์ธ ์‹คํŒจ: ${accountError.message}",
Toast.LENGTH_SHORT
).show()
return@loginWithKakaoAccount
}
if (accountToken != null) {
onSuccess(accountToken.accessToken, accountToken.refreshToken)
}
}
} else if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
} else {
UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
Log.d("KAKAO_LOGIN", "loginWithKakaoAccount called. token=$token, error=$error")
if (error != null) {
onFailure(error)
Toast.makeText(context, "๋กœ๊ทธ์ธ ์‹คํŒจ: ${error.message}", Toast.LENGTH_SHORT).show()
return@loginWithKakaoAccount
}
if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
}
}
Comment on lines +78 to +123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ› ๏ธ Refactor suggestion

์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ตฌํ˜„์ด ์ž˜ ๋˜์–ด ์žˆ์ง€๋งŒ ๊ฐœ์„  ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์นด์นด์˜คํ†ก ์•ฑ ๋กœ๊ทธ์ธ๊ณผ ๊ณ„์ • ๋กœ๊ทธ์ธ์˜ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ๊ฐœ์„ ์‚ฌํ•ญ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”:

  1. ๋ฌธ์ž์—ด ํ•˜๋“œ์ฝ”๋”ฉ: ํ† ์ŠคํŠธ ๋ฉ”์‹œ์ง€๋“ค์ด ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค
  2. ๋กœ๊ทธ ์ผ๊ด€์„ฑ: ์ผ๋ถ€ ๋กœ๊ทธ๋งŒ ๊ตฌ์ฒด์ ์ธ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
  3. ํ† ํฐ ๋ณด์•ˆ: ์•ก์„ธ์Šค ํ† ํฐ์„ ๋กœ๊ทธ์— ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์€ ๋ณด์•ˆ์ƒ ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
                if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
-                    Toast.makeText(context, "๋กœ๊ทธ์ธ ์ทจ์†Œ", Toast.LENGTH_SHORT).show()
+                    Toast.makeText(context, context.getString(R.string.login_cancelled), Toast.LENGTH_SHORT).show()
                    return@loginWithKakaoTalk
                }
-            Log.d("KAKAO_LOGIN", "loginWithKakaoAccount called. token=$token, error=$error")
+            Log.d("OAUTH_LOGIN", "loginWithKakaoAccount called")
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun startKakaoLogin(
context: Context,
onSuccess: (accessToken: String, refreshToken: String?) -> Unit = { _, _ -> },
onFailure: (Throwable) -> Unit = {}
) {
val activity = context as? Activity ?: return
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
UserApiClient.instance.loginWithKakaoTalk(activity) { token, error ->
if (error != null) {
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
Toast.makeText(context, "๋กœ๊ทธ์ธ ์ทจ์†Œ", Toast.LENGTH_SHORT).show()
return@loginWithKakaoTalk
}
UserApiClient.instance.loginWithKakaoAccount(context) { accountToken, accountError ->
if (accountError != null) {
onFailure(accountError)
Toast.makeText(
context,
"๋กœ๊ทธ์ธ ์‹คํŒจ: ${accountError.message}",
Toast.LENGTH_SHORT
).show()
return@loginWithKakaoAccount
}
if (accountToken != null) {
onSuccess(accountToken.accessToken, accountToken.refreshToken)
}
}
} else if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
} else {
UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
Log.d("KAKAO_LOGIN", "loginWithKakaoAccount called. token=$token, error=$error")
if (error != null) {
onFailure(error)
Toast.makeText(context, "๋กœ๊ทธ์ธ ์‹คํŒจ: ${error.message}", Toast.LENGTH_SHORT).show()
return@loginWithKakaoAccount
}
if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
}
}
fun startKakaoLogin(
context: Context,
onSuccess: (accessToken: String, refreshToken: String?) -> Unit = { _, _ -> },
onFailure: (Throwable) -> Unit = {}
) {
val activity = context as? Activity ?: return
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
UserApiClient.instance.loginWithKakaoTalk(activity) { token, error ->
if (error != null) {
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
Toast.makeText(
context,
context.getString(R.string.login_cancelled),
Toast.LENGTH_SHORT
).show()
return@loginWithKakaoTalk
}
UserApiClient.instance.loginWithKakaoAccount(context) { accountToken, accountError ->
if (accountError != null) {
onFailure(accountError)
Toast.makeText(
context,
"๋กœ๊ทธ์ธ ์‹คํŒจ: ${accountError.message}",
Toast.LENGTH_SHORT
).show()
return@loginWithKakaoAccount
}
if (accountToken != null) {
onSuccess(accountToken.accessToken, accountToken.refreshToken)
}
}
} else if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
} else {
UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
Log.d("OAUTH_LOGIN", "loginWithKakaoAccount called")
if (error != null) {
onFailure(error)
Toast.makeText(
context,
"๋กœ๊ทธ์ธ ์‹คํŒจ: ${error.message}",
Toast.LENGTH_SHORT
).show()
return@loginWithKakaoAccount
}
if (token != null) {
onSuccess(token.accessToken, token.refreshToken)
}
}
}
}
๐Ÿค– Prompt for AI Agents
In
feature/oauth/src/main/java/com/teamsolply/solply/oauth/presentation/OauthScreen.kt
between lines 77 and 122, the toast messages are hardcoded in Korean and should
be moved to string resources for localization support. Also, ensure all log
statements use a consistent and specific tag instead of generic ones. Finally,
remove or avoid logging access tokens or any sensitive token information to
prevent security risks.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.teamsolply.solply.oauth.presentation

import com.teamsolply.solply.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class OauthViewModel @Inject constructor() :
BaseViewModel<OauthState, OauthIntent, OauthSideEffect>(OauthState()) {
override fun handleIntent(intent: OauthIntent) {
when (intent) {
OauthIntent.KakaoLoginClick -> postSideEffect(OauthSideEffect.StartKakaoLogin)
}
}
}
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven(url = "https://devrepo.kakao.com/nexus/content/groups/public/")
}
}

Expand All @@ -37,3 +38,4 @@ include(":local")
include(":remote")
include(":feature:main")
include(":feature:home")
include(":feature:oauth")