From 498f271db2522d2d99bf532a840784a118d201ec Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:21:26 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20Remote=20Config=EC=97=90=EC=84=9C?= =?UTF-8?q?=20Password=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20dataSource?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FirebaseRemoteConfigDataSource.kt | 1 + .../FirebaseRemoteConfigDataSourceImpl.kt | 19 +++++++++++++++---- .../repository/RemoteConfigRepositoryImpl.kt | 12 ++++++++++++ .../yapp/domain/firebase/RemoteConfigData.kt | 6 ++++++ .../repository/RemoteConfigRepository.kt | 1 + 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSource.kt b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSource.kt index 61924f62..7d59be3a 100644 --- a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSource.kt +++ b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSource.kt @@ -12,4 +12,5 @@ interface FirebaseRemoteConfigDataSource { suspend fun getTeamList(): List suspend fun getQrPassword(): String suspend fun shouldShowGuestButton(): Boolean + suspend fun getSignUpPassword(): String } \ No newline at end of file diff --git a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt index 6c297064..9a0d031e 100644 --- a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt +++ b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt @@ -72,9 +72,9 @@ class FirebaseRemoteConfigDataSourceImpl @Inject constructor() : FirebaseRemoteC return suspendCancellableCoroutine { cancellableContinuation -> firebaseRemoteConfig.fetchAndActivate().addOnSuccessListener { val entities = firebaseRemoteConfig.getString(RemoteConfigData.AttendanceSelectTeams.key) - .let { jsonString -> - Json.decodeFromString>(jsonString) - } + .let { jsonString -> + Json.decodeFromString>(jsonString) + } cancellableContinuation.resume(value = entities, onCancellation = null) }.addOnFailureListener { exception -> @@ -98,7 +98,7 @@ class FirebaseRemoteConfigDataSourceImpl @Inject constructor() : FirebaseRemoteC return suspendCancellableCoroutine { cancellableContinuation -> firebaseRemoteConfig.fetchAndActivate().addOnSuccessListener { val shouldShowGuest = firebaseRemoteConfig.getString(RemoteConfigData.ShouldShowGuestButton.key) - .toBooleanStrict() + .toBooleanStrict() cancellableContinuation.resume(shouldShowGuest) }.addOnFailureListener { exception -> @@ -107,4 +107,15 @@ class FirebaseRemoteConfigDataSourceImpl @Inject constructor() : FirebaseRemoteC } } + override suspend fun getSignUpPassword(): String { + return suspendCancellableCoroutine { cancellableContinuation -> + firebaseRemoteConfig.fetchAndActivate().addOnSuccessListener { + val password = firebaseRemoteConfig.getString(RemoteConfigData.SignUpPassword.key) + cancellableContinuation.resume(password, null) + }.addOnFailureListener { exception -> + cancellableContinuation.resumeWithException(exception) + } + } + } + } \ No newline at end of file diff --git a/data/src/main/java/com/yapp/data/repository/RemoteConfigRepositoryImpl.kt b/data/src/main/java/com/yapp/data/repository/RemoteConfigRepositoryImpl.kt index 26c9d309..131a9671 100644 --- a/data/src/main/java/com/yapp/data/repository/RemoteConfigRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/data/repository/RemoteConfigRepositoryImpl.kt @@ -94,4 +94,16 @@ class RemoteConfigRepositoryImpl @Inject constructor( ) } + override suspend fun getSignUpPassword(): Result { + return runCatching { + firebaseRemoteConfigDataSource.getSignUpPassword() + }.fold( + onSuccess = { signUpPassword: String -> + Result.success(signUpPassword) + }, + onFailure = { exception -> + Result.failure(exception) + } + ) + } } \ No newline at end of file diff --git a/domain/src/main/java/com/yapp/domain/firebase/RemoteConfigData.kt b/domain/src/main/java/com/yapp/domain/firebase/RemoteConfigData.kt index 769ee236..4149d4b3 100644 --- a/domain/src/main/java/com/yapp/domain/firebase/RemoteConfigData.kt +++ b/domain/src/main/java/com/yapp/domain/firebase/RemoteConfigData.kt @@ -34,6 +34,11 @@ sealed class RemoteConfigData { override val defaultValue: String = "fail" } + object SignUpPassword : RemoteConfigData() { + override val key: String = SIGN_UP_PASSWORD + override val defaultValue: String = "" + } + companion object { private const val ATTENDANCE_MAGINOTLINE_TIME = "attendance_maginotline_time" private const val ATTENDANCE_SESSION_LIST = "attendance_session_list" @@ -41,6 +46,7 @@ sealed class RemoteConfigData { private const val ATTENDANCE_CONFIG = "config" private const val ATTENDANCE_QR_PASSWORD = "attendance_qr_password" private const val SHOULD_SHOW_GUEST_BUTTON = "should_show_guest_button" + private const val SIGN_UP_PASSWORD = "attendance_signup_password" val defaultMaps = mapOf( MaginotlineTime.defaultValue to MaginotlineTime.key, diff --git a/domain/src/main/java/com/yapp/domain/repository/RemoteConfigRepository.kt b/domain/src/main/java/com/yapp/domain/repository/RemoteConfigRepository.kt index b624ec35..83544165 100644 --- a/domain/src/main/java/com/yapp/domain/repository/RemoteConfigRepository.kt +++ b/domain/src/main/java/com/yapp/domain/repository/RemoteConfigRepository.kt @@ -12,4 +12,5 @@ interface RemoteConfigRepository { suspend fun getTeamList(): Result> suspend fun getQrPassword(): Result suspend fun shouldShowGuestButton(): Result + suspend fun getSignUpPassword(): Result } \ No newline at end of file From dbfa0ba7aa2a69854738aeb6bdd5a9f475e2d13d Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:22:07 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20Password=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=ED=95=98=EC=97=AC=20=EC=84=B1=EA=B3=B5=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=EB=A5=BC=20=EB=82=98=EB=88=84=EB=8A=94=20=EC=9C=A0?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/usecases/CheckSignUpPasswordUseCase.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 domain/src/main/java/com/yapp/domain/usecases/CheckSignUpPasswordUseCase.kt diff --git a/domain/src/main/java/com/yapp/domain/usecases/CheckSignUpPasswordUseCase.kt b/domain/src/main/java/com/yapp/domain/usecases/CheckSignUpPasswordUseCase.kt new file mode 100644 index 00000000..692187b3 --- /dev/null +++ b/domain/src/main/java/com/yapp/domain/usecases/CheckSignUpPasswordUseCase.kt @@ -0,0 +1,14 @@ +package com.yapp.domain.usecases + +import com.yapp.domain.repository.RemoteConfigRepository +import javax.inject.Inject + +class CheckSignUpPasswordUseCase @Inject constructor( + private val remoteConfigRepository: RemoteConfigRepository, +) { + suspend operator fun invoke(inputPassword: String): Result { + return remoteConfigRepository.getSignUpPassword().mapCatching { qrPassword: String -> + inputPassword == qrPassword + } + } +} \ No newline at end of file From 66552241e7382b2a39b83ae83e14c68a946c0eb9 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:22:57 +0900 Subject: [PATCH 03/13] =?UTF-8?q?refactor:=20Keyboard=20Visiblity=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EB=A5=BC=20compose=20State=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B3=B5=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yapp/common/util/Keyboard.kt | 40 +++++++++++++++++++ .../common/util/KeyboardVisibilityUtils.kt | 39 ------------------ 2 files changed, 40 insertions(+), 39 deletions(-) create mode 100644 common/src/main/java/com/yapp/common/util/Keyboard.kt delete mode 100644 common/src/main/java/com/yapp/common/util/KeyboardVisibilityUtils.kt diff --git a/common/src/main/java/com/yapp/common/util/Keyboard.kt b/common/src/main/java/com/yapp/common/util/Keyboard.kt new file mode 100644 index 00000000..a65de52a --- /dev/null +++ b/common/src/main/java/com/yapp/common/util/Keyboard.kt @@ -0,0 +1,40 @@ +package com.yapp.common.util + +import android.graphics.Rect +import android.view.View +import android.view.ViewTreeObserver +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.produceState +import androidx.compose.ui.platform.LocalView + +private const val KeyBoardVisibleThreshold = 0.15f + +/** + * 키보드의 Show/Hide 상태를 가져온다. + * @return 키보드의 visible 상태 + */ +@Composable +fun rememberKeyboardVisible( + initialKeyboardState: Boolean = false, +): State { + val view = LocalView.current + return produceState(initialValue = initialKeyboardState) { + val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener { + value = view.isKeyboardOpen() + } + view.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener) + awaitDispose { + view.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener) + } + } +} + +private fun View.isKeyboardOpen(): Boolean { + val rect = Rect().also { + getWindowVisibleDisplayFrame(it) + } + val screenHeight = rootView.height + val keypadHeight = screenHeight - rect.bottom + return keypadHeight > screenHeight * KeyBoardVisibleThreshold +} \ No newline at end of file diff --git a/common/src/main/java/com/yapp/common/util/KeyboardVisibilityUtils.kt b/common/src/main/java/com/yapp/common/util/KeyboardVisibilityUtils.kt deleted file mode 100644 index cbb19a55..00000000 --- a/common/src/main/java/com/yapp/common/util/KeyboardVisibilityUtils.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.yapp.common.util - -import android.graphics.Rect -import android.view.ViewTreeObserver -import android.view.Window - -class KeyboardVisibilityUtils( - private val window: Window, - private val onShowKeyboard: () -> Unit, - private val onHideKeyboard: () -> Unit -) { - private val windowVisibleDisplayFrame = Rect() - private var lastVisibleDecorViewHeight: Int = Int.MAX_VALUE - private val MIN_KEYBOARD_HEIGHT_PX = 100 - - private val onGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener { - window.decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame) - val visibleDecorViewHeight = windowVisibleDisplayFrame.height() - - if (lastVisibleDecorViewHeight != 0) { - if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) { - onShowKeyboard.invoke() - } else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) { - onHideKeyboard.invoke() - } - } - - lastVisibleDecorViewHeight = visibleDecorViewHeight - } - - init { - window.decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener) - } - - fun detachKeyboardListener() { - window.decorView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener) - } - -} \ No newline at end of file From c28cfabc2ed0c653467c79edeeac7a6491f18c00 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:23:48 +0900 Subject: [PATCH 04/13] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=ED=99=94=EB=A9=B4=EB=8F=84=20rememberKeyb?= =?UTF-8?q?oardVisibillity=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/member/signup/name/Name.kt | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/name/Name.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/name/Name.kt index f4002477..2ae29ed3 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/name/Name.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/name/Name.kt @@ -1,31 +1,52 @@ package com.yapp.presentation.ui.member.signup.name -import android.app.Activity import androidx.activity.compose.BackHandler +import androidx.compose.animation.Crossfade import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.insets.navigationBarsWithImePadding import com.google.accompanist.insets.statusBarsPadding -import com.yapp.common.theme.* -import com.yapp.common.util.KeyboardVisibilityUtils +import com.yapp.common.theme.AttendanceTheme +import com.yapp.common.theme.AttendanceTypography +import com.yapp.common.util.rememberKeyboardVisible import com.yapp.common.yds.YDSAppBar import com.yapp.common.yds.YDSButtonLarge import com.yapp.common.yds.YDSPopupDialog import com.yapp.common.yds.YdsButtonState import com.yapp.presentation.R import com.yapp.presentation.ui.member.signup.name.NameContract.NameSideEffect -import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.* +import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.InputName +import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.OnBackButtonClick +import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.OnCancelButtonClick +import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.OnDismissDialogButtonClick +import com.yapp.presentation.ui.member.signup.name.NameContract.NameUiEvent.OnNextButtonClick import kotlinx.coroutines.flow.collectLatest @OptIn(ExperimentalComposeUiApi::class) @@ -36,12 +57,7 @@ fun Name( onClickNextBtn: (String) -> Unit ) { val uiState by viewModel.uiState.collectAsState() - var isKeyboardOpened by remember { mutableStateOf(false) } - val keyboardVisibilityUtils = KeyboardVisibilityUtils( - window = (LocalContext.current as Activity).window, - onShowKeyboard = { isKeyboardOpened = true }, - onHideKeyboard = { isKeyboardOpened = false } - ) + val isKeyboardVisible by rememberKeyboardVisible() val onCancelButtonClick by remember { mutableStateOf({ viewModel.setEvent(OnCancelButtonClick) }) } val onNextButtonClick: () -> Unit by remember { @@ -101,10 +117,9 @@ fun Name( NextButton( enabled = uiState.name.isNotBlank(), - isKeyboardOpened = isKeyboardOpened, + isKeyboardVisible = isKeyboardVisible, modifier = Modifier.align(Alignment.BottomCenter), onClickNextBtn = { onNextButtonClick() }, - keyboardVisibilityUtils = keyboardVisibilityUtils ) } } @@ -155,7 +170,10 @@ fun InputName(name: String, onInputName: (String) -> Unit) { singleLine = true, modifier = Modifier .fillMaxWidth() - .background(color = AttendanceTheme.colors.grayScale.Gray200, shape = RoundedCornerShape(50.dp)), + .background( + color = AttendanceTheme.colors.grayScale.Gray200, + shape = RoundedCornerShape(50.dp) + ), placeholder = { Text( text = stringResource(id = R.string.name_example_hint), @@ -178,19 +196,17 @@ fun InputName(name: String, onInputName: (String) -> Unit) { @Composable fun NextButton( enabled: Boolean, - isKeyboardOpened: Boolean, + isKeyboardVisible: Boolean, modifier: Modifier, onClickNextBtn: () -> Unit, - keyboardVisibilityUtils: KeyboardVisibilityUtils ) { Box( modifier = modifier, ) { - if (isKeyboardOpened) { + if (isKeyboardVisible) { OnKeyboardNextButton( enabled = enabled, onClickNextBtn = onClickNextBtn, - keyboardVisibilityUtils = keyboardVisibilityUtils ) } else { YDSButtonLarge( @@ -199,7 +215,6 @@ fun NextButton( onClick = { if (enabled) { onClickNextBtn() - keyboardVisibilityUtils.detachKeyboardListener() } }, modifier = Modifier.padding(start = 24.dp, end = 24.dp, bottom = 40.dp) @@ -211,18 +226,17 @@ fun NextButton( @Composable fun OnKeyboardNextButton( + modifier: Modifier = Modifier, enabled: Boolean, onClickNextBtn: () -> Unit, - keyboardVisibilityUtils: KeyboardVisibilityUtils ) { Button( enabled = enabled, contentPadding = PaddingValues(0.dp), onClick = { onClickNextBtn() - keyboardVisibilityUtils.detachKeyboardListener() }, - modifier = Modifier + modifier = modifier .fillMaxWidth() .height(60.dp), shape = RoundedCornerShape(0.dp), From 9d7b1045085ed4b69a0559f2da2618455cd7f50f Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:24:00 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat:=20strings,=20drawable=20=EB=A6=AC?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/illust_password_1.xml | 77 +++++++++++++++ .../main/res/drawable/illust_password_2.xml | 94 +++++++++++++++++++ .../main/res/drawable/illust_password_3.xml | 86 +++++++++++++++++ .../main/res/drawable/illust_password_4.xml | 83 ++++++++++++++++ presentation/src/main/res/values/strings.xml | 6 +- 5 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 common/src/main/res/drawable/illust_password_1.xml create mode 100644 common/src/main/res/drawable/illust_password_2.xml create mode 100644 common/src/main/res/drawable/illust_password_3.xml create mode 100644 common/src/main/res/drawable/illust_password_4.xml diff --git a/common/src/main/res/drawable/illust_password_1.xml b/common/src/main/res/drawable/illust_password_1.xml new file mode 100644 index 00000000..63bf3ac1 --- /dev/null +++ b/common/src/main/res/drawable/illust_password_1.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/main/res/drawable/illust_password_2.xml b/common/src/main/res/drawable/illust_password_2.xml new file mode 100644 index 00000000..9a96bc86 --- /dev/null +++ b/common/src/main/res/drawable/illust_password_2.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/main/res/drawable/illust_password_3.xml b/common/src/main/res/drawable/illust_password_3.xml new file mode 100644 index 00000000..fadb40f4 --- /dev/null +++ b/common/src/main/res/drawable/illust_password_3.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/main/res/drawable/illust_password_4.xml b/common/src/main/res/drawable/illust_password_4.xml new file mode 100644 index 00000000..77d4248b --- /dev/null +++ b/common/src/main/res/drawable/illust_password_4.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 8931ff25..a510b536 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -31,7 +31,11 @@ 관리 20기 누적 출결 점수 누적 점수 확인하기 - + + 너, 내 동료가 돼라! + 암호 코드 4자리를 입력해주세요 + 틀린 코드입니다 + 속한 직군을\n알려주세요 YAPP 시작하기 From 86fe963ac5f19afbfbd7125f20f12812d16dffbb Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:24:14 +0900 Subject: [PATCH 06/13] =?UTF-8?q?feat:=20=EC=95=94=ED=98=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=B0=8F=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../signup/password/PassWordViewModel.kt | 65 +++++ .../ui/member/signup/password/Password.kt | 231 ++++++++++++++++++ .../signup/password/PasswordContract.kt | 28 +++ 3 files changed, 324 insertions(+) create mode 100644 presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt create mode 100644 presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt create mode 100644 presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt new file mode 100644 index 00000000..0feab8d3 --- /dev/null +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt @@ -0,0 +1,65 @@ +package com.yapp.presentation.ui.member.signup.password + +import androidx.lifecycle.viewModelScope +import com.google.firebase.FirebaseNetworkException +import com.yapp.common.base.BaseViewModel +import com.yapp.domain.usecases.CheckSignUpPasswordUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class PassWordViewModel @Inject constructor( + private val checkSignUpPasswordUseCase: CheckSignUpPasswordUseCase, +) : + BaseViewModel( + PasswordContract.PasswordUiState() + ) { + + override suspend fun handleEvent(event: PasswordContract.PasswordUiEvent) { + when (event) { + is PasswordContract.PasswordUiEvent.InputPassword -> { + updatePassword(password = event.password) + } + + PasswordContract.PasswordUiEvent.OnBackButtonClick -> { + setEffect(PasswordContract.PasswordSideEffect.NavigateToPreviousScreen) + } + + PasswordContract.PasswordUiEvent.OnNextButtonClick -> { + checkPassword(password = currentState.inputPassword) + } + } + } + + private fun updatePassword(password: String) { + if (password.length <= PasswordDigit) { + setState { copy(inputPassword = password, isWrong = false) } + } + } + + private fun checkPassword(password: String) = viewModelScope.launch { + setEffect(PasswordContract.PasswordSideEffect.KeyboardHide) + checkSignUpPasswordUseCase(password) + .onSuccess { isPasswordValid -> + when (isPasswordValid) { + true -> { + setEffect(PasswordContract.PasswordSideEffect.NavigateToNextScreen) + } + + false -> { + setEffect(PasswordContract.PasswordSideEffect.KeyboardHide) + setState { + copy( + isWrong = true, + ) + } + } + } + }.onFailure { exception -> + if (exception is FirebaseNetworkException) { + setEffect(PasswordContract.PasswordSideEffect.ShowToast("네트워크 연결을 확인해주세요")) + } + } + } +} diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt new file mode 100644 index 00000000..82c02f5d --- /dev/null +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt @@ -0,0 +1,231 @@ +@file:OptIn(ExperimentalComposeUiApi::class) + +package com.yapp.presentation.ui.member.signup.password + +import android.widget.Toast +import androidx.annotation.DrawableRes +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.NonRestartableComposable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.google.accompanist.insets.navigationBarsWithImePadding +import com.google.accompanist.insets.statusBarsPadding +import com.yapp.common.flow.collectAsStateWithLifecycle +import com.yapp.common.theme.AttendanceTheme +import com.yapp.common.theme.AttendanceTypography +import com.yapp.common.theme.Light_Gray_200 +import com.yapp.common.util.rememberKeyboardVisible +import com.yapp.common.yds.YDSAppBar +import com.yapp.presentation.R +import com.yapp.presentation.ui.member.signup.name.OnKeyboardNextButton +import kotlinx.coroutines.flow.collectLatest + +internal const val PasswordDigit = 4 + +@Composable +internal fun Password( + viewModel: PassWordViewModel = hiltViewModel(), + onClickBackButton: () -> Unit, + onClickNextButton: () -> Unit +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val keyboardVisible by rememberKeyboardVisible() + val focusRequester = remember { FocusRequester() } + val context = LocalContext.current + val keyboardController = LocalSoftwareKeyboardController.current + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + + LaunchedEffect(key1 = viewModel.effect) { + viewModel.effect.collectLatest { + when (it) { + is PasswordContract.PasswordSideEffect.ShowToast -> { + Toast.makeText(context, it.message, Toast.LENGTH_SHORT).show() + } + + PasswordContract.PasswordSideEffect.KeyboardHide -> { + keyboardController?.hide() + } + + PasswordContract.PasswordSideEffect.NavigateToNextScreen -> { + onClickNextButton() + } + + PasswordContract.PasswordSideEffect.NavigateToPreviousScreen -> { + onClickBackButton() + } + } + } + } + + Scaffold( + topBar = { + YDSAppBar( + modifier = Modifier.background(AttendanceTheme.colors.backgroundColors.background), + onClickBackButton = onClickBackButton, + ) + }, + modifier = Modifier + .fillMaxSize() + .statusBarsPadding() + .navigationBarsWithImePadding() + ) { contentPadding -> + Box( + modifier = Modifier + .fillMaxSize() + .background(AttendanceTheme.colors.backgroundColors.background) + .padding(contentPadding) + ) { + Column( + modifier = Modifier.padding(horizontal = 24.dp) + ) { + Spacer(modifier = Modifier.padding(top = 40.dp)) + Text( + text = stringResource(id = R.string.member_signup_password_title), + color = AttendanceTheme.colors.grayScale.Gray1200, + style = AttendanceTypography.h1 + ) + Spacer(modifier = Modifier.padding(top = 12.dp)) + Text( + text = stringResource(id = R.string.member_signup_password_subtitle), + color = AttendanceTheme.colors.grayScale.Gray800, + style = AttendanceTypography.body1 + ) + Spacer(modifier = Modifier.padding(top = 28.dp)) + PasswordTextField( + modifier = Modifier + .wrapContentSize() + .focusRequester(focusRequester), + value = uiState.inputPassword, + onValueChange = { + viewModel.setEvent(PasswordContract.PasswordUiEvent.InputPassword(it)) + }, + ) + Spacer(modifier = Modifier.padding(top = 20.dp)) + AnimatedVisibility( + visible = uiState.isWrong, + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + Text( + text = stringResource(id = R.string.member_signup_password_wrong_code), + color = AttendanceTheme.colors.etcColors.EtcRed, + style = AttendanceTypography.subtitle1, + ) + } + } + } + if (keyboardVisible) { + OnKeyboardNextButton( + modifier = Modifier.align(Alignment.BottomCenter), + enabled = uiState.inputPassword.length == PasswordDigit, + onClickNextBtn = { + viewModel.setEvent(PasswordContract.PasswordUiEvent.OnNextButtonClick) + }, + ) + } + } + } +} + +@Composable +private fun PasswordTextField( + modifier: Modifier = Modifier, + value: String, + onValueChange: (String) -> Unit +) { + BasicTextField( + modifier = modifier, + value = value, + onValueChange = onValueChange, + decorationBox = { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Absolute.SpaceBetween, + ) { + value.forEachIndexed { index, _ -> + PasswordBox( + resId = getPasswordImageByIndex(index) + ) + } + repeat(PasswordDigit - value.length) { + GrayBox() + } + } + }, + ) +} + +private fun getPasswordImageByIndex(index: Int): Int { + return when (index) { + 0 -> com.yapp.common.R.drawable.illust_password_1 + 1 -> com.yapp.common.R.drawable.illust_password_2 + 2 -> com.yapp.common.R.drawable.illust_password_3 + else -> com.yapp.common.R.drawable.illust_password_4 + } +} + +@Composable +@NonRestartableComposable +private fun PasswordBox( + modifier: Modifier = Modifier, + @DrawableRes resId: Int, +) { + GrayBox(modifier = modifier) { + Image( + modifier = Modifier.fillMaxSize(), + painter = painterResource(id = resId), + contentDescription = null, + ) + } +} + +@Composable +@NonRestartableComposable +private fun GrayBox( + modifier: Modifier = Modifier, + content: (@Composable () -> Unit)? = null, +) { + Box( + modifier = modifier + .size(72.dp) + .clip(CircleShape) + .background(Light_Gray_200), + ) { + content?.invoke() + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt new file mode 100644 index 00000000..6c7093a0 --- /dev/null +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt @@ -0,0 +1,28 @@ +package com.yapp.presentation.ui.member.signup.password + +import com.yapp.common.base.UiEvent +import com.yapp.common.base.UiSideEffect +import com.yapp.common.base.UiState + +class PasswordContract { + data class PasswordUiState( + val isError: Boolean = false, + val correctPassword: String = "", + val inputPassword: String = "", + val nextButtonEnabled: Boolean = false, + val isWrong: Boolean = false, + ) : UiState + + sealed class PasswordSideEffect : UiSideEffect { + object NavigateToPreviousScreen : PasswordSideEffect() + object NavigateToNextScreen : PasswordSideEffect() + object KeyboardHide : PasswordSideEffect() + class ShowToast(val message: String) : PasswordSideEffect() + } + + sealed class PasswordUiEvent : UiEvent { + data class InputPassword(val password: String) : PasswordUiEvent() + object OnNextButtonClick : PasswordUiEvent() + object OnBackButtonClick : PasswordUiEvent() + } +} From c92798a1153a25d43a587c1adf6d51d70268f759 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Fri, 21 Jul 2023 16:25:41 +0900 Subject: [PATCH 07/13] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=9B=84=20Navigate=ED=95=98=EA=B3=A0,=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=ED=94=8C=EB=A1=9C=EC=9A=B0=EB=A1=9C=20?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EA=B0=80=EB=8F=84=EB=A1=9D=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 --- .../yapp/presentation/ui/AttendanceScreen.kt | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt b/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt index 0ec28847..0a977c08 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt @@ -8,7 +8,14 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -39,6 +46,7 @@ import com.yapp.presentation.ui.member.qrcodescanner.QrCodeScanner import com.yapp.presentation.ui.member.score.detail.SessionDetail import com.yapp.presentation.ui.member.setting.MemberSetting import com.yapp.presentation.ui.member.signup.name.Name +import com.yapp.presentation.ui.member.signup.password.Password import com.yapp.presentation.ui.member.signup.position.Position import com.yapp.presentation.ui.member.signup.team.Team import com.yapp.presentation.ui.splash.Splash @@ -84,7 +92,7 @@ fun AttendanceScreen( } }, navigateToSignUpScreen = { - navController.navigate(AttendanceScreenRoute.SIGNUP_NAME.route) { + navController.navigate(AttendanceScreenRoute.SIGNUP_PASSWORD.route) { popUpTo(AttendanceScreenRoute.LOGIN.route) { inclusive = true } } }, @@ -235,6 +243,19 @@ fun AttendanceScreen( SessionDetail { navController.popBackStack() } } + composable( + route = AttendanceScreenRoute.SIGNUP_PASSWORD.route, + ) { + SetStatusBarColorByRoute(it.destination.route) + Password( + onClickBackButton = { navController.popBackStack() }, + onClickNextButton = { + navController.navigate(AttendanceScreenRoute.SIGNUP_NAME.route) { + popUpTo(AttendanceScreenRoute.SIGNUP_NAME.route) { inclusive = true } + } + }) + } + composable( route = AttendanceScreenRoute.SIGNUP_NAME.route ) { @@ -321,6 +342,7 @@ enum class AttendanceScreenRoute(val route: String) { SIGNUP_NAME("signup-name"), SIGNUP_POSITION("signup-position"), SIGNUP_TEAM("signup-team"), + SIGNUP_PASSWORD("signup-password"), HELP("help"), ADMIN_TOTAL_SCORE("admin-total-score"), SESSION_DETAIL("session-detail"), From 659cc8ebf82982ae43244e51f1ef48868e704967 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sat, 22 Jul 2023 13:02:15 +0900 Subject: [PATCH 08/13] =?UTF-8?q?fix=20:=20keyboardoptions,=20keboardactio?= =?UTF-8?q?ns=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=EC=97=90=20=EC=A0=9C?= =?UTF-8?q?=EA=B3=B5=20@TaeseongYun?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/member/signup/password/Password.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt index 82c02f5d..53c7cf17 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt @@ -19,6 +19,8 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -36,6 +38,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.insets.navigationBarsWithImePadding @@ -132,6 +135,9 @@ internal fun Password( onValueChange = { viewModel.setEvent(PasswordContract.PasswordUiEvent.InputPassword(it)) }, + keyboardOptions = KeyboardOptions().copy( + keyboardType = KeyboardType.NumberPassword, + ), ) Spacer(modifier = Modifier.padding(top = 20.dp)) AnimatedVisibility( @@ -163,15 +169,19 @@ internal fun Password( } @Composable -private fun PasswordTextField( +internal fun PasswordTextField( modifier: Modifier = Modifier, value: String, - onValueChange: (String) -> Unit + onValueChange: (String) -> Unit, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default, + keyboardActions: KeyboardActions = KeyboardActions.Default, ) { BasicTextField( modifier = modifier, value = value, onValueChange = onValueChange, + keyboardOptions = keyboardOptions, + keyboardActions = keyboardActions, decorationBox = { Row( modifier = Modifier.fillMaxWidth(), From 48830c85ccb1468a7299b11427f7e70170b4a1b1 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sat, 22 Jul 2023 21:00:07 +0900 Subject: [PATCH 09/13] fix: duplicate keyboard hide effect --- .../presentation/ui/member/signup/password/PassWordViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt index 0feab8d3..c574055a 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt @@ -48,7 +48,6 @@ internal class PassWordViewModel @Inject constructor( } false -> { - setEffect(PasswordContract.PasswordSideEffect.KeyboardHide) setState { copy( isWrong = true, From c80cc6c52342a12773d2d759ca54607be84591f9 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sat, 22 Jul 2023 21:37:09 +0900 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20Back=20Button=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=8F=8C=EC=95=84=EA=B0=80=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yapp/presentation/ui/AttendanceScreen.kt | 8 ++++++-- .../presentation/ui/member/signup/password/Password.kt | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt b/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt index 0a977c08..c9f48708 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/AttendanceScreen.kt @@ -248,10 +248,14 @@ fun AttendanceScreen( ) { SetStatusBarColorByRoute(it.destination.route) Password( - onClickBackButton = { navController.popBackStack() }, + onClickBackButton = { + navController.navigate(AttendanceScreenRoute.LOGIN.route) { + popUpTo(AttendanceScreenRoute.SIGNUP_PASSWORD.route) { inclusive = true } + } + }, onClickNextButton = { navController.navigate(AttendanceScreenRoute.SIGNUP_NAME.route) { - popUpTo(AttendanceScreenRoute.SIGNUP_NAME.route) { inclusive = true } + popUpTo(AttendanceScreenRoute.SIGNUP_PASSWORD.route) { inclusive = true } } }) } diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt index 53c7cf17..b20c05d8 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt @@ -97,7 +97,9 @@ internal fun Password( topBar = { YDSAppBar( modifier = Modifier.background(AttendanceTheme.colors.backgroundColors.background), - onClickBackButton = onClickBackButton, + onClickBackButton = { + viewModel.setEvent(PasswordContract.PasswordUiEvent.OnBackButtonClick) + }, ) }, modifier = Modifier From 8e92b6f03b047baf1f5837d52ee14f0e5bdc10b5 Mon Sep 17 00:00:00 2001 From: Choi Sang Rok Date: Sun, 23 Jul 2023 17:39:30 +0900 Subject: [PATCH 11/13] fix: wrong space Co-authored-by: Jeongho --- .../data/datasource/FirebaseRemoteConfigDataSourceImpl.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt index 9a0d031e..c924a7bf 100644 --- a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt +++ b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt @@ -72,9 +72,9 @@ class FirebaseRemoteConfigDataSourceImpl @Inject constructor() : FirebaseRemoteC return suspendCancellableCoroutine { cancellableContinuation -> firebaseRemoteConfig.fetchAndActivate().addOnSuccessListener { val entities = firebaseRemoteConfig.getString(RemoteConfigData.AttendanceSelectTeams.key) - .let { jsonString -> - Json.decodeFromString>(jsonString) - } + .let { jsonString -> + Json.decodeFromString>(jsonString) + } cancellableContinuation.resume(value = entities, onCancellation = null) }.addOnFailureListener { exception -> From 95dd41b72af56b7512ff987cc57c808074574d27 Mon Sep 17 00:00:00 2001 From: Choi Sang Rok Date: Sun, 23 Jul 2023 17:39:54 +0900 Subject: [PATCH 12/13] fix: wrong space Co-authored-by: Jeongho --- .../yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt index c924a7bf..a3ecae1e 100644 --- a/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt +++ b/data/src/main/java/com/yapp/data/datasource/FirebaseRemoteConfigDataSourceImpl.kt @@ -98,7 +98,7 @@ class FirebaseRemoteConfigDataSourceImpl @Inject constructor() : FirebaseRemoteC return suspendCancellableCoroutine { cancellableContinuation -> firebaseRemoteConfig.fetchAndActivate().addOnSuccessListener { val shouldShowGuest = firebaseRemoteConfig.getString(RemoteConfigData.ShouldShowGuestButton.key) - .toBooleanStrict() + .toBooleanStrict() cancellableContinuation.resume(shouldShowGuest) }.addOnFailureListener { exception -> From 61eb2f24ef9cdab84538cd7fdd994e3cf441dc3a Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 23 Jul 2023 17:47:35 +0900 Subject: [PATCH 13/13] =?UTF-8?q?refactor=20:=20@hoyahozz=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../signup/password/PassWordViewModel.kt | 26 ++++++++++--------- .../ui/member/signup/password/Password.kt | 19 +++++++------- .../signup/password/PasswordContract.kt | 6 ++++- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt index c574055a..eb683759 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PassWordViewModel.kt @@ -4,6 +4,10 @@ import androidx.lifecycle.viewModelScope import com.google.firebase.FirebaseNetworkException import com.yapp.common.base.BaseViewModel import com.yapp.domain.usecases.CheckSignUpPasswordUseCase +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordSideEffect +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordUiEvent +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordUiState +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordUiState.Companion.PasswordDigit import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -11,22 +15,19 @@ import javax.inject.Inject @HiltViewModel internal class PassWordViewModel @Inject constructor( private val checkSignUpPasswordUseCase: CheckSignUpPasswordUseCase, -) : - BaseViewModel( - PasswordContract.PasswordUiState() - ) { +) : BaseViewModel(PasswordUiState()) { - override suspend fun handleEvent(event: PasswordContract.PasswordUiEvent) { + override suspend fun handleEvent(event: PasswordUiEvent) { when (event) { - is PasswordContract.PasswordUiEvent.InputPassword -> { + is PasswordUiEvent.InputPassword -> { updatePassword(password = event.password) } - PasswordContract.PasswordUiEvent.OnBackButtonClick -> { - setEffect(PasswordContract.PasswordSideEffect.NavigateToPreviousScreen) + PasswordUiEvent.OnBackButtonClick -> { + setEffect(PasswordSideEffect.NavigateToPreviousScreen) } - PasswordContract.PasswordUiEvent.OnNextButtonClick -> { + PasswordUiEvent.OnNextButtonClick -> { checkPassword(password = currentState.inputPassword) } } @@ -39,12 +40,12 @@ internal class PassWordViewModel @Inject constructor( } private fun checkPassword(password: String) = viewModelScope.launch { - setEffect(PasswordContract.PasswordSideEffect.KeyboardHide) + setEffect(PasswordSideEffect.KeyboardHide) checkSignUpPasswordUseCase(password) .onSuccess { isPasswordValid -> when (isPasswordValid) { true -> { - setEffect(PasswordContract.PasswordSideEffect.NavigateToNextScreen) + setEffect(PasswordSideEffect.NavigateToNextScreen) } false -> { @@ -57,8 +58,9 @@ internal class PassWordViewModel @Inject constructor( } }.onFailure { exception -> if (exception is FirebaseNetworkException) { - setEffect(PasswordContract.PasswordSideEffect.ShowToast("네트워크 연결을 확인해주세요")) + setEffect(PasswordSideEffect.ShowToast("네트워크 연결을 확인해주세요")) } } } + } diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt index b20c05d8..d08963de 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/Password.kt @@ -51,10 +51,11 @@ import com.yapp.common.util.rememberKeyboardVisible import com.yapp.common.yds.YDSAppBar import com.yapp.presentation.R import com.yapp.presentation.ui.member.signup.name.OnKeyboardNextButton +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordSideEffect +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordUiEvent +import com.yapp.presentation.ui.member.signup.password.PasswordContract.PasswordUiState.Companion.PasswordDigit import kotlinx.coroutines.flow.collectLatest -internal const val PasswordDigit = 4 - @Composable internal fun Password( viewModel: PassWordViewModel = hiltViewModel(), @@ -74,19 +75,19 @@ internal fun Password( LaunchedEffect(key1 = viewModel.effect) { viewModel.effect.collectLatest { when (it) { - is PasswordContract.PasswordSideEffect.ShowToast -> { + is PasswordSideEffect.ShowToast -> { Toast.makeText(context, it.message, Toast.LENGTH_SHORT).show() } - PasswordContract.PasswordSideEffect.KeyboardHide -> { + PasswordSideEffect.KeyboardHide -> { keyboardController?.hide() } - PasswordContract.PasswordSideEffect.NavigateToNextScreen -> { + PasswordSideEffect.NavigateToNextScreen -> { onClickNextButton() } - PasswordContract.PasswordSideEffect.NavigateToPreviousScreen -> { + PasswordSideEffect.NavigateToPreviousScreen -> { onClickBackButton() } } @@ -98,7 +99,7 @@ internal fun Password( YDSAppBar( modifier = Modifier.background(AttendanceTheme.colors.backgroundColors.background), onClickBackButton = { - viewModel.setEvent(PasswordContract.PasswordUiEvent.OnBackButtonClick) + viewModel.setEvent(PasswordUiEvent.OnBackButtonClick) }, ) }, @@ -135,7 +136,7 @@ internal fun Password( .focusRequester(focusRequester), value = uiState.inputPassword, onValueChange = { - viewModel.setEvent(PasswordContract.PasswordUiEvent.InputPassword(it)) + viewModel.setEvent(PasswordUiEvent.InputPassword(it)) }, keyboardOptions = KeyboardOptions().copy( keyboardType = KeyboardType.NumberPassword, @@ -162,7 +163,7 @@ internal fun Password( modifier = Modifier.align(Alignment.BottomCenter), enabled = uiState.inputPassword.length == PasswordDigit, onClickNextBtn = { - viewModel.setEvent(PasswordContract.PasswordUiEvent.OnNextButtonClick) + viewModel.setEvent(PasswordUiEvent.OnNextButtonClick) }, ) } diff --git a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt index 6c7093a0..fb504173 100644 --- a/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt +++ b/presentation/src/main/java/com/yapp/presentation/ui/member/signup/password/PasswordContract.kt @@ -11,7 +11,11 @@ class PasswordContract { val inputPassword: String = "", val nextButtonEnabled: Boolean = false, val isWrong: Boolean = false, - ) : UiState + ) : UiState { + companion object { + const val PasswordDigit = 4 + } + } sealed class PasswordSideEffect : UiSideEffect { object NavigateToPreviousScreen : PasswordSideEffect()