Skip to content
558 changes: 558 additions & 0 deletions Add_WooPosEmptyScreen_component_and_refactor_empty_list_handling.patch

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.woocommerce.android.ui.woopos.common.composeui.component

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosSpacing
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTheme
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTypography
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.toAdaptivePadding

@Composable
fun WooPosEmptyScreen(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
) {
WooPosItemsEmptyListInternal(
modifier = modifier,
title = title,
message = message,
contentDescription = contentDescription,
icon = icon,
actionLabel = null,
onActionClicked = null
)
}

@Composable
fun WooPosEmptyScreen(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
actionLabel: String,
onActionClicked: (() -> Unit),
) {
WooPosItemsEmptyListInternal(
modifier = modifier,
title = title,
message = message,
contentDescription = contentDescription,
icon = icon,
actionLabel = actionLabel,
onActionClicked = onActionClicked
)
}

@Composable
private fun WooPosItemsEmptyListInternal(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
actionLabel: String?,
onActionClicked: (() -> Unit)? = null,
) {
Box(
modifier = modifier.verticalScroll(rememberScrollState()),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
modifier = Modifier.size(148.dp),
painter = icon,
contentDescription = contentDescription,
)

Spacer(modifier = Modifier.height(WooPosSpacing.XLarge.value.toAdaptivePadding()))

WooPosText(
text = title,
style = WooPosTypography.Heading,
fontWeight = FontWeight.Bold,
)

Spacer(modifier = Modifier.height(WooPosSpacing.Medium.value.toAdaptivePadding()))

WooPosText(
text = message,
style = WooPosTypography.BodyLarge,
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Center
)

Spacer(modifier = Modifier.height(WooPosSpacing.XLarge.value.toAdaptivePadding()))

if (onActionClicked != null && actionLabel != null) {
WooPosButton(
text = actionLabel,
onClick = onActionClicked,
modifier = WooPosErrorAndEmptyStateButtonModifier
)
}
}
}
}

@WooPosPreview
@Composable
fun WooPosEmptyScreenPreview() {
WooPosTheme {
WooPosEmptyScreen(
modifier = Modifier.fillMaxSize(),
title = "Empty List",
message = "This list is empty",
contentDescription = ""
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.woocommerce.android.ui.woopos.common.composeui.component

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

val WooPosErrorAndEmptyStateButtonModifier = Modifier
.fillMaxWidth(0.3f)
.height(80.dp)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand Down Expand Up @@ -38,7 +37,8 @@ fun WooPosErrorScreen(
secondaryButton: Button? = null
) {
Column(
modifier = modifier.fillMaxSize()
modifier = modifier
.fillMaxSize()
.clip(RoundedCornerShape(WooPosCornerRadius.Medium.value))
.padding(WooPosSpacing.XLarge.value.toAdaptivePadding()),
horizontalAlignment = Alignment.CenterHorizontally,
Expand Down Expand Up @@ -77,19 +77,15 @@ fun WooPosErrorScreen(
WooPosButton(
text = it.text,
onClick = it.click,
modifier = Modifier
.fillMaxWidth(.5f)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kidinov In this case (and in the empty state), the button has a narrower width in the design. Let me know if you have a better idea for how to adapt it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That changes the state on all 11 places where this component is used. If this is what Wagner's idea was, then it's fine. Overall, I think it looks ok

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to extract that constant so that changing the width will only require one change. This is because both buttons must have the same width

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I created a shared modifier here 3c3b5f4

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, make it more specific by not calling it just Button

.height(80.dp)
modifier = WooPosErrorAndEmptyStateButtonModifier
)
}
secondaryButton?.let {
Spacer(modifier = Modifier.height(WooPosSpacing.Medium.value.toAdaptivePadding()))
WooPosOutlinedButton(
text = it.text,
onClick = it.click,
modifier = Modifier
.fillMaxWidth(.5f)
.height(80.dp)
modifier = WooPosErrorAndEmptyStateButtonModifier
)
}
Spacer(modifier = Modifier.height(WooPosSpacing.Medium.value.toAdaptivePadding()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
Expand All @@ -21,9 +20,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.LocalOffer
import androidx.compose.material3.MaterialTheme
Expand All @@ -36,7 +33,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
Expand All @@ -46,15 +42,13 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview
import com.woocommerce.android.ui.woopos.common.composeui.component.ShadowType
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosButton
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosCard
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosLazyColumn
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosShimmerBox
Expand Down Expand Up @@ -533,102 +527,6 @@ private fun ItemsLoadingItem() {
}
}

@Composable
fun WooPosItemsEmptyList(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
) {
WooPosItemsEmptyListInternal(
modifier = modifier,
title = title,
message = message,
contentDescription = contentDescription,
icon = icon,
actionLabel = null,
onActionClicked = null
)
}

@Composable
fun WooPosItemsEmptyList(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
actionLabel: String,
onActionClicked: (() -> Unit),
) {
WooPosItemsEmptyListInternal(
modifier = modifier,
title = title,
message = message,
contentDescription = contentDescription,
icon = icon,
actionLabel = actionLabel,
onActionClicked = onActionClicked
)
}

@Composable
private fun WooPosItemsEmptyListInternal(
modifier: Modifier = Modifier,
title: String,
message: String,
contentDescription: String,
icon: Painter = painterResource(R.drawable.ic_woo_pos_not_found),
actionLabel: String?,
onActionClicked: (() -> Unit)? = null,
) {
Box(
modifier = modifier.verticalScroll(rememberScrollState()),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
modifier = Modifier.size(148.dp),
painter = icon,
contentDescription = contentDescription,
)

Spacer(modifier = Modifier.height(WooPosSpacing.XLarge.value.toAdaptivePadding()))

WooPosText(
text = title,
style = WooPosTypography.Heading,
fontWeight = FontWeight.Bold,
)

Spacer(modifier = Modifier.height(WooPosSpacing.Medium.value.toAdaptivePadding()))

WooPosText(
text = message,
style = WooPosTypography.BodyLarge,
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Center
)

Spacer(modifier = Modifier.height(WooPosSpacing.XLarge.value.toAdaptivePadding()))

if (onActionClicked != null && actionLabel != null) {
WooPosButton(
text = actionLabel,
onClick = onActionClicked,
modifier = Modifier
.fillMaxWidth(0.5f)
.height(80.dp)
)
}
}
}
}

@Composable
private fun InfiniteListHandler(
listState: LazyListState,
Expand Down Expand Up @@ -702,19 +600,6 @@ fun ItemListPreview() {
}
}

@WooPosPreview
@Composable
fun EmptyListPreview() {
WooPosTheme {
WooPosItemsEmptyList(
modifier = Modifier.fillMaxSize(),
title = "Empty List",
message = "This list is empty",
contentDescription = ""
)
}
}

@WooPosPreview
@Composable
fun LoadingListPreview() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview
import com.woocommerce.android.ui.woopos.common.composeui.component.Button
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosEmptyScreen
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosErrorScreen
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosPaginationErrorIndicator
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosSpacing
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTheme
import com.woocommerce.android.ui.woopos.home.items.WooPosCouponsViewState
import com.woocommerce.android.ui.woopos.home.items.WooPosItemList
import com.woocommerce.android.ui.woopos.home.items.WooPosItemSelectionViewState
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsEmptyList
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsLoadingIndicator
import com.woocommerce.android.ui.woopos.home.items.WooPosPaginationState
import com.woocommerce.android.ui.woopos.home.items.WooPosPullToRefreshState
Expand Down Expand Up @@ -92,7 +92,7 @@ private fun WooPosCouponsScreen(
modifier = Modifier.padding(top = WooPosSpacing.Large.value)
)

is WooPosCouponsViewState.Empty -> WooPosItemsEmptyList(
is WooPosCouponsViewState.Empty -> WooPosEmptyScreen(
modifier = Modifier.fillMaxSize(),
icon = painterResource(id = R.drawable.img_empty_coupon_list),
title = stringResource(id = R.string.woopos_coupons_empty_list_title),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview
import com.woocommerce.android.ui.woopos.common.composeui.component.Button
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosEmptyScreen
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosErrorScreen
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosPaginationErrorIndicator
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosSpacing
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTheme
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.toAdaptivePadding
import com.woocommerce.android.ui.woopos.home.items.WooPosItemList
import com.woocommerce.android.ui.woopos.home.items.WooPosItemSelectionViewState
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsEmptyList
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsLoadingIndicator

@Composable
Expand Down Expand Up @@ -96,7 +96,7 @@ private fun WooPosCouponsSearchScreen(
}

WooPosCouponsSearchViewState.Empty::class.java -> {
WooPosItemsEmptyList(
WooPosEmptyScreen(
modifier = Modifier
.fillMaxSize()
.padding(
Expand Down
Loading