-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feat/#12] 7주차 과제 구현 #13
base: develop
Are you sure you want to change the base?
Changes from all commits
3186454
73964a1
4753dd3
7d6bff0
8c07f52
785472b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.sopt.and.presentation.my.contract | ||
|
||
import org.sopt.and.presentation.util.base.UiEvent | ||
|
||
sealed class MyEvent: UiEvent { | ||
data class GetMyHobby(val hobby: String): MyEvent() | ||
data object OnLogoutButtonClick: MyEvent() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
package org.sopt.and.presentation.my.model | ||
|
||
import org.sopt.and.presentation.util.KeyUtil.DEFAULT_STRING | ||
import org.sopt.and.presentation.util.base.UiState | ||
|
||
data class MyState( | ||
val hobby: String = DEFAULT_STRING | ||
) | ||
): UiState |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
package org.sopt.and.presentation.my.sideeffect | ||
|
||
import androidx.annotation.StringRes | ||
import org.sopt.and.presentation.util.base.UiSideEffect | ||
|
||
sealed class MySideEffect { | ||
sealed class MySideEffect: UiSideEffect { | ||
data class SnackBar(@StringRes val message: Int): MySideEffect() | ||
data class SnackBarText(val message: String): MySideEffect() | ||
data object Logout: MySideEffect() | ||
data object NavigateToSignIn: MySideEffect() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,61 @@ | ||
package org.sopt.and.presentation.my.viewmodel | ||
|
||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import dagger.hilt.android.lifecycle.HiltViewModel | ||
import kotlinx.coroutines.flow.MutableSharedFlow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.asSharedFlow | ||
import kotlinx.coroutines.flow.asStateFlow | ||
import kotlinx.coroutines.flow.update | ||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.launch | ||
import org.sopt.and.domain.exception.onError | ||
import org.sopt.and.domain.exception.onSuccess | ||
import org.sopt.and.domain.repository.UserRepository | ||
import org.sopt.and.presentation.delegate.NetworkDelegate | ||
import org.sopt.and.presentation.my.contract.MyEvent | ||
import org.sopt.and.presentation.my.model.MyState | ||
import org.sopt.and.presentation.my.sideeffect.MySideEffect | ||
import org.sopt.and.presentation.sign.signin.sideeffect.SignInSideEffect | ||
import org.sopt.and.presentation.util.base.BaseViewModel | ||
import javax.inject.Inject | ||
|
||
@HiltViewModel | ||
class MyViewModel @Inject constructor( | ||
private val userRepository: UserRepository, | ||
private val networkDelegate: NetworkDelegate | ||
): ViewModel() { | ||
): BaseViewModel<MyState, MyEvent, MySideEffect>() { | ||
|
||
private val _state = MutableStateFlow(MyState()) | ||
val state = _state.asStateFlow() | ||
override fun createInitialState(): MyState = MyState() | ||
|
||
private val _intent = MutableSharedFlow<MySideEffect>() | ||
val intent = _intent.asSharedFlow() | ||
override suspend fun handleEvent(event: MyEvent) { | ||
when(event) { | ||
MyEvent.OnLogoutButtonClick -> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is를 붙이고 안붙이고의 차이는 뭔가요?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getMyHobby는 data class 상태(프로퍼티)를 가지며, is로 타입 검사를 통해 특정 클래스로 매칭이 필요합니다 ! onLoginButtonClick은 data object이기 때문에 상태가 없는 단일 객체로, 고유 값으로 비교가 가능합니다! |
||
navigateToSignIn() | ||
} | ||
is MyEvent.GetMyHobby -> { | ||
setState { copy(hobby = event.hobby) } | ||
} | ||
} | ||
} | ||
|
||
val networkState get() = networkDelegate.networkState | ||
|
||
fun getMyHobby() = viewModelScope.launch { | ||
val token = userRepository.getToken() | ||
userRepository.getMyHobby(token).onSuccess { result -> | ||
_state.update { | ||
it.copy(hobby = result.hobby) | ||
} | ||
setEvent(MyEvent.GetMyHobby(result.hobby)) | ||
networkDelegate.handleNetworkSuccess() | ||
}.onError { | ||
networkDelegate.handleGetMyHobbyError(it) | ||
} | ||
} | ||
|
||
fun onLogOutButtonClick() = viewModelScope.launch { | ||
_intent.emit(MySideEffect.Logout) | ||
private fun navigateToSignIn() = viewModelScope.launch { | ||
delay(100) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delay를 주는 이유가 무엇인가용?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 있고 아래도 있던데 저도 궁금합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 궁금합니당 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 화면 이동 되면서 스낵바가 안 떠서 delay를 줬는데 좋은 방법은 아닌 것 같아요... 다른 방법이 있을까요 ? ㅠㅠ |
||
setSideEffect(MySideEffect.NavigateToSignIn) | ||
} | ||
|
||
fun clearUserPreference() = viewModelScope.launch { | ||
userRepository.clearUserPreference() | ||
} | ||
|
||
suspend fun handleMyIntentError(message: String) { | ||
_intent.emit(MySideEffect.SnackBarText(message)) | ||
fun handleMyIntentError(message: String) { | ||
setSideEffect(MySideEffect.SnackBarText(message)) | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,8 @@ import org.sopt.and.presentation.component.WavveActionTextField | |
import org.sopt.and.presentation.component.WavveTextField | ||
import org.sopt.and.presentation.delegate.NetworkState | ||
import org.sopt.and.presentation.extension.noRippleClickable | ||
import org.sopt.and.presentation.sign.signin.sideeffect.SignInSideEffect | ||
import org.sopt.and.presentation.sign.signin.contract.SignInEvent | ||
import org.sopt.and.presentation.sign.signin.contract.SignInSideEffect | ||
import org.sopt.and.presentation.sign.signin.viewmodel.SignInViewModel | ||
import org.sopt.and.presentation.ui.theme.FirstGrey | ||
import org.sopt.and.presentation.ui.theme.SecondGrey | ||
|
@@ -56,20 +57,21 @@ fun SignInScreen( | |
viewModel: SignInViewModel = hiltViewModel() | ||
){ | ||
|
||
val state by viewModel.state.collectAsStateWithLifecycle() | ||
val state by viewModel.uiState.collectAsStateWithLifecycle() | ||
val context = rememberUpdatedState(LocalContext.current).value | ||
val snackBarHostState = remember { SnackbarHostState() } | ||
|
||
LaunchedEffect(viewModel.intent) { | ||
viewModel.intent.collect{ intent -> | ||
when(intent) { | ||
SignInSideEffect.SignIn -> { | ||
viewModel.saveUser(state.id, state.password) | ||
LaunchedEffect(viewModel.sideEffect) { | ||
viewModel.sideEffect.collect{ sideEffect -> | ||
when(sideEffect) { | ||
is SignInSideEffect.SnackBar -> snackBarHostState.showSnackbar(context.getString(sideEffect.message)) | ||
is SignInSideEffect.SnackBarText -> snackBarHostState.showSnackbar(sideEffect.message) | ||
SignInSideEffect.NavigateToSignUp -> { | ||
navigateToSignUp() | ||
Comment on lines
+68
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에도 있는 질문인데 is의 유무로 인해 어떤 차이가 있는 건가요!? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 궁금해요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #13 (comment) |
||
} | ||
SignInSideEffect.NavigateToMy -> { | ||
navigateToMy() | ||
} | ||
SignInSideEffect.SignUp -> navigateToSignUp() | ||
is SignInSideEffect.SnackBar -> snackBarHostState.showSnackbar(context.getString(intent.message)) | ||
is SignInSideEffect.SnackBarText -> snackBarHostState.showSnackbar(intent.message) | ||
} | ||
} | ||
} | ||
|
@@ -93,7 +95,9 @@ fun SignInScreen( | |
WavveTextField( | ||
value = state.id, | ||
hint = stringResource(R.string.signup_login_hint), | ||
onValueChange = viewModel::updateId, | ||
onValueChange = { | ||
viewModel.setEvent(SignInEvent.OnIdChanged(it)) | ||
}, | ||
modifier = Modifier.padding(horizontal = 8.dp) | ||
) | ||
|
||
|
@@ -102,7 +106,9 @@ fun SignInScreen( | |
WavveActionTextField( | ||
value = state.password, | ||
hint = stringResource(R.string.signin_password_hint), | ||
onValueChange = viewModel::updatePassword, | ||
onValueChange = { | ||
viewModel.setEvent(SignInEvent.OnPasswordChanged(it)) | ||
}, | ||
modifier = Modifier.padding(horizontal = 8.dp) | ||
) | ||
|
||
|
@@ -175,7 +181,7 @@ fun SignInScreen( | |
modifier = Modifier | ||
.noRippleClickable( | ||
onClick = { | ||
viewModel.onSignUpButtonClick() | ||
viewModel.setEvent(SignInEvent.OnSignUpButtonClick) | ||
} | ||
) | ||
) | ||
|
@@ -214,10 +220,10 @@ private suspend fun collectNetworkState(viewModel: SignInViewModel) { | |
// TODO 로딩 추가 | ||
} | ||
is NetworkState.Error -> { | ||
viewModel.handleSignInIntentError(networkState.title + networkState.msg) | ||
viewModel.handleSignInSideEffectError(networkState.title + networkState.msg) | ||
} | ||
is NetworkState.Success -> { | ||
viewModel.handleSignInIntentSuccess() | ||
viewModel.handleSignInSideEffectSuccess() | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.sopt.and.presentation.sign.signin.contract | ||
|
||
import org.sopt.and.presentation.util.base.UiEvent | ||
|
||
sealed class SignInEvent: UiEvent { | ||
data class OnIdChanged(val id: String) : SignInEvent() | ||
data class OnPasswordChanged(val password: String) : SignInEvent() | ||
data object OnSignInButtonClick : SignInEvent() | ||
data object OnSignUpButtonClick : SignInEvent() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.sopt.and.presentation.sign.signin.contract | ||
|
||
import androidx.annotation.StringRes | ||
import org.sopt.and.presentation.util.base.UiSideEffect | ||
|
||
sealed class SignInSideEffect: UiSideEffect { | ||
data class SnackBar(@StringRes val message: Int) : SignInSideEffect() | ||
data class SnackBarText(val message: String) : SignInSideEffect() | ||
data object NavigateToSignUp: SignInSideEffect() | ||
data object NavigateToMy: SignInSideEffect() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
package org.sopt.and.presentation.sign.signin.model | ||
package org.sopt.and.presentation.sign.signin.contract | ||
|
||
import org.sopt.and.presentation.util.KeyUtil.DEFAULT_STRING | ||
import org.sopt.and.presentation.util.base.UiState | ||
|
||
data class SignInState( | ||
val id: String = DEFAULT_STRING, | ||
val password: String = DEFAULT_STRING, | ||
) | ||
): UiState |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네이밍 변경 좋네요!