diff --git a/data/src/main/java/kr/genti/data/dataSource/GenerateDataSource.kt b/data/src/main/java/kr/genti/data/dataSource/GenerateDataSource.kt index 9160952c..1ae9ae3c 100644 --- a/data/src/main/java/kr/genti/data/dataSource/GenerateDataSource.kt +++ b/data/src/main/java/kr/genti/data/dataSource/GenerateDataSource.kt @@ -5,6 +5,7 @@ import kr.genti.data.dto.request.ReportRequestDto import kr.genti.data.dto.response.GenerateStatusDto import kr.genti.data.dto.response.OpenchatDto import kr.genti.data.dto.response.PicturePagedListDto +import kr.genti.data.dto.response.ServerAvailableDto interface GenerateDataSource { suspend fun getGenerateStatus(): BaseResponse @@ -30,4 +31,6 @@ interface GenerateDataSource { suspend fun getOpenchatData(): BaseResponse suspend fun getIsUserVerified(): BaseResponse + + suspend fun getIsServerAvailable(): BaseResponse } diff --git a/data/src/main/java/kr/genti/data/dataSourceImpl/GenerateDataSourceImpl.kt b/data/src/main/java/kr/genti/data/dataSourceImpl/GenerateDataSourceImpl.kt index 496e0031..b4bed88e 100644 --- a/data/src/main/java/kr/genti/data/dataSourceImpl/GenerateDataSourceImpl.kt +++ b/data/src/main/java/kr/genti/data/dataSourceImpl/GenerateDataSourceImpl.kt @@ -6,6 +6,7 @@ import kr.genti.data.dto.request.ReportRequestDto import kr.genti.data.dto.response.GenerateStatusDto import kr.genti.data.dto.response.OpenchatDto import kr.genti.data.dto.response.PicturePagedListDto +import kr.genti.data.dto.response.ServerAvailableDto import kr.genti.data.service.GenerateService import javax.inject.Inject @@ -39,4 +40,6 @@ data class GenerateDataSourceImpl override suspend fun getOpenchatData(): BaseResponse = generateService.getOpenchatData() override suspend fun getIsUserVerified(): BaseResponse = generateService.getIsUserVerified() + + override suspend fun getIsServerAvailable(): BaseResponse = generateService.getIsServerAvailable() } diff --git a/data/src/main/java/kr/genti/data/dto/response/ServerAvailableDto.kt b/data/src/main/java/kr/genti/data/dto/response/ServerAvailableDto.kt new file mode 100644 index 00000000..d713696a --- /dev/null +++ b/data/src/main/java/kr/genti/data/dto/response/ServerAvailableDto.kt @@ -0,0 +1,15 @@ +package kr.genti.data.dto.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kr.genti.domain.entity.response.ServerAvailableModel + +@Serializable +data class ServerAvailableDto( + @SerialName("status") + val status: Boolean, + @SerialName("message") + val message: String?, +) { + fun toModel() = ServerAvailableModel(status, message) +} diff --git a/data/src/main/java/kr/genti/data/repositoryImpl/GenerateRepositoryImpl.kt b/data/src/main/java/kr/genti/data/repositoryImpl/GenerateRepositoryImpl.kt index fc8c9b1d..50a31f7c 100644 --- a/data/src/main/java/kr/genti/data/repositoryImpl/GenerateRepositoryImpl.kt +++ b/data/src/main/java/kr/genti/data/repositoryImpl/GenerateRepositoryImpl.kt @@ -6,6 +6,7 @@ import kr.genti.domain.entity.request.ReportRequestModel import kr.genti.domain.entity.response.GenerateStatusModel import kr.genti.domain.entity.response.OpenchatModel import kr.genti.domain.entity.response.PicturePagedListModel +import kr.genti.domain.entity.response.ServerAvailableModel import kr.genti.domain.repository.GenerateRepository import javax.inject.Inject @@ -68,4 +69,9 @@ class GenerateRepositoryImpl runCatching { generateDataSource.getIsUserVerified().response } + + override suspend fun getIsServerAvailable(): Result = + runCatching { + generateDataSource.getIsServerAvailable().response.toModel() + } } diff --git a/data/src/main/java/kr/genti/data/service/GenerateService.kt b/data/src/main/java/kr/genti/data/service/GenerateService.kt index a7d3adc3..1b4e77f5 100644 --- a/data/src/main/java/kr/genti/data/service/GenerateService.kt +++ b/data/src/main/java/kr/genti/data/service/GenerateService.kt @@ -5,6 +5,7 @@ import kr.genti.data.dto.request.ReportRequestDto import kr.genti.data.dto.response.GenerateStatusDto import kr.genti.data.dto.response.OpenchatDto import kr.genti.data.dto.response.PicturePagedListDto +import kr.genti.data.dto.response.ServerAvailableDto import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.POST @@ -49,4 +50,7 @@ interface GenerateService { @GET("api/v1/user-verification") suspend fun getIsUserVerified(): BaseResponse + + @GET("api/v1/maintenance") + suspend fun getIsServerAvailable(): BaseResponse } diff --git a/domain/src/main/kotlin/kr/genti/domain/entity/response/ServerAvailableModel.kt b/domain/src/main/kotlin/kr/genti/domain/entity/response/ServerAvailableModel.kt new file mode 100644 index 00000000..b745c2ba --- /dev/null +++ b/domain/src/main/kotlin/kr/genti/domain/entity/response/ServerAvailableModel.kt @@ -0,0 +1,6 @@ +package kr.genti.domain.entity.response + +data class ServerAvailableModel( + val status: Boolean, + val message: String?, +) diff --git a/domain/src/main/kotlin/kr/genti/domain/repository/GenerateRepository.kt b/domain/src/main/kotlin/kr/genti/domain/repository/GenerateRepository.kt index b96b34ca..7a34143a 100644 --- a/domain/src/main/kotlin/kr/genti/domain/repository/GenerateRepository.kt +++ b/domain/src/main/kotlin/kr/genti/domain/repository/GenerateRepository.kt @@ -4,6 +4,7 @@ import kr.genti.domain.entity.request.ReportRequestModel import kr.genti.domain.entity.response.GenerateStatusModel import kr.genti.domain.entity.response.OpenchatModel import kr.genti.domain.entity.response.PicturePagedListModel +import kr.genti.domain.entity.response.ServerAvailableModel interface GenerateRepository { suspend fun getGenerateStatus(): Result @@ -29,4 +30,6 @@ interface GenerateRepository { suspend fun getOpenchatData(): Result suspend fun getIsUserVerified(): Result + + suspend fun getIsServerAvailable(): Result } diff --git a/presentation/src/main/java/kr/genti/presentation/main/CreateErrorDialog.kt b/presentation/src/main/java/kr/genti/presentation/main/CreateErrorDialog.kt index d5a878c7..6280f848 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/CreateErrorDialog.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/CreateErrorDialog.kt @@ -13,9 +13,9 @@ import kr.genti.core.extension.setOnSingleClickListener import kr.genti.core.extension.stringOf import kr.genti.core.extension.toast import kr.genti.presentation.R -import kr.genti.presentation.databinding.DialogWaitingErrorBinding +import kr.genti.presentation.databinding.DialogCreateErrorBinding -class CreateErrorDialog : BaseDialog(R.layout.dialog_waiting_error) { +class CreateErrorDialog : BaseDialog(R.layout.dialog_create_error) { private val viewModel by activityViewModels() override fun onStart() { diff --git a/presentation/src/main/java/kr/genti/presentation/main/CreateFinishedDialog.kt b/presentation/src/main/java/kr/genti/presentation/main/CreateFinishedDialog.kt index 802e3d98..191a3bf3 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/CreateFinishedDialog.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/CreateFinishedDialog.kt @@ -9,10 +9,10 @@ import kr.genti.core.extension.setOnSingleClickListener import kr.genti.core.extension.stringOf import kr.genti.core.extension.toast import kr.genti.presentation.R -import kr.genti.presentation.databinding.DialogMainFinishedBinding +import kr.genti.presentation.databinding.DialogCreateFinishedBinding import kr.genti.presentation.generate.finished.FinishedActivity -class CreateFinishedDialog : BaseDialog(R.layout.dialog_main_finished) { +class CreateFinishedDialog : BaseDialog(R.layout.dialog_create_finished) { private val viewModel by activityViewModels() override fun onStart() { diff --git a/presentation/src/main/java/kr/genti/presentation/main/CreateUnableDialog.kt b/presentation/src/main/java/kr/genti/presentation/main/CreateUnableDialog.kt new file mode 100644 index 00000000..98f97590 --- /dev/null +++ b/presentation/src/main/java/kr/genti/presentation/main/CreateUnableDialog.kt @@ -0,0 +1,55 @@ +package kr.genti.presentation.main + +import android.os.Bundle +import android.view.View +import android.view.WindowManager +import kr.genti.core.base.BaseDialog +import kr.genti.core.extension.setOnSingleClickListener +import kr.genti.presentation.R +import kr.genti.presentation.databinding.DialogCreateUnableBinding + +class CreateUnableDialog : BaseDialog(R.layout.dialog_create_unable) { + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setLayout( + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.WRAP_CONTENT, + ) + setBackgroundDrawableResource(R.color.transparent) + } + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + + initCloseBtnListener() + setBodyText() + } + + private fun initCloseBtnListener() { + binding.btnClose.setOnSingleClickListener { dismiss() } + binding.btnReturn.setOnSingleClickListener { dismiss() } + } + + private fun setBodyText() { + binding.tvLogoutSubtitle.text = arguments?.getString(ARG_BODY) + binding.tvLogoutSubtitle.invalidate() + } + + companion object { + private const val ARG_BODY = "ARG_BODY" + + @JvmStatic + fun newInstance(body: String): CreateUnableDialog = + CreateUnableDialog().apply { + arguments = + Bundle().apply { + putString(ARG_BODY, body) + } + } + } +} diff --git a/presentation/src/main/java/kr/genti/presentation/main/MainActivity.kt b/presentation/src/main/java/kr/genti/presentation/main/MainActivity.kt index b0b34617..490b306b 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/MainActivity.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/MainActivity.kt @@ -37,6 +37,7 @@ class MainActivity : BaseActivity(R.layout.activity_main) { private var createFinishedDialog: CreateFinishedDialog? = null private var createErrorDialog: CreateErrorDialog? = null + private var createUnableDialog: CreateUnableDialog? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,6 +50,7 @@ class MainActivity : BaseActivity(R.layout.activity_main) { observeStatusResult() observeNotificationState() observeResetResult() + observeServerAvailableState() observeUserVerifyState() } @@ -112,7 +114,7 @@ class MainActivity : BaseActivity(R.layout.activity_main) { private fun navigateByGenerateStatus() { when (viewModel.currentStatus) { GenerateStatus.NEW_REQUEST_AVAILABLE -> { - viewModel.getIsUserVerifiedFromServer() + viewModel.getIsServerAvailable() } GenerateStatus.AWAIT_USER_VERIFICATION -> { @@ -199,6 +201,27 @@ class MainActivity : BaseActivity(R.layout.activity_main) { }.launchIn(lifecycleScope) } + private fun observeServerAvailableState() { + viewModel.serverAvailableState + .flowWithLifecycle(lifecycle) + .onEach { state -> + when (state) { + is UiState.Success -> { + if (state.data.status) { + viewModel.getIsUserVerifiedFromServer() + } else { + createUnableDialog = CreateUnableDialog.newInstance(state.data.message.orEmpty()) + createUnableDialog?.show(supportFragmentManager, DIALOG_UNABLE) + } + } + + is UiState.Failure -> toast(stringOf(R.string.error_msg)) + else -> return@onEach + } + viewModel.resetIsUserVerified() + }.launchIn(lifecycleScope) + } + private fun observeUserVerifyState() { viewModel.userVerifyState .flowWithLifecycle(lifecycle) @@ -236,13 +259,16 @@ class MainActivity : BaseActivity(R.layout.activity_main) { override fun onDestroy() { super.onDestroy() + createFinishedDialog = null createErrorDialog = null + createUnableDialog = null } companion object { private const val DIALOG_FINISHED = "DIALOG_FINISHED" private const val DIALOG_ERROR = "DIALOG_ERROR" + private const val DIALOG_UNABLE = "DIALOG_UNABLE" const val TYPE_SUCCESS = "SUCCESS" const val TYPE_CANCELED = "CANCELED" diff --git a/presentation/src/main/java/kr/genti/presentation/main/MainViewModel.kt b/presentation/src/main/java/kr/genti/presentation/main/MainViewModel.kt index 44271a0b..a6400a60 100644 --- a/presentation/src/main/java/kr/genti/presentation/main/MainViewModel.kt +++ b/presentation/src/main/java/kr/genti/presentation/main/MainViewModel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kr.genti.core.state.UiState import kr.genti.domain.entity.response.GenerateStatusModel +import kr.genti.domain.entity.response.ServerAvailableModel import kr.genti.domain.enums.GenerateStatus import kr.genti.domain.repository.GenerateRepository import javax.inject.Inject @@ -29,6 +30,10 @@ class MainViewModel private val _notificationState = MutableStateFlow(GenerateStatus.EMPTY) val notificationState: StateFlow = _notificationState + private val _serverAvailableState = + MutableStateFlow>(UiState.Empty) + val serverAvailableState: StateFlow> = _serverAvailableState + private val _userVerifyState = MutableStateFlow>(UiState.Empty) val userVerifyState: StateFlow> = _userVerifyState @@ -73,6 +78,19 @@ class MainViewModel fun checkNewPictureInitialized() = ::newPicture.isInitialized + 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 getIsUserVerifiedFromServer() { _userVerifyState.value = UiState.Loading viewModelScope.launch { diff --git a/presentation/src/main/res/drawable/shape_white_fill_14_rect.xml b/presentation/src/main/res/drawable/shape_white_fill_14_rect.xml index 8053d273..fae12551 100644 --- a/presentation/src/main/res/drawable/shape_white_fill_14_rect.xml +++ b/presentation/src/main/res/drawable/shape_white_fill_14_rect.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/presentation/src/main/res/layout/activity_verify.xml b/presentation/src/main/res/layout/activity_verify.xml index 8a6c4ac6..09273f6f 100644 --- a/presentation/src/main/res/layout/activity_verify.xml +++ b/presentation/src/main/res/layout/activity_verify.xml @@ -49,6 +49,7 @@ android:layout_height="wrap_content" android:layout_marginTop="64dp" android:gravity="center" + android:textSize="22dp" android:lineSpacingMultiplier="1.1" android:text="@string/verify_before_tv_title" android:textColor="@color/white" @@ -65,7 +66,7 @@ android:gravity="center" android:text="@string/verify_before_tv_subtitle" android:textColor="#99FFFFFF" - android:textSize="13sp" + android:textSize="13dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_before_verify_title" /> @@ -78,7 +79,7 @@ android:gravity="center" android:text="@string/verify_before_tv_baby" android:textColor="#4DFFFFFF" - android:textSize="13sp" + android:textSize="13dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_before_verify_subtitle" /> @@ -116,7 +117,7 @@ android:paddingVertical="14dp" android:text="@string/verify_before_btn_photo" android:textColor="#0D2D2B" - android:textSize="16sp" + android:textSize="16dp" app:layout_constraintBottom_toTopOf="@id/tv_before_verify_warning" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> @@ -130,7 +131,7 @@ android:gravity="center" android:text="@string/verify_before_tv_warning" android:textColor="#4DFFFFFF" - android:textSize="12sp" + android:textSize="12dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> @@ -153,6 +154,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="64dp" + android:textSize="22dp" android:gravity="center" android:lineSpacingMultiplier="1.1" android:text="@string/verify_after_tv_title" @@ -170,7 +172,7 @@ android:gravity="center" android:text="@string/verify_after_tv_subtitle" android:textColor="#99FFFFFF" - android:textSize="13sp" + android:textSize="13dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_after_verify_title" /> @@ -208,7 +210,7 @@ android:gravity="center" android:text="@string/verify_after_tv_guide" android:textColor="@color/green_new" - android:textSize="13sp" + android:textSize="13dp" app:layout_constraintBottom_toBottomOf="@id/iv_photo_taken" app:layout_constraintEnd_toEndOf="@id/iv_photo_taken" app:layout_constraintStart_toStartOf="@id/iv_photo_taken" /> @@ -225,7 +227,7 @@ android:paddingVertical="14dp" android:text="@string/verify_after_btn_retake" android:textColor="#0D2D2B" - android:textSize="16sp" + android:textSize="16dp" app:layout_constraintBottom_toTopOf="@id/btn_verify" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> @@ -242,7 +244,7 @@ android:paddingVertical="14dp" android:text="@string/verify_after_btn_verify" android:textColor="#0D2D2B" - android:textSize="16sp" + android:textSize="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/presentation/src/main/res/layout/dialog_waiting_error.xml b/presentation/src/main/res/layout/dialog_create_error.xml similarity index 100% rename from presentation/src/main/res/layout/dialog_waiting_error.xml rename to presentation/src/main/res/layout/dialog_create_error.xml diff --git a/presentation/src/main/res/layout/dialog_main_finished.xml b/presentation/src/main/res/layout/dialog_create_finished.xml similarity index 100% rename from presentation/src/main/res/layout/dialog_main_finished.xml rename to presentation/src/main/res/layout/dialog_create_finished.xml diff --git a/presentation/src/main/res/layout/dialog_create_guide.xml b/presentation/src/main/res/layout/dialog_create_guide.xml index 2dad1b96..8dde8fa4 100644 --- a/presentation/src/main/res/layout/dialog_create_guide.xml +++ b/presentation/src/main/res/layout/dialog_create_guide.xml @@ -97,10 +97,11 @@ style="@style/TextAppearance.Genti.BodyNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="20dp" android:layout_marginStart="24dp" android:text="@string/create_guide_tv_ex" android:textColor="@color/green_1" - app:layout_constraintBottom_toTopOf="@id/iv_guide_ex" + app:layout_constraintTop_toBottomOf="@id/tv_guide_title_down" app:layout_constraintStart_toStartOf="@id/iv_guide_bg" /> diff --git a/presentation/src/main/res/layout/dialog_create_unable.xml b/presentation/src/main/res/layout/dialog_create_unable.xml new file mode 100644 index 00000000..743a60fd --- /dev/null +++ b/presentation/src/main/res/layout/dialog_create_unable.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/dialog_setting_logout.xml b/presentation/src/main/res/layout/dialog_setting_logout.xml index a213ac78..058eb0c8 100644 --- a/presentation/src/main/res/layout/dialog_setting_logout.xml +++ b/presentation/src/main/res/layout/dialog_setting_logout.xml @@ -33,9 +33,9 @@ diff --git a/presentation/src/main/res/layout/dialog_setting_quit.xml b/presentation/src/main/res/layout/dialog_setting_quit.xml index e20cc9a9..1601f7ae 100644 --- a/presentation/src/main/res/layout/dialog_setting_quit.xml +++ b/presentation/src/main/res/layout/dialog_setting_quit.xml @@ -33,9 +33,9 @@