Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4132fea6 authored by Andre Le's avatar Andre Le Committed by Android (Google) Code Review
Browse files

Merge "StatusBarDate: Add date on the status bar for the desktop experience" into main

parents ed8c9395 641c72d0
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ class StatusBarBoundsViewModelTest : SysuiTestCase() {
        }

    @Test
    fun clockBounds_getsUpdatedBounds() =
    fun clockBounds_getsUpdatedWhenClockBoundsChanged() =
        kosmos.runTest {
            val firstRect = Rect(1, 2, 3, 4)
            clockBounds = firstRect
@@ -139,4 +139,18 @@ class StatusBarBoundsViewModelTest : SysuiTestCase() {

            assertThat(underTest.clockBounds).isEqualTo(newRect)
        }

    @Test
    fun dateBounds_getsUpdatedWhenUpdateDateBoundsCalled() =
        kosmos.runTest {
            val firstRect = Rect(1, 2, 3, 4)
            underTest.updateDateBounds(firstRect)

            assertThat(underTest.dateBounds).isEqualTo(firstRect)

            val newRect = Rect(5, 6, 7, 8)
            underTest.updateDateBounds(newRect)

            assertThat(underTest.dateBounds).isEqualTo(newRect)
        }
}
+86 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = emptyList(),
                startSideContainerBounds = rect(left = 10, right = 100, top = 0, bottom = 50),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -43,12 +44,29 @@ class ChipsMaxWidthTest : SysuiTestCase() {
        assertThat(result).isEqualTo(70.dp)
    }

    @Test
    fun chipsMaxWidth_ltr_withDate_usesDateAndStartSideContainerBounds() {
        val result =
            chipsMaxWidth(
                appHandles = emptyList(),
                startSideContainerBounds = rect(left = 10, right = 100, top = 0, bottom = 50),
                dateBounds = rect(left = 30, right = 60, top = 0, bottom = 50),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
            )

        // 60 -> 100
        assertThat(result).isEqualTo(40.dp)
    }

    @Test
    fun chipsMaxWidth_rtl_noAppHandles_usesClockAndStartSideContainerBounds() {
        val result =
            chipsMaxWidth(
                appHandles = emptyList(),
                startSideContainerBounds = rect(left = 1000, right = 1400, top = 0, bottom = 50),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -58,12 +76,29 @@ class ChipsMaxWidthTest : SysuiTestCase() {
        assertThat(result).isEqualTo(350.dp)
    }

    @Test
    fun chipsMaxWidth_rtl_withDates_noAppHandles_usesClockAndStartSideContainerBounds() {
        val result =
            chipsMaxWidth(
                appHandles = emptyList(),
                startSideContainerBounds = rect(left = 1000, right = 1400, top = 0, bottom = 50),
                dateBounds = rect(left = 1200, right = 1350, top = 0, bottom = 50),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
            )

        // 1000 <- 1200
        assertThat(result).isEqualTo(200.dp)
    }

    @Test
    fun chipsMaxWidth_ltr_oneAppHandle_yOutside_usesClockAndStartSideContainerBounds() {
        val result =
            chipsMaxWidth(
                appHandles = listOf(rect(top = 100, bottom = 150, left = 80, right = 120)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -80,6 +115,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 100, bottom = 150, left = 800, right = 1200)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -96,6 +132,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 10, bottom = 40, left = 120, right = 200)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -112,6 +149,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 10, bottom = 40, left = 600, right = 800)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -128,6 +166,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 0, bottom = 0, left = 0, right = 0)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -143,6 +182,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 1400, bottom = 1400, left = 1400, right = 1400)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -158,6 +198,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 10, bottom = 40, left = 80, right = 120)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -167,12 +208,29 @@ class ChipsMaxWidthTest : SysuiTestCase() {
        assertThat(result).isEqualTo(50.dp)
    }

    @Test
    fun chipsMaxWidth_withDateBounds_ltr_oneAppHandle_closerThanStartSideEnd_usesAppHandleBounds() {
        val result =
            chipsMaxWidth(
                appHandles = listOf(rect(top = 10, bottom = 40, left = 80, right = 120)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = rect(left = 30, right = 45, top = 0, bottom = 50),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
            )

        // 45 -> 80, 80 from app handle
        assertThat(result).isEqualTo(35.dp)
    }

    @Test
    fun chipsMaxWidth_rtl_oneAppHandle_closerThanStartSideEnd_usesAppHandleBounds() {
        val result =
            chipsMaxWidth(
                appHandles = listOf(rect(left = 800, right = 1100, top = 10, bottom = 40)),
                startSideContainerBounds = rect(left = 1000, right = 1400, top = 0, bottom = 50),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -182,6 +240,22 @@ class ChipsMaxWidthTest : SysuiTestCase() {
        assertThat(result).isEqualTo(250.dp)
    }

    @Test
    fun chipsMaxWidth_withDateBounds_rtl_oneAppHandle_closerThanStartSideEnd_usesAppHandleBounds() {
        val result =
            chipsMaxWidth(
                appHandles = listOf(rect(left = 800, right = 1100, top = 10, bottom = 40)),
                startSideContainerBounds = rect(left = 1000, right = 1400, top = 0, bottom = 50),
                dateBounds = rect(left = 1200, right = 1350, top = 0, bottom = 50),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
            )

        // 1100 <- 1200, 1100 from app handle
        assertThat(result).isEqualTo(100.dp)
    }

    @Test
    fun chipsMaxWidth_ltr_oneAppHandle_yOverlapsWithTopOnly_usesAppHandleBounds() {
        val result =
@@ -192,6 +266,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 40, bottom = 80, left = 80, right = 120)
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -211,6 +286,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 40, bottom = 80, left = 800, right = 1100)
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -230,6 +306,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 0, bottom = 40, left = 80, right = 120)
                    ),
                startSideContainerBounds = rect(top = 10, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -249,6 +326,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 0, bottom = 40, left = 800, right = 1100)
                    ),
                startSideContainerBounds = rect(top = 10, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -270,6 +348,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 10, bottom = 40, left = 90, right = 120),
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -291,6 +370,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 10, bottom = 40, left = 1300, right = 1450),
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1600),
                dateBounds = Rect(),
                clockBounds = rect(left = 1550, right = 1600, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -314,6 +394,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 10, bottom = 40, left = 90, right = 120),
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 10, right = 100),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 1f,
@@ -337,6 +418,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(top = 100, bottom = 200, left = 1300, right = 1450),
                    ),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1600),
                dateBounds = Rect(),
                clockBounds = rect(top = 0, bottom = 50, left = 1550, right = 1600),
                isRtl = true,
                density = 1f,
@@ -356,6 +438,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                        rect(left = 80, right = 120, top = 10, bottom = 40)
                    ),
                // Clock ends at 100
                dateBounds = Rect(),
                clockBounds = rect(left = 0, right = 100, top = 0, bottom = 50),
                startSideContainerBounds = rect(left = 0, right = 200, top = 0, bottom = 50),
                isRtl = false,
@@ -377,6 +460,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
                    ),
                startSideContainerBounds = rect(left = 800, right = 1300, top = 0, bottom = 50),
                // Clock starts at 1200
                dateBounds = Rect(),
                clockBounds = rect(left = 1200, right = 1300, top = 0, bottom = 50),
                isRtl = true,
                density = 1f,
@@ -392,6 +476,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(left = 80, right = 120, top = 10, bottom = 40)),
                startSideContainerBounds = rect(left = 10, right = 100, top = 0, bottom = 50),
                dateBounds = Rect(),
                clockBounds = rect(left = 10, right = 30, top = 0, bottom = 50),
                isRtl = false,
                density = 5f,
@@ -407,6 +492,7 @@ class ChipsMaxWidthTest : SysuiTestCase() {
            chipsMaxWidth(
                appHandles = listOf(rect(top = 10, bottom = 40, left = 800, right = 1100)),
                startSideContainerBounds = rect(top = 0, bottom = 50, left = 1000, right = 1400),
                dateBounds = Rect(),
                clockBounds = rect(left = 1350, right = 1400, top = 0, bottom = 50),
                isRtl = true,
                density = 10f,
+16 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn

@@ -70,6 +71,17 @@ constructor(
            source = _startSideContainerBounds,
        )

    private val _dateBounds = MutableStateFlow(Rect())

    /** The on-screen bounds of the status bar date. This is a hydrated value. */
    // TODO(b/390204943): Re-implement this in Compose once the Clock is a Composable.
    val dateBounds: Rect by
        hydrator.hydratedStateOf(
            traceName = "StatusBar.dateBounds",
            initialValue = Rect(),
            source = _dateBounds,
        )

    private val _clockBounds: Flow<Rect> =
        conflatedCallbackFlow {
                val layoutListener =
@@ -94,6 +106,10 @@ constructor(
        hydrator.activate()
    }

    fun updateDateBounds(bounds: Rect) {
        _dateBounds.value = bounds
    }

    @AssistedFactory
    interface Factory {
        fun create(startSideContainerView: View, clockView: Clock): StatusBarBoundsViewModel
+62 −7
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.layout.wrapContentWidth
@@ -33,6 +34,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
@@ -43,7 +46,11 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.android.compose.theme.PlatformTheme
import com.android.compose.theme.colorAttr
import com.android.keyguard.AlphaOptimizedLinearLayout
import com.android.systemui.Flags
import com.android.systemui.clock.ui.viewmodel.AmPmStyle
import com.android.systemui.clock.ui.viewmodel.ClockViewModel
import com.android.systemui.compose.modifiers.sysUiResTagContainer
import com.android.systemui.display.dagger.SystemUIDisplaySubcomponent.DisplayAware
import com.android.systemui.lifecycle.WindowLifecycleState
@@ -56,6 +63,7 @@ import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.dagger.MediaModule.POPUP
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.shade.ui.composable.VariableDayDate
import com.android.systemui.statusbar.StatusBarAlwaysUseRegionSampling
import com.android.systemui.statusbar.chips.ui.compose.OngoingActivityChips
import com.android.systemui.statusbar.core.NewStatusBarIcons
@@ -101,6 +109,7 @@ class StatusBarRootFactory
constructor(
    private val notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
    private val iconViewStoreFactory: ConnectedDisplaysStatusBarNotificationIconViewStore.Factory,
    private val clockViewModelFactory: ClockViewModel.Factory,
    private val darkIconManagerFactory: DarkIconManager.Factory,
    private val iconController: StatusBarIconController,
    private val ongoingCallController: OngoingCallController,
@@ -123,6 +132,7 @@ constructor(
                        statusBarViewBinder = homeStatusBarViewBinder,
                        notificationIconsBinder = notificationIconsBinder,
                        iconViewStoreFactory = iconViewStoreFactory,
                        clockViewModelFactory = clockViewModelFactory,
                        darkIconManagerFactory = darkIconManagerFactory,
                        iconController = iconController,
                        ongoingCallController = ongoingCallController,
@@ -160,6 +170,7 @@ fun StatusBarRoot(
    statusBarViewBinder: HomeStatusBarViewBinder,
    notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
    iconViewStoreFactory: ConnectedDisplaysStatusBarNotificationIconViewStore.Factory,
    clockViewModelFactory: ClockViewModel.Factory,
    darkIconManagerFactory: DarkIconManager.Factory,
    iconController: StatusBarIconController,
    ongoingCallController: OngoingCallController,
@@ -200,8 +211,9 @@ fun StatusBarRoot(
                inflater.inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView

            if (StatusBarChipsModernization.isEnabled) {
                addStartSideChipsComposable(
                addStartSideComposable(
                    phoneStatusBarView = phoneStatusBarView,
                    clockViewModelFactory = clockViewModelFactory,
                    statusBarViewModel = statusBarViewModel,
                    iconViewStore = iconViewStore,
                    appHandlesViewModel = appHandlesViewModel,
@@ -336,8 +348,9 @@ fun StatusBarRoot(
}

/** Adds the composable chips shown on the start side of the status bar. */
private fun addStartSideChipsComposable(
private fun addStartSideComposable(
    phoneStatusBarView: PhoneStatusBarView,
    clockViewModelFactory: ClockViewModel.Factory,
    statusBarViewModel: HomeStatusBarViewModel,
    iconViewStore: NotificationIconContainerViewBinder.IconViewStore?,
    appHandlesViewModel: AppHandlesViewModel,
@@ -351,11 +364,18 @@ private fun addStartSideChipsComposable(

    val composeView =
        ComposeView(context).apply {
            val showDate = Flags.statusBarDate() && statusBarViewModel.isDesktopStatusBarEnabled

            layoutParams =
                LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.WRAP_CONTENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT,
                    )
                    .apply {
                        if (showDate) {
                            gravity = android.view.Gravity.CENTER_VERTICAL
                        }
                    }

            setContent {
                val statusBarBoundsViewModel =
@@ -365,6 +385,33 @@ private fun addStartSideChipsComposable(
                            clockView = clockView,
                        )
                    }

                if (showDate) {
                    val clockViewModel =
                        rememberViewModel("HomeStatusBar.Clock") {
                            clockViewModelFactory.create(AmPmStyle.Gone)
                        }
                    VariableDayDate(
                        longerDateText = clockViewModel.longerDateText,
                        shorterDateText = clockViewModel.shorterDateText,
                        textColor = colorAttr(R.attr.wallpaperTextColor),
                        modifier =
                            Modifier.padding(horizontal = 4.dp)
                                .wrapContentSize()
                                .onGloballyPositioned { coordinates ->
                                    val boundsInWindow = coordinates.boundsInWindow()
                                    val bounds =
                                        Rect(
                                            boundsInWindow.left.toInt(),
                                            boundsInWindow.top.toInt(),
                                            boundsInWindow.right.toInt(),
                                            boundsInWindow.bottom.toInt(),
                                        )
                                    statusBarBoundsViewModel.updateDateBounds(bounds)
                                },
                    )
                }

                val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
                val density = context.resources.displayMetrics.density

@@ -372,6 +419,7 @@ private fun addStartSideChipsComposable(
                    remember(
                        appHandlesViewModel.appHandleBounds,
                        statusBarBoundsViewModel.startSideContainerBounds,
                        statusBarBoundsViewModel.dateBounds,
                        statusBarBoundsViewModel.clockBounds,
                        isRtl,
                        density,
@@ -380,6 +428,7 @@ private fun addStartSideChipsComposable(
                            appHandles = appHandlesViewModel.appHandleBounds,
                            startSideContainerBounds =
                                statusBarBoundsViewModel.startSideContainerBounds,
                            dateBounds = statusBarBoundsViewModel.dateBounds,
                            clockBounds = statusBarBoundsViewModel.clockBounds,
                            isRtl = isRtl,
                            density = density,
@@ -415,6 +464,7 @@ private fun addStartSideChipsComposable(
fun chipsMaxWidth(
    appHandles: List<Rect>,
    startSideContainerBounds: Rect,
    dateBounds: Rect,
    clockBounds: Rect,
    isRtl: Boolean,
    density: Float,
@@ -424,19 +474,24 @@ fun chipsMaxWidth(
            .filterNot { it.isEmpty }
            // Only care about app handles in the same possible region as the chips
            .filter { Rect.intersects(it, startSideContainerBounds) }

    // The chips should be next to the date if it is showing, otherwise they should be next to the
    // clock.
    val clockOrDateBounds = if (dateBounds.isEmpty) clockBounds else dateBounds

    val widthInPx =
        if (isRtl) {
                val chipsLeftBasedOnAppHandles =
                    relevantAppHandles.maxOfOrNull { it.right } ?: Int.MIN_VALUE
                val chipsLeftBasedOnContainer = startSideContainerBounds.left
                val chipsLeft = maxOf(chipsLeftBasedOnAppHandles, chipsLeftBasedOnContainer)
                /* width= */ clockBounds.left - chipsLeft
                /* width= */ clockOrDateBounds.left - chipsLeft
            } else { // LTR
                val chipsRightBasedOnAppHandles =
                    relevantAppHandles.minOfOrNull { it.left } ?: Int.MAX_VALUE
                val chipsRightBasedOnContainer = startSideContainerBounds.right
                val chipsRight = minOf(chipsRightBasedOnAppHandles, chipsRightBasedOnContainer)
                /* width= */ chipsRight - clockBounds.right
                /* width= */ chipsRight - clockOrDateBounds.right
            }
            .coerceAtLeast(0)

+13 −0
Original line number Diff line number Diff line
@@ -28,3 +28,16 @@ val Kosmos.clockViewModel: ClockViewModel by
            amPmStyle = AmPmStyle.Shown,
        )
    }

var Kosmos.clockViewModelFactory: ClockViewModel.Factory by
    Kosmos.Fixture {
        object : ClockViewModel.Factory {
            override fun create(amPmStyle: AmPmStyle): ClockViewModel {
                return ClockViewModel(
                    clockInteractor = clockInteractor,
                    dateFormatUtil = dateFormatUtil,
                    amPmStyle = amPmStyle,
                )
            }
        }
    }
Loading