Skip to content
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

[2 pane layout] Tablet mode detection logic change #13228

Merged
merged 10 commits into from
Jan 30, 2025
2 changes: 2 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*** For entries which are touching the Android Wear app's, start entry with `[WEAR]` too.
21.6
-----
- [*] Updated tablet detection logic to consider both width and height dimensions, enhancing compatibility with larger phones and tablets, particularly in landscape mode [https://github.com/woocommerce/woocommerce-android/pull/13228]

- [**] The UK customers have access to the POS now [https://github.com/woocommerce/woocommerce-android/pull/13386]
- [Internal] [*] Fixed a bug that could lead to a crash when formatting dates and times [https://github.com/woocommerce/woocommerce-android/pull/13393]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ package com.woocommerce.android.analytics
import android.content.Context
import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_DEVICE_TYPE_COMPACT
import com.woocommerce.android.analytics.AnalyticsTracker.Companion.VALUE_DEVICE_TYPE_REGULAR
import com.woocommerce.android.extensions.WindowSizeClass
import com.woocommerce.android.extensions.windowSizeClass
import com.woocommerce.android.extensions.isTwoPanesShouldBeUsed

val Context.deviceTypeToAnalyticsString: String
get() = buildAnalyticsDeviceTypeValue(
IsScreenLargerThanCompactValue(value = windowSizeClass != WindowSizeClass.Compact)
IsScreenInTwoPaneLayout(value = isTwoPanesShouldBeUsed)
)

val IsScreenLargerThanCompactValue.deviceTypeToAnalyticsString: String
val IsScreenInTwoPaneLayout.deviceTypeToAnalyticsString: String
get() = buildAnalyticsDeviceTypeValue(this)

private fun buildAnalyticsDeviceTypeValue(isScreenSizeLargerThanCompact: IsScreenLargerThanCompactValue) =
if (isScreenSizeLargerThanCompact.value) {
VALUE_DEVICE_TYPE_REGULAR
private fun buildAnalyticsDeviceTypeValue(isScreenInTwoPaneLayout: IsScreenInTwoPaneLayout) =
// Keeping the value as it is to maintain backward compatibility with the existing analytics data
if (isScreenInTwoPaneLayout.value) {
VALUE_DEVICE_TYPE_REGULAR // 2 pane layout
} else {
VALUE_DEVICE_TYPE_COMPACT
VALUE_DEVICE_TYPE_COMPACT // Single pane layout
}

@JvmInline
value class IsScreenLargerThanCompactValue(val value: Boolean)
value class IsScreenInTwoPaneLayout(val value: Boolean)
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,29 @@ import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import com.woocommerce.android.util.SystemVersionUtils
import kotlinx.parcelize.Parcelize
import kotlin.math.max
import kotlin.math.min

val Context.windowSizeClass: WindowSizeClass
get() = determineWindowWidthSizeClassByGivenSize(resources.configuration.screenWidthDp)
val Context.isTwoPanesShouldBeUsed: Boolean
get() = determineIfTwoPanesShouldBeUsed(
resources.configuration.screenWidthDp,
resources.configuration.screenHeightDp
)

val Context.windowHeightSizeClass: WindowSizeClass
get() = determineWindowHeightSizeClassByGivenSize(resources.configuration.screenHeightDp)

private fun determineWindowWidthSizeClassByGivenSize(sizeDp: Int): WindowSizeClass {
return when {
sizeDp < WindowSizeClass.Compact.maxWidthDp -> WindowSizeClass.Compact
sizeDp < WindowSizeClass.Medium.maxWidthDp -> WindowSizeClass.Medium
else -> WindowSizeClass.ExpandedAndBigger
}
private const val MIN_SCREEN_SHORT_SIZE_DP = 674
private const val MIN_SCREEN_LONG_SIZE_DP = 800

private fun determineIfTwoPanesShouldBeUsed(widthDp: Int, heightDp: Int): Boolean {
val minScreenShortSizeDP = MIN_SCREEN_SHORT_SIZE_DP
val minScreenLongSizeDP = MIN_SCREEN_LONG_SIZE_DP

val shortSize = min(widthDp, heightDp)
val longSize = max(widthDp, heightDp)

return shortSize >= minScreenShortSizeDP && longSize >= minScreenLongSizeDP
}

private fun determineWindowHeightSizeClassByGivenSize(sizeDp: Int): WindowSizeClass {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,15 @@ import com.woocommerce.android.R
import com.woocommerce.android.databinding.FragmentOrderCreateEditFormBinding
import com.woocommerce.android.databinding.LayoutOrderCreationCustomerInfoBinding
import com.woocommerce.android.databinding.OrderCreationAdditionalInfoCollectionSectionBinding
import com.woocommerce.android.extensions.WindowSizeClass
import com.woocommerce.android.extensions.handleDialogNotice
import com.woocommerce.android.extensions.handleDialogResult
import com.woocommerce.android.extensions.handleResult
import com.woocommerce.android.extensions.hide
import com.woocommerce.android.extensions.isNotNullOrEmpty
import com.woocommerce.android.extensions.isTwoPanesShouldBeUsed
import com.woocommerce.android.extensions.navigateSafely
import com.woocommerce.android.extensions.show
import com.woocommerce.android.extensions.takeIfNotEqualTo
import com.woocommerce.android.extensions.windowSizeClass
import com.woocommerce.android.model.Address
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.barcodescanner.BarcodeScanningFragment
Expand Down Expand Up @@ -119,7 +118,6 @@ class OrderCreateEditFormFragment :
BackPressListener {
private companion object {
private const val TABLET_PANES_WIDTH_RATIO = 0.5F
private const val XL_TABLET_PANES_WIDTH_RATIO = 0.6F
}
private val viewModel by fixedHiltNavGraphViewModels<OrderCreateEditViewModel>(R.id.nav_graph_order_creations)
private val sharedViewModel: ProductSelectorSharedViewModel by activityViewModels()
Expand Down Expand Up @@ -171,8 +169,8 @@ class OrderCreateEditFormFragment :
viewModel.addCoupon(it)
}
handleTaxRateSelectionResult()
viewModel.onDeviceConfigurationChanged(requireContext().windowSizeClass)
if (requireContext().windowSizeClass != WindowSizeClass.Compact) syncSelectedItems()
viewModel.onDeviceConfigurationChanged(requireContext().isTwoPanesShouldBeUsed)
if (requireContext().isTwoPanesShouldBeUsed) syncSelectedItems()
}

private fun syncSelectedItems() {
Expand Down Expand Up @@ -229,13 +227,12 @@ class OrderCreateEditFormFragment :
}

private fun FragmentOrderCreateEditFormBinding.adjustUIForScreenSize() {
productSelectorNavContainer.isVisible = requireContext().windowSizeClass != WindowSizeClass.Compact
when (requireContext().windowSizeClass) {
WindowSizeClass.Compact -> twoPaneLayoutGuideline.setGuidelinePercent(0.0f)
WindowSizeClass.Medium -> twoPaneLayoutGuideline.setGuidelinePercent(TABLET_PANES_WIDTH_RATIO)
WindowSizeClass.ExpandedAndBigger -> twoPaneLayoutGuideline.setGuidelinePercent(XL_TABLET_PANES_WIDTH_RATIO)
productSelectorNavContainer.isVisible = requireContext().isTwoPanesShouldBeUsed
when (requireContext().isTwoPanesShouldBeUsed) {
false -> twoPaneLayoutGuideline.setGuidelinePercent(0.0f)
true -> twoPaneLayoutGuideline.setGuidelinePercent(TABLET_PANES_WIDTH_RATIO)
}
setupToolbars(requireContext().windowSizeClass != WindowSizeClass.Compact)
setupToolbars(requireContext().isTwoPanesShouldBeUsed)
}

private fun FragmentOrderCreateEditFormBinding.setupToolbars(isTablet: Boolean) {
Expand Down Expand Up @@ -605,7 +602,7 @@ class OrderCreateEditFormFragment :
binding.productsSection.hideAddProductsHeaderActions()
binding.productsSection.hideHeader()
binding.productsSection.content = null
if (requireContext().windowSizeClass == WindowSizeClass.Compact) {
if (!requireContext().isTwoPanesShouldBeUsed) {
binding.productsSection.setProductSectionButtons(
addProductsButton = AddButton(
text = getString(R.string.order_creation_add_products),
Expand All @@ -631,7 +628,7 @@ class OrderCreateEditFormFragment :
private fun productAddedCustomAmountUnset(binding: FragmentOrderCreateEditFormBinding) {
val isEditable = viewModel.viewStateData.liveData.value?.isEditable == true
if (isEditable) {
if (requireContext().windowSizeClass == WindowSizeClass.Compact) {
if (!requireContext().isTwoPanesShouldBeUsed) {
binding.productsSection.showAddProductsHeaderActions()
} else {
binding.productsSection.hideAddProductsHeaderActions()
Expand Down Expand Up @@ -662,7 +659,7 @@ class OrderCreateEditFormFragment :
binding.customAmountsSection.removeCustomSectionButtons()
binding.customAmountsSection.showHeader()
if (viewModel.viewStateData.liveData.value?.isEditable == true) {
if (requireContext().windowSizeClass == WindowSizeClass.Compact) {
if (!requireContext().isTwoPanesShouldBeUsed) {
binding.productsSection.showAddProductsHeaderActions()
} else {
binding.productsSection.hideAddProductsHeaderActions()
Expand All @@ -684,7 +681,7 @@ class OrderCreateEditFormFragment :
}

private fun FragmentOrderCreateEditFormBinding.renderDefaultProductsSectionButtons() {
if (requireContext().windowSizeClass == WindowSizeClass.Compact) {
if (!requireContext().isTwoPanesShouldBeUsed) {
productsSection.setProductSectionButtons(
addProductsButton = AddButton(
text = getString(R.string.order_creation_add_products),
Expand Down Expand Up @@ -1223,7 +1220,7 @@ class OrderCreateEditFormFragment :
}

is OnSelectedProductsSyncRequested -> {
if (requireContext().windowSizeClass != WindowSizeClass.Compact) {
if (requireContext().isTwoPanesShouldBeUsed) {
sharedViewModel.selectedItems.value.let { viewModel.onProductsSelected(it) }
}
}
Expand Down Expand Up @@ -1310,7 +1307,7 @@ class OrderCreateEditFormFragment :
isEachAddButtonEnabled = true
content.customAmountAdapter?.isLocked = false
}
if (requireContext().windowSizeClass != WindowSizeClass.Compact) {
if (requireContext().isTwoPanesShouldBeUsed) {
sharedViewModel.onProductSelectionStateChanged(true)
}
}
Expand Down Expand Up @@ -1340,7 +1337,7 @@ class OrderCreateEditFormFragment :
isEachAddButtonEnabled = false
content.customAmountAdapter?.isLocked = true
}
if (requireContext().windowSizeClass != WindowSizeClass.Compact) {
if (requireContext().isTwoPanesShouldBeUsed) {
sharedViewModel.onProductSelectionStateChanged(false)
}
}
Expand Down
Loading