Skip to content

Add tapping functionality to domain cards on the Site Domain screen #19910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1cd5253
Remove an unused view from `domain_site_domains_card.xml`
irfano Jan 9, 2024
134f0c1
Convert `sealed` sub-objects of `AllDomains` to `data object`s
irfano Jan 9, 2024
2ee4dce
Fetch all domains in "Site Domains" screen
irfano Jan 9, 2024
3f643b0
Add a click listener param to the card item on "Site Domains" screen
irfano Jan 9, 2024
55b0053
Set domain card's click listener using result of all-domains endpoint
irfano Jan 9, 2024
28a937d
Log endpoint errors in the `FetchAllDomainsUseCase`
irfano Jan 9, 2024
83647df
Use `FetchAllDomainsUseCase` instead of a store in the view model
irfano Jan 9, 2024
aa7a172
Open domain management details screen when the site domain card tapped
irfano Jan 9, 2024
c602d1b
Add a chevron to the domain card on the "Site Domains" screen
irfano Jan 9, 2024
0348685
Add `ic_dot_white_8dp.xml`
irfano Jan 9, 2024
e3a3034
Add domain status label to domain card layout on Site Domain screen
irfano Jan 9, 2024
4454fa0
Add params to SiteDomains model for domain status
irfano Jan 9, 2024
a76887d
Add domain status color logic to `DomainsDashboardViewModel`
irfano Jan 9, 2024
419e24d
Fill domain status data from the view model
irfano Jan 9, 2024
846b0c7
Set the domain card view according to the domain status data
irfano Jan 9, 2024
b8ab319
Hide expiry date if the domain doesn't have registration
irfano Jan 10, 2024
caccb5d
Merge pull request #19912 from wordpress-mobile/feature/domain-status…
ravishanker Jan 10, 2024
e98bb86
Remove the chevron from the domain cards
irfano Jan 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistr
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.ClaimDomain
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetDomain
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetPlan
import org.wordpress.android.ui.domains.management.details.DomainManagementDetailsActivity
import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.util.config.DomainManagementFeatureConfig
import org.wordpress.android.util.extensions.getSerializableExtraCompat
Expand Down Expand Up @@ -100,16 +101,22 @@ class DomainsDashboardFragment : Fragment(R.layout.domains_dashboard_fragment),
action.site,
DOMAIN_PURCHASE
)

is ClaimDomain -> ActivityLauncher.viewDomainRegistrationActivityForResult(
this,
action.site,
CTA_DOMAIN_CREDIT_REDEMPTION
)

is GetPlan -> ActivityLauncher.viewDomainRegistrationActivityForResult(
this,
action.site,
FREE_DOMAIN_WITH_ANNUAL_PLAN
)

is DomainsDashboardNavigationAction.OpenDomainManagement -> startActivity(
DomainManagementDetailsActivity.createIntent(requireContext(), action.domain, action.detailUrl)
)
}

@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.wordpress.android.ui.domains

import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.ADD_DOMAIN
import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PURCHASE_DOMAIN
Expand All @@ -22,8 +23,11 @@ sealed class DomainsDashboardItem(val type: Type) {

data class SiteDomains(
val domain: UiString,
val expiry: UiString,
val isPrimary: Boolean,
val domainStatus: UiString,
@ColorRes val domainStatusColor: Int,
val expiry: UiString?,
val onDomainClick: ListItemInteraction? = null
) : DomainsDashboardItem(SITE_DOMAINS)

data class AddDomain(val onClick: ListItemInteraction) : DomainsDashboardItem(ADD_DOMAIN)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.wordpress.android.ui.domains
import org.wordpress.android.fluxc.model.SiteModel

sealed class DomainsDashboardNavigationAction {
data class OpenDomainManagement(val domain: String, val detailUrl: String) : DomainsDashboardNavigationAction()
data class GetDomain(val site: SiteModel) : DomainsDashboardNavigationAction()
data class ClaimDomain(val site: SiteModel) : DomainsDashboardNavigationAction()
data class GetPlan(val site: SiteModel) : DomainsDashboardNavigationAction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ sealed class DomainsDashboardViewHolder<T : ViewBinding>(
uiHelpers.setTextOrHide(siteDomain, item.domain)
uiHelpers.setTextOrHide(siteDomainExpiryDate, item.expiry)
primarySiteDomainChip.isVisible = item.isPrimary
uiHelpers.setTextOrHide(siteDomainStatus, item.domainStatus)
siteDomainStatus.compoundDrawablesRelative.first().setTint(
siteDomainStatus.context.getColor(item.domainStatusColor)
)
item.onDomainClick?.let { interaction -> root.setOnClickListener { interaction.click() } }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAINS_DASHBOARD_V
import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED
import org.wordpress.android.fluxc.model.PlanModel
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.rest.wpcom.site.AllDomainsDomain
import org.wordpress.android.fluxc.network.rest.wpcom.site.Domain
import org.wordpress.android.fluxc.network.rest.wpcom.site.StatusType
import org.wordpress.android.fluxc.store.SiteStore
import org.wordpress.android.modules.BG_THREAD
import org.wordpress.android.ui.domains.DomainsDashboardItem.AddDomain
Expand All @@ -23,6 +25,10 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomainsHeader
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.ClaimDomain
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetDomain
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetPlan
import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.OpenDomainManagement
import org.wordpress.android.ui.domains.management.getDomainDetailsUrl
import org.wordpress.android.ui.domains.usecases.AllDomains
import org.wordpress.android.ui.domains.usecases.FetchAllDomainsUseCase
import org.wordpress.android.ui.domains.usecases.FetchPlansUseCase
import org.wordpress.android.ui.plans.isDomainCreditAvailable
import org.wordpress.android.ui.utils.HtmlMessageUtils
Expand All @@ -46,6 +52,7 @@ class DomainsDashboardViewModel @Inject constructor(
private val analyticsTrackerWrapper: AnalyticsTrackerWrapper,
private val htmlMessageUtils: HtmlMessageUtils,
private val fetchPlansUseCase: FetchPlansUseCase,
private val fetchAllDomainsUseCase: FetchAllDomainsUseCase,
@Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher
) : ScopedViewModel(bgDispatcher) {
lateinit var site: SiteModel
Expand Down Expand Up @@ -80,9 +87,11 @@ class DomainsDashboardViewModel @Inject constructor(

val deferredPlansResult = async { fetchPlansUseCase.execute(site) }
val deferredDomainsResult = async { siteStore.fetchSiteDomains(site) }
val deferredAllDomainsResult = async { fetchAllDomainsUseCase.execute() }

val plansResult = deferredPlansResult.await()
val domainsResult = deferredDomainsResult.await()
val allDomainsResult = deferredAllDomainsResult.await()

if (plansResult.isError) {
AppLog.e(DOMAIN_REGISTRATION, "An error occurred while fetching plans: ${plansResult.error.message}")
Expand All @@ -92,10 +101,17 @@ class DomainsDashboardViewModel @Inject constructor(
AppLog.e(DOMAIN_REGISTRATION, "An error occurred while fetching domains: ${domainsResult.error.message}")
}

buildDashboardItems(site, plansResult.plans.orEmpty(), domainsResult.domains.orEmpty())
val allDomains = if (allDomainsResult is AllDomains.Success) allDomainsResult.domains else emptyList()

buildDashboardItems(site, plansResult.plans.orEmpty(), domainsResult.domains.orEmpty(), allDomains)
}

private fun buildDashboardItems(site: SiteModel, plans: List<PlanModel>, domains: List<Domain>) {
private fun buildDashboardItems(
site: SiteModel,
plans: List<PlanModel>,
domains: List<Domain>,
allDomains: List<AllDomainsDomain>
) {
val listItems = mutableListOf<DomainsDashboardItem>()

listItems += SiteDomainsHeader(UiStringRes(R.string.domains_free_domain))
Expand All @@ -106,8 +122,10 @@ class DomainsDashboardViewModel @Inject constructor(

listItems += SiteDomains(
UiStringText(freeDomainUrl),
UiStringRes(R.string.domains_site_domain_never_expires),
freeDomainIsPrimary
freeDomainIsPrimary,
UiStringRes(R.string.active),
getStatusColor(StatusType.SUCCESS),
UiStringRes(R.string.domains_site_domain_never_expires)
)

val customDomains = domains.filter { !it.wpcomDomain }
Expand All @@ -116,7 +134,7 @@ class DomainsDashboardViewModel @Inject constructor(
val hasPaidPlan = !SiteUtils.onFreePlan(site)

if (hasCustomDomains) {
listItems += buildCustomDomainItems(site, customDomains)
listItems += buildCustomDomainItems(site, customDomains, allDomains)
}

listItems += buildCtaItems(hasCustomDomains, hasDomainCredit, hasPaidPlan)
Expand All @@ -125,6 +143,13 @@ class DomainsDashboardViewModel @Inject constructor(
_uiModel.postValue(listItems)
}

private fun getStatusColor(statusType: StatusType?) = when (statusType) {
StatusType.SUCCESS -> R.color.jetpack_green_50
StatusType.NEUTRAL -> R.color.gray_50
StatusType.WARNING -> R.color.orange_50
else -> R.color.red_50
}

private fun buildCtaItems(
hasCustomDomains: Boolean,
hasDomainCredit: Boolean,
Expand Down Expand Up @@ -161,7 +186,11 @@ class DomainsDashboardViewModel @Inject constructor(
return listItems
}

private fun buildCustomDomainItems(site: SiteModel, customDomains: List<Domain>): List<DomainsDashboardItem> {
private fun buildCustomDomainItems(
site: SiteModel,
customDomains: List<Domain>,
allDomains: List<AllDomainsDomain>
): List<DomainsDashboardItem> {
val listItems = mutableListOf<DomainsDashboardItem>()
listItems += SiteDomainsHeader(
UiStringResWithParams(
Expand All @@ -170,9 +199,18 @@ class DomainsDashboardViewModel @Inject constructor(
)
)
listItems += customDomains.map {
val allDomainsDomain = allDomains.find { allDomainsItem -> it.domain == allDomainsItem.domain }

SiteDomains(
UiStringText(it.domain.orEmpty()),
if (it.expirySoon) {
it.primaryDomain,
allDomainsDomain?.domainStatus?.status?.let { status ->
UiStringText(status)
} ?: UiStringRes(R.string.error),
getStatusColor(allDomainsDomain?.domainStatus?.statusType),
if (!it.hasRegistration) {
null
} else if (it.expirySoon) {
UiStringText(
htmlMessageUtils.getHtmlMessageFromStringFormatResId(
R.string.domains_site_domain_expires_soon,
Expand All @@ -185,14 +223,23 @@ class DomainsDashboardViewModel @Inject constructor(
listOf(UiStringText(it.expiry.orEmpty()))
)
},
it.primaryDomain
allDomainsDomain?.let { ListItemInteraction.create(allDomainsDomain, this::onDomainClick) }
)
}
return listItems
}

private fun getCleanUrl(url: String?) = StringUtils.removeTrailingSlash(UrlUtils.removeScheme(url))

private fun onDomainClick(allDomainsDomain: AllDomainsDomain) {
_onNavigation.value = Event(
OpenDomainManagement(
allDomainsDomain.domain ?: return,
allDomainsDomain.getDomainDetailsUrl() ?: return
)
)
}

private fun onGetDomainClick() {
analyticsTrackerWrapper.track(DOMAINS_DASHBOARD_GET_DOMAIN_TAPPED, site)
_onNavigation.value = Event(GetDomain(site))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.wordpress.android.ui.domains.usecases

import org.wordpress.android.fluxc.network.rest.wpcom.site.AllDomainsDomain
import org.wordpress.android.fluxc.store.SiteStore
import org.wordpress.android.util.AppLog
import javax.inject.Inject

class FetchAllDomainsUseCase @Inject constructor(
Expand All @@ -10,7 +11,11 @@ class FetchAllDomainsUseCase @Inject constructor(
suspend fun execute(): AllDomains {
val result = siteStore.fetchAllDomains()
return when {
result.isError -> AllDomains.Error
result.isError -> {
AppLog.e(AppLog.T.API, "An error occurred while fetching all domains: ${result.error.message}")
AllDomains.Error
}

result.domains.isNullOrEmpty() -> AllDomains.Empty
else -> AllDomains.Success(requireNotNull(result.domains))
}
Expand All @@ -22,7 +27,7 @@ sealed interface AllDomains {
val domains: List<AllDomainsDomain>,
) : AllDomains

object Empty : AllDomains
data object Empty : AllDomains

object Error : AllDomains
data object Error : AllDomains
}
9 changes: 9 additions & 0 deletions WordPress/src/main/res/drawable/ic_dot_white_8dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<size
android:width="8dp"
android:height="8dp" />
<solid android:color="@color/white" />
</shape>
33 changes: 20 additions & 13 deletions WordPress/src/main/res/layout/domain_site_domains_card.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,15 @@
android:layout_height="wrap_content"
android:padding="@dimen/margin_extra_large">

<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/primary_site_domain_actions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_ellipsis_vertical_white_24dp"
app:tint="?attr/wpColorOnSurfaceMedium" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/site_domain_expiry_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_medium_large"
android:text="@string/domains_site_domain_never_expires"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toEndOf="@id/site_domain_status"
app:layout_constraintTop_toBottomOf="@id/primary_site_domain_chip" />

<com.google.android.material.chip.Chip
Expand All @@ -55,14 +47,29 @@
app:layout_constraintTop_toBottomOf="@+id/site_domain"
app:textStartPadding="@dimen/margin_small" />

<com.google.android.material.textview.MaterialTextView
style="?attr/textAppearanceBody2"
android:id="@+id/site_domain_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_medium_large"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_dot_white_8dp"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/primary_site_domain_chip"
tools:text="Active" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/site_domain"
style="?attr/textAppearanceSubtitle1"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/domains_site_domain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="travelwithkids.wordpress.com" />

</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.wordpress.android.BaseUnitTest
import org.wordpress.android.R
import org.wordpress.android.fluxc.model.PlanModel
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.rest.wpcom.site.AllDomainsDomain
import org.wordpress.android.fluxc.network.rest.wpcom.site.Domain
import org.wordpress.android.fluxc.store.SiteStore
import org.wordpress.android.fluxc.store.SiteStore.FetchedDomainsPayload
Expand All @@ -19,6 +20,8 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchaseDomain
import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchasePlan
import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomains
import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomainsHeader
import org.wordpress.android.ui.domains.usecases.AllDomains
import org.wordpress.android.ui.domains.usecases.FetchAllDomainsUseCase
import org.wordpress.android.ui.domains.usecases.FetchPlansUseCase
import org.wordpress.android.ui.plans.PlansConstants.FREE_PLAN_ID
import org.wordpress.android.ui.plans.PlansConstants.PREMIUM_PLAN_ID
Expand All @@ -32,6 +35,7 @@ class DomainsDashboardViewModelTest : BaseUnitTest() {
private val analyticsTracker: AnalyticsTrackerWrapper = mock()
private val htmlMessageUtils: HtmlMessageUtils = mock()
private val fetchPlansUseCase: FetchPlansUseCase = mock()
private val fetchAllDomainsUseCase: FetchAllDomainsUseCase = mock()

private lateinit var viewModel: DomainsDashboardViewModel

Expand All @@ -44,6 +48,7 @@ class DomainsDashboardViewModelTest : BaseUnitTest() {
analyticsTracker,
htmlMessageUtils,
fetchPlansUseCase,
fetchAllDomainsUseCase,
testDispatcher()
)

Expand Down Expand Up @@ -171,6 +176,8 @@ class DomainsDashboardViewModelTest : BaseUnitTest() {

val plan = if (hasDomainCredits) planWithCredits else planWithNoCredits
whenever(fetchPlansUseCase.execute(site)).thenReturn(OnPlansFetched(site, listOf(plan)))
val allDomains = if (hasCustomDomains) listOf(allDomainsDomain) else emptyList()
whenever(fetchAllDomainsUseCase.execute()).thenReturn(AllDomains.Success(allDomains))

viewModel.start(site)
}
Expand All @@ -189,6 +196,8 @@ class DomainsDashboardViewModelTest : BaseUnitTest() {
wpcomDomain = false
)

private val allDomainsDomain = AllDomainsDomain(domain = "henna.tattoo")

private val siteWithFreePlan = SiteModel().apply {
siteId = TEST_SITE_ID
url = TEST_DOMAIN_NAME
Expand Down