Skip to content

Commit

Permalink
Merge pull request #93 from boostcampwm2023/feat/and/splash-screen
Browse files Browse the repository at this point in the history
SplashScreen ๊ตฌํ˜„, ๋กœ๊ทธ์ธ & ํšŒ์›๊ฐ€์ž… ์‹œ ํ† ํฐ ์ €์žฅ
  • Loading branch information
ootr47 authored Nov 21, 2023
2 parents 234c7d9 + 87020ff commit dc90571
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 78 deletions.
13 changes: 8 additions & 5 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
android:theme="@style/Theme.PriceGuard"
tools:targetApi="34">
<activity
android:name=".ui.main.additem.AddItemActivity"
android:exported="false" />
<activity
android:name=".ui.intro.IntroActivity"
android:exported="true" >
android:name=".ui.splash.SplashScreenActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.intro.IntroActivity"
android:exported="false" />
<activity
android:name=".ui.login.LoginActivity"
android:exported="false" />
Expand All @@ -34,6 +34,9 @@
<activity
android:name=".ui.main.MainActivity"
android:exported="false" />
<activity
android:name=".ui.main.additem.AddItemActivity"
android:exported="false" />
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ data class LoginResponse(

data class LoginResult(
val loginState: LoginState,
val loginResponse: LoginResponse? = null
val accessToken: String?,
val refreshToken: String?
)

enum class LoginState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package app.priceguard.data.dto
import kotlinx.serialization.Serializable

@Serializable
data class SignUpRequest(
data class SignupRequest(
val email: String,
val userName: String,
val password: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ package app.priceguard.data.dto
import kotlinx.serialization.Serializable

@Serializable
data class SignUpResponse(
data class SignupResponse(
val statusCode: Int,
val message: String,
val accessToken: String,
val refreshToken: String
)

data class SignUpResult(
val signUpState: SignUpState,
val signUpResponse: SignUpResponse? = null
data class SignupResult(
val signUpState: SignupState,
val accessToken: String?,
val refreshToken: String?
)

enum class SignUpState {
enum class SignupState {
SUCCESS,
INVALID_PARAMETER,
DUPLICATE_EMAIL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package app.priceguard.data.network

import app.priceguard.data.dto.LoginRequest
import app.priceguard.data.dto.LoginResponse
import app.priceguard.data.dto.SignUpRequest
import app.priceguard.data.dto.SignUpResponse
import app.priceguard.data.dto.SignupRequest
import app.priceguard.data.dto.SignupResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
Expand All @@ -17,6 +17,6 @@ interface UserAPI {

@POST("register")
suspend fun register(
@Body request: SignUpRequest
): Response<SignUpResponse>
@Body request: SignupRequest
): Response<SignupResponse>
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package app.priceguard.data.repository

import app.priceguard.data.dto.LoginResult
import app.priceguard.data.dto.SignUpResult
import app.priceguard.data.dto.SignupResult

interface UserRepository {

suspend fun signUp(email: String, userName: String, password: String): SignUpResult
suspend fun signUp(email: String, userName: String, password: String): SignupResult

suspend fun login(email: String, password: String): LoginResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,37 @@ package app.priceguard.data.repository
import app.priceguard.data.dto.LoginRequest
import app.priceguard.data.dto.LoginResult
import app.priceguard.data.dto.LoginState
import app.priceguard.data.dto.SignUpRequest
import app.priceguard.data.dto.SignUpResult
import app.priceguard.data.dto.SignUpState
import app.priceguard.data.dto.SignupRequest
import app.priceguard.data.dto.SignupResult
import app.priceguard.data.dto.SignupState
import app.priceguard.data.network.APIResult
import app.priceguard.data.network.UserAPI
import app.priceguard.data.network.getApiResult
import javax.inject.Inject

class UserRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : UserRepository {

override suspend fun signUp(email: String, userName: String, password: String): SignUpResult {
override suspend fun signUp(email: String, userName: String, password: String): SignupResult {
val response = getApiResult {
userAPI.register(SignUpRequest(email, userName, password))
userAPI.register(SignupRequest(email, userName, password))
}
when (response) {
is APIResult.Success -> {
return SignUpResult(SignUpState.SUCCESS, response.data)
return SignupResult(SignupState.SUCCESS, response.data.accessToken, response.data.refreshToken)
}

is APIResult.Error -> {
return when (response.code) {
400 -> {
SignUpResult(SignUpState.INVALID_PARAMETER)
SignupResult(SignupState.INVALID_PARAMETER, null, null)
}

409 -> {
SignUpResult(SignUpState.DUPLICATE_EMAIL)
SignupResult(SignupState.DUPLICATE_EMAIL, null, null)
}

else -> {
SignUpResult(SignUpState.UNDEFINED_ERROR)
SignupResult(SignupState.UNDEFINED_ERROR, null, null)
}
}
}
Expand All @@ -46,17 +46,17 @@ class UserRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Use
}
when (response) {
is APIResult.Success -> {
return LoginResult(LoginState.SUCCESS, response.data)
return LoginResult(LoginState.SUCCESS, response.data.accessToken, response.data.refreshToken)
}

is APIResult.Error -> {
return when (response.code) {
400 -> {
LoginResult(LoginState.INVALID_PARAMETER)
LoginResult(LoginState.INVALID_PARAMETER, null, null)
}

else -> {
LoginResult(LoginState.UNDEFINED_ERROR)
LoginResult(LoginState.UNDEFINED_ERROR, null, null)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class LoginActivity : AppCompatActivity() {
private fun initListener() {
with(binding) {
btnLoginLogin.setOnClickListener {
(binding.btnLoginLogin as MaterialButton).icon = getCircularProgressIndicatorDrawable(this@LoginActivity)
(binding.btnLoginLogin as MaterialButton).icon =
getCircularProgressIndicatorDrawable(this@LoginActivity)
}
btnLoginSignup.setOnClickListener {
gotoSignUp()
Expand All @@ -47,7 +48,8 @@ class LoginActivity : AppCompatActivity() {
loginViewModel.event.collect { eventType ->
when (eventType) {
LoginEvent.LoginStart -> {
(binding.btnLoginLogin as MaterialButton).icon = getCircularProgressIndicatorDrawable(this@LoginActivity)
(binding.btnLoginLogin as MaterialButton).icon =
getCircularProgressIndicatorDrawable(this@LoginActivity)
}

else -> {
Expand All @@ -72,8 +74,8 @@ class LoginActivity : AppCompatActivity() {
showDialog(getString(R.string.login_fail), getString(R.string.login_fail_message))
}

is LoginEvent.LoginSuccess -> {
gotoHome()
is LoginEvent.LoginInfoSaved -> {
gotoHomeActivity()
}

else -> {}
Expand All @@ -93,7 +95,7 @@ class LoginActivity : AppCompatActivity() {
startActivity(Intent(this, SignupActivity::class.java))
}

private fun gotoHome() {
private fun gotoHomeActivity() {
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
Expand Down
60 changes: 41 additions & 19 deletions android/app/src/main/java/app/priceguard/ui/login/LoginViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package app.priceguard.ui.login
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.priceguard.data.dto.LoginResponse
import app.priceguard.data.dto.LoginState
import app.priceguard.data.repository.TokenRepository
import app.priceguard.data.repository.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
Expand All @@ -18,7 +18,8 @@ import kotlinx.coroutines.launch

@HiltViewModel
class LoginViewModel @Inject constructor(
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val tokenRepository: TokenRepository
) : ViewModel() {

data class State(
Expand All @@ -31,8 +32,9 @@ class LoginViewModel @Inject constructor(
sealed class LoginEvent {
data object LoginStart : LoginEvent()
data object Invalid : LoginEvent()
data class LoginSuccess(val response: LoginResponse?) : LoginEvent()
data class LoginSuccess(val accessToken: String, val refreshToken: String) : LoginEvent()
data class LoginFailure(val status: LoginState) : LoginEvent()
data object LoginInfoSaved : LoginEvent()
}

private val emailPattern =
Expand Down Expand Up @@ -62,35 +64,55 @@ class LoginViewModel @Inject constructor(
}

viewModelScope.launch {
_state.value = _state.value.copy(isLoading = true)
setLoading(true)
sendLoginEvent(LoginEvent.LoginStart)

if (checkEmailAndPassword()) {
val result = userRepository.login(_state.value.email, _state.value.password)
if (!checkEmailAndPassword()) {
sendLoginEvent(LoginEvent.Invalid)
setLoading(false)
return@launch
}

when (result.loginState) {
LoginState.SUCCESS -> {
_state.value = _state.value.copy(isLoginFinished = true)
sendLoginEvent(
LoginEvent.LoginSuccess(result.loginResponse)
)
}
val result = userRepository.login(_state.value.email, _state.value.password)

if (result.accessToken == null || result.refreshToken == null) {
sendLoginEvent(LoginEvent.LoginFailure(result.loginState))
setLoading(false)
return@launch
}

else -> {
sendLoginEvent(LoginEvent.LoginFailure(result.loginState))
}
when (result.loginState) {
LoginState.SUCCESS -> {
setLoginFinished(true)
sendLoginEvent(LoginEvent.LoginSuccess(result.accessToken, result.refreshToken))
saveTokens(result.accessToken, result.refreshToken)
sendLoginEvent(LoginEvent.LoginInfoSaved)
}

else -> {
sendLoginEvent(LoginEvent.LoginFailure(result.loginState))
}
} else {
sendLoginEvent(LoginEvent.Invalid)
}
_state.value = _state.value.copy(isLoading = false)
setLoading(false)
}
}

private suspend fun saveTokens(accessToken: String, refreshToken: String) {
tokenRepository.storeTokens(accessToken, refreshToken)
}

private suspend fun sendLoginEvent(event: LoginEvent) {
_event.emit(event)
}

private fun setLoading(isLoading: Boolean) {
_state.value = _state.value.copy(isLoading = isLoading)
}

private fun setLoginFinished(finished: Boolean) {
_state.value = _state.value.copy(isLoginFinished = finished)
}

private fun checkEmailAndPassword(): Boolean {
return emailPattern.matchEntire(_state.value.email) != null && passwordPattern.matchEntire(
_state.value.password
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.NestedScrollView
import androidx.databinding.DataBindingUtil
import app.priceguard.R
import app.priceguard.data.dto.SignUpState
import app.priceguard.data.dto.SignupState
import app.priceguard.databinding.ActivitySignupBinding
import app.priceguard.ui.main.MainActivity
import app.priceguard.ui.signup.SignupViewModel.SignupEvent
Expand Down Expand Up @@ -73,42 +73,40 @@ class SignupActivity : AppCompatActivity() {

is SignupEvent.SignupSuccess -> {
(binding.btnSignupSignup as MaterialButton).icon = null
val response = event.response

if (response == null) {
showDialog(getString(R.string.error), getString(R.string.undefined_error))
} else {
// TODO: DataStore์— ์ €์žฅํ•˜๊ธฐ
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)

// TODO: ๋’ค์— ์•กํ‹ฐ๋น„ํ‹ฐ ์Šคํƒ ๋‹ค ๋‚ ๋ฆฌ๊ธฐ
finish()
}
}

is SignupEvent.SignupFailure -> {
(binding.btnSignupSignup as MaterialButton).icon = null
when (event.errorState) {
SignUpState.INVALID_PARAMETER -> {
SignupState.INVALID_PARAMETER -> {
showDialog(getString(R.string.error), getString(R.string.invalid_parameter))
}

SignUpState.DUPLICATE_EMAIL -> {
SignupState.DUPLICATE_EMAIL -> {
showDialog(getString(R.string.error), getString(R.string.duplicate_email))
}

SignUpState.UNDEFINED_ERROR -> {
SignupState.UNDEFINED_ERROR -> {
showDialog(getString(R.string.error), getString(R.string.undefined_error))
}

else -> {}
}
}

SignupEvent.SignupInfoSaved -> {
gotoHomeActivity()
}
}
}

private fun gotoHomeActivity() {
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}

private fun setNavigationButton() {
binding.mtSignupTopbar.setNavigationOnClickListener {
finish()
Expand Down
Loading

0 comments on commit dc90571

Please sign in to comment.