Skip to content

Commit

Permalink
* Fixes: the switch from one wp.com site to another wp.com
Browse files Browse the repository at this point in the history
Fixes: the issue in which dashboard cards shown were not correct, the
collect job for cards was not cancelled properly which resulted in
dashboard cards shown in the wrong site.
  • Loading branch information
AjeshRPai committed Feb 7, 2024
1 parent beca431 commit 6e1a955
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package org.wordpress.android.ui.mysite.cards
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.distinctUntilChanged
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.ui.mysite.BlazeCardViewModelSlice
import org.wordpress.android.ui.mysite.MySiteCardAndItem
Expand Down Expand Up @@ -42,6 +44,8 @@ class DashboardCardsViewModelSlice @Inject constructor(
) {
private lateinit var scope: CoroutineScope

private var job: Job? = null

private val _onSnackbar = MutableLiveData<Event<SnackbarMessageHolder>>()
val onSnackbarMessage = merge(
_onSnackbar,
Expand Down Expand Up @@ -169,16 +173,19 @@ class DashboardCardsViewModelSlice @Inject constructor(
}

fun buildCards(site: SiteModel) {
jpMigrationSuccessCardViewModelSlice.buildCard()
jetpackInstallFullPluginCardViewModelSlice.buildCard(site)
blazeCardViewModelSlice.buildCard(site)
bloggingPromptCardViewModelSlice.buildCard(site)
bloganuaryNudgeCardViewModelSlice.buildCard()
personalizeCardViewModelSlice.buildCard()
quickLinksItemViewModelSlice.buildCard(site)
plansCardViewModelSlice.buildCard(site)
cardViewModelSlice.buildCard(site)
quickStartCardViewModelSlice.build(site)
job?.cancel()
job = scope.launch {
jpMigrationSuccessCardViewModelSlice.buildCard()
jetpackInstallFullPluginCardViewModelSlice.buildCard(site)
blazeCardViewModelSlice.buildCard(site)
bloggingPromptCardViewModelSlice.buildCard(site)
bloganuaryNudgeCardViewModelSlice.buildCard()
personalizeCardViewModelSlice.buildCard()
quickLinksItemViewModelSlice.buildCard(site)
plansCardViewModelSlice.buildCard(site)
cardViewModelSlice.buildCard(site)
quickStartCardViewModelSlice.build(site)
}
}


Expand All @@ -197,6 +204,7 @@ class DashboardCardsViewModelSlice @Inject constructor(

fun onCleared() {
quickLinksItemViewModelSlice.onCleared()
job?.cancel()
scope.cancel()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package org.wordpress.android.ui.mysite.cards.dashboard

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.distinctUntilChanged
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.wordpress.android.R
Expand Down Expand Up @@ -54,11 +53,48 @@ class CardViewModelSlice @Inject constructor(
) {
private lateinit var scope: CoroutineScope

private var collectJob: Job? = null
private var fetchJob: Job? = null

private val _isRefreshing = MutableLiveData<Boolean>()
val isRefreshing: LiveData<Boolean> = _isRefreshing

private val _uiModel = MutableLiveData<CardsState?>()
val uiModel: LiveData<CardsState?> = _uiModel.distinctUntilChanged()
val uiModel: MutableLiveData<CardsState> = merge(
dynamicCardsViewModelSlice.topDynamicCards,
todaysStatsViewModelSlice.uiModel,
pagesCardViewModelSlice.uiModel,
postsCardViewModelSlice.uiModel,
activityLogCardViewModelSlice.uiModel,
dynamicCardsViewModelSlice.bottomDynamicCards
) { topDynamicCards, todaysStatsCard, pagesCard, postsCard, activityCard, bottomDynamicCards ->
val state = mergeUiModels(
topDynamicCards,
todaysStatsCard,
pagesCard,
postsCard,
activityCard,
bottomDynamicCards
)
state
} as MutableLiveData<CardsState>

private fun mergeUiModels(
topDynamicCards: List<MySiteCardAndItem.Card>?,
todaysStatsCard: MySiteCardAndItem.Card.TodaysStatsCard?,
pagesCard: MySiteCardAndItem.Card.PagesCard?,
postsCard: List<MySiteCardAndItem.Card>?,
activityCard: MySiteCardAndItem.Card.ActivityCard?,
bottomDynamicCards: List<MySiteCardAndItem.Card>?
): CardsState {
val cards = mutableListOf<MySiteCardAndItem.Card>()
topDynamicCards?.let { cards.addAll(topDynamicCards) }
todaysStatsCard?.let { cards.add(todaysStatsCard) }
pagesCard?.let { cards.add(pagesCard) }
postsCard?.let { cards.addAll(postsCard) }
activityCard?.let { cards.add(activityCard) }
bottomDynamicCards?.let { cards.addAll(bottomDynamicCards) }
return CardsState.Success(cards)
}

private val _onNavigation = MutableLiveData<Event<SiteNavigationAction>>()
val onNavigation = merge(
Expand Down Expand Up @@ -94,7 +130,8 @@ class CardViewModelSlice @Inject constructor(
) {
_isRefreshing.postValue(true)
// fetch data from store and then refresh the data from the server
scope.launch(bgDispatcher) {
collectJob?.cancel()
collectJob = scope.launch(bgDispatcher) {
cardsStore.getCards(siteModel)
.map { it.model }
.map { cards -> cards?.filter { getCardTypes(siteModel).contains(it.type) } }
Expand All @@ -109,7 +146,8 @@ class CardViewModelSlice @Inject constructor(
selectedSite: SiteModel
) {
_isRefreshing.postValue(true)
scope.launch(bgDispatcher) {
fetchJob?.cancel()
fetchJob = scope.launch(bgDispatcher) {
val payload = CardsRestClient.FetchCardsPayload(
selectedSite,
getCardTypes(selectedSite),
Expand Down Expand Up @@ -157,28 +195,28 @@ class CardViewModelSlice @Inject constructor(
}

private fun postErrorState() {
if ((_uiModel.value == null) || isUiModelEmpty()){
if ((uiModel.value == null) || isUiModelEmpty()) {
// if the
_uiModel.postValue(
uiModel.postValue(
CardsState.ErrorState(
MySiteCardAndItem.Card.ErrorCard(
onRetryClick = ListItemInteraction.create(this::onDashboardErrorRetry)
)
)
)
} else if (_uiModel.value is CardsState.ErrorState) {
} else if (uiModel.value is CardsState.ErrorState) {
// if the error state is already posted, then post the snackbar message
_onSnackbarMessage.postValue(
Event(
SnackbarMessageHolder(UiString.UiStringRes(R.string.my_site_dashboard_update_error))
)
_onSnackbarMessage.postValue(
Event(
SnackbarMessageHolder(UiString.UiStringRes(R.string.my_site_dashboard_update_error))
)
}
)
}
_isRefreshing.postValue(false)
}

private fun isUiModelEmpty(): Boolean {
return (_uiModel.value is CardsState.Success) && (_uiModel.value as CardsState.Success).cards.isEmpty()
return (uiModel.value is CardsState.Success) && (uiModel.value as CardsState.Success).cards.isEmpty()
}

private fun onDashboardErrorRetry() {
Expand All @@ -188,63 +226,46 @@ class CardViewModelSlice @Inject constructor(
fun postState(cards: List<CardModel>?) {
_isRefreshing.postValue(false)
if (cards.isNullOrEmpty()) {
_uiModel.postValue(CardsState.Success(emptyList()))
uiModel.postValue(CardsState.Success(emptyList()))
return
}
scope.launch {
val result = mutableListOf<MySiteCardAndItem.Card>()

val topDynamicCards = async {
dynamicCardsViewModelSlice.buildTopDynamicCards(
cards.firstOrNull { it is CardModel.DynamicCardsModel } as? CardModel.DynamicCardsModel
)
}

val todayStatsCard = async {
todaysStatsViewModelSlice.buildTodaysStatsCard(
cards.firstOrNull { it is CardModel.TodaysStatsCardModel } as? CardModel.TodaysStatsCardModel
)
}
dynamicCardsViewModelSlice.buildTopDynamicCards(
cards.firstOrNull { it is CardModel.DynamicCardsModel } as? CardModel.DynamicCardsModel
)

val postCard = async {
postsCardViewModelSlice.buildPostCard(
cards.firstOrNull { it is CardModel.PostsCardModel } as? CardModel.PostsCardModel
)
}

val pagesCard = async {
pagesCardViewModelSlice.buildCard(
cards.firstOrNull { it is CardModel.PagesCardModel } as? CardModel.PagesCardModel
)
}
todaysStatsViewModelSlice.buildTodaysStatsCard(
cards.firstOrNull { it is CardModel.TodaysStatsCardModel } as? CardModel.TodaysStatsCardModel
)

val activityCard = async {
activityLogCardViewModelSlice.buildCard(
cards.firstOrNull { it is CardModel.ActivityCardModel } as? CardModel.ActivityCardModel
)
}
postsCardViewModelSlice.buildPostCard(
cards.firstOrNull { it is CardModel.PostsCardModel } as? CardModel.PostsCardModel
)

val bottomDynamicCards = async {
dynamicCardsViewModelSlice.buildBottomDynamicCards(
cards.firstOrNull { it is CardModel.DynamicCardsModel } as? CardModel.DynamicCardsModel
)
}
pagesCardViewModelSlice.buildCard(
cards.firstOrNull { it is CardModel.PagesCardModel } as? CardModel.PagesCardModel
)

result.apply {
topDynamicCards.await()?.let { addAll(it) }
todayStatsCard.await()?.let { add(it) }
postCard.await().let { addAll(it) }
pagesCard.await()?.let { add(it) }
activityCard.await()?.let { add(it) }
bottomDynamicCards.await()?.let { addAll(it) }
}.toList()
activityLogCardViewModelSlice.buildCard(
cards.firstOrNull { it is CardModel.ActivityCardModel } as? CardModel.ActivityCardModel
)

_uiModel.postValue(CardsState.Success(result))
dynamicCardsViewModelSlice.buildBottomDynamicCards(
cards.firstOrNull { it is CardModel.DynamicCardsModel } as? CardModel.DynamicCardsModel
)
}
}

fun clearValue() {
_uiModel.postValue(null)
uiModel.postValue(CardsState.Success(emptyList()))
collectJob?.cancel()
fetchJob?.cancel()
dynamicCardsViewModelSlice.clearValue()
todaysStatsViewModelSlice.clearValue()
pagesCardViewModelSlice.clearValue()
postsCardViewModelSlice.clearValue()
activityLogCardViewModelSlice.clearValue()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.wordpress.android.ui.mysite.cards.dashboard.activity

import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import org.wordpress.android.fluxc.model.dashboard.CardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItem
Expand All @@ -21,14 +22,17 @@ class ActivityLogCardViewModelSlice @Inject constructor(
private val appPrefsWrapper: AppPrefsWrapper,
private val activityCardBuilder: ActivityCardBuilder
) {
private val _uiModel = MutableLiveData<MySiteCardAndItem.Card.ActivityCard?>()
val uiModel = _uiModel as LiveData<MySiteCardAndItem.Card.ActivityCard?>

private val _onNavigation = MutableLiveData<Event<SiteNavigationAction>>()
val onNavigation = _onNavigation

private val _refresh = MutableLiveData<Event<Boolean>>()
val refresh = _refresh

fun buildCard(activityCardModel: CardModel.ActivityCardModel?): MySiteCardAndItem.Card.ActivityCard? {
return activityCardBuilder.build(getActivityLogCardBuilderParams(activityCardModel))
fun buildCard(activityCardModel: CardModel.ActivityCardModel?) {
_uiModel.postValue(activityCardBuilder.build(getActivityLogCardBuilderParams(activityCardModel)))
}

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
Expand Down Expand Up @@ -75,8 +79,13 @@ class ActivityLogCardViewModelSlice @Inject constructor(
_onNavigation.value =
Event(SiteNavigationAction.OpenActivityLog(requireNotNull(selectedSiteRepository.getSelectedSite())))
}

private fun onActivityCardMoreMenuClick() = cardsTracker.trackCardMoreMenuClicked(CardsTracker.Type.ACTIVITY.label)

fun clearValue() {
_uiModel.value = null
}

enum class MenuItemType(val label: String) {
ALL_ACTIVITY("all_activity"),
HIDE_THIS("hide_this")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.mysite.cards.dashboard.pages

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import org.wordpress.android.fluxc.model.dashboard.CardModel.PagesCardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItem
Expand All @@ -17,14 +18,19 @@ class PagesCardViewModelSlice @Inject constructor(
private val appPrefsWrapper: AppPrefsWrapper,
private val pagesCardBuilder: PagesCardBuilder
) {
private val _uiModel = MutableLiveData<MySiteCardAndItem.Card.PagesCard?>()
val uiModel: LiveData<MySiteCardAndItem.Card.PagesCard?> = _uiModel

private val _onNavigation = MutableLiveData<Event<SiteNavigationAction>>()
val onNavigation = _onNavigation

private val _refresh = MutableLiveData<Event<Boolean>>()
val refresh = _refresh

fun buildCard(pagesCardModel: PagesCardModel?): MySiteCardAndItem.Card.PagesCard? {
return pagesCardBuilder.build(getPagesCardBuilderParams(pagesCardModel))
fun buildCard(pagesCardModel: PagesCardModel?) {
_uiModel.postValue(
pagesCardBuilder.build(getPagesCardBuilderParams(pagesCardModel))
)
}

fun getPagesCardBuilderParams(pagesCardModel: PagesCardModel?): PagesCardBuilderParams {
Expand Down Expand Up @@ -100,6 +106,10 @@ class PagesCardViewModelSlice @Inject constructor(
)
)
}

fun clearValue() {
_uiModel.postValue(null)
}
}

enum class PagesMenuItemType(val label: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.mysite.cards.dashboard.posts

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import org.wordpress.android.fluxc.model.dashboard.CardModel.PostsCardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItem
Expand All @@ -18,14 +19,17 @@ class PostsCardViewModelSlice @Inject constructor(
private val appPrefsWrapper: AppPrefsWrapper,
private val postCardBuilder: PostCardBuilder
) {
private val _uiModel = MutableLiveData<List<MySiteCardAndItem.Card>?>()
val uiModel = _uiModel as LiveData<List<MySiteCardAndItem.Card>?>

private val _onNavigation = MutableLiveData<Event<SiteNavigationAction>>()
val onNavigation = _onNavigation

private val _refresh = MutableLiveData<Event<Boolean>>()
val refresh = _refresh

fun buildPostCard(postsCardModel: PostsCardModel?): List<MySiteCardAndItem.Card.PostCard> {
return postCardBuilder.build(getPostsCardBuilderParams(postsCardModel))
fun buildPostCard(postsCardModel: PostsCardModel?) {
_uiModel.postValue(postCardBuilder.build(getPostsCardBuilderParams(postsCardModel)))
}

fun getPostsCardBuilderParams(postsCardModel: PostsCardModel?) : PostCardBuilderParams {
Expand Down Expand Up @@ -111,4 +115,8 @@ class PostsCardViewModelSlice @Inject constructor(
PostCardType.SCHEDULED -> PostMenuCard.SCHEDULED_POSTS
}
}

fun clearValue() {
_uiModel.postValue(null)
}
}
Loading

0 comments on commit 6e1a955

Please sign in to comment.