diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index b7b8cc5c9..3d5d71280 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -33,7 +33,8 @@ android { versionName = "1.1.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - testInstrumentationRunnerArguments["runnerBuilder"] = "de.mannodermaus.junit5.AndroidJUnit5Builder" + testInstrumentationRunnerArguments["runnerBuilder"] = + "de.mannodermaus.junit5.AndroidJUnit5Builder" vectorDrawables { useSupportLibrary = true } @@ -168,6 +169,9 @@ dependencies { // Hilt implementation(libs.hilt.android) kapt(libs.hilt.compiler) + + // Skeleton-UI + implementation(libs.shimmer) } kapt { diff --git a/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailFragment.kt b/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailFragment.kt index 30d0cbaaf..29421bd5b 100644 --- a/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailFragment.kt +++ b/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailFragment.kt @@ -116,7 +116,8 @@ class OfferingDetailFragment : Fragment(), OnOfferingDeleteAlertClickListener { viewModel.showAlertEvent.observe(viewLifecycleOwner) { val alertBinding = DialogAlertBinding.inflate(layoutInflater, null, false) - alertBinding.tvDialogMessage.text = getString(R.string.offering_detail_participate_alert) + alertBinding.tvDialogMessage.text = + getString(R.string.offering_detail_participate_alert) alertBinding.listener = viewModel dialog.setContentView(alertBinding.root) @@ -126,6 +127,10 @@ class OfferingDetailFragment : Fragment(), OnOfferingDeleteAlertClickListener { viewModel.alertCancelEvent.observe(viewLifecycleOwner) { dialog.dismiss() } + + viewModel.loading.observe(viewLifecycleOwner) { + startShimmer(it) + } } override fun onClickConfirm() { @@ -207,6 +212,14 @@ class OfferingDetailFragment : Fragment(), OnOfferingDeleteAlertClickListener { toast?.show() } + private fun startShimmer(isLoading: Boolean) { + if (isLoading) { + binding.sflOfferingDetail.startShimmer() + return + } + binding.sflOfferingDetail.stopShimmer() + } + companion object { const val OFFERING_DETAIL_BUNDLE_KEY = "offering_detail_bundle_key" const val UPDATED_OFFERING_ID_KEY = "updated_offering_id" diff --git a/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailViewModel.kt b/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailViewModel.kt index 21455ec1e..4e55a2266 100644 --- a/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailViewModel.kt +++ b/android/app/src/main/java/com/zzang/chongdae/presentation/view/offeringdetail/OfferingDetailViewModel.kt @@ -95,19 +95,27 @@ class OfferingDetailViewModel private val _alertCancelEvent = MutableSingleLiveData() val alertCancelEvent: SingleLiveData get() = _alertCancelEvent + private val _loading: MutableLiveData = MutableLiveData(false) + val loading: LiveData get() = _loading + init { loadOffering() } fun loadOffering() { viewModelScope.launch { + _loading.value = true when (val result = offeringDetailRepository.fetchOfferingDetail(offeringId)) { is Result.Error -> when (result.error) { DataError.Network.UNAUTHORIZED -> { when (authRepository.saveRefresh()) { - is Result.Success -> loadOffering() + is Result.Success -> { + loadOffering() + } + is Result.Error -> { + _loading.value = false userPreferencesDataStore.removeAllData() _refreshTokenExpiredEvent.setValue(Unit) return@launch @@ -125,6 +133,7 @@ class OfferingDetailViewModel } is Result.Success -> { + _loading.value = false _offeringDetail.value = result.data _currentCount.value = result.data.currentCount.value _offeringCondition.value = result.data.condition diff --git a/android/app/src/main/res/layout/fragment_offering_detail.xml b/android/app/src/main/res/layout/fragment_offering_detail.xml index 3b78b262a..eed126b3a 100644 --- a/android/app/src/main/res/layout/fragment_offering_detail.xml +++ b/android/app/src/main/res/layout/fragment_offering_detail.xml @@ -23,6 +23,7 @@ android:layout_height="0dp" android:overScrollMode="never" android:scrollbars="none" + app:isVisible="@{!vm.loading}" app:layout_constraintBottom_toTopOf="@id/btn_participate" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -362,7 +363,7 @@ app:condition="@{vm.offeringCondition}" app:currentCount="@{vm.currentCount}" app:debouncedOnClick="@{() -> vm.onParticipateClick()}" - app:isVisible="@{!vm.isParticipated}" + app:isVisible="@{vm.isParticipated && !vm.loading}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -382,11 +383,23 @@ android:text="@string/offering_detail_move_comment_detail" android:textColor="@color/white" app:debouncedOnClick="@{() -> vm.onClickMoveCommentDetail()}" - app:isVisible="@{vm.isParticipated}" + app:isVisible="@{vm.isParticipated && !vm.loading}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/sv_layout" /> + + + + + + diff --git a/android/app/src/main/res/layout/fragment_offering_detail_shimmer.xml b/android/app/src/main/res/layout/fragment_offering_detail_shimmer.xml new file mode 100644 index 000000000..714815577 --- /dev/null +++ b/android/app/src/main/res/layout/fragment_offering_detail_shimmer.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +