diff --git a/presentation/src/main/java/kr/genti/presentation/generate/waiting/PushDialog.kt b/presentation/src/main/java/kr/genti/presentation/generate/waiting/PushDialog.kt index bfa4cb2f..3ba78fbd 100644 --- a/presentation/src/main/java/kr/genti/presentation/generate/waiting/PushDialog.kt +++ b/presentation/src/main/java/kr/genti/presentation/generate/waiting/PushDialog.kt @@ -26,7 +26,7 @@ class PushDialog : BaseDialog(R.layout.dialog_push) { super.onStart() dialog?.window?.apply { setLayout( - WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, ) setBackgroundDrawableResource(R.color.transparent) @@ -50,7 +50,12 @@ class PushDialog : BaseDialog(R.layout.dialog_push) { } private fun initCloseBtnListener() { - binding.btnClose.setOnSingleClickListener { dismiss() } + binding.btnClose.setOnSingleClickListener { + with(requireActivity()) { + setResult(Activity.RESULT_OK) + finish() + } + } } private fun initGetAlarmBtnListener() { @@ -92,13 +97,4 @@ class PushDialog : BaseDialog(R.layout.dialog_push) { requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) } } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - - with(requireActivity()) { - setResult(Activity.RESULT_OK) - finish() - } - } } diff --git a/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileFragment.kt b/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileFragment.kt index 4691ab2e..60d7c669 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileFragment.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileFragment.kt @@ -19,9 +19,14 @@ import kr.genti.core.extension.stringOf import kr.genti.core.extension.toast import kr.genti.core.state.UiState import kr.genti.domain.entity.response.ImageModel +import kr.genti.domain.enums.GenerateStatus import kr.genti.presentation.R import kr.genti.presentation.create.CreateActivity import kr.genti.presentation.databinding.FragmentProfileBinding +import kr.genti.presentation.generate.waiting.WaitingActivity +import kr.genti.presentation.main.CreateErrorDialog +import kr.genti.presentation.main.CreateFinishedDialog +import kr.genti.presentation.main.CreateUnableDialog import kr.genti.presentation.setting.SettingActivity import kr.genti.presentation.util.AmplitudeManager @@ -34,6 +39,9 @@ class ProfileFragment() : BaseFragment(R.layout.fragment private val viewModel by activityViewModels() private var profileImageDialog: ProfileImageDialog? = null + private var createFinishedDialog: CreateFinishedDialog? = null + private var createErrorDialog: CreateErrorDialog? = null + private var createUnableDialog: CreateUnableDialog? = null override fun onViewCreated( view: View, @@ -47,6 +55,7 @@ class ProfileFragment() : BaseFragment(R.layout.fragment setListWithInfinityScroll() observeGenerateStatus() observePictureListPageState() + observeServerAvailableState() } private fun initView() { @@ -78,7 +87,27 @@ class ProfileFragment() : BaseFragment(R.layout.fragment } private fun initMoveClickListener(x: Boolean) { - startActivity(Intent(requireActivity(), CreateActivity::class.java)) + when (viewModel.currentStatus) { + GenerateStatus.NEW_REQUEST_AVAILABLE -> { + viewModel.getIsServerAvailable() + } + + GenerateStatus.AWAIT_USER_VERIFICATION -> { + createFinishedDialog = CreateFinishedDialog() + createFinishedDialog?.show(parentFragmentManager, DIALOG_FINISHED) + } + + GenerateStatus.IN_PROGRESS -> { + startActivity(Intent(requireActivity(), WaitingActivity::class.java)) + } + + GenerateStatus.CANCELED -> { + createErrorDialog = CreateErrorDialog() + createErrorDialog?.show(parentFragmentManager, DIALOG_ERROR) + } + + GenerateStatus.EMPTY -> return + } } private fun setListWithInfinityScroll() { @@ -153,13 +182,41 @@ class ProfileFragment() : BaseFragment(R.layout.fragment } } + private fun observeServerAvailableState() { + viewModel.serverAvailableState.flowWithLifecycle(lifecycle).onEach { state -> + when (state) { + is UiState.Success -> { + if (state.data.status) { + AmplitudeManager.trackEvent("click_createpictab") + startActivity(Intent(requireActivity(), CreateActivity::class.java)) + } else { + createUnableDialog = + CreateUnableDialog.newInstance(state.data.message.orEmpty()) + createUnableDialog?.show(parentFragmentManager, DIALOG_UNABLE) + } + } + + is UiState.Failure -> toast(stringOf(R.string.error_msg)) + else -> return@onEach + } + viewModel.resetIsServerAvailable() + }.launchIn(lifecycleScope) + } + override fun onDestroyView() { super.onDestroyView() _adapter = null profileImageDialog = null + createFinishedDialog = null + createErrorDialog = null + createUnableDialog = null } companion object { private const val IMAGE_VIEWER = "IMAGE_VIEWER" + + private const val DIALOG_FINISHED = "DIALOG_FINISHED" + private const val DIALOG_ERROR = "DIALOG_ERROR" + private const val DIALOG_UNABLE = "DIALOG_UNABLE" } } diff --git a/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileViewModel.kt b/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileViewModel.kt index 985419ca..c27088b5 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileViewModel.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/profile/ProfileViewModel.kt @@ -8,66 +8,92 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kr.genti.core.state.UiState import kr.genti.domain.entity.response.PicturePagedListModel +import kr.genti.domain.entity.response.ServerAvailableModel import kr.genti.domain.enums.GenerateStatus import kr.genti.domain.repository.GenerateRepository import javax.inject.Inject @HiltViewModel class ProfileViewModel - @Inject - constructor( - private val generateRepository: GenerateRepository, - ) : ViewModel() { - private val _getGenerateStatusState = - MutableStateFlow>(UiState.Empty) - val getGenerateStatusState: StateFlow> = _getGenerateStatusState +@Inject +constructor( + private val generateRepository: GenerateRepository, +) : ViewModel() { + private val _getGenerateStatusState = + MutableStateFlow>(UiState.Empty) + val getGenerateStatusState: StateFlow> = _getGenerateStatusState - private val _getPictureListState = - MutableStateFlow>(UiState.Loading) - val getPictureListState: StateFlow> = _getPictureListState + var currentStatus: GenerateStatus = GenerateStatus.NEW_REQUEST_AVAILABLE - private var currentPage = -1 - private var isPagingFinish = false - private var totalPage = Int.MAX_VALUE + private val _serverAvailableState = + MutableStateFlow>(UiState.Empty) + val serverAvailableState: StateFlow> = _serverAvailableState - var isFirstLoading = true + private val _getPictureListState = + MutableStateFlow>(UiState.Loading) + val getPictureListState: StateFlow> = _getPictureListState - fun getGenerateStatusFromServer() { - viewModelScope.launch { - _getGenerateStatusState.value = UiState.Loading - generateRepository.getGenerateStatus() - .onSuccess { - _getGenerateStatusState.value = - UiState.Success(it.status == GenerateStatus.IN_PROGRESS) - } - .onFailure { t -> - _getGenerateStatusState.value = UiState.Failure(t.message.toString()) - } - } + private var currentPage = -1 + private var isPagingFinish = false + private var totalPage = Int.MAX_VALUE + + var isFirstLoading = true + + fun getGenerateStatusFromServer() { + viewModelScope.launch { + _getGenerateStatusState.value = UiState.Loading + generateRepository.getGenerateStatus() + .onSuccess { + currentStatus = it.status + _getGenerateStatusState.value = + UiState.Success(it.status == GenerateStatus.IN_PROGRESS) + + } + .onFailure { t -> + _getGenerateStatusState.value = UiState.Failure(t.message.toString()) + } } + } + + fun getIsServerAvailable() { + _serverAvailableState.value = UiState.Loading + viewModelScope.launch { + generateRepository + .getIsServerAvailable() + .onSuccess { + _serverAvailableState.value = UiState.Success(it) + }.onFailure { + _serverAvailableState.value = UiState.Failure(it.message.orEmpty()) + } + } + } + + fun resetIsServerAvailable() { + _serverAvailableState.value = UiState.Empty + } - fun getPictureListFromServer() { - viewModelScope.launch { - if (isPagingFinish) return@launch - _getPictureListState.value = UiState.Loading - generateRepository.getGeneratedPictureList( - ++currentPage, - 10, - null, - null, - ) - .onSuccess { - totalPage = it.totalPages - 1 - if (totalPage == currentPage) isPagingFinish = true - if (it.content.isEmpty()) { - _getPictureListState.value = UiState.Empty - return@launch - } - if (isFirstLoading) isFirstLoading = false - _getPictureListState.value = UiState.Success(it) - }.onFailure { - _getPictureListState.value = UiState.Failure(it.message.toString()) + fun getPictureListFromServer() { + viewModelScope.launch { + if (isPagingFinish) return@launch + _getPictureListState.value = UiState.Loading + generateRepository.getGeneratedPictureList( + ++currentPage, + 10, + null, + null, + ) + .onSuccess { + totalPage = it.totalPages - 1 + if (totalPage == currentPage) isPagingFinish = true + if (it.content.isEmpty()) { + _getPictureListState.value = UiState.Empty + return@launch } - } + if (isFirstLoading) isFirstLoading = false + _getPictureListState.value = UiState.Success(it) + }.onFailure { + _getPictureListState.value = UiState.Failure(it.message.toString()) + } } } +} diff --git a/presentation/src/main/res/drawable/btn_play.xml b/presentation/src/main/res/drawable/ic_play.xml similarity index 100% rename from presentation/src/main/res/drawable/btn_play.xml rename to presentation/src/main/res/drawable/ic_play.xml diff --git a/presentation/src/main/res/drawable/img_alarm.png b/presentation/src/main/res/drawable/img_alarm.png index 2723140e..2b58393f 100644 Binary files a/presentation/src/main/res/drawable/img_alarm.png and b/presentation/src/main/res/drawable/img_alarm.png differ diff --git a/presentation/src/main/res/drawable/img_glow.png b/presentation/src/main/res/drawable/img_glow.png new file mode 100644 index 00000000..fbcc58df Binary files /dev/null and b/presentation/src/main/res/drawable/img_glow.png differ diff --git a/presentation/src/main/res/drawable/img_wait_background.png b/presentation/src/main/res/drawable/img_wait_background.png deleted file mode 100644 index 9d2c5c88..00000000 Binary files a/presentation/src/main/res/drawable/img_wait_background.png and /dev/null differ diff --git a/presentation/src/main/res/drawable/img_wait_character.png b/presentation/src/main/res/drawable/img_wait_character.png deleted file mode 100644 index a3cebdb9..00000000 Binary files a/presentation/src/main/res/drawable/img_wait_character.png and /dev/null differ diff --git a/presentation/src/main/res/drawable/img_waiting_title.xml b/presentation/src/main/res/drawable/img_waiting_title.xml deleted file mode 100644 index a46d96e7..00000000 --- a/presentation/src/main/res/drawable/img_waiting_title.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/presentation/src/main/res/drawable/shape_gray_fill_16_rect.xml b/presentation/src/main/res/drawable/shape_gray_fill_16_rect.xml new file mode 100644 index 00000000..0a3552c3 --- /dev/null +++ b/presentation/src/main/res/drawable/shape_gray_fill_16_rect.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/activity_wait.xml b/presentation/src/main/res/layout/activity_wait.xml index 7d72ea3e..d3bbc5c2 100644 --- a/presentation/src/main/res/layout/activity_wait.xml +++ b/presentation/src/main/res/layout/activity_wait.xml @@ -8,107 +8,125 @@ + android:layout_height="match_parent" + android:background="@color/black"> - - - - + app:layout_constraintTop_toBottomOf="@id/tv_wait_header" /> - + - + - + - + - + - - + diff --git a/presentation/src/main/res/layout/dialog_push.xml b/presentation/src/main/res/layout/dialog_push.xml index 22422f49..06fc0efb 100644 --- a/presentation/src/main/res/layout/dialog_push.xml +++ b/presentation/src/main/res/layout/dialog_push.xml @@ -8,103 +8,91 @@ - + app:layout_constraintTop_toTopOf="parent"> - + - + - - - + - + - + - + diff --git a/presentation/src/main/res/layout/fragment_define.xml b/presentation/src/main/res/layout/fragment_define.xml index b9765dcf..a21c242b 100644 --- a/presentation/src/main/res/layout/fragment_define.xml +++ b/presentation/src/main/res/layout/fragment_define.xml @@ -146,7 +146,7 @@ android:background="@drawable/sel_btn" android:enabled="@{vm.isWritten}" android:padding="10dp" - android:src="@drawable/btn_play" + android:src="@drawable/ic_play" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/presentation/src/main/res/layout/fragment_pose.xml b/presentation/src/main/res/layout/fragment_pose.xml index 8f297f40..1c703e4f 100644 --- a/presentation/src/main/res/layout/fragment_pose.xml +++ b/presentation/src/main/res/layout/fragment_pose.xml @@ -23,10 +23,10 @@ + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/iv_ratio_3_2" + app:layout_constraintVertical_chainStyle="packed" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_ratio_3_2_title" /> @@ -135,35 +135,35 @@ android:id="@+id/iv_ratio_2_3" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="16dp" android:src="@drawable/img_ratio_2_3" - app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - android:layout_marginTop="16dp" - app:layout_constraintTop_toTopOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/iv_ratio_2_3" + app:layout_constraintVertical_chainStyle="packed" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_ratio_2_3_title" /> @@ -174,7 +174,6 @@ style="@style/TextAppearance.Genti.Subtitle2_16_Bold" android:layout_width="0dp" android:layout_height="wrap_content" - android:textColor="@color/black" android:layout_marginHorizontal="16dp" android:layout_marginBottom="28dp" android:background="@drawable/sel_btn" @@ -182,6 +181,7 @@ android:gravity="center" android:paddingVertical="14dp" android:text="@string/btn_next" + android:textColor="@color/black" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index b5c65264..f184b2e9 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -73,11 +73,13 @@ 을 선택해야 해요! 예시 - 세상에 없던 나만의\n 사진을 찍고있어요! - • • • - 예상 소요시간은 2시간입니다. - 미리 만들어놓은 컨셉에 얼굴만 바꾸는게 아니라\n’나만의 하나뿐인 사진’을 찍어드리기 위해 \n배경부터 의상, 구도까지 꼼꼼하게 준비하고 있어요 피드로 돌아가기 + 사진 생성 중 + 세상에 없던\n나만의 사진을 찍고 있어요! + 사진이 완성되면, 완료 알림을 보내드려요. + 예상 소요 시간 + 2시간 정도 걸릴 예정이에요. + 세상에 하나뿐인 사진을 만들어 드리기 위해\n배경부터 의상까지 꼼꼼하게 준비하고 있어요. 정말 죄송합니다. 서버에 오류가 발생해서\n사진이 만들어지지 않았어요. @@ -141,8 +143,9 @@ 탈퇴하기 사진 완성 알림을 받아보세요! - 알림에 동의해 주시면\n사진이 완성되었을 때 알려드릴게요 - 사진 완성 알림 받기 + 알림에 동의해 주시면\n사진이 완성되었을 때 알려드릴게요. + 다음에 + 알림 받기 내가 만든 특별한 사진, 다른 사람에게 보여주고 싶다면?