diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index bf2077f2..4a9e40b0 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -33,7 +33,7 @@ android {
gradleLocalProperties(rootDir).getProperty("native.app.key"),
)
manifestPlaceholders["NATIVE_APP_KEY"] =
- gradleLocalProperties(rootDir).getProperty("native.app.key")
+ gradleLocalProperties(rootDir).getProperty("nativeAppKey")
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 06886f39..313da73a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,12 +21,11 @@
android:exported="true">
-
-
+
@@ -37,7 +36,7 @@
android:screenOrientation="portrait" />
@@ -48,7 +47,7 @@
@@ -58,7 +57,7 @@
android:screenOrientation="portrait" />
diff --git a/app/src/main/java/com/going/going/di/DataSourceModule.kt b/app/src/main/java/com/going/going/di/DataSourceModule.kt
index 9e7eb073..66020dce 100644
--- a/app/src/main/java/com/going/going/di/DataSourceModule.kt
+++ b/app/src/main/java/com/going/going/di/DataSourceModule.kt
@@ -1,8 +1,8 @@
package com.going.going.di
-import com.going.data.datasource.LoginDataSource
+import com.going.data.datasource.AuthDataSource
import com.going.data.datasource.MockDataSource
-import com.going.data.datasourceImpl.LoginDataSourceImpl
+import com.going.data.datasourceImpl.AuthDataSourceImpl
import com.going.data.datasourceImpl.MockDataSourceImpl
import dagger.Module
import dagger.Provides
@@ -21,8 +21,6 @@ object DataSourceModule {
@Provides
@Singleton
- fun provideLoginDataSource(loginDataSourceImpl: LoginDataSourceImpl): LoginDataSource =
- loginDataSourceImpl
-
-
+ fun provideAuthDataSource(authDataSourceImpl: AuthDataSourceImpl): AuthDataSource =
+ authDataSourceImpl
}
diff --git a/app/src/main/java/com/going/going/di/DataStoreModule.kt b/app/src/main/java/com/going/going/di/DataStoreModule.kt
new file mode 100644
index 00000000..52a36091
--- /dev/null
+++ b/app/src/main/java/com/going/going/di/DataStoreModule.kt
@@ -0,0 +1,27 @@
+package com.going.going.di
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.going.data.local.GoingDataStoreImpl
+import com.going.data.local.GoingDataStore
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object DataStoreModule {
+
+ @Provides
+ @Singleton
+ fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences =
+ context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
+
+ @Provides
+ @Singleton
+ fun provideGoingDataStore(dataStoreImpl: GoingDataStoreImpl): GoingDataStore =
+ dataStoreImpl
+}
diff --git a/app/src/main/java/com/going/going/di/RepositoryModule.kt b/app/src/main/java/com/going/going/di/RepositoryModule.kt
index 54247470..cad8a8ac 100644
--- a/app/src/main/java/com/going/going/di/RepositoryModule.kt
+++ b/app/src/main/java/com/going/going/di/RepositoryModule.kt
@@ -1,8 +1,10 @@
package com.going.going.di
-import com.going.data.repositoryImpl.LoginRepositoryImpl
+import com.going.data.repositoryImpl.TokenRepositoryImpl
+import com.going.data.repositoryImpl.AuthRepositoryImpl
import com.going.data.repositoryImpl.MockRepositoryImpl
-import com.going.domain.repository.LoginRepository
+import com.going.domain.repository.TokenRepository
+import com.going.domain.repository.AuthRepository
import com.going.domain.repository.MockRepository
import dagger.Module
import dagger.Provides
@@ -21,6 +23,11 @@ object RepositoryModule {
@Provides
@Singleton
- fun provideLoginRepository(loginRepositoryImpl: LoginRepositoryImpl): LoginRepository =
- loginRepositoryImpl
+ fun provideAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository =
+ authRepositoryImpl
+
+ @Provides
+ @Singleton
+ fun provideTokenRepository(tokenRepositoryImpl: TokenRepositoryImpl): TokenRepository =
+ tokenRepositoryImpl
}
diff --git a/app/src/main/java/com/going/going/di/ServiceModule.kt b/app/src/main/java/com/going/going/di/ServiceModule.kt
index 1f39737b..1e96393d 100644
--- a/app/src/main/java/com/going/going/di/ServiceModule.kt
+++ b/app/src/main/java/com/going/going/di/ServiceModule.kt
@@ -1,6 +1,6 @@
package com.going.going.di
-import com.going.data.service.LoginService
+import com.going.data.service.AuthService
import com.going.data.service.MockService
import dagger.Module
import dagger.Provides
@@ -20,7 +20,6 @@ object ServiceModule {
@Provides
@Singleton
- fun provideLoginService(retrofit: Retrofit): LoginService =
- retrofit.create(LoginService::class.java)
-
+ fun provideLoginService(retrofit: Retrofit): AuthService =
+ retrofit.create(AuthService::class.java)
}
diff --git a/core-ui/build.gradle.kts b/core-ui/build.gradle.kts
index c9e7e617..eccb92a0 100644
--- a/core-ui/build.gradle.kts
+++ b/core-ui/build.gradle.kts
@@ -47,4 +47,4 @@ dependencies {
testImplementation(TestDependencies.jUnit)
androidTestImplementation(TestDependencies.androidTest)
androidTestImplementation(TestDependencies.espresso)
-}
\ No newline at end of file
+}
diff --git a/data/src/main/java/com/going/data/datasource/AuthDataSource.kt b/data/src/main/java/com/going/data/datasource/AuthDataSource.kt
new file mode 100644
index 00000000..e0da7f45
--- /dev/null
+++ b/data/src/main/java/com/going/data/datasource/AuthDataSource.kt
@@ -0,0 +1,18 @@
+package com.going.data.datasource
+
+import com.going.data.dto.BaseResponse
+import com.going.data.dto.request.SignInRequestDto
+import com.going.data.dto.request.SignUpRequestDto
+import com.going.data.dto.response.AuthResponseDto
+
+interface AuthDataSource {
+ suspend fun postSignIn(
+ Authorization: String,
+ platform: SignInRequestDto,
+ ): BaseResponse
+
+ suspend fun postSignUp(
+ Authorization: String,
+ data: SignUpRequestDto,
+ ): BaseResponse
+}
diff --git a/data/src/main/java/com/going/data/datasource/LoginDataSource.kt b/data/src/main/java/com/going/data/datasource/LoginDataSource.kt
deleted file mode 100644
index 254e1b4c..00000000
--- a/data/src/main/java/com/going/data/datasource/LoginDataSource.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.going.data.datasource
-
-import com.going.data.dto.BaseResponse
-import com.going.data.dto.request.RequestLoginDto
-import com.going.data.dto.response.LoginResponseDto
-
-interface LoginDataSource {
- suspend fun postLogin(
- Authorization: String,
- platform: RequestLoginDto,
- ): BaseResponse
-}
diff --git a/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt
new file mode 100644
index 00000000..2c561ab7
--- /dev/null
+++ b/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt
@@ -0,0 +1,24 @@
+package com.going.data.datasourceImpl
+
+import com.going.data.datasource.AuthDataSource
+import com.going.data.dto.BaseResponse
+import com.going.data.dto.request.SignInRequestDto
+import com.going.data.dto.request.SignUpRequestDto
+import com.going.data.dto.response.AuthResponseDto
+import com.going.data.service.AuthService
+import javax.inject.Inject
+
+class AuthDataSourceImpl @Inject constructor(
+ private val authService: AuthService,
+) : AuthDataSource {
+ override suspend fun postSignIn(
+ Authorization: String,
+ platform: SignInRequestDto,
+ ): BaseResponse =
+ authService.postSignin(Authorization, platform)
+
+ override suspend fun postSignUp(
+ Authorization: String,
+ data: SignUpRequestDto,
+ ): BaseResponse = authService.postSignUp(Authorization, data)
+}
diff --git a/data/src/main/java/com/going/data/datasourceImpl/LoginDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/LoginDataSourceImpl.kt
deleted file mode 100644
index b2f5c59b..00000000
--- a/data/src/main/java/com/going/data/datasourceImpl/LoginDataSourceImpl.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.going.data.datasourceImpl
-
-import com.going.data.datasource.LoginDataSource
-import com.going.data.dto.BaseResponse
-import com.going.data.dto.request.RequestLoginDto
-import com.going.data.dto.response.LoginResponseDto
-import com.going.data.service.LoginService
-import javax.inject.Inject
-
-class LoginDataSourceImpl @Inject constructor(
- private val loginService: LoginService,
-) : LoginDataSource {
- override suspend fun postLogin(
- Authorization: String,
- platform: RequestLoginDto,
- ): BaseResponse =
- loginService.postSignin(Authorization, platform)
-}
diff --git a/data/src/main/java/com/going/data/dto/request/RequestLoginDto.kt b/data/src/main/java/com/going/data/dto/request/RequestLoginDto.kt
deleted file mode 100644
index a10a4310..00000000
--- a/data/src/main/java/com/going/data/dto/request/RequestLoginDto.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.going.data.dto.request
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class RequestLoginDto(
- @SerialName("platform")
- val platform: String
-)
diff --git a/data/src/main/java/com/going/data/dto/request/SignInRequestDto.kt b/data/src/main/java/com/going/data/dto/request/SignInRequestDto.kt
new file mode 100644
index 00000000..bd982038
--- /dev/null
+++ b/data/src/main/java/com/going/data/dto/request/SignInRequestDto.kt
@@ -0,0 +1,15 @@
+package com.going.data.dto.request
+
+import com.going.domain.entity.request.RequestSignInModel
+import com.going.domain.entity.request.RequestSignUpModel
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SignInRequestDto(
+ @SerialName("platform")
+ val platform: String
+)
+
+fun RequestSignInModel.toSignInRequestDto(): SignInRequestDto =
+ SignInRequestDto(platform)
diff --git a/data/src/main/java/com/going/data/dto/request/SignUpRequestDto.kt b/data/src/main/java/com/going/data/dto/request/SignUpRequestDto.kt
new file mode 100644
index 00000000..c5f8b525
--- /dev/null
+++ b/data/src/main/java/com/going/data/dto/request/SignUpRequestDto.kt
@@ -0,0 +1,18 @@
+package com.going.data.dto.request
+
+import com.going.domain.entity.request.RequestSignUpModel
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SignUpRequestDto(
+ @SerialName("name")
+ val name: String,
+ @SerialName("intro")
+ val intro: String,
+ @SerialName("platform")
+ val platform: String,
+)
+
+fun RequestSignUpModel.toSignUpRequestDto(): SignUpRequestDto =
+ SignUpRequestDto(name, intro, platform)
diff --git a/data/src/main/java/com/going/data/dto/response/AuthResponseDto.kt b/data/src/main/java/com/going/data/dto/response/AuthResponseDto.kt
new file mode 100644
index 00000000..25cc1041
--- /dev/null
+++ b/data/src/main/java/com/going/data/dto/response/AuthResponseDto.kt
@@ -0,0 +1,16 @@
+package com.going.data.dto.response
+
+import com.going.domain.entity.response.AuthTokenModel
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class AuthResponseDto(
+ @SerialName("accessToken")
+ val accessToken: String,
+ @SerialName("refreshToken")
+ val refreshToken: String,
+) {
+ fun toAuthTokenModel() =
+ AuthTokenModel(accessToken = accessToken, refreshToken = refreshToken)
+}
diff --git a/data/src/main/java/com/going/data/dto/response/LoginResponseDto.kt b/data/src/main/java/com/going/data/dto/response/LoginResponseDto.kt
deleted file mode 100644
index c52b73e6..00000000
--- a/data/src/main/java/com/going/data/dto/response/LoginResponseDto.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.going.data.dto.response
-
-import com.going.domain.entity.response.AuthTokenModel
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class LoginResponseDto(
- @SerialName("accessToken")
- val accessToken: String,
- @SerialName("refreshToken")
- val refreshToken: String,
-) {
- fun toAuthTokenModel() =
- AuthTokenModel(accessToken = accessToken, refreshToken = refreshToken)
-}
-
-// @Serializable
-// data class LoginResponseDto(
-// @SerialName("status")
-// val status: Int,
-// @SerialName("message")
-// val message: String,
-// @SerialName("data")
-// val data: Data,
-// ) {
-// @Serializable
-// data class Data(
-// @SerialName("accessToken")
-// val accessToken: String,
-// @SerialName("refreshToken")
-// val refreshToken: String,
-// )
-//
-// fun toAuthTokenModel() =
-// AuthTokenModel(accessToken = data.accessToken, refreshToken = data.refreshToken)
-// }
diff --git a/data/src/main/java/com/going/data/local/GoingDataStore.kt b/data/src/main/java/com/going/data/local/GoingDataStore.kt
new file mode 100644
index 00000000..e331b14c
--- /dev/null
+++ b/data/src/main/java/com/going/data/local/GoingDataStore.kt
@@ -0,0 +1,6 @@
+package com.going.data.local
+
+interface GoingDataStore {
+ var accessToken: String
+ var refreshToken: String
+}
diff --git a/data/src/main/java/com/going/data/local/GoingDataStoreImpl.kt b/data/src/main/java/com/going/data/local/GoingDataStoreImpl.kt
new file mode 100644
index 00000000..d1de4eb1
--- /dev/null
+++ b/data/src/main/java/com/going/data/local/GoingDataStoreImpl.kt
@@ -0,0 +1,22 @@
+package com.going.data.local
+
+import android.content.SharedPreferences
+import androidx.core.content.edit
+import javax.inject.Inject
+
+class GoingDataStoreImpl @Inject constructor(
+ private val dataStore: SharedPreferences,
+) : GoingDataStore {
+ override var accessToken: String
+ get() = dataStore.getString(ACCESS_TOKEN, "") ?: ""
+ set(value) = dataStore.edit { putString(ACCESS_TOKEN, value) }
+
+ override var refreshToken: String
+ get() = dataStore.getString(REFRESH_TOKEN, "") ?: ""
+ set(value) = dataStore.edit { putString(REFRESH_TOKEN, value) }
+
+ companion object {
+ private const val ACCESS_TOKEN = "ACCESS_TOKEN"
+ private const val REFRESH_TOKEN = "REFRESH_TOKEN"
+ }
+}
diff --git a/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt
new file mode 100644
index 00000000..4aeb29db
--- /dev/null
+++ b/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt
@@ -0,0 +1,36 @@
+package com.going.data.repositoryImpl
+
+import com.going.data.datasource.AuthDataSource
+import com.going.data.dto.request.toSignInRequestDto
+import com.going.data.dto.request.toSignUpRequestDto
+import com.going.domain.entity.request.RequestSignInModel
+import com.going.domain.entity.request.RequestSignUpModel
+import com.going.domain.entity.response.AuthTokenModel
+import com.going.domain.repository.AuthRepository
+import javax.inject.Inject
+
+class AuthRepositoryImpl @Inject constructor(
+ private val authDataSource: AuthDataSource,
+) : AuthRepository {
+ override suspend fun postSignIn(
+ Authorization: String,
+ requestSignIpModel: RequestSignInModel,
+ ): Result =
+ runCatching {
+ authDataSource.postSignIn(
+ Authorization,
+ requestSignIpModel.toSignInRequestDto(),
+ ).data.toAuthTokenModel()
+ }
+
+ override suspend fun postSignUp(
+ Authorization: String,
+ requestSignUpModel: RequestSignUpModel,
+ ): Result =
+ runCatching {
+ authDataSource.postSignUp(
+ Authorization,
+ requestSignUpModel.toSignUpRequestDto(),
+ ).data.toAuthTokenModel()
+ }
+}
diff --git a/data/src/main/java/com/going/data/repositoryImpl/LoginRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/LoginRepositoryImpl.kt
deleted file mode 100644
index 04d5e991..00000000
--- a/data/src/main/java/com/going/data/repositoryImpl/LoginRepositoryImpl.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.going.data.repositoryImpl
-
-import com.going.data.datasource.LoginDataSource
-import com.going.data.dto.request.RequestLoginDto
-import com.going.domain.entity.response.AuthTokenModel
-import com.going.domain.repository.LoginRepository
-import javax.inject.Inject
-
-class LoginRepositoryImpl @Inject constructor(
- private val loginDataSource: LoginDataSource,
-) : LoginRepository {
- override suspend fun postSignin(
- Authorization: String,
- platform: String,
- ): Result =
- runCatching {
- loginDataSource.postLogin(
- Authorization,
- RequestLoginDto(platform),
- ).data.toAuthTokenModel()
- }
-}
diff --git a/data/src/main/java/com/going/data/repositoryImpl/TokenRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/TokenRepositoryImpl.kt
new file mode 100644
index 00000000..ba4b219d
--- /dev/null
+++ b/data/src/main/java/com/going/data/repositoryImpl/TokenRepositoryImpl.kt
@@ -0,0 +1,18 @@
+package com.going.data.repositoryImpl
+
+import com.going.data.local.GoingDataStore
+import com.going.domain.repository.TokenRepository
+import javax.inject.Inject
+
+class TokenRepositoryImpl @Inject constructor(
+ private val goingDataStore: GoingDataStore,
+) : TokenRepository {
+ override fun getAccessToken(): String = goingDataStore.accessToken
+
+ override fun setTokens(accessToken: String, refreshToken: String) {
+ goingDataStore.accessToken = accessToken
+ goingDataStore.refreshToken = refreshToken
+ }
+
+ override fun getRefreshToken(): String = goingDataStore.refreshToken
+}
diff --git a/data/src/main/java/com/going/data/service/AuthService.kt b/data/src/main/java/com/going/data/service/AuthService.kt
new file mode 100644
index 00000000..0102622a
--- /dev/null
+++ b/data/src/main/java/com/going/data/service/AuthService.kt
@@ -0,0 +1,23 @@
+package com.going.data.service
+
+import com.going.data.dto.BaseResponse
+import com.going.data.dto.request.SignInRequestDto
+import com.going.data.dto.request.SignUpRequestDto
+import com.going.data.dto.response.AuthResponseDto
+import retrofit2.http.Body
+import retrofit2.http.Header
+import retrofit2.http.POST
+
+interface AuthService {
+ @POST("api/users/signin")
+ suspend fun postSignin(
+ @Header("Authorization") Authorization: String,
+ @Body body: SignInRequestDto,
+ ): BaseResponse
+
+ @POST("api/users/signup")
+ suspend fun postSignUp(
+ @Header("Authorization") Authorization: String,
+ @Body body: SignUpRequestDto,
+ ): BaseResponse
+}
diff --git a/data/src/main/java/com/going/data/service/LoginService.kt b/data/src/main/java/com/going/data/service/LoginService.kt
deleted file mode 100644
index 1859e29b..00000000
--- a/data/src/main/java/com/going/data/service/LoginService.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.going.data.service
-
-import com.going.data.dto.BaseResponse
-import com.going.data.dto.request.RequestLoginDto
-import com.going.data.dto.response.LoginResponseDto
-import retrofit2.http.Body
-import retrofit2.http.Header
-import retrofit2.http.POST
-
-interface LoginService {
- @POST("api/users/signin")
- suspend fun postSignin(
- @Header("Authorization") Authorization: String,
- @Body body: RequestLoginDto,
- ): BaseResponse
-}
diff --git a/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignInModel.kt b/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignInModel.kt
new file mode 100644
index 00000000..fc88c6ea
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignInModel.kt
@@ -0,0 +1,5 @@
+package com.going.domain.entity.request
+
+data class RequestSignInModel(
+ val platform: String
+)
diff --git a/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignUpModel.kt b/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignUpModel.kt
new file mode 100644
index 00000000..17be5dc3
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/entity/request/RequestSignUpModel.kt
@@ -0,0 +1,7 @@
+package com.going.domain.entity.request
+
+data class RequestSignUpModel(
+ val name: String,
+ val intro: String,
+ val platform: String,
+)
diff --git a/domain/src/main/kotlin/com/going/domain/repository/AuthRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/AuthRepository.kt
new file mode 100644
index 00000000..1f4ebdd7
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/repository/AuthRepository.kt
@@ -0,0 +1,17 @@
+package com.going.domain.repository
+
+import com.going.domain.entity.request.RequestSignInModel
+import com.going.domain.entity.request.RequestSignUpModel
+import com.going.domain.entity.response.AuthTokenModel
+
+interface AuthRepository {
+ suspend fun postSignIn(
+ Authorization: String,
+ data: RequestSignInModel,
+ ): Result
+
+ suspend fun postSignUp(
+ Authorization: String,
+ data: RequestSignUpModel,
+ ): Result
+}
diff --git a/domain/src/main/kotlin/com/going/domain/repository/LoginRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/LoginRepository.kt
deleted file mode 100644
index 8b70be28..00000000
--- a/domain/src/main/kotlin/com/going/domain/repository/LoginRepository.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.going.domain.repository
-
-import com.going.domain.entity.response.AuthTokenModel
-
-interface LoginRepository {
- suspend fun postSignin(
- Authorization: String,
- platform: String,
- ): Result
-}
diff --git a/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt
new file mode 100644
index 00000000..dbcbbff1
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/repository/TokenRepository.kt
@@ -0,0 +1,9 @@
+package com.going.domain.repository
+
+interface TokenRepository {
+ fun getAccessToken(): String
+
+ fun getRefreshToken(): String
+
+ fun setTokens(accessToken: String, refreshToken: String)
+}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingViewModel.kt b/presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingViewModel.kt
deleted file mode 100644
index 73c90f54..00000000
--- a/presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingViewModel.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.going.presentation.onboarding
-
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import com.going.domain.entity.NameState
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import java.text.BreakIterator
-
-class OnboardingProfileSettingViewModel : ViewModel() {
- val name = MutableLiveData(String())
- val nowNameLength = MutableLiveData(0)
- val info = MutableLiveData(String())
- val nowInfoLength = MutableLiveData(0)
-
- val isNameAvailable = MutableLiveData(NameState.Empty)
- val isProfileAvailable = MutableLiveData(false)
-
- private val _isMoveScreenAvailable = MutableStateFlow(false)
- val isMoveScreenAvailable: StateFlow = _isMoveScreenAvailable
-
- fun getMaxNameLen() = MAX_NAME_LEN
- fun getMaxInfoLen() = MAX_INFO_LEN
-
- fun checkProfileAvailable() {
- nowNameLength.value = getGraphemeLength(name.value)
- nowInfoLength.value = getGraphemeLength(info.value)
-
- isNameAvailable.value = when {
- nowNameLength.value == 0 -> NameState.Empty
- name.value.isNullOrBlank() -> NameState.Blank
- else -> NameState.Success
- }
-
- val isInfoAvailable = getGraphemeLength(info.value) in 1..MAX_INFO_LEN
-
- isProfileAvailable.value =
- (isNameAvailable.value == NameState.Success) && isInfoAvailable
- }
-
- // 이모지 포함 글자 수 세는 함수
- private fun getGraphemeLength(value: String?): Int {
- BREAK_ITERATOR.setText(value)
-
- var count = 0
- while (BREAK_ITERATOR.next() != BreakIterator.DONE) {
- count++
- }
-
- return count
- }
-
- fun setIsMoveScreenAvailable() {
- _isMoveScreenAvailable.value = true
- }
-
- companion object {
- val BREAK_ITERATOR: BreakIterator = BreakIterator.getCharacterInstance()
-
- const val MAX_NAME_LEN = 3
- const val MAX_INFO_LEN = 20
- }
-}
diff --git a/presentation/src/main/java/com/going/presentation/auth/SignInActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt
similarity index 57%
rename from presentation/src/main/java/com/going/presentation/auth/SignInActivity.kt
rename to presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt
index a11e9a6f..40de59c6 100644
--- a/presentation/src/main/java/com/going/presentation/auth/SignInActivity.kt
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInActivity.kt
@@ -1,4 +1,4 @@
-package com.going.presentation.auth
+package com.going.presentation.onboarding.signin
import android.content.Intent
import android.net.Uri
@@ -8,9 +8,11 @@ import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.going.presentation.R
import com.going.presentation.databinding.ActivitySigninBinding
+import com.going.presentation.onboarding.signup.OnboardingProfileSettingActivity
+import com.going.presentation.tendencytest.TendencyTestActivity
import com.going.ui.base.BaseActivity
-import com.going.ui.extension.UiState
import com.going.ui.extension.setOnSingleClickListener
+import com.going.ui.extension.toast
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@@ -53,28 +55,43 @@ class SignInActivity : BaseActivity(R.layout.activity_sig
}
private fun observePostChangeTokenState() {
- viewModel.postChangeTokenState.flowWithLifecycle(lifecycle).onEach { tokenState ->
- when (tokenState) {
- is UiState.Success -> {
- // 성공 했을 때 로직
- }
+ viewModel.postChangeTokenState.flowWithLifecycle(lifecycle).onEach { state ->
+ when (state) {
+ SignInState.SUCCESS -> navigateToMainScreen()
+ SignInState.SIGN_UP -> navigateToOnboardingScreen()
+ SignInState.TENDENCY -> navigateToTendencyScreen()
+ SignInState.FAIL -> toast(getString(R.string.server_error))
+ SignInState.LOADING -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
- is UiState.Failure -> {
- // 실패 했을 때 로직
- }
+ private fun navigateToMainScreen() {
+ // 추후 대시보드 연결시 연결 예정
+ Intent(this, OnboardingProfileSettingActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
+ finish()
+ }
- is UiState.Empty -> {
- // 여튼 로직
- }
+ private fun navigateToOnboardingScreen() {
+ Intent(this, OnboardingProfileSettingActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
+ finish()
+ }
- is UiState.Loading -> {
- // 로딩 중 로직
- }
- }
- }.launchIn(lifecycleScope)
+ private fun navigateToTendencyScreen() {
+ Intent(this, TendencyTestActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
+ finish()
}
- companion object{
+ companion object {
const val TERMS_URL = "http://www.naver.com"
}
}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInState.kt b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInState.kt
new file mode 100644
index 00000000..667187fa
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInState.kt
@@ -0,0 +1,9 @@
+package com.going.presentation.onboarding.signin
+
+sealed interface SignInState {
+ object LOADING : SignInState
+ object SUCCESS : SignInState
+ object FAIL : SignInState
+ object SIGN_UP : SignInState
+ object TENDENCY : SignInState
+}
diff --git a/presentation/src/main/java/com/going/presentation/auth/SignInViewModel.kt b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInViewModel.kt
similarity index 64%
rename from presentation/src/main/java/com/going/presentation/auth/SignInViewModel.kt
rename to presentation/src/main/java/com/going/presentation/onboarding/signin/SignInViewModel.kt
index b4bcc28f..d4b80f38 100644
--- a/presentation/src/main/java/com/going/presentation/auth/SignInViewModel.kt
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signin/SignInViewModel.kt
@@ -1,11 +1,12 @@
-package com.going.presentation.auth
+package com.going.presentation.onboarding.signin
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.going.domain.entity.response.AuthTokenModel
-import com.going.domain.repository.LoginRepository
-import com.going.ui.extension.UiState
+import com.going.domain.entity.request.RequestSignInModel
+import com.going.domain.repository.AuthRepository
+import com.going.domain.repository.TokenRepository
+import com.going.presentation.util.toErrorCode
import com.kakao.sdk.auth.model.OAuthToken
import com.kakao.sdk.common.model.ClientError
import com.kakao.sdk.common.model.ClientErrorCause
@@ -14,15 +15,15 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
-import timber.log.Timber
import javax.inject.Inject
@HiltViewModel
class SignInViewModel @Inject constructor(
- private val loginRepository: LoginRepository,
+ private val authRepository: AuthRepository,
+ private val tokenRepository: TokenRepository,
) : ViewModel() {
- private val _postChangeTokenState = MutableStateFlow>(UiState.Empty)
- val postChangeTokenState: StateFlow> = _postChangeTokenState
+ private val _postChangeTokenState = MutableStateFlow(SignInState.LOADING)
+ val postChangeTokenState: StateFlow = _postChangeTokenState
private val _isAppLoginAvailable = MutableStateFlow(true)
val isAppLoginAvailable: StateFlow = _isAppLoginAvailable
@@ -65,28 +66,30 @@ class SignInViewModel @Inject constructor(
// 서버통신 - 카카오 토큰 보내서 서비스 토큰 받아오기 - 서버와 협의 후 수정예정
private fun changeTokenFromServer(
accessToken: String,
- social: String = KAKAO,
+ platform: String = KAKAO,
) {
- _postChangeTokenState.value = UiState.Loading
+ _postChangeTokenState.value = SignInState.LOADING
viewModelScope.launch {
- // 통신 로직
- loginRepository.postSignin(accessToken, social).onSuccess {
- // 성공시 서버에서 준 정보를 넣는 예시 코드
- Timber.e("성공고오고오고공")
- _postChangeTokenState.value = UiState.Success(
- AuthTokenModel(
- accessToken = "testAccessToekn",
- refreshToken = "testRefreshToekn",
- ),
- )
- }.onFailure { err ->
- Timber.e("실패패패패패패")
+ authRepository.postSignIn(accessToken, RequestSignInModel(platform)).onSuccess {
+ tokenRepository.setTokens(it.accessToken, it.refreshToken)
+
+ _postChangeTokenState.value = SignInState.SUCCESS
+ }.onFailure {
+ val errorCode = toErrorCode(it)
+
+ _postChangeTokenState.value = when (errorCode) {
+ SIGN_UP -> SignInState.SIGN_UP
+ TENDENCY -> SignInState.TENDENCY
+ else -> SignInState.FAIL
+ }
}
}
}
companion object {
const val KAKAO = "kakao"
+ const val SIGN_UP = "e4041"
+ const val TENDENCY = "e4045"
}
}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingActivity.kt
similarity index 76%
rename from presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingActivity.kt
rename to presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingActivity.kt
index 02b2b608..3174a88c 100644
--- a/presentation/src/main/java/com/going/presentation/onboarding/OnboardingProfileSettingActivity.kt
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingActivity.kt
@@ -1,5 +1,6 @@
-package com.going.presentation.onboarding
+package com.going.presentation.onboarding.signup
+import android.content.Intent
import android.os.Bundle
import android.view.inputmethod.EditorInfo
import android.widget.TextView
@@ -10,10 +11,16 @@ import androidx.lifecycle.lifecycleScope
import com.going.domain.entity.NameState
import com.going.presentation.R
import com.going.presentation.databinding.ActivityOnboardingProfileSettingBinding
+import com.going.presentation.onboarding.splash.SplashActivity
+import com.going.presentation.tendencytest.TendencyTestActivity
import com.going.ui.base.BaseActivity
+import com.going.ui.extension.setOnSingleClickListener
+import com.going.ui.extension.toast
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+@AndroidEntryPoint
class OnboardingProfileSettingActivity :
BaseActivity(R.layout.activity_onboarding_profile_setting) {
private val viewModel by viewModels()
@@ -24,9 +31,10 @@ class OnboardingProfileSettingActivity :
initBindingViewModel()
initOnLineInfoEditorActionListener()
initSetOnFocusChangeListener()
+ initSignUpBtnClickListener()
observeIsNameAvailable()
- observeIsProfileAvailable()
observeTextLength()
+ observeIsSignUpState()
}
private fun initBindingViewModel() {
@@ -70,6 +78,12 @@ class OnboardingProfileSettingActivity :
}
}
+ private fun initSignUpBtnClickListener() {
+ binding.btnOnboardingProfileSettingFinish.setOnSingleClickListener {
+ viewModel.startSignUp()
+ }
+ }
+
private fun observeIsNameAvailable() {
viewModel.isNameAvailable.observe(this) { state ->
setColors(
@@ -107,12 +121,6 @@ class OnboardingProfileSettingActivity :
counter.setTextColor(getColor(color))
}
- private fun observeIsProfileAvailable() {
- viewModel.isMoveScreenAvailable.flowWithLifecycle(lifecycle).onEach { isEnd ->
- if (isEnd) moveSplash()
- }.launchIn(lifecycleScope)
- }
-
// 커스텀 글자수 제한 함수
private fun observeTextLength() {
viewModel.nowNameLength.observe(this) { length ->
@@ -138,7 +146,30 @@ class OnboardingProfileSettingActivity :
}
}
- private fun moveSplash() {
- // 스플래시로 이동
+ private fun observeIsSignUpState() {
+ viewModel.isSignUpState.flowWithLifecycle(lifecycle).onEach { state ->
+ when (state) {
+ is SignUpState.SUCCESS -> navigateToTendencyTestScreen()
+ is SignUpState.FAIL -> toast(getString(R.string.server_error))
+ is SignUpState.LOG_IN -> navigateToSplashScreen()
+ is SignUpState.LOADING -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun navigateToSplashScreen() {
+ Intent(this, SplashActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
+ finish()
+ }
+
+ private fun navigateToTendencyTestScreen() {
+ Intent(this, TendencyTestActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
+ finish()
}
}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingViewModel.kt b/presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingViewModel.kt
new file mode 100644
index 00000000..37fb9b51
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signup/OnboardingProfileSettingViewModel.kt
@@ -0,0 +1,105 @@
+package com.going.presentation.onboarding.signup
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.going.domain.entity.NameState
+import com.going.domain.entity.request.RequestSignUpModel
+import com.going.domain.repository.AuthRepository
+import com.kakao.sdk.auth.AuthApiClient
+import com.kakao.sdk.auth.TokenManagerProvider
+import com.kakao.sdk.user.UserApiClient
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+import java.text.BreakIterator
+import javax.inject.Inject
+
+@HiltViewModel
+class OnboardingProfileSettingViewModel @Inject constructor(
+ private val authRepository: AuthRepository,
+) : ViewModel() {
+ val name = MutableStateFlow("")
+ val nowNameLength = MutableLiveData(0)
+ val info = MutableStateFlow("")
+ val nowInfoLength = MutableLiveData(0)
+
+ val isNameAvailable = MutableLiveData(NameState.Empty)
+ val isProfileAvailable = MutableLiveData(false)
+
+ private val _isSignUpState = MutableStateFlow(SignUpState.LOADING)
+ val isSignUpState: StateFlow = _isSignUpState
+
+ fun getMaxNameLen() = MAX_NAME_LEN
+ fun getMaxInfoLen() = MAX_INFO_LEN
+
+ fun checkProfileAvailable() {
+ nowNameLength.value = getGraphemeLength(name.value)
+ nowInfoLength.value = getGraphemeLength(info.value)
+
+ isNameAvailable.value = when {
+ nowNameLength.value == 0 -> NameState.Empty
+ name.value.isNullOrBlank() -> NameState.Blank
+ else -> NameState.Success
+ }
+
+ val isInfoAvailable = getGraphemeLength(info.value) in 1..MAX_INFO_LEN
+
+ isProfileAvailable.value =
+ (isNameAvailable.value == NameState.Success) && isInfoAvailable
+ }
+
+ // 이모지 포함 글자 수 세는 함수
+ private fun getGraphemeLength(value: String?): Int {
+ BREAK_ITERATOR.setText(value)
+
+ var count = 0
+ while (BREAK_ITERATOR.next() != BreakIterator.DONE) {
+ count++
+ }
+
+ return count
+ }
+
+ fun startSignUp() {
+ _isSignUpState.value = SignUpState.LOADING
+
+ if (AuthApiClient.instance.hasToken()) {
+ UserApiClient.instance.accessTokenInfo { _, error ->
+ if (error == null) {
+ val kakaoAccessToken =
+ TokenManagerProvider.instance.manager.getToken()?.accessToken
+ signUpWithServer(kakaoAccessToken.toString())
+ } else {
+ _isSignUpState.value = SignUpState.LOG_IN
+ }
+ }
+ } else {
+ _isSignUpState.value = SignUpState.LOG_IN
+ }
+ }
+
+ private fun signUpWithServer(kakaoAccessToken: String) {
+ viewModelScope.launch {
+ authRepository.postSignUp(
+ kakaoAccessToken,
+ RequestSignUpModel(name.value, info.value, KAKAO),
+ ).onSuccess {
+ _isSignUpState.value = SignUpState.SUCCESS
+ }.onFailure {
+ _isSignUpState.value = SignUpState.FAIL
+ }
+ }
+ }
+
+ companion object {
+ val BREAK_ITERATOR: BreakIterator = BreakIterator.getCharacterInstance()
+
+ const val KAKAO = "kakao"
+ const val MAX_NAME_LEN = 3
+ const val MAX_INFO_LEN = 20
+ const val SIGN_UP = "e4041"
+ const val TENDENCY = "e4045"
+ }
+}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/signup/SignUpState.kt b/presentation/src/main/java/com/going/presentation/onboarding/signup/SignUpState.kt
new file mode 100644
index 00000000..36394c87
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/onboarding/signup/SignUpState.kt
@@ -0,0 +1,8 @@
+package com.going.presentation.onboarding.signup
+
+sealed interface SignUpState {
+ object LOADING : SignUpState
+ object SUCCESS : SignUpState
+ object FAIL : SignUpState
+ object LOG_IN : SignUpState
+}
diff --git a/presentation/src/main/java/com/going/presentation/splash/NetworkManager.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/NetworkManager.kt
similarity index 93%
rename from presentation/src/main/java/com/going/presentation/splash/NetworkManager.kt
rename to presentation/src/main/java/com/going/presentation/onboarding/splash/NetworkManager.kt
index 8474f875..06cde7dc 100644
--- a/presentation/src/main/java/com/going/presentation/splash/NetworkManager.kt
+++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/NetworkManager.kt
@@ -1,4 +1,4 @@
-package com.going.presentation.splash
+package com.going.presentation.onboarding.splash
import android.content.Context
import android.net.ConnectivityManager
diff --git a/presentation/src/main/java/com/going/presentation/splash/SplashActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt
similarity index 74%
rename from presentation/src/main/java/com/going/presentation/splash/SplashActivity.kt
rename to presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt
index a6758d43..31f83c8d 100644
--- a/presentation/src/main/java/com/going/presentation/splash/SplashActivity.kt
+++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt
@@ -1,16 +1,21 @@
-package com.going.presentation.splash
+package com.going.presentation.onboarding.splash
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
+import androidx.activity.viewModels
import com.going.presentation.R
-import com.going.presentation.auth.SignInActivity
import com.going.presentation.databinding.ActivitySplashBinding
+import com.going.presentation.onboarding.signin.SignInActivity
+import com.going.presentation.onboarding.signup.OnboardingProfileSettingActivity
import com.going.ui.base.BaseActivity
+import dagger.hilt.android.AndroidEntryPoint
+@AndroidEntryPoint
class SplashActivity : BaseActivity(R.layout.activity_splash) {
+ private val viewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -27,8 +32,7 @@ class SplashActivity : BaseActivity(R.layout.activity_spl
private fun initSplash() {
Handler(Looper.getMainLooper()).postDelayed({
- navigateToSignInScreen()
- if (false) { // 자동 로그인 판정으로 변경 예정
+ if (viewModel.getHasAccessToken()) {
navigateToMainScreen()
} else {
navigateToSignInScreen()
@@ -51,6 +55,10 @@ class SplashActivity : BaseActivity(R.layout.activity_spl
private fun navigateToMainScreen() {
// Main이 나오면 구현 예정
+ Intent(this, OnboardingProfileSettingActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(this)
+ }
finish()
}
diff --git a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt
new file mode 100644
index 00000000..5ea3c164
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashViewModel.kt
@@ -0,0 +1,13 @@
+package com.going.presentation.onboarding.splash
+
+import androidx.lifecycle.ViewModel
+import com.going.domain.repository.TokenRepository
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+@HiltViewModel
+class SplashViewModel @Inject constructor(
+ private val tokenRepository: TokenRepository,
+) : ViewModel() {
+ fun getHasAccessToken(): Boolean = tokenRepository.getAccessToken() != ""
+}
diff --git a/presentation/src/main/java/com/going/presentation/util/JsonExt.kt b/presentation/src/main/java/com/going/presentation/util/JsonExt.kt
new file mode 100644
index 00000000..9aea58f3
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/util/JsonExt.kt
@@ -0,0 +1,12 @@
+package com.going.presentation.util
+
+import org.json.JSONObject
+import retrofit2.HttpException
+
+fun toErrorCode(throwable: Throwable): String = if (throwable is HttpException) {
+ val jsonTemp = throwable.response()?.errorBody()?.byteString().toString()
+ val json = jsonTemp.slice(6 until jsonTemp.length)
+ JSONObject(json).getString("code")
+} else {
+ "NOT_HTTP"
+}
diff --git a/presentation/src/main/res/layout/activity_onboarding_profile_setting.xml b/presentation/src/main/res/layout/activity_onboarding_profile_setting.xml
index 6e2ef9f8..59aad5ba 100644
--- a/presentation/src/main/res/layout/activity_onboarding_profile_setting.xml
+++ b/presentation/src/main/res/layout/activity_onboarding_profile_setting.xml
@@ -10,7 +10,7 @@
+ type="com.going.presentation.onboarding.signup.OnboardingProfileSettingViewModel" />