From 7edc6e04bede76bbd53182b35b2a7923b8164862 Mon Sep 17 00:00:00 2001 From: youngjinc Date: Mon, 23 Sep 2024 18:45:10 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20=EB=B2=84=EC=A0=84=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20API=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/model/system/AppVersionDto.kt | 14 ++++ .../data/repositories/SystemRepositoryImpl.kt | 13 ++++ .../data/services/retrofit/SystemService.kt | 14 ++++ .../wishboard/di/RepositoryModule.kt | 3 + .../hyeeyoung/wishboard/di/ServiceModule.kt | 5 ++ .../domain/model/system/AppVersionDto.kt | 6 ++ .../domain/repositories/SystemRepository.kt | 7 ++ .../common/screens/OneButtonDialogFragment.kt | 43 +++++++++++-- .../presentation/splash/SplashActivity.kt | 64 +++++++++++++++---- .../presentation/splash/SplashViewModel.kt | 37 +++++++++++ .../wishitem/screens/WishBasicFragment.kt | 28 ++++++-- app/src/main/res/layout/dialog_one_button.xml | 6 +- 12 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/hyeeyoung/wishboard/data/model/system/AppVersionDto.kt create mode 100644 app/src/main/java/com/hyeeyoung/wishboard/data/repositories/SystemRepositoryImpl.kt create mode 100644 app/src/main/java/com/hyeeyoung/wishboard/data/services/retrofit/SystemService.kt create mode 100644 app/src/main/java/com/hyeeyoung/wishboard/domain/model/system/AppVersionDto.kt create mode 100644 app/src/main/java/com/hyeeyoung/wishboard/domain/repositories/SystemRepository.kt diff --git a/app/src/main/java/com/hyeeyoung/wishboard/data/model/system/AppVersionDto.kt b/app/src/main/java/com/hyeeyoung/wishboard/data/model/system/AppVersionDto.kt new file mode 100644 index 00000000..f60071d6 --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/data/model/system/AppVersionDto.kt @@ -0,0 +1,14 @@ +package com.hyeeyoung.wishboard.data.model.system + +import com.hyeeyoung.wishboard.domain.model.system.AppVersion + +data class AppVersionDto( + val platform: String, + val minVersion: String, + val recommendedVersion: String, +) { + fun toDomain(): AppVersion = AppVersion( + minVersionCode = minVersion.toIntOrNull() ?: 0, + latestVersionCode = recommendedVersion.toIntOrNull() ?: 0 + ) +} diff --git a/app/src/main/java/com/hyeeyoung/wishboard/data/repositories/SystemRepositoryImpl.kt b/app/src/main/java/com/hyeeyoung/wishboard/data/repositories/SystemRepositoryImpl.kt new file mode 100644 index 00000000..ec013d36 --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/data/repositories/SystemRepositoryImpl.kt @@ -0,0 +1,13 @@ +package com.hyeeyoung.wishboard.data.repositories + +import com.hyeeyoung.wishboard.data.services.retrofit.SystemService +import com.hyeeyoung.wishboard.domain.model.system.AppVersion +import com.hyeeyoung.wishboard.domain.repositories.SystemRepository +import javax.inject.Inject + +class SystemRepositoryImpl @Inject constructor(private val systemService: SystemService) : + SystemRepository { + override suspend fun fetchAppVersion(): Result = runCatching { + systemService.fetchAppVersion().body()?.data?.toDomain() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/data/services/retrofit/SystemService.kt b/app/src/main/java/com/hyeeyoung/wishboard/data/services/retrofit/SystemService.kt new file mode 100644 index 00000000..2fa729e7 --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/data/services/retrofit/SystemService.kt @@ -0,0 +1,14 @@ +package com.hyeeyoung.wishboard.data.services.retrofit + +import com.hyeeyoung.wishboard.data.model.base.BaseResponseResult +import com.hyeeyoung.wishboard.data.model.system.AppVersionDto +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Query + +interface SystemService { + @GET("version") + suspend fun fetchAppVersion( + @Query("osType") osType: String = "AOS" + ): Response> +} \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/di/RepositoryModule.kt b/app/src/main/java/com/hyeeyoung/wishboard/di/RepositoryModule.kt index e5eb1fe2..795cd65b 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/di/RepositoryModule.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/di/RepositoryModule.kt @@ -33,4 +33,7 @@ abstract class RepositoryModule { @Binds abstract fun bindPhotoRepository(photoRepositoryImpl: PhotoRepositoryImpl): PhotoRepository + + @Binds + abstract fun bindSystemRepository(systemRepositoryImpl: SystemRepositoryImpl): SystemRepository } \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/di/ServiceModule.kt b/app/src/main/java/com/hyeeyoung/wishboard/di/ServiceModule.kt index 31a4a546..6c77c13c 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/di/ServiceModule.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/di/ServiceModule.kt @@ -40,4 +40,9 @@ object ServiceModule { @Provides fun provideUserService(retrofit: Retrofit): UserService = retrofit.create(UserService::class.java) + + @Singleton + @Provides + fun provideSystemService(retrofit: Retrofit): SystemService = + retrofit.create(SystemService::class.java) } \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/domain/model/system/AppVersionDto.kt b/app/src/main/java/com/hyeeyoung/wishboard/domain/model/system/AppVersionDto.kt new file mode 100644 index 00000000..05639678 --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/domain/model/system/AppVersionDto.kt @@ -0,0 +1,6 @@ +package com.hyeeyoung.wishboard.domain.model.system + +data class AppVersion( + val minVersionCode: Int, + val latestVersionCode: Int, +) diff --git a/app/src/main/java/com/hyeeyoung/wishboard/domain/repositories/SystemRepository.kt b/app/src/main/java/com/hyeeyoung/wishboard/domain/repositories/SystemRepository.kt new file mode 100644 index 00000000..950e7b41 --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/domain/repositories/SystemRepository.kt @@ -0,0 +1,7 @@ +package com.hyeeyoung.wishboard.domain.repositories + +import com.hyeeyoung.wishboard.domain.model.system.AppVersion + +interface SystemRepository { + suspend fun fetchAppVersion(): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/common/screens/OneButtonDialogFragment.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/common/screens/OneButtonDialogFragment.kt index 6edc9c1f..079a2c3f 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/common/screens/OneButtonDialogFragment.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/common/screens/OneButtonDialogFragment.kt @@ -5,23 +5,52 @@ import android.view.View import com.hyeeyoung.wishboard.R import com.hyeeyoung.wishboard.databinding.DialogOneButtonBinding import com.hyeeyoung.wishboard.presentation.base.screen.BaseDialogFragment +import com.hyeeyoung.wishboard.presentation.common.types.DialogButtonReplyType +import com.hyeeyoung.wishboard.util.DialogListener -class OneButtonDialogFragment( - private val title: String, - private val description: String? -) : BaseDialogFragment(R.layout.dialog_one_button) { +class OneButtonDialogFragment : + BaseDialogFragment(R.layout.dialog_one_button) { + private lateinit var listener: DialogListener override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.title.text = title - binding.description.text = description + + arguments?.let { + binding.title.text = it.getString(ARG_TITLE) + binding.description.text = it.getString(ARG_DESCRIPTION) + binding.yes.text = it.getString(ARG_BUTTON_TEXT) ?: getString(R.string.confirm) + } addListener() } private fun addListener() { binding.yes.setOnClickListener { - dismiss() + listener.onButtonClicked(DialogButtonReplyType.YES.name) + } + } + + fun setListener(listener: DialogListener) { + this.listener = listener + } + + companion object { + private const val ARG_TITLE = "title" + private const val ARG_DESCRIPTION = "description" + private const val ARG_BUTTON_TEXT = "buttonText" + + fun newInstance( + title: String, + description: String?, + buttonText: String? = null, + ): OneButtonDialogFragment { + val args = Bundle().apply { + putString(ARG_TITLE, title) + putString(ARG_DESCRIPTION, description) + putString(ARG_BUTTON_TEXT, buttonText) + } + + return OneButtonDialogFragment().apply { arguments = args } } } } \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt index 226d2c6d..a7460752 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt @@ -11,6 +11,7 @@ import com.google.android.play.core.install.model.UpdateAvailability import com.hyeeyoung.wishboard.BuildConfig import com.hyeeyoung.wishboard.R import com.hyeeyoung.wishboard.databinding.ActivitySplashBinding +import com.hyeeyoung.wishboard.presentation.common.screens.OneButtonDialogFragment import com.hyeeyoung.wishboard.presentation.common.screens.TwoButtonDialogFragment import com.hyeeyoung.wishboard.presentation.common.types.DialogButtonReplyType import com.hyeeyoung.wishboard.presentation.main.MainActivity @@ -28,7 +29,7 @@ class SplashActivity : BaseActivity(R.layout.activity_spl override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - lifecycleScope.launch() { + lifecycleScope.launch { delay(2000) checkForNewVersionUpdate() } @@ -45,21 +46,42 @@ class SplashActivity : BaseActivity(R.layout.activity_spl val appUpdateManager = AppUpdateManagerFactory.create(this@SplashActivity) val appUpdateInfoTask = appUpdateManager.appUpdateInfo - appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> - if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE - && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) - && appUpdateInfo.availableVersionCode() != BuildConfig.VERSION_CODE - ) { - showUpdateDialog() - } else { - moveToNext() +// appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> +// if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE +// && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) +// && appUpdateInfo.availableVersionCode() != BuildConfig.VERSION_CODE +// ) { +// showOptionalUpdateDialog() +// viewModel.checkForAppUpdate( +// playStoreVersionCode = appUpdateInfo.availableVersionCode(), +// moveToNext = { moveToNext() }, +// showUpdateDialog = { isForceUpdate -> +// when (isForceUpdate) { +// true -> showForceUpdateDialog() +// false -> showOptionalUpdateDialog() +// } +// } +// ) +// } else { +// moveToNext() +// } +// }.addOnFailureListener { +// moveToNext() +// } + + viewModel.checkForAppUpdate( + playStoreVersionCode = 39, + moveToNext = { moveToNext() }, + showUpdateDialog = { isForceUpdate -> + when (isForceUpdate) { + true -> showForceUpdateDialog() + false -> showOptionalUpdateDialog() + } } - }.addOnFailureListener { - moveToNext() - } + ) } - private fun showUpdateDialog() { + private fun showOptionalUpdateDialog() { TwoButtonDialogFragment.newInstance( title = getString(R.string.app_update_dialog_title), description = getString(R.string.app_update_dialog_description), @@ -76,6 +98,22 @@ class SplashActivity : BaseActivity(R.layout.activity_spl }.show(supportFragmentManager, "UpdateDialog") } + private fun showForceUpdateDialog() { + OneButtonDialogFragment.newInstance( + title = getString(R.string.app_update_dialog_title), + description = getString(R.string.app_update_dialog_description), + buttonText = getString(R.string.app_update_dialog_yes_button_text), + ).apply { + setListener(object : DialogListener { + override fun onButtonClicked(clicked: String) { + if (clicked == DialogButtonReplyType.YES.name) { + moveToPlayStore() + } + } + }) + }.show(supportFragmentManager, "ForceUpdateDialog") + } + private fun moveToPlayStore() { Intent(Intent.ACTION_VIEW).apply { data = diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt index 62b3b76a..8a17b290 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt @@ -1,13 +1,50 @@ package com.hyeeyoung.wishboard.presentation.splash import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.hyeeyoung.wishboard.BuildConfig import com.hyeeyoung.wishboard.data.local.WishBoardPreference +import com.hyeeyoung.wishboard.domain.repositories.SystemRepository import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @HiltViewModel class SplashViewModel @Inject constructor( private val localStorage: WishBoardPreference, + private val systemRepository: SystemRepository, ) : ViewModel() { fun isLogin() = localStorage.isLogin + + fun checkForAppUpdate( + playStoreVersionCode: Int, + moveToNext: () -> Unit, + showUpdateDialog: (isForceUpdate: Boolean) -> Unit + ) { + viewModelScope.launch { + Timber.e("0") + systemRepository.fetchAppVersion().onSuccess { remoteVersion -> + if (remoteVersion == null) { + Timber.e("1") + return@launch + } + /** TODO 토스트 문구 띄우기 */ + when { + BuildConfig.VERSION_CODE < playStoreVersionCode -> { + showUpdateDialog(BuildConfig.VERSION_CODE < remoteVersion.minVersionCode) + Timber.e("2") + } + + else -> { + moveToNext() + Timber.e("3") + } + } + }.onFailure { + /** TODO 토스트 문구 띄우기 */ + Timber.e("4") + } + } + } } diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt index 25bae0ea..c0841e63 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt @@ -14,14 +14,20 @@ import com.hyeeyoung.wishboard.databinding.FragmentWishBinding import com.hyeeyoung.wishboard.designsystem.component.CustomSnackbar import com.hyeeyoung.wishboard.domain.model.WishItemDetail import com.hyeeyoung.wishboard.presentation.common.screens.OneButtonDialogFragment +import com.hyeeyoung.wishboard.presentation.common.types.DialogButtonReplyType import com.hyeeyoung.wishboard.presentation.common.types.ProcessStatus import com.hyeeyoung.wishboard.presentation.folder.screens.FolderListBottomDialogFragment import com.hyeeyoung.wishboard.presentation.noti.screens.NotiSettingBottomDialogFragment import com.hyeeyoung.wishboard.presentation.wishitem.WishItemStatus import com.hyeeyoung.wishboard.presentation.wishitem.viewmodels.WishItemRegistrationViewModel import com.hyeeyoung.wishboard.util.BaseFragment +import com.hyeeyoung.wishboard.util.DialogListener import com.hyeeyoung.wishboard.util.FolderListDialogListener -import com.hyeeyoung.wishboard.util.extension.* +import com.hyeeyoung.wishboard.util.extension.getParcelableValue +import com.hyeeyoung.wishboard.util.extension.requestCamera +import com.hyeeyoung.wishboard.util.extension.requestSelectPicture +import com.hyeeyoung.wishboard.util.extension.showPhotoDialog +import com.hyeeyoung.wishboard.util.extension.takePicture import com.hyeeyoung.wishboard.util.setOnSingleClickListener import dagger.hilt.android.AndroidEntryPoint @@ -128,6 +134,7 @@ class WishBasicFragment : BaseFragment(R.layout.fragment_wi moveToPrevious(WishItemStatus.ADDED) } } + else -> {} } } @@ -137,10 +144,12 @@ class WishBasicFragment : BaseFragment(R.layout.fragment_wi ProcessStatus.IDLE -> { binding.loadingLottie.visibility = View.GONE } + ProcessStatus.IN_PROGRESS -> { binding.loadingLottie.visibility = View.VISIBLE binding.loadingLottie.playAnimation() } + else -> {} } } @@ -159,11 +168,18 @@ class WishBasicFragment : BaseFragment(R.layout.fragment_wi } private fun showItemNonUpdateDialog() { - val dialog = OneButtonDialogFragment( - getString(R.string.item_non_update_dialog_title), - getString(R.string.item_non_update_dialog_description) - ) - dialog.show(parentFragmentManager, "ItemNonUpdateDialog") + OneButtonDialogFragment.newInstance( + title = getString(R.string.item_non_update_dialog_title), + description = getString(R.string.item_non_update_dialog_description) + ).apply { + setListener(object : DialogListener { + override fun onButtonClicked(clicked: String) { + if (clicked == DialogButtonReplyType.YES.name) { + dismiss() + } + } + }) + }.show(parentFragmentManager, "ItemNonUpdateDialog") } private fun showFolderListDialog() { diff --git a/app/src/main/res/layout/dialog_one_button.xml b/app/src/main/res/layout/dialog_one_button.xml index 4ae04a5a..12136c94 100644 --- a/app/src/main/res/layout/dialog_one_button.xml +++ b/app/src/main/res/layout/dialog_one_button.xml @@ -18,8 +18,8 @@ app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintTop_toBottomOf="@id/description" + tools:text="@string/confirm" />