From bf2738dbe2eb5ca68b123b91d6817ecd5bfc26dd Mon Sep 17 00:00:00 2001 From: "kyle.lee" Date: Sun, 27 Oct 2024 15:39:33 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=ED=85=8C=EB=A7=88=20=EA=B0=9C?= =?UTF-8?q?=EB=B3=84=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/adminmain/AdminMainViewModel.kt | 22 ------------------- .../ui/adminmain/ThemesAdapter.kt | 10 +++------ .../src/main/res/layout/item_theme.xml | 22 ------------------- 3 files changed, 3 insertions(+), 51 deletions(-) diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt index 4a59c71e..e0035d93 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt @@ -57,28 +57,6 @@ class AdminMainViewModel @Inject constructor( } } - fun updateTheme(themeId: Int) = intent { - themeRepository - .getThemes() - .onSuccess { themes -> - themes - .find { it.id == themeId } - ?.let { themeRepository.upsertTheme(it) } - }.onFailure { - handleError(it) - return@intent - } - - hintRepository.saveHints(themeId).onSuccess { updatedAt -> - reduce { - state.copy( - themes = state.themes.toMutableList() - .map { if (it.id == themeId) it.copy(recentUpdated = updatedAt) else it }, - ) - } - }.onFailure(::handleError) - } - fun start(themeId: Int, readyToStart: () -> Unit) = intent { themeRepository.updateLatestTheme(themeId) withContext(Dispatchers.Main) { diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/ThemesAdapter.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/ThemesAdapter.kt index 8d1e308a..239f7082 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/ThemesAdapter.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/ThemesAdapter.kt @@ -11,14 +11,12 @@ import com.nextroom.nextroom.presentation.databinding.ItemThemeBinding import com.nextroom.nextroom.presentation.model.ThemeInfoPresentation class ThemesAdapter( - private val onStartGame: (Int) -> Unit, - private val onClickUpdate: (Int) -> Unit, + private val onStartGame: (Int) -> Unit ) : ListAdapter(diffUtil) { class ThemeViewHolder( private val binding: ItemThemeBinding, - onStartGame: (Int) -> Unit, - onClickUpdate: (Int) -> Unit, + onStartGame: (Int) -> Unit ) : RecyclerView.ViewHolder(binding.root) { private lateinit var item: ThemeInfoPresentation @@ -26,7 +24,6 @@ class ThemesAdapter( init { binding.root.setOnClickListener { onStartGame(item.id) } - binding.btnUpdate.setOnClickListener { onClickUpdate(item.id) } } fun bind(themeInfo: ThemeInfoPresentation) = with(binding) { @@ -44,8 +41,7 @@ class ThemesAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ThemeViewHolder { return ThemeViewHolder( ItemThemeBinding.inflate(LayoutInflater.from(parent.context), parent, false), - onStartGame, - onClickUpdate, + onStartGame ) } diff --git a/presentation/src/main/res/layout/item_theme.xml b/presentation/src/main/res/layout/item_theme.xml index b0b2d603..74bdc9e3 100644 --- a/presentation/src/main/res/layout/item_theme.xml +++ b/presentation/src/main/res/layout/item_theme.xml @@ -35,28 +35,6 @@ app:layout_constraintTop_toBottomOf="@id/tv_theme_name" tools:text="최근 업데이트 : 2023.01.02" /> - - - - Date: Sun, 27 Oct 2024 15:40:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=ED=85=8C=EB=A7=88=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=EC=A0=90=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD.=20=EC=B2=AB=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=20=EB=B0=8F=20refresh=20=ED=95=A0=EB=95=8C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/repository/HintRepositoryImpl.kt | 5 +- .../domain/repository/HintRepository.kt | 2 +- .../ui/adminmain/AdminMainFragment.kt | 7 +- .../ui/adminmain/AdminMainViewModel.kt | 83 ++++++++++++++----- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/data/src/main/java/com/nextroom/nextroom/data/repository/HintRepositoryImpl.kt b/data/src/main/java/com/nextroom/nextroom/data/repository/HintRepositoryImpl.kt index bff14994..b01a4247 100644 --- a/data/src/main/java/com/nextroom/nextroom/data/repository/HintRepositoryImpl.kt +++ b/data/src/main/java/com/nextroom/nextroom/data/repository/HintRepositoryImpl.kt @@ -24,12 +24,13 @@ class HintRepositoryImpl @Inject constructor( return hintLocalDataSource.getHint(themeId, hintCode)?.toDomain() } - override suspend fun saveHints(themeId: Int): Result { + //TODO : 리팩토링 필요. hint를 저장하는데, 최신의 updatedTime이 나올거라고 예상할수가 없고 그래서도 안됨 + override suspend fun saveHints(themeId: Int): Result> { val updatedTime = System.currentTimeMillis() return hintRemoteDataSource.getHints(themeId) .suspendOnSuccess { themeLocalDataSource.updateUpdatedInfo(themeId, updatedTime) hintLocalDataSource.saveHints(themeId, it) - }.mapOnSuccess { updatedTime } + }.mapOnSuccess { Pair(themeId, updatedTime) } } } diff --git a/domain/src/main/java/com/nextroom/nextroom/domain/repository/HintRepository.kt b/domain/src/main/java/com/nextroom/nextroom/domain/repository/HintRepository.kt index 7c7ac876..c592ad5f 100644 --- a/domain/src/main/java/com/nextroom/nextroom/domain/repository/HintRepository.kt +++ b/domain/src/main/java/com/nextroom/nextroom/domain/repository/HintRepository.kt @@ -5,5 +5,5 @@ import com.nextroom.nextroom.domain.model.Result interface HintRepository { suspend fun getHint(hintCode: String): Hint? - suspend fun saveHints(themeId: Int): Result + suspend fun saveHints(themeId: Int): Result> } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainFragment.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainFragment.kt index c9299d43..a646931f 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainFragment.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainFragment.kt @@ -34,10 +34,7 @@ class AdminMainFragment : private val viewModel: AdminMainViewModel by viewModels() private val adapter: ThemesAdapter by lazy { - ThemesAdapter( - onStartGame = ::startGame, - onClickUpdate = viewModel::updateTheme, - ) + ThemesAdapter(onStartGame = ::startGame) } private val state: AdminMainState get() = viewModel.container.stateFlow.value @@ -88,7 +85,7 @@ class AdminMainFragment : } srlTheme.setOnRefreshListener { - viewModel.loadData() + viewModel.fetchData() } llBanner.setOnClickListener { diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt index e0035d93..65c9096c 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/adminmain/AdminMainViewModel.kt @@ -1,10 +1,10 @@ package com.nextroom.nextroom.presentation.ui.adminmain import androidx.lifecycle.viewModelScope +import com.nextroom.nextroom.domain.model.Mypage import com.nextroom.nextroom.domain.model.Result import com.nextroom.nextroom.domain.model.onFailure import com.nextroom.nextroom.domain.model.onSuccess -import com.nextroom.nextroom.domain.model.suspendOnSuccess import com.nextroom.nextroom.domain.repository.AdminRepository import com.nextroom.nextroom.domain.repository.BannerRepository import com.nextroom.nextroom.domain.repository.DataStoreRepository @@ -15,7 +15,11 @@ import com.nextroom.nextroom.presentation.model.ThemeInfoPresentation import com.nextroom.nextroom.presentation.model.toPresentation import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch +import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withContext import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.syntax.simple.intent @@ -36,7 +40,7 @@ class AdminMainViewModel @Inject constructor( override val container: Container = container(AdminMainState(loading = true)) init { - loadData() + fetchData() fetchBanners() viewModelScope.launch { @@ -64,30 +68,69 @@ class AdminMainViewModel @Inject constructor( } } - fun loadData() = intent { + fun fetchData() = intent { reduce { state.copy(loading = true) } - adminRepository.getUserSubscribe().suspendOnSuccess { - reduce { state.copy(subscribeStatus = it.status) } - themeRepository.getThemes().onSuccess { - updateThemes( - it.map { themeInfo -> - val updatedAt = themeRepository.getUpdatedInfo(themeInfo.id) - themeInfo.toPresentation(updatedAt) - }, - ) + + viewModelScope.launch { + supervisorScope { + try { + val userSubscribeDeferred = async(Dispatchers.IO) { fetchUserSubscribe() } + val themesDeferred = async(Dispatchers.IO) { getThemes() } + + userSubscribeDeferred.await() + .getOrNull + ?.let { + updateSubscribeStatus(it) + } + + val themes = themesDeferred.await() + val updateAtHashMap = mutableMapOf() + saveHints(themes) + .associate { it.getOrThrow } + .also { updateAtHashMap.putAll(it) } + if (state.themes.isEmpty()) { + updateThemes(themes) + } else { + updateThemes( + state.themes + .toMutableList() + .map { if (it.id in updateAtHashMap) it.copy(recentUpdated = updateAtHashMap.getValue(it.id)) else it } + ) + } + } catch (ex: Exception) { + //TODO : 리팩토링 필요. ex로 부터 어떤 에러인지 추출할수가 없음. 중간에 에러 정보를 잃음. + handleError(Result.Failure.OperationError(ex)) + } } } - themeRepository.getThemes().onSuccess { - updateThemes( - it.map { themeInfo -> - val updatedAt = themeRepository.getUpdatedInfo(themeInfo.id) - themeInfo.toPresentation(updatedAt) - }, - ) - }.onFailure(::handleError) + reduce { state.copy(loading = false) } } + private fun updateSubscribeStatus(myPage: Mypage) = intent { + reduce { state.copy(subscribeStatus = myPage.status) } + } + + private suspend fun fetchUserSubscribe() = adminRepository.getUserSubscribe() + + private suspend fun getThemes(): List { + return themeRepository.getThemes() + .getOrThrow + .map { themeInfo -> + themeRepository + .getUpdatedInfo(themeInfo.id) + .let { updatedAt -> + themeInfo.toPresentation(updatedAt) + } + } + } + + private suspend fun saveHints(themes: List) = coroutineScope { + return@coroutineScope themes + .map { theme -> async(Dispatchers.IO) { hintRepository.saveHints(theme.id) } } + .awaitAll() + } + private fun updateShopInfo(shopName: String) = intent { reduce { state.copy(shopName = shopName) } }