Skip to content

Commit

Permalink
Merge pull request #19721 from wordpress-mobile/feature/sotw-card-wor…
Browse files Browse the repository at this point in the history
…dpress

[SotW 2023] Add State of the Word post-event card to WordPress
  • Loading branch information
Thomas Horta authored Dec 2, 2023
2 parents 0a3337b + 0d89762 commit 7a84e46
Show file tree
Hide file tree
Showing 23 changed files with 595 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.PostCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.QuickLinksItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.QuickStartCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.TodaysStatsCard.TodaysStatsCardWithData
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.WpSotw2023NudgeCardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.CategoryEmptyHeaderItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.CategoryHeaderItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.InfoItem
Expand Down Expand Up @@ -51,6 +52,7 @@ import org.wordpress.android.ui.mysite.cards.nocards.NoCardsMessageViewHolder
import org.wordpress.android.ui.mysite.cards.personalize.PersonalizeCardViewHolder
import org.wordpress.android.ui.mysite.cards.quicklinksitem.QuickLinkRibbonViewHolder
import org.wordpress.android.ui.mysite.cards.quickstart.QuickStartCardViewHolder
import org.wordpress.android.ui.mysite.cards.sotw2023.WpSotw2023NudgeCardViewHolder
import org.wordpress.android.ui.mysite.items.categoryheader.MySiteCategoryItemEmptyViewHolder
import org.wordpress.android.ui.mysite.items.categoryheader.MySiteCategoryItemViewHolder
import org.wordpress.android.ui.mysite.items.infoitem.MySiteInfoItemViewHolder
Expand Down Expand Up @@ -123,6 +125,7 @@ class MySiteAdapter(
)
MySiteCardAndItem.Type.NO_CARDS_MESSAGE.ordinal -> NoCardsMessageViewHolder(parent)
MySiteCardAndItem.Type.PERSONALIZE_CARD.ordinal -> PersonalizeCardViewHolder(parent)
MySiteCardAndItem.Type.WP_SOTW_2023_NUDGE_CARD.ordinal -> WpSotw2023NudgeCardViewHolder(parent)
else -> throw IllegalArgumentException("Unexpected view type")
}
}
Expand Down Expand Up @@ -156,6 +159,7 @@ class MySiteAdapter(
is JetpackInstallFullPluginCardViewHolder -> holder.bind(getItem(position) as JetpackInstallFullPluginCard)
is NoCardsMessageViewHolder -> holder.bind(getItem(position) as MySiteCardAndItem.Card.NoCardsMessage)
is PersonalizeCardViewHolder -> holder.bind(getItem(position) as PersonalizeCardModel)
is WpSotw2023NudgeCardViewHolder -> holder.bind(getItem(position) as WpSotw2023NudgeCardModel)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.PostCard.PostCardW
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.QuickLinksItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.QuickStartCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.TodaysStatsCard.TodaysStatsCardWithData
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.WpSotw2023NudgeCardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.CategoryEmptyHeaderItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.CategoryHeaderItem
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Item.InfoItem
Expand Down Expand Up @@ -64,6 +65,7 @@ object MySiteAdapterDiffCallback : DiffUtil.ItemCallback<MySiteCardAndItem>() {
oldItem is MySiteCardAndItem.Card.NoCardsMessage && updatedItem is
MySiteCardAndItem.Card.NoCardsMessage -> true
oldItem is PersonalizeCardModel && updatedItem is PersonalizeCardModel -> true
oldItem is WpSotw2023NudgeCardModel && updatedItem is WpSotw2023NudgeCardModel -> true
else -> throw UnsupportedOperationException("Diff not implemented yet")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte
JETPACK_INSTALL_FULL_PLUGIN_CARD,
NO_CARDS_MESSAGE,
PERSONALIZE_CARD,
WP_SOTW_2023_NUDGE_CARD,
}

data class SiteInfoHeaderCard(
Expand Down Expand Up @@ -380,6 +381,14 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte
val onMoreMenuClick: ListItemInteraction,
) : Card(type = Type.DASHBOARD_PLANS_CARD)

data class WpSotw2023NudgeCardModel(
val title: UiString,
val text: UiString,
val ctaText: UiString,
val onHideMenuItemClick: ListItemInteraction,
val onCtaClick: ListItemInteraction,
) : Card(type = Type.WP_SOTW_2023_NUDGE_CARD)

data class NoCardsMessage(val title: UiString, val message: UiString) : Card(Type.NO_CARDS_MESSAGE)
data class PersonalizeCardModel(val onClick: () -> Unit) : Card(Type.PERSONALIZE_CARD)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment),
ActivityLauncher.viewCurrentBlogPostsOfType(requireActivity(), action.site, PostListType.SCHEDULED)
is SiteNavigationAction.OpenStatsInsights ->
ActivityLauncher.viewBlogStatsForTimeframe(requireActivity(), action.site, StatsTimeframe.INSIGHTS)
is SiteNavigationAction.OpenTodaysStatsGetMoreViewsExternalUrl ->
is SiteNavigationAction.OpenExternalUrl ->
ActivityLauncher.openUrlExternal(requireActivity(), action.url)
is SiteNavigationAction.OpenJetpackPoweredBottomSheet -> showJetpackPoweredBottomSheet()
is SiteNavigationAction.OpenJetpackMigrationDeleteWP -> showJetpackMigrationDeleteWP()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import org.wordpress.android.ui.mysite.cards.quickstart.QuickStartRepository
import org.wordpress.android.ui.mysite.cards.quickstart.QuickStartRepository.QuickStartCategory
import org.wordpress.android.ui.mysite.cards.siteinfo.SiteInfoHeaderCardBuilder
import org.wordpress.android.ui.mysite.cards.siteinfo.SiteInfoHeaderCardViewModelSlice
import org.wordpress.android.ui.mysite.cards.sotw2023.WpSotw2023NudgeCardViewModelSlice
import org.wordpress.android.ui.mysite.items.infoitem.MySiteInfoItemBuilder
import org.wordpress.android.ui.mysite.items.listitem.SiteItemsBuilder
import org.wordpress.android.ui.mysite.items.listitem.SiteItemsViewModelSlice
Expand Down Expand Up @@ -169,6 +170,7 @@ class MySiteViewModel @Inject constructor(
private val siteInfoHeaderCardViewModelSlice: SiteInfoHeaderCardViewModelSlice,
private val quickLinksItemViewModelSlice: QuickLinksItemViewModelSlice,
private val bloganuaryNudgeCardViewModelSlice: BloganuaryNudgeCardViewModelSlice,
private val sotw2023NudgeCardViewModelSlice: WpSotw2023NudgeCardViewModelSlice,
) : ScopedViewModel(mainDispatcher) {
private val _onSnackbarMessage = MutableLiveData<Event<SnackbarMessageHolder>>()
private val _onNavigation = MutableLiveData<Event<SiteNavigationAction>>()
Expand Down Expand Up @@ -231,7 +233,8 @@ class MySiteViewModel @Inject constructor(
bloganuaryNudgeCardViewModelSlice.onNavigation,
personalizeCardViewModelSlice.onNavigation,
siteInfoHeaderCardViewModelSlice.onNavigation,
quickLinksItemViewModelSlice.navigation
quickLinksItemViewModelSlice.navigation,
sotw2023NudgeCardViewModelSlice.onNavigation,
)

val onMediaUpload = siteInfoHeaderCardViewModelSlice.onMediaUpload
Expand All @@ -247,6 +250,7 @@ class MySiteViewModel @Inject constructor(
postsCardViewModelSlice.refresh,
activityLogCardViewModelSlice.refresh,
bloganuaryNudgeCardViewModelSlice.refresh,
sotw2023NudgeCardViewModelSlice.refresh,
)
val domainTransferCardRefresh = domainTransferCardViewModel.refresh

Expand Down Expand Up @@ -322,6 +326,7 @@ class MySiteViewModel @Inject constructor(
siteInfoHeaderCardViewModelSlice.initialize(viewModelScope)
quickLinksItemViewModelSlice.initialization(viewModelScope)
quickLinksItemViewModelSlice.start()
sotw2023NudgeCardViewModelSlice.initialize(viewModelScope)
}

@Suppress("LongParameterList")
Expand Down Expand Up @@ -423,8 +428,11 @@ class MySiteViewModel @Inject constructor(

val siteItems = getSiteItems(site, activeTask, backupAvailable, scanAvailable)

val sotw2023Card = sotw2023NudgeCardViewModelSlice.buildCard()

return mutableListOf<MySiteCardAndItem>().apply {
infoItem?.let { add(infoItem) }
sotw2023Card?.let { add(it) }
addAll(siteItems)
jetpackSwitchMenu?.let { add(jetpackSwitchMenu) }
if (jetpackFeatureCardHelper.shouldShowFeatureCardAtTop())
Expand Down Expand Up @@ -988,6 +996,8 @@ class MySiteViewModel @Inject constructor(
.forEach { personalizeCardViewModelSlice.trackShown(it.type) }
siteSelected.dashboardData.filterIsInstance<MySiteCardAndItem.Card.NoCardsMessage>()
.forEach { noCardsMessageViewModelSlice.trackShown(it.type) }
siteSelected.dashboardData.filterIsInstance<MySiteCardAndItem.Card.WpSotw2023NudgeCardModel>()
.forEach { _ -> sotw2023NudgeCardViewModelSlice.trackShown() }
}

private fun resetShownTrackers() {
Expand All @@ -997,6 +1007,7 @@ class MySiteViewModel @Inject constructor(
jetpackFeatureCardShownTracker.resetShown()
jetpackInstallFullPluginShownTracker.resetShown()
personalizeCardViewModelSlice.resetShown()
sotw2023NudgeCardViewModelSlice.resetShown()
}

// FluxC events
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ sealed class SiteNavigationAction {
data class EditDraftPost(val site: SiteModel, val postId: Int) : SiteNavigationAction()
data class EditScheduledPost(val site: SiteModel, val postId: Int) : SiteNavigationAction()
data class OpenStatsInsights(val site: SiteModel) : SiteNavigationAction()
data class OpenTodaysStatsGetMoreViewsExternalUrl(val url: String) : SiteNavigationAction()
data class OpenExternalUrl(val url: String) : SiteNavigationAction()
object OpenJetpackPoweredBottomSheet : SiteNavigationAction()
object OpenJetpackMigrationDeleteWP : SiteNavigationAction()
data class OpenJetpackFeatureOverlay(val source: JetpackFeatureCollectionOverlaySource) : SiteNavigationAction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class TodaysStatsViewModelSlice @Inject constructor(
_onNavigation.value = Event(SiteNavigationAction.ShowJetpackRemovalStaticPostersView)
} else {
_onNavigation.value = Event(
SiteNavigationAction.OpenTodaysStatsGetMoreViewsExternalUrl(
SiteNavigationAction.OpenExternalUrl(
TodaysStatsCardBuilder.URL_GET_MORE_VIEWS_AND_TRAFFIC
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.wordpress.android.ui.mysite.cards.sotw2023

import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import org.wordpress.android.R
import org.wordpress.android.ui.compose.components.card.UnelevatedCard
import org.wordpress.android.ui.compose.styles.DashboardCardTypography
import org.wordpress.android.ui.compose.theme.AppTheme
import org.wordpress.android.ui.compose.unit.Margin
import org.wordpress.android.ui.compose.utils.uiStringText
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.WpSotw2023NudgeCardModel
import org.wordpress.android.ui.mysite.cards.compose.MySiteCardToolbar
import org.wordpress.android.ui.mysite.cards.compose.MySiteCardToolbarContextMenuItem
import org.wordpress.android.ui.utils.ListItemInteraction
import org.wordpress.android.ui.utils.UiString.UiStringRes

@Composable
fun WpSotw2023NudgeCard(
model: WpSotw2023NudgeCardModel,
modifier: Modifier = Modifier,
) {
UnelevatedCard(
modifier = modifier.semantics(mergeDescendants = true) {},
) {
Column(
modifier = Modifier.padding(bottom = Margin.Medium.value)
) {
CardToolbar(model)

Spacer(Modifier.height(Margin.Medium.value))

Text(
text = uiStringText(model.text),
style = DashboardCardTypography.detailText,
modifier = Modifier.padding(horizontal = Margin.ExtraLarge.value),
)

Spacer(Modifier.height(Margin.Small.value))

TextButton(
onClick = { model.onCtaClick.click() },
modifier = Modifier.padding(horizontal = Margin.Small.value)
) {
Text(
text = uiStringText(model.ctaText),
style = DashboardCardTypography.footerCTA,
)
}
}
}
}

@Composable
private fun CardToolbar(
model: WpSotw2023NudgeCardModel
) {
MySiteCardToolbar(
contextMenuItems = listOf(
MySiteCardToolbarContextMenuItem.Option(
text = stringResource(R.string.my_site_dashboard_card_more_menu_hide_card),
onClick = { model.onHideMenuItemClick.click() },
)
),
) {
Text(
text = uiStringText(uiString = model.title),
style = DashboardCardTypography.smallTitle,
textAlign = TextAlign.Start,
fontWeight = FontWeight.Medium,
)
}
}

@Preview(name = "Light Mode")
@Preview(name = "Dark Mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun WpSotw2023NudgeCardPreview() {
AppTheme {
WpSotw2023NudgeCard(
model = WpSotw2023NudgeCardModel(
title = UiStringRes(R.string.wp_sotw_2023_dashboard_nudge_title),
text = UiStringRes(R.string.wp_sotw_2023_dashboard_nudge_text),
ctaText = UiStringRes(R.string.wp_sotw_2023_dashboard_nudge_cta),
onHideMenuItemClick = ListItemInteraction.create {},
onCtaClick = ListItemInteraction.create {},
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.wordpress.android.ui.mysite.cards.sotw2023

import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
import javax.inject.Inject

class WpSotw2023NudgeCardAnalyticsTracker @Inject constructor(
private val analyticsTracker: AnalyticsTrackerWrapper,
) {
private var cardShownTracked: Boolean = false

fun resetShown() {
cardShownTracked = false
}

fun trackShown() {
if (!cardShownTracked) {
cardShownTracked = true
analyticsTracker.track(AnalyticsTracker.Stat.SOTW_2023_NUDGE_POST_EVENT_CARD_SHOWN)
}
}

fun trackCtaTapped() {
analyticsTracker.track(AnalyticsTracker.Stat.SOTW_2023_NUDGE_POST_EVENT_CARD_CTA_TAPPED)
}

fun trackHideTapped() {
analyticsTracker.track(AnalyticsTracker.Stat.SOTW_2023_NUDGE_POST_EVENT_CARD_HIDE_TAPPED)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.wordpress.android.ui.mysite.cards.sotw2023

import android.view.ViewGroup
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ViewCompositionStrategy
import org.wordpress.android.databinding.WpSotw20223NudgeCardBinding
import org.wordpress.android.ui.compose.theme.AppTheme
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.WpSotw2023NudgeCardModel
import org.wordpress.android.ui.mysite.MySiteCardAndItemViewHolder
import org.wordpress.android.util.extensions.viewBinding

class WpSotw2023NudgeCardViewHolder(parent: ViewGroup) :
MySiteCardAndItemViewHolder<WpSotw20223NudgeCardBinding>(parent.viewBinding(WpSotw20223NudgeCardBinding::inflate)) {
fun bind(cardModel: WpSotw2023NudgeCardModel) = with(binding.wpSotw2023NudgeCard) {
// Dispose of the Composition when the view's LifecycleOwner is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool)
setContent {
AppTheme {
WpSotw2023NudgeCard(
model = cardModel,
modifier = Modifier.fillMaxWidth(),
)
}
}
}
}
Loading

0 comments on commit 7a84e46

Please sign in to comment.