summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt193
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/ChipChronometerBinder.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt55
8 files changed, 263 insertions, 53 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 4993b5661373..b5cfc7e9080d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -573,6 +573,8 @@ class NotifChipsViewModelTest : SysuiTestCase() {
assertThat(latest!![0]).isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).startTimeMs)
.isEqualTo(whenElapsed)
+ assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).isEventInFuture)
+ .isFalse()
}
@Test
@@ -608,6 +610,8 @@ class NotifChipsViewModelTest : SysuiTestCase() {
assertThat(latest!![0]).isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).startTimeMs)
.isEqualTo(whenElapsed)
+ assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).isEventInFuture)
+ .isTrue()
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt
index 4e92540396d3..cd9970cfa614 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt
@@ -35,55 +35,153 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ChronometerStateTest : SysuiTestCase() {
- private lateinit var mockTimeSource: MutableTimeSource
+ private lateinit var fakeTimeSource: MutableTimeSource
@Before
fun setup() {
- mockTimeSource = MutableTimeSource()
+ fakeTimeSource = MutableTimeSource()
}
@Test
- fun initialText_isCorrect() = runTest {
- val state = ChronometerState(mockTimeSource, 0L)
- assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(0))
+ fun initialText_isEventInFutureFalse_timeIsNow() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 3_000, isEventInFuture = false)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 0))
}
@Test
- fun textUpdates_withTime() = runTest {
- val startTime = 1000L
- val state = ChronometerState(mockTimeSource, startTime)
+ fun initialText_isEventInFutureFalse_timeInPast() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 1_000, isEventInFuture = false)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 2))
+ }
+
+ @Test
+ fun initialText_isEventInFutureFalse_timeInFuture() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 5_000, isEventInFuture = false)
+ // When isEventInFuture=false, eventTimeMillis needs to be in the past if we want text to
+ // show
+ assertThat(state.currentTimeText).isNull()
+ }
+
+ @Test
+ fun initialText_isEventInFutureTrue_timeIsNow() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 3_000, isEventInFuture = true)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 0))
+ }
+
+ @Test
+ fun initialText_isEventInFutureTrue_timeInFuture() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 5_000, isEventInFuture = true)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 2))
+ }
+
+ @Test
+ fun initialText_isEventInFutureTrue_timeInPast() = runTest {
+ fakeTimeSource.time = 3_000
+ val state =
+ ChronometerState(fakeTimeSource, eventTimeMillis = 1_000, isEventInFuture = true)
+ // When isEventInFuture=true, eventTimeMillis needs to be in the future if we want text to
+ // show
+ assertThat(state.currentTimeText).isNull()
+ }
+
+ @Test
+ fun textUpdates_isEventInFutureFalse_timeInPast() = runTest {
+ val eventTime = 1000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = false)
val job = launch { state.run() }
val elapsedTime = 5000L
- mockTimeSource.time = startTime + elapsedTime
+ fakeTimeSource.time = eventTime + elapsedTime
advanceTimeBy(elapsedTime)
assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(elapsedTime / 1000))
+ val additionalTime = 6000L
+ fakeTimeSource.time += additionalTime
+ advanceTimeBy(additionalTime)
+ assertThat(state.currentTimeText)
+ .isEqualTo(formatElapsedTime((elapsedTime + additionalTime) / 1000))
+
job.cancelAndJoin()
}
@Test
- fun textUpdates_toLargerValue() = runTest {
- val startTime = 1000L
- val state = ChronometerState(mockTimeSource, startTime)
+ fun textUpdates_isEventInFutureFalse_timeChangesFromFutureToPast() = runTest {
+ val eventTime = 15_000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = false)
val job = launch { state.run() }
- val elapsedTime = 15000L
- mockTimeSource.time = startTime + elapsedTime
- advanceTimeBy(elapsedTime)
- assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(elapsedTime / 1000))
+ // WHEN the time is 5 but the eventTime is 15
+ fakeTimeSource.time = 5_000L
+ advanceTimeBy(5_000L)
+ // THEN no text is shown
+ assertThat(state.currentTimeText).isNull()
+
+ // WHEN the time advances to 40
+ fakeTimeSource.time = 40_000L
+ advanceTimeBy(35_000)
+ // THEN text is shown as 25 seconds (40 - 15)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 25))
job.cancelAndJoin()
}
@Test
- fun textUpdates_afterResettingBase() = runTest {
+ fun textUpdates_isEventInFutureTrue_timeInFuture() = runTest {
+ val eventTime = 15_000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = true)
+ val job = launch { state.run() }
+
+ fakeTimeSource.time = 5_000L
+ advanceTimeBy(5_000L)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 10))
+
+ val additionalTime = 6000L
+ fakeTimeSource.time += additionalTime
+ advanceTimeBy(additionalTime)
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 4))
+
+ job.cancelAndJoin()
+ }
+
+ @Test
+ fun textUpdates_isEventInFutureTrue_timeChangesFromFutureToPast() = runTest {
+ val eventTime = 15_000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = true)
+ val job = launch { state.run() }
+
+ // WHEN the time is 5 and the eventTime is 15
+ fakeTimeSource.time = 5_000L
+ advanceTimeBy(5_000L)
+ // THEN 10 seconds is shown
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 10))
+
+ // WHEN the time advances to 40 (past the event time)
+ fakeTimeSource.time = 40_000L
+ advanceTimeBy(35_000)
+ // THEN no text is shown
+ assertThat(state.currentTimeText).isNull()
+
+ job.cancelAndJoin()
+ }
+
+ @Test
+ fun textUpdates_afterResettingBase_isEventInFutureFalse() = runTest {
val initialElapsedTime = 30000L
val startTime = 50000L
- val state = ChronometerState(mockTimeSource, startTime)
+ val state = ChronometerState(fakeTimeSource, startTime, isEventInFuture = false)
val job = launch { state.run() }
- mockTimeSource.time = startTime + initialElapsedTime
+ fakeTimeSource.time = startTime + initialElapsedTime
advanceTimeBy(initialElapsedTime)
assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(initialElapsedTime / 1000))
@@ -91,15 +189,68 @@ class ChronometerStateTest : SysuiTestCase() {
val newElapsedTime = 5000L
val newStartTime = 100000L
- val newState = ChronometerState(mockTimeSource, newStartTime)
+ val newState = ChronometerState(fakeTimeSource, newStartTime, isEventInFuture = false)
val newJob = launch { newState.run() }
- mockTimeSource.time = newStartTime + newElapsedTime
+ fakeTimeSource.time = newStartTime + newElapsedTime
advanceTimeBy(newElapsedTime)
assertThat(newState.currentTimeText).isEqualTo(formatElapsedTime(newElapsedTime / 1000))
newJob.cancelAndJoin()
}
+
+ @Test
+ fun textUpdates_afterResettingBase_isEventInFutureTrue() = runTest {
+ val initialElapsedTime = 40_000L
+ val eventTime = 50_000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = true)
+ val job = launch { state.run() }
+
+ fakeTimeSource.time = initialElapsedTime
+ advanceTimeBy(initialElapsedTime)
+ // Time should be 50 - 40 = 10
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 10))
+
+ job.cancelAndJoin()
+
+ val newElapsedTime = 75_000L
+ val newEventTime = 100_000L
+ val newState = ChronometerState(fakeTimeSource, newEventTime, isEventInFuture = true)
+ val newJob = launch { newState.run() }
+
+ fakeTimeSource.time = newElapsedTime
+ advanceTimeBy(newElapsedTime - initialElapsedTime)
+ // Time should be 100 - 75 = 25
+ assertThat(newState.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 25))
+
+ newJob.cancelAndJoin()
+ }
+
+ @Test
+ fun textUpdates_afterResettingisEventInFuture() = runTest {
+ val initialElapsedTime = 40_000L
+ val eventTime = 50_000L
+ val state = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = true)
+ val job = launch { state.run() }
+
+ fakeTimeSource.time = initialElapsedTime
+ advanceTimeBy(initialElapsedTime)
+ // Time should be 50 - 40 = 10
+ assertThat(state.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 10))
+
+ job.cancelAndJoin()
+
+ val newElapsedTime = 70_000L
+ val newState = ChronometerState(fakeTimeSource, eventTime, isEventInFuture = false)
+ val newJob = launch { newState.run() }
+
+ fakeTimeSource.time = newElapsedTime
+ advanceTimeBy(newElapsedTime - initialElapsedTime)
+ // Time should be 70 - 50 = 20
+ assertThat(newState.currentTimeText).isEqualTo(formatElapsedTime(/* elapsedSeconds= */ 20))
+
+ newJob.cancelAndJoin()
+ }
}
/** A fake implementation of [TimeSource] that allows the caller to set the current time */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index 2fe627020ebf..06656b744a5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -141,7 +141,7 @@ constructor(
// When we're promoting notifications automatically, the `when` time set on the
// notification will likely just be set to the current time, which would cause the chip
// to always show "now". We don't want early testers to get that experience since it's
- // not what will happen at launch, so just don't show any time.
+ // not what will happen at launch, so just don't show any time.onometerstate
return OngoingActivityChipModel.Active.IconOnly(
this.key,
icon,
@@ -194,12 +194,12 @@ constructor(
}
}
is PromotedNotificationContentModel.When.Chronometer -> {
- // TODO(b/364653005): Check isCountDown and support CountDown.
return OngoingActivityChipModel.Active.Timer(
this.key,
icon,
colors,
startTimeMs = this.promotedContent.time.elapsedRealtimeMillis,
+ isEventInFuture = this.promotedContent.time.isCountDown,
onClickListenerLegacy,
clickBehavior,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/ChipChronometerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/ChipChronometerBinder.kt
index 2032ec8af78c..1eb46d8cc3d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/ChipChronometerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/ChipChronometerBinder.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.ui.binder
+import android.annotation.ElapsedRealtimeLong
import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
object ChipChronometerBinder {
@@ -25,9 +26,11 @@ object ChipChronometerBinder {
* @param startTimeMs the time this event started, relative to
* [com.android.systemui.util.time.SystemClock.elapsedRealtime]. See
* [android.widget.Chronometer.setBase].
+ * @param isCountDown see [android.widget.Chronometer.setCountDown].
*/
- fun bind(startTimeMs: Long, view: ChipChronometer) {
+ fun bind(@ElapsedRealtimeLong startTimeMs: Long, isCountDown: Boolean, view: ChipChronometer) {
view.base = startTimeMs
+ view.isCountDown = isCountDown
view.start()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
index 6f8552738d33..77e0dde3dec5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -315,7 +315,11 @@ object OngoingActivityChipBinder {
chipShortTimeDeltaView.visibility = View.GONE
}
is OngoingActivityChipModel.Active.Timer -> {
- ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
+ ChipChronometerBinder.bind(
+ chipModel.startTimeMs,
+ chipModel.isEventInFuture,
+ chipTimeView,
+ )
chipTimeView.visibility = View.VISIBLE
chipTextView.visibility = View.GONE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
index 55d753662a65..f650d8d7d10d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
@@ -74,25 +74,30 @@ fun ChipContent(viewModel: OngoingActivityChipModel.Active, modifier: Modifier =
val textMeasurer = rememberTextMeasurer()
when (viewModel) {
is OngoingActivityChipModel.Active.Timer -> {
- val timerState = rememberChronometerState(startTimeMillis = viewModel.startTimeMs)
- val text = timerState.currentTimeText
- Text(
- text = text,
- style = textStyle,
- color = textColor,
- softWrap = false,
- modifier =
- modifier
- .hideTextIfDoesNotFit(
- text = text,
- textStyle = textStyle,
- textMeasurer = textMeasurer,
- maxTextWidth = maxTextWidth,
- startPadding = startPadding,
- endPadding = endPadding,
- )
- .neverDecreaseWidth(density),
- )
+ val timerState =
+ rememberChronometerState(
+ eventTimeMillis = viewModel.startTimeMs,
+ isCountDown = viewModel.isEventInFuture,
+ )
+ timerState.currentTimeText?.let { text ->
+ Text(
+ text = text,
+ style = textStyle,
+ color = textColor,
+ softWrap = false,
+ modifier =
+ modifier
+ .hideTextIfDoesNotFit(
+ text = text,
+ textStyle = textStyle,
+ textMeasurer = textMeasurer,
+ maxTextWidth = maxTextWidth,
+ startPadding = startPadding,
+ endPadding = endPadding,
+ )
+ .neverDecreaseWidth(density),
+ )
+ }
}
is OngoingActivityChipModel.Active.Countdown -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
index 8e470742f174..106a36313190 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
@@ -105,6 +105,12 @@ sealed class OngoingActivityChipModel {
* [android.widget.Chronometer.setBase].
*/
@ElapsedRealtimeLong val startTimeMs: Long,
+ /**
+ * True if this chip represents an event starting in the future and false if this chip
+ * represents an event that has already started. If true, [startTimeMs] should be in the
+ * future. Otherwise, [startTimeMs] should be in the past.
+ */
+ val isEventInFuture: Boolean = false,
override val onClickListenerLegacy: View.OnClickListener?,
override val clickBehavior: ClickBehavior,
override val isHidden: Boolean = false,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt
index 62789782d0a9..7402583cafe2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.statusbar.chips.ui.viewmodel
+import android.annotation.ElapsedRealtimeLong
import android.os.SystemClock
import android.text.format.DateUtils.formatElapsedTime
import androidx.compose.runtime.Composable
@@ -27,6 +28,7 @@ import androidx.compose.runtime.setValue
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle
+import kotlin.math.absoluteValue
import kotlinx.coroutines.delay
/** Platform-optimized interface for getting current time */
@@ -34,18 +36,50 @@ fun interface TimeSource {
fun getCurrentTime(): Long
}
-/** Holds and manages the state for a Chronometer */
-class ChronometerState(private val timeSource: TimeSource, private val startTimeMillis: Long) {
- private var currentTimeMillis by mutableLongStateOf(0L)
+/**
+ * Holds and manages the state for a Chronometer, which shows a timer in a format like "MM:SS" or
+ * "H:MM:SS".
+ *
+ * If [isEventInFuture] is false, then this Chronometer is counting up from an event that started in
+ * the past, like a phone call that was answered. [eventTimeMillis] represents the time the event
+ * started and the timer will tick up: 04:00, 04:01, ... No timer is shown if [eventTimeMillis] is
+ * in the future and [isEventInFuture] is false.
+ *
+ * If [isEventInFuture] is true, then this Chronometer is counting down to an event that will occur
+ * in the future, like a future meeting. [eventTimeMillis] represents the time the event will occur
+ * and the timer will tick down: 04:00, 03:59, ... No timer is shown if [eventTimeMillis] is in the
+ * past and [isEventInFuture] is true.
+ */
+class ChronometerState(
+ private val timeSource: TimeSource,
+ @ElapsedRealtimeLong private val eventTimeMillis: Long,
+ private val isEventInFuture: Boolean,
+) {
+ private var currentTimeMillis by mutableLongStateOf(timeSource.getCurrentTime())
private val elapsedTimeMillis: Long
- get() = maxOf(0L, currentTimeMillis - startTimeMillis)
+ get() =
+ if (isEventInFuture) {
+ eventTimeMillis - currentTimeMillis
+ } else {
+ currentTimeMillis - eventTimeMillis
+ }
- val currentTimeText: String by derivedStateOf { formatElapsedTime(elapsedTimeMillis / 1000) }
+ /**
+ * The current timer string in a format like "MM:SS" or "H:MM:SS", or null if we shouldn't show
+ * the timer string.
+ */
+ val currentTimeText: String? by derivedStateOf {
+ if (elapsedTimeMillis < 0) {
+ null
+ } else {
+ formatElapsedTime(elapsedTimeMillis / 1000)
+ }
+ }
suspend fun run() {
while (true) {
currentTimeMillis = timeSource.getCurrentTime()
- val delaySkewMillis = (currentTimeMillis - startTimeMillis) % 1000L
+ val delaySkewMillis = (eventTimeMillis - currentTimeMillis).absoluteValue % 1000L
delay(1000L - delaySkewMillis)
}
}
@@ -54,13 +88,16 @@ class ChronometerState(private val timeSource: TimeSource, private val startTime
/** Remember and manage the ChronometerState */
@Composable
fun rememberChronometerState(
- startTimeMillis: Long,
+ eventTimeMillis: Long,
+ isCountDown: Boolean,
timeSource: TimeSource = remember { TimeSource { SystemClock.elapsedRealtime() } },
): ChronometerState {
val state =
- remember(timeSource, startTimeMillis) { ChronometerState(timeSource, startTimeMillis) }
+ remember(timeSource, eventTimeMillis, isCountDown) {
+ ChronometerState(timeSource, eventTimeMillis, isCountDown)
+ }
val lifecycleOwner = LocalLifecycleOwner.current
- LaunchedEffect(lifecycleOwner, timeSource, startTimeMillis) {
+ LaunchedEffect(lifecycleOwner, timeSource, eventTimeMillis) {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { state.run() }
}