From 9ecb7b08752ce8b59d054929410bb51fc00836c0 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Thu, 4 Jul 2024 17:55:15 +0900 Subject: [PATCH 01/19] =?UTF-8?q?[ADD/#5]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/terning/feature/onboarding/login/LoginScreen.kt | 4 ++++ .../com/terning/feature/onboarding/signup/SignUpScreen.kt | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt diff --git a/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt new file mode 100644 index 000000000..9ea4963aa --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.login + +class LoginScreen { +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt new file mode 100644 index 000000000..146bcf4a0 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.signup + +class SignUpScreen { +} \ No newline at end of file From 185fda5ae423726df3368a09cd8be4c9620a5139 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Thu, 4 Jul 2024 22:36:56 +0900 Subject: [PATCH 02/19] =?UTF-8?q?[ADD/#5]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?sdk=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/terning/point/MyApp.kt | 5 +++++ .../com/terning/feature/onboarding/signin/SignInScreen.kt | 4 ++++ settings.gradle.kts | 3 +++ 3 files changed, 12 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 98ac3bc11..10c9b471c 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -13,6 +13,7 @@ class MyApp : Application() { initTimber() setDayMode() + initKakoSdk() } private fun initTimber() { @@ -22,4 +23,8 @@ class MyApp : Application() { private fun setDayMode() { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) } + + private fun initKakoSdk(){ + + } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt new file mode 100644 index 000000000..9dc6e3a96 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.signin + +class SignInScreen { +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 8a2c140ec..bd88f3f5d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,6 +16,9 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + + // KakaoSDK repository + maven(url = "https://devrepo.kakao.com/nexus/content/groups/public/") } } From 95d0f4203358491bc49b990eef0148aa508d4cbc Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 01:47:04 +0900 Subject: [PATCH 03/19] =?UTF-8?q?[ADD/#5]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++++ app/src/main/java/com/terning/point/MyApp.kt | 3 ++- feature/build.gradle.kts | 3 +++ gradle/libs.versions.toml | 5 +++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4a074d97a..ad0edb4b0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -104,4 +104,8 @@ dependencies { debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + + // KakaoDependencies + implementation(libs.kakao.user) + } diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 10c9b471c..891ddbb4e 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -4,6 +4,7 @@ import android.app.Application import androidx.appcompat.app.AppCompatDelegate import dagger.hilt.android.HiltAndroidApp import timber.log.Timber +import com.kakao.sdk.common.KakaoSdk @HiltAndroidApp class MyApp : Application() { @@ -25,6 +26,6 @@ class MyApp : Application() { } private fun initKakoSdk(){ - +// KakaoSdk.init(this, BuildConfig.NATIVE_APP_KEY) } } \ No newline at end of file diff --git a/feature/build.gradle.kts b/feature/build.gradle.kts index 56209c2ce..d76df3c05 100644 --- a/feature/build.gradle.kts +++ b/feature/build.gradle.kts @@ -91,4 +91,7 @@ dependencies { implementation(libs.ossLicense) implementation(libs.lottie) + // KakaoDependencies + implementation(libs.kakao.user) + } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bcce3048f..1d9d49213 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -74,6 +74,9 @@ foundationAndroid = "1.6.8" material3Android = "1.2.1" lifecycleRuntimeComposeAndroid = "2.8.2" +## Kakao +kakaoVersion = "2.14.0" + [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidxCore" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" } @@ -149,6 +152,8 @@ timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } ossLicense = {group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "ossVersion"} lottie = {group = "com.airbnb.android", name = "lottie", version.ref = "lottieVersion"} +kakao-user = {group = "com.kakao.sdk", name = "v2-user", version.ref = "kakaoVersion"} + [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } From 7e342295801c4a3f2b3dcdfeab3e3e46a91b77e5 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 02:38:13 +0900 Subject: [PATCH 04/19] =?UTF-8?q?[FEAT/#5]=20NATIVE=5FAPP=5FKEY=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 8 ++++++++ app/src/main/java/com/terning/point/MyApp.kt | 2 +- feature/src/main/AndroidManifest.xml | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ad0edb4b0..93facf65f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -23,6 +23,14 @@ android { vectorDrawables { useSupportLibrary = true } + + buildConfigField( + "String", + "NATIVE_APP_KEY", + gradleLocalProperties(rootDir, providers).getProperty("native.app.key"), + ) + manifestPlaceholders["NATIVE_APP_KEY"] = + gradleLocalProperties(rootDir, providers).getProperty("nativeAppKey") } buildTypes { diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 891ddbb4e..8e8cc6670 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -26,6 +26,6 @@ class MyApp : Application() { } private fun initKakoSdk(){ -// KakaoSdk.init(this, BuildConfig.NATIVE_APP_KEY) + KakaoSdk.init(this, BuildConfig.NATIVE_APP_KEY) } } \ No newline at end of file diff --git a/feature/src/main/AndroidManifest.xml b/feature/src/main/AndroidManifest.xml index f2df3a230..1e31d319a 100644 --- a/feature/src/main/AndroidManifest.xml +++ b/feature/src/main/AndroidManifest.xml @@ -14,5 +14,21 @@ + + + + + + + + + + + + \ No newline at end of file From ee4abf8fbba4c9d77a01236056dcb7d855dbf27c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 02:43:13 +0900 Subject: [PATCH 05/19] [FEAT/#5] kakaoVersion Update --- 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 1d9d49213..1a57fcdb2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,7 @@ material3Android = "1.2.1" lifecycleRuntimeComposeAndroid = "2.8.2" ## Kakao -kakaoVersion = "2.14.0" +kakaoVersion = "2.20.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidxCore" } From a08222f77f3cd13a567a0f5ee04a59aa228986af Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 03:10:07 +0900 Subject: [PATCH 06/19] [ADD/#5] add signin, signup, filtering screen --- .../feature/onboarding/filtering/FilteringRoute.kt | 9 +++++++++ .../filtering/navigation/FilteringNavigation.kt | 4 ++++ .../feature/onboarding/login/LoginScreen.kt | 4 ---- .../feature/onboarding/signin/SignInRoute.kt | 14 ++++++++++++++ .../signin/{SignInScreen.kt => SignInViewModel.kt} | 2 +- .../signin/navigation/SignInNavigation.kt | 4 ++++ .../feature/onboarding/signup/SignUpRoute.kt | 13 +++++++++++++ .../feature/onboarding/signup/SignUpScreen.kt | 4 ---- .../signup/navigation/SignUpNavigation.kt | 4 ++++ 9 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/filtering/FilteringRoute.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/filtering/navigation/FilteringNavigation.kt delete mode 100644 feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt rename feature/src/main/java/com/terning/feature/onboarding/signin/{SignInScreen.kt => SignInViewModel.kt} (66%) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt delete mode 100644 feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt diff --git a/feature/src/main/java/com/terning/feature/onboarding/filtering/FilteringRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/filtering/FilteringRoute.kt new file mode 100644 index 000000000..bf1e1ec23 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/filtering/FilteringRoute.kt @@ -0,0 +1,9 @@ +package com.terning.feature.onboarding.filtering + +import androidx.compose.runtime.Composable +import com.terning.feature.onboarding.filtering.navigation.FilteringNavigation + +@Composable +fun FilteringRoute(){ + +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/filtering/navigation/FilteringNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/filtering/navigation/FilteringNavigation.kt new file mode 100644 index 000000000..6dcc12e7b --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/filtering/navigation/FilteringNavigation.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.filtering.navigation + +class FilteringNavigation { +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt deleted file mode 100644 index 9ea4963aa..000000000 --- a/feature/src/main/java/com/terning/feature/onboarding/login/LoginScreen.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.terning.feature.onboarding.login - -class LoginScreen { -} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt new file mode 100644 index 000000000..62f54dce0 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -0,0 +1,14 @@ +package com.terning.feature.onboarding.signin + +import androidx.compose.runtime.Composable + +@Composable +fun SignInRoute() { + + SignInScreen() +} + +@Composable +fun SignInScreen() { + +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt similarity index 66% rename from feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt rename to feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index 9dc6e3a96..bef98fbfc 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInScreen.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -1,4 +1,4 @@ package com.terning.feature.onboarding.signin -class SignInScreen { +class SignInViewModel { } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt new file mode 100644 index 000000000..4d5ef935c --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.signin.navigation + +class SignInNavigation { +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt new file mode 100644 index 000000000..b4dc67b6a --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt @@ -0,0 +1,13 @@ +package com.terning.feature.onboarding.signup + +import androidx.compose.runtime.Composable + +@Composable +fun SingUpRoute() { + SignUpScreen() +} + +@Composable +fun SignUpScreen() { + +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt deleted file mode 100644 index 146bcf4a0..000000000 --- a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpScreen.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.terning.feature.onboarding.signup - -class SignUpScreen { -} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt new file mode 100644 index 000000000..0a264f0ec --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt @@ -0,0 +1,4 @@ +package com.terning.feature.onboarding.signup.navigation + +class SignUpNavigation { +} \ No newline at end of file From 415619458a2956ecec6352808985a16028053c3e Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 03:18:23 +0900 Subject: [PATCH 07/19] [ADD/#5] add signin, signup navigation --- .../signin/navigation/SignInNavigation.kt | 25 +++++++++++++++++-- .../feature/onboarding/signup/SignUpRoute.kt | 2 +- .../signup/navigation/SignUpNavigation.kt | 25 +++++++++++++++++-- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt index 4d5ef935c..ccfd53068 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt @@ -1,4 +1,25 @@ package com.terning.feature.onboarding.signin.navigation -class SignInNavigation { -} \ No newline at end of file +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import com.terning.core.navigation.MainTabRoute +import com.terning.feature.onboarding.signin.SignInRoute +import kotlinx.serialization.Serializable + +fun NavController.navigateSignIn(navOptions: NavOptions? = null) { + navigate( + route = SignIn, + navOptions = navOptions + ) +} + +fun NavGraphBuilder.signInNavGraph() { + composable { + SignInRoute() + } +} + +@Serializable +data object SignIn : MainTabRoute \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt index b4dc67b6a..9d3d3d411 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signup/SignUpRoute.kt @@ -3,7 +3,7 @@ package com.terning.feature.onboarding.signup import androidx.compose.runtime.Composable @Composable -fun SingUpRoute() { +fun SignUpRoute() { SignUpScreen() } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt index 0a264f0ec..1379d0a64 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signup/navigation/SignUpNavigation.kt @@ -1,4 +1,25 @@ package com.terning.feature.onboarding.signup.navigation -class SignUpNavigation { -} \ No newline at end of file +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import com.terning.core.navigation.MainTabRoute +import com.terning.feature.onboarding.signup.SignUpRoute +import kotlinx.serialization.Serializable + +fun NavController.navigateSignUp(navOptions: NavOptions? = null) { + navigate( + route = SignUp, + navOptions = navOptions + ) +} + +fun NavGraphBuilder.signUpNavGraph() { + composable { + SignUpRoute() + } +} + +@Serializable +data object SignUp : MainTabRoute \ No newline at end of file From de120c93575f4b1e53c89b786cd3c12b6cf25b21 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 04:46:55 +0900 Subject: [PATCH 08/19] =?UTF-8?q?[UI/#5]=20KakaoButton=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/feature/main/MainNavigator.kt | 3 +- .../com/terning/feature/main/MainScreen.kt | 3 + .../feature/onboarding/signin/SignInRoute.kt | 39 ++++++++++++- .../signin/component/KakaoButton.kt | 52 ++++++++++++++++++ .../src/main/res/drawable/ic_signin_kakao.xml | 14 +++++ .../main/res/drawable/img_terning_point.png | Bin 0 -> 26834 bytes feature/src/main/res/values/strings.xml | 3 + 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt create mode 100644 feature/src/main/res/drawable/ic_signin_kakao.xml create mode 100644 feature/src/main/res/drawable/img_terning_point.png diff --git a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt index 4ca92ceec..220aaa28f 100644 --- a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -12,6 +12,7 @@ import androidx.navigation.navOptions import com.terning.feature.first.navigation.First import com.terning.feature.first.navigation.navigateFirst import com.terning.feature.mock.navigation.navigateMock +import com.terning.feature.onboarding.signin.navigation.SignIn class MainNavigator( val navController: NavHostController @@ -20,7 +21,7 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - val startDestination = First + val startDestination = SignIn val currentTab: MainTab? @Composable get() = MainTab.find { tab -> diff --git a/feature/src/main/java/com/terning/feature/main/MainScreen.kt b/feature/src/main/java/com/terning/feature/main/MainScreen.kt index 29167b458..c079e6d9d 100644 --- a/feature/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/src/main/java/com/terning/feature/main/MainScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.unit.sp import androidx.navigation.compose.NavHost import com.terning.feature.first.navigation.firstNavGraph import com.terning.feature.mock.navigation.mockNavGraph +import com.terning.feature.onboarding.signin.navigation.signInNavGraph @Composable fun MainScreen( @@ -44,6 +45,8 @@ fun MainScreen( ) { firstNavGraph() mockNavGraph() + signInNavGraph() + signInNavGraph() } } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index 62f54dce0..b5eb56842 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -1,6 +1,19 @@ package com.terning.feature.onboarding.signin +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.feature.R +import com.terning.feature.onboarding.signin.component.KakaoButton @Composable fun SignInRoute() { @@ -9,6 +22,30 @@ fun SignInRoute() { } @Composable -fun SignInScreen() { +fun SignInScreen( + onSignInClick: () -> Unit = {} +) { + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = R.drawable.img_terning_point), + contentDescription = null, + modifier = Modifier + .size(500.dp) + .aspectRatio(1f), + ) + KakaoButton( + title = stringResource(id = R.string.sign_in_kakao_button), + onSignInClick = { onSignInClick() } + ) + } +} +@Preview(showBackground = true) +@Composable +fun SignInScreenPreview() { + SignInScreen() } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt new file mode 100644 index 000000000..1179e6ec9 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt @@ -0,0 +1,52 @@ +package com.terning.feature.onboarding.signin.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.core.extension.noRippleClickable +import com.terning.feature.R + + +@Composable +fun KakaoButton( + title: String, + modifier: Modifier = Modifier, + onSignInClick: () -> Unit +) { + Row( + modifier = modifier + .fillMaxWidth() + .background(Color.Yellow) + .noRippleClickable { onSignInClick() } + .padding(vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Image( + painter = painterResource(id = R.drawable.ic_signin_kakao), + contentDescription = null, + modifier = Modifier.padding(horizontal = 8.dp) + ) + Text( + text = title, + // TODO : style 추가하기 + ) + } +} + +@Preview(showBackground = true) +@Composable +fun KakaoButtonPreview() { + KakaoButton("카카오로 로그인하기", onSignInClick = {}) +} \ No newline at end of file diff --git a/feature/src/main/res/drawable/ic_signin_kakao.xml b/feature/src/main/res/drawable/ic_signin_kakao.xml new file mode 100644 index 000000000..cbe75d056 --- /dev/null +++ b/feature/src/main/res/drawable/ic_signin_kakao.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/feature/src/main/res/drawable/img_terning_point.png b/feature/src/main/res/drawable/img_terning_point.png new file mode 100644 index 0000000000000000000000000000000000000000..fc21583192637fa0c90213312cd8e01f1363e946 GIT binary patch literal 26834 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⪼MW|R~&KL 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 literal 0 HcmV?d00001 diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 51ab71090..362c90c7e 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -8,4 +8,7 @@ first mock + + 카카오로 로그인하기 + \ No newline at end of file From 552b34fc74981a9065f1153297f528efc4f6fb78 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 17:42:45 +0900 Subject: [PATCH 09/19] =?UTF-8?q?[FEAT/#5]=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=ED=86=A1=20=EC=86=8C=EC=85=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/terning/point/MyApp.kt | 5 ++ .../com/terning/core/extension/ContextExt.kt | 4 +- .../com/terning/feature/main/MainScreen.kt | 5 +- .../com/terning/feature/mock/MockRoute.kt | 2 +- .../feature/onboarding/signin/SignInRoute.kt | 37 +++++++++- .../onboarding/signin/SignInSideEffect.kt | 7 ++ .../feature/onboarding/signin/SignInState.kt | 7 ++ .../onboarding/signin/SignInViewModel.kt | 72 ++++++++++++++++++- .../signin/navigation/SignInNavigation.kt | 9 ++- feature/src/main/res/values/strings.xml | 3 + 10 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt create mode 100644 feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 8e8cc6670..9cd58ab1d 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -1,10 +1,12 @@ package com.terning.point import android.app.Application +import android.util.Log import androidx.appcompat.app.AppCompatDelegate import dagger.hilt.android.HiltAndroidApp import timber.log.Timber import com.kakao.sdk.common.KakaoSdk +import com.kakao.sdk.common.util.Utility @HiltAndroidApp class MyApp : Application() { @@ -15,6 +17,9 @@ class MyApp : Application() { initTimber() setDayMode() initKakoSdk() + + var keyHash = Utility.getKeyHash(this) + Log.i("GlobalApplication", "$keyHash") } private fun initTimber() { diff --git a/core/src/main/java/com/terning/core/extension/ContextExt.kt b/core/src/main/java/com/terning/core/extension/ContextExt.kt index 7deeaaec9..277fa47a1 100644 --- a/core/src/main/java/com/terning/core/extension/ContextExt.kt +++ b/core/src/main/java/com/terning/core/extension/ContextExt.kt @@ -7,8 +7,8 @@ import android.view.inputmethod.InputMethodManager import android.widget.Toast import androidx.annotation.StringRes -fun Context.toast(@StringRes message: Int) { - Toast.makeText(this, getString(message), Toast.LENGTH_SHORT).show() +fun Context.toast( message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } fun Context.longToast(@StringRes message: Int) { diff --git a/feature/src/main/java/com/terning/feature/main/MainScreen.kt b/feature/src/main/java/com/terning/feature/main/MainScreen.kt index c079e6d9d..43c2b2241 100644 --- a/feature/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/src/main/java/com/terning/feature/main/MainScreen.kt @@ -19,6 +19,7 @@ import androidx.navigation.compose.NavHost import com.terning.feature.first.navigation.firstNavGraph import com.terning.feature.mock.navigation.mockNavGraph import com.terning.feature.onboarding.signin.navigation.signInNavGraph +import com.terning.feature.onboarding.signup.navigation.signUpNavGraph @Composable fun MainScreen( @@ -45,8 +46,8 @@ fun MainScreen( ) { firstNavGraph() mockNavGraph() - signInNavGraph() - signInNavGraph() + signInNavGraph( navHostController = navigator.navController) + signUpNavGraph() } } } diff --git a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt index a9a958ddf..2cb8cad65 100644 --- a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt +++ b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt @@ -36,7 +36,7 @@ fun MockRoute( viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) .collect { sideEffect -> when (sideEffect) { - is MockSideEffect.Toast -> context.toast(sideEffect.message) + is MockSideEffect.Toast -> context.toast(sideEffect.message.toString()) } } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index b5eb56842..bb291ed5f 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -4,25 +4,55 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.flowWithLifecycle +import androidx.navigation.NavHostController +import com.terning.core.extension.toast import com.terning.feature.R +import com.terning.feature.first.navigation.navigateFirst import com.terning.feature.onboarding.signin.component.KakaoButton @Composable -fun SignInRoute() { +fun SignInRoute( + viewModel: SignInViewModel = hiltViewModel(), + navController: NavHostController, +) { + val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + val signInState by viewModel.signInState.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner) - SignInScreen() + LaunchedEffect(viewModel.signInSideEffects, lifecycleOwner) { + viewModel.signInSideEffects.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) + .collect { sideEffect -> + when (sideEffect) { + is SignInSideEffect.ShowToast -> context.toast(sideEffect.message) + is SignInSideEffect.NavigateToMain -> navController.navigateFirst() + } + } + } + + SignInScreen( + onSignInClick = { viewModel.startKakaoLogIn(context) } + ) } @Composable fun SignInScreen( + modifier: Modifier = Modifier, onSignInClick: () -> Unit = {} ) { Column( @@ -39,7 +69,8 @@ fun SignInScreen( ) KakaoButton( title = stringResource(id = R.string.sign_in_kakao_button), - onSignInClick = { onSignInClick() } + onSignInClick = { onSignInClick() }, + modifier = modifier.padding(horizontal = 20.dp) ) } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt new file mode 100644 index 000000000..9273eb1d2 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt @@ -0,0 +1,7 @@ +package com.terning.feature.onboarding.signin + +sealed class SignInSideEffect { + data object NavigateToMain : SignInSideEffect() + // data class ShowToast(@StringRes val message: Int, val formatArgs: List = emptyList()) : SignInSideEffect() + data class ShowToast(val message: String) : SignInSideEffect() +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt new file mode 100644 index 000000000..1eba33899 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt @@ -0,0 +1,7 @@ +package com.terning.feature.onboarding.signin + +import com.terning.core.state.UiState + +data class SignInState ( + val accessToken: UiState? = UiState.Loading +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index bef98fbfc..d43945d15 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -1,4 +1,74 @@ package com.terning.feature.onboarding.signin -class SignInViewModel { +import android.content.Context +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +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 com.terning.core.state.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SignInViewModel @Inject constructor() : ViewModel() { + + private val _signInState = MutableStateFlow(SignInState()) + val signInState: StateFlow + get() = _signInState.asStateFlow() + + private val _signInSideEffects = MutableSharedFlow() + val signInSideEffects: SharedFlow + get() = _signInSideEffects.asSharedFlow() + + fun startKakaoLogIn(context: Context) { + // 카카오톡 실행 가능 여부 확인 + if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { + // 카카오톡 로그인 시도 + UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> + signInResult(context, token, error) + } + } else { + // 카카오톡 앱이 없는 경우에 웹 로그인 활용 + UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> + signInResult(context, token, error) + } + } + } + + private fun signInResult(context: Context, token: OAuthToken?, error: Throwable?) { + viewModelScope.launch { + if (error != null) { + if (error.toString().contains("statusCode=302")) { + UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> + signInResult(context, token, error) + // 성공 후에 넘어가게 + } + } else { + if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { + // 로그인 취소 처리 + _signInSideEffects.emit(SignInSideEffect.ShowToast("로그인 취소")) + } else { + // 로그인 실패 처리 + _signInSideEffects.emit(SignInSideEffect.ShowToast("로그인 실패 ${error.localizedMessage}")) + Log.d("kakao", error.toString()) + } + } + } else if (token != null) { + // 로그인 성공 처리 (액세스 토큰 저장 및 메인 화면으로 이동) + _signInState.value = + _signInState.value.copy(accessToken = UiState.Success(token.accessToken)) + _signInSideEffects.emit(SignInSideEffect.NavigateToMain) + } + } + } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt index ccfd53068..0c3d35760 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/navigation/SignInNavigation.kt @@ -2,6 +2,7 @@ package com.terning.feature.onboarding.signin.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController import androidx.navigation.NavOptions import androidx.navigation.compose.composable import com.terning.core.navigation.MainTabRoute @@ -15,9 +16,13 @@ fun NavController.navigateSignIn(navOptions: NavOptions? = null) { ) } -fun NavGraphBuilder.signInNavGraph() { +fun NavGraphBuilder.signInNavGraph( + navHostController: NavHostController +) { composable { - SignInRoute() + SignInRoute( + navController = navHostController + ) } } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 362c90c7e..20ebfecdc 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -10,5 +10,8 @@ 카카오로 로그인하기 + 카카오톡 로그인 실패 %s + 웹 로그인 실패 + 로그인 취소 \ No newline at end of file From 8b3b34b78bf71a19de39850c7e326a271eff642c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 18:14:30 +0900 Subject: [PATCH 10/19] =?UTF-8?q?[FEAT/#5]=20SignInViewModel=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/core/extension/ContextExt.kt | 7 +-- .../com/terning/feature/mock/MockRoute.kt | 2 +- .../onboarding/signin/SignInSideEffect.kt | 5 +- .../onboarding/signin/SignInViewModel.kt | 58 +++++++++++-------- feature/src/main/res/values/strings.xml | 5 +- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/com/terning/core/extension/ContextExt.kt b/core/src/main/java/com/terning/core/extension/ContextExt.kt index 277fa47a1..370fb9f06 100644 --- a/core/src/main/java/com/terning/core/extension/ContextExt.kt +++ b/core/src/main/java/com/terning/core/extension/ContextExt.kt @@ -1,14 +1,11 @@ package com.terning.core.extension -import android.app.Activity import android.content.Context -import android.view.View -import android.view.inputmethod.InputMethodManager import android.widget.Toast import androidx.annotation.StringRes -fun Context.toast( message: String) { - Toast.makeText(this, message, Toast.LENGTH_SHORT).show() +fun Context.toast(@StringRes message: Int) { + Toast.makeText(this, getString(message), Toast.LENGTH_SHORT).show() } fun Context.longToast(@StringRes message: Int) { diff --git a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt index 2cb8cad65..a9a958ddf 100644 --- a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt +++ b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt @@ -36,7 +36,7 @@ fun MockRoute( viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) .collect { sideEffect -> when (sideEffect) { - is MockSideEffect.Toast -> context.toast(sideEffect.message.toString()) + is MockSideEffect.Toast -> context.toast(sideEffect.message) } } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt index 9273eb1d2..f08decff9 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt @@ -1,7 +1,8 @@ package com.terning.feature.onboarding.signin +import androidx.annotation.StringRes + sealed class SignInSideEffect { data object NavigateToMain : SignInSideEffect() - // data class ShowToast(@StringRes val message: Int, val formatArgs: List = emptyList()) : SignInSideEffect() - data class ShowToast(val message: String) : SignInSideEffect() + data class ShowToast(@StringRes val message: Int) : SignInSideEffect() } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index d43945d15..90c72292d 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -1,7 +1,6 @@ package com.terning.feature.onboarding.signin import android.content.Context -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kakao.sdk.auth.model.OAuthToken @@ -9,6 +8,7 @@ import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient import com.terning.core.state.UiState +import com.terning.feature.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -31,14 +31,11 @@ class SignInViewModel @Inject constructor() : ViewModel() { get() = _signInSideEffects.asSharedFlow() fun startKakaoLogIn(context: Context) { - // 카카오톡 실행 가능 여부 확인 if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { - // 카카오톡 로그인 시도 UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> signInResult(context, token, error) } } else { - // 카카오톡 앱이 없는 경우에 웹 로그인 활용 UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> signInResult(context, token, error) } @@ -48,27 +45,42 @@ class SignInViewModel @Inject constructor() : ViewModel() { private fun signInResult(context: Context, token: OAuthToken?, error: Throwable?) { viewModelScope.launch { if (error != null) { - if (error.toString().contains("statusCode=302")) { - UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> - signInResult(context, token, error) - // 성공 후에 넘어가게 - } - } else { - if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { - // 로그인 취소 처리 - _signInSideEffects.emit(SignInSideEffect.ShowToast("로그인 취소")) - } else { - // 로그인 실패 처리 - _signInSideEffects.emit(SignInSideEffect.ShowToast("로그인 실패 ${error.localizedMessage}")) - Log.d("kakao", error.toString()) - } - } + signInFailure(context, token, error) } else if (token != null) { - // 로그인 성공 처리 (액세스 토큰 저장 및 메인 화면으로 이동) - _signInState.value = - _signInState.value.copy(accessToken = UiState.Success(token.accessToken)) - _signInSideEffects.emit(SignInSideEffect.NavigateToMain) + signInSuccess(token) } } } + + private fun signInFailure(context: Context, token: OAuthToken?, error: Throwable?) { + if (error.toString().contains(KAKAO_NOT_LOGGED_IN)) { + UserApiClient.instance.loginWithKakaoAccount(context) { _, _ -> + signInResult(context, token, error) + } + } else { + sigInCancellationOrError(error) + } + } + + private fun sigInCancellationOrError(error: Throwable?) { + viewModelScope.launch { + if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { + _signInSideEffects.emit(SignInSideEffect.ShowToast(R.string.sign_in_kakao_cancel)) + } else { + _signInSideEffects.emit(SignInSideEffect.ShowToast(R.string.sign_in_kakao_login_fail)) + } + } + } + + private fun signInSuccess(token: OAuthToken) { + viewModelScope.launch { + _signInState.value = + _signInState.value.copy(accessToken = UiState.Success(token.accessToken)) + _signInSideEffects.emit(SignInSideEffect.NavigateToMain) + } + } + + companion object { + private const val KAKAO_NOT_LOGGED_IN = "statusCode=302" + } } \ No newline at end of file diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 20ebfecdc..711aa3563 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -10,8 +10,7 @@ 카카오로 로그인하기 - 카카오톡 로그인 실패 %s - 웹 로그인 실패 - 로그인 취소 + 카카오톡 로그인에 실패했습니다 + 로그인을 취소하였습니다 \ No newline at end of file From 350c569bcb2e1048f7a777303cbee9c7589c23d0 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 18:35:19 +0900 Subject: [PATCH 11/19] =?UTF-8?q?[CHORE/#5]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/terning/feature/mock/MockRoute.kt | 2 +- .../com/terning/feature/onboarding/signin/SignInRoute.kt | 8 +++++--- .../feature/onboarding/signin/component/KakaoButton.kt | 9 +++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt index a9a958ddf..2890a19f9 100644 --- a/feature/src/main/java/com/terning/feature/mock/MockRoute.kt +++ b/feature/src/main/java/com/terning/feature/mock/MockRoute.kt @@ -26,7 +26,7 @@ fun MockRoute( val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current - val state by viewModel.state.collectAsStateWithLifecycle(lifecycleOwner = LocalLifecycleOwner.current) + val state by viewModel.state.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner) LaunchedEffect(key1 = true) { viewModel.getFriendsInfo(2) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index bb291ed5f..5e7342f2f 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -21,6 +21,7 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import androidx.navigation.NavHostController +import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.toast import com.terning.feature.R import com.terning.feature.first.navigation.navigateFirst @@ -64,8 +65,7 @@ fun SignInScreen( painter = painterResource(id = R.drawable.img_terning_point), contentDescription = null, modifier = Modifier - .size(500.dp) - .aspectRatio(1f), + .size(500.dp), ) KakaoButton( title = stringResource(id = R.string.sign_in_kakao_button), @@ -78,5 +78,7 @@ fun SignInScreen( @Preview(showBackground = true) @Composable fun SignInScreenPreview() { - SignInScreen() + TerningTheme { + SignInScreen() + } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt index 1179e6ec9..97591bb83 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/component/KakaoButton.kt @@ -14,10 +14,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.noRippleClickable import com.terning.feature.R - @Composable fun KakaoButton( title: String, @@ -48,5 +48,10 @@ fun KakaoButton( @Preview(showBackground = true) @Composable fun KakaoButtonPreview() { - KakaoButton("카카오로 로그인하기", onSignInClick = {}) + TerningTheme { + KakaoButton( + title = "카카오로 로그인하기", + onSignInClick = {} + ) + } } \ No newline at end of file From ac8dd672952086bc6d3917663ccbd1c190180216 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 18:39:43 +0900 Subject: [PATCH 12/19] =?UTF-8?q?[CHORE/#5]=20nonnull=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/terning/feature/onboarding/signin/SignInState.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt index 1eba33899..f517d6e63 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInState.kt @@ -3,5 +3,5 @@ package com.terning.feature.onboarding.signin import com.terning.core.state.UiState data class SignInState ( - val accessToken: UiState? = UiState.Loading + val accessToken: UiState = UiState.Loading ) \ No newline at end of file From 47aa109a5a4c6d76235df590b923f054c0462154 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 6 Jul 2024 18:44:28 +0900 Subject: [PATCH 13/19] =?UTF-8?q?[CHORE/#5]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/terning/point/MyApp.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 9cd58ab1d..005a6a02a 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -17,9 +17,6 @@ class MyApp : Application() { initTimber() setDayMode() initKakoSdk() - - var keyHash = Utility.getKeyHash(this) - Log.i("GlobalApplication", "$keyHash") } private fun initTimber() { From 354052106a1e12a12f1a2664e19974af90413b61 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 04:53:01 +0900 Subject: [PATCH 14/19] =?UTF-8?q?[FIX/#5]=20=EC=BB=A8=ED=94=8C=EB=A6=AD=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/feature/onboarding/signin/SignInRoute.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index 5e7342f2f..bb6689889 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -2,7 +2,6 @@ package com.terning.feature.onboarding.signin import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -24,7 +23,7 @@ import androidx.navigation.NavHostController import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.toast import com.terning.feature.R -import com.terning.feature.first.navigation.navigateFirst +import com.terning.feature.home.navigation.navigateHome import com.terning.feature.onboarding.signin.component.KakaoButton @Composable @@ -41,7 +40,7 @@ fun SignInRoute( .collect { sideEffect -> when (sideEffect) { is SignInSideEffect.ShowToast -> context.toast(sideEffect.message) - is SignInSideEffect.NavigateToMain -> navController.navigateFirst() + is SignInSideEffect.NavigateToMain -> navController.navigateHome() } } } From 4bcb604bb7fa9282dcef3dba73215a737c6a3ff0 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 05:27:42 +0900 Subject: [PATCH 15/19] =?UTF-8?q?[FIX/#5]=20=EB=AC=B4=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/terning/point/MyApp.kt | 6 ++---- .../terning/feature/onboarding/signin/SignInRoute.kt | 1 + .../feature/onboarding/signin/SignInViewModel.kt | 12 ++++++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/terning/point/MyApp.kt b/app/src/main/java/com/terning/point/MyApp.kt index 005a6a02a..2d991562c 100644 --- a/app/src/main/java/com/terning/point/MyApp.kt +++ b/app/src/main/java/com/terning/point/MyApp.kt @@ -1,12 +1,10 @@ package com.terning.point import android.app.Application -import android.util.Log import androidx.appcompat.app.AppCompatDelegate +import com.kakao.sdk.common.KakaoSdk import dagger.hilt.android.HiltAndroidApp import timber.log.Timber -import com.kakao.sdk.common.KakaoSdk -import com.kakao.sdk.common.util.Utility @HiltAndroidApp class MyApp : Application() { @@ -27,7 +25,7 @@ class MyApp : Application() { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) } - private fun initKakoSdk(){ + private fun initKakoSdk() { KakaoSdk.init(this, BuildConfig.NATIVE_APP_KEY) } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index bb6689889..5b4c9baab 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -24,6 +24,7 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.toast import com.terning.feature.R import com.terning.feature.home.navigation.navigateHome +import com.terning.feature.mypage.navigation.navigateMyPage import com.terning.feature.onboarding.signin.component.KakaoButton @Composable diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index 90c72292d..1ab0a6824 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -45,17 +45,21 @@ class SignInViewModel @Inject constructor() : ViewModel() { private fun signInResult(context: Context, token: OAuthToken?, error: Throwable?) { viewModelScope.launch { if (error != null) { - signInFailure(context, token, error) + signInFailure(context, error) } else if (token != null) { signInSuccess(token) } } } - private fun signInFailure(context: Context, token: OAuthToken?, error: Throwable?) { + private fun signInFailure(context: Context, error: Throwable?) { if (error.toString().contains(KAKAO_NOT_LOGGED_IN)) { - UserApiClient.instance.loginWithKakaoAccount(context) { _, _ -> - signInResult(context, token, error) + UserApiClient.instance.loginWithKakaoAccount(context) { token, _ -> + if (error != null) { + sigInCancellationOrError(error) + } else if (token != null) { + signInSuccess(token) + } } } else { sigInCancellationOrError(error) From 11104168ffd883a59d7eb2b93279e330493f4156 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 05:58:31 +0900 Subject: [PATCH 16/19] =?UTF-8?q?[FIX/#5]=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/onboarding/signin/SignInViewModel.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index 1ab0a6824..de5e914f5 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -54,12 +54,8 @@ class SignInViewModel @Inject constructor() : ViewModel() { private fun signInFailure(context: Context, error: Throwable?) { if (error.toString().contains(KAKAO_NOT_LOGGED_IN)) { - UserApiClient.instance.loginWithKakaoAccount(context) { token, _ -> - if (error != null) { - sigInCancellationOrError(error) - } else if (token != null) { - signInSuccess(token) - } + UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> + signInResult(context, token, error) } } else { sigInCancellationOrError(error) @@ -87,4 +83,4 @@ class SignInViewModel @Inject constructor() : ViewModel() { companion object { private const val KAKAO_NOT_LOGGED_IN = "statusCode=302" } -} \ No newline at end of file +} From 2dc3f9808e46e84275a63d546821c725aaee575a Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 06:02:12 +0900 Subject: [PATCH 17/19] =?UTF-8?q?[CHORE/#5]=20NavigateToHome=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/terning/feature/onboarding/signin/SignInRoute.kt | 3 +-- .../com/terning/feature/onboarding/signin/SignInSideEffect.kt | 2 +- .../com/terning/feature/onboarding/signin/SignInViewModel.kt | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt index 5b4c9baab..707a13a21 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInRoute.kt @@ -24,7 +24,6 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.toast import com.terning.feature.R import com.terning.feature.home.navigation.navigateHome -import com.terning.feature.mypage.navigation.navigateMyPage import com.terning.feature.onboarding.signin.component.KakaoButton @Composable @@ -41,7 +40,7 @@ fun SignInRoute( .collect { sideEffect -> when (sideEffect) { is SignInSideEffect.ShowToast -> context.toast(sideEffect.message) - is SignInSideEffect.NavigateToMain -> navController.navigateHome() + is SignInSideEffect.NavigateToHome -> navController.navigateHome() } } } diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt index f08decff9..412652e66 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInSideEffect.kt @@ -3,6 +3,6 @@ package com.terning.feature.onboarding.signin import androidx.annotation.StringRes sealed class SignInSideEffect { - data object NavigateToMain : SignInSideEffect() + data object NavigateToHome : SignInSideEffect() data class ShowToast(@StringRes val message: Int) : SignInSideEffect() } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt index de5e914f5..639b9eb71 100644 --- a/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt +++ b/feature/src/main/java/com/terning/feature/onboarding/signin/SignInViewModel.kt @@ -76,7 +76,7 @@ class SignInViewModel @Inject constructor() : ViewModel() { viewModelScope.launch { _signInState.value = _signInState.value.copy(accessToken = UiState.Success(token.accessToken)) - _signInSideEffects.emit(SignInSideEffect.NavigateToMain) + _signInSideEffects.emit(SignInSideEffect.NavigateToHome) } } From da0b647a03b2d39064078779b8f524988d32c630 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 06:04:34 +0900 Subject: [PATCH 18/19] [CHORE/#5] startDestination SignIn -> Home --- .../src/main/java/com/terning/feature/main/MainNavigator.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt index 472557036..a885ac342 100644 --- a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -10,9 +10,9 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import com.terning.feature.calendar.navigation.navigateCalendar +import com.terning.feature.home.navigation.Home import com.terning.feature.home.navigation.navigateHome import com.terning.feature.mypage.navigation.navigateMyPage -import com.terning.feature.onboarding.signin.navigation.SignIn import com.terning.feature.search.navigation.navigateSearch class MainNavigator( @@ -22,7 +22,7 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - val startDestination = SignIn + val startDestination = Home val currentTab: MainTab? @Composable get() = MainTab.find { tab -> From a8449f02693a83d7768fceb41559afe33cb92cff Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 7 Jul 2024 06:11:50 +0900 Subject: [PATCH 19/19] [CHORE/#5] startDestination Home -> SignIn --- .../src/main/java/com/terning/feature/main/MainNavigator.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt index a885ac342..472557036 100644 --- a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -10,9 +10,9 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import com.terning.feature.calendar.navigation.navigateCalendar -import com.terning.feature.home.navigation.Home import com.terning.feature.home.navigation.navigateHome import com.terning.feature.mypage.navigation.navigateMyPage +import com.terning.feature.onboarding.signin.navigation.SignIn import com.terning.feature.search.navigation.navigateSearch class MainNavigator( @@ -22,7 +22,7 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - val startDestination = Home + val startDestination = SignIn val currentTab: MainTab? @Composable get() = MainTab.find { tab ->