Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerStateTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt +2 −2 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.systemui.statusbar.chips.ui.compose package com.android.systemui.statusbar.chips.ui.viewmodel import android.text.format.DateUtils.formatElapsedTime import androidx.test.ext.junit.runners.AndroidJUnit4 Loading packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt +6 −3 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier Loading @@ -47,6 +48,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth import com.android.systemui.statusbar.chips.ui.model.ColorsModel import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel import com.android.systemui.statusbar.chips.ui.viewmodel.rememberChronometerState @Composable fun OngoingActivityChip(model: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) { Loading Loading @@ -195,11 +197,12 @@ private fun ChipContent(viewModel: OngoingActivityChipModel.Shown, modifier: Mod val context = LocalContext.current when (viewModel) { is OngoingActivityChipModel.Shown.Timer -> { ChronometerText( startTimeMillis = viewModel.startTimeMs, val timerState = rememberChronometerState(startTimeMillis = viewModel.startTimeMs) Text( text = timerState.currentTimeText, style = MaterialTheme.typography.labelLarge, color = Color(viewModel.colors.text(context)), modifier = modifier, modifier = modifier.neverDecreaseWidth(), ) } Loading packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt→packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt +6 −31 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.statusbar.chips.ui.compose package com.android.systemui.statusbar.chips.ui.viewmodel import android.os.SystemClock import android.text.format.DateUtils.formatElapsedTime import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf Loading @@ -26,13 +24,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth import kotlinx.coroutines.delay /** Platform-optimized interface for getting current time */ Loading @@ -59,7 +53,10 @@ class ChronometerState(private val timeSource: TimeSource, private val startTime /** Remember and manage the ChronometerState */ @Composable fun rememberChronometerState(timeSource: TimeSource, startTimeMillis: Long): ChronometerState { fun rememberChronometerState( startTimeMillis: Long, timeSource: TimeSource = remember { TimeSource { SystemClock.elapsedRealtime() } }, ): ChronometerState { val state = remember(timeSource, startTimeMillis) { ChronometerState(timeSource, startTimeMillis) } val lifecycleOwner = LocalLifecycleOwner.current Loading @@ -69,25 +66,3 @@ fun rememberChronometerState(timeSource: TimeSource, startTimeMillis: Long): Chr return state } /** * A composable chronometer that displays elapsed time with constrained width. The width of the text * is only allowed to increase. This ensures there is no visual jitter when individual digits in the * text change due to the timer ticking. */ @Composable fun ChronometerText( startTimeMillis: Long, modifier: Modifier = Modifier, color: Color = Color.Unspecified, style: TextStyle = LocalTextStyle.current, timeSource: TimeSource = remember { TimeSource { SystemClock.elapsedRealtime() } }, ) { val state = rememberChronometerState(timeSource, startTimeMillis) Text( text = state.currentTimeText, style = style, color = color, modifier = modifier.neverDecreaseWidth(), ) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerStateTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerStateTest.kt +2 −2 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.systemui.statusbar.chips.ui.compose package com.android.systemui.statusbar.chips.ui.viewmodel import android.text.format.DateUtils.formatElapsedTime import androidx.test.ext.junit.runners.AndroidJUnit4 Loading
packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt +6 −3 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier Loading @@ -47,6 +48,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth import com.android.systemui.statusbar.chips.ui.model.ColorsModel import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel import com.android.systemui.statusbar.chips.ui.viewmodel.rememberChronometerState @Composable fun OngoingActivityChip(model: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) { Loading Loading @@ -195,11 +197,12 @@ private fun ChipContent(viewModel: OngoingActivityChipModel.Shown, modifier: Mod val context = LocalContext.current when (viewModel) { is OngoingActivityChipModel.Shown.Timer -> { ChronometerText( startTimeMillis = viewModel.startTimeMs, val timerState = rememberChronometerState(startTimeMillis = viewModel.startTimeMs) Text( text = timerState.currentTimeText, style = MaterialTheme.typography.labelLarge, color = Color(viewModel.colors.text(context)), modifier = modifier, modifier = modifier.neverDecreaseWidth(), ) } Loading
packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt→packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChronometerState.kt +6 −31 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.statusbar.chips.ui.compose package com.android.systemui.statusbar.chips.ui.viewmodel import android.os.SystemClock import android.text.format.DateUtils.formatElapsedTime import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf Loading @@ -26,13 +24,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth import kotlinx.coroutines.delay /** Platform-optimized interface for getting current time */ Loading @@ -59,7 +53,10 @@ class ChronometerState(private val timeSource: TimeSource, private val startTime /** Remember and manage the ChronometerState */ @Composable fun rememberChronometerState(timeSource: TimeSource, startTimeMillis: Long): ChronometerState { fun rememberChronometerState( startTimeMillis: Long, timeSource: TimeSource = remember { TimeSource { SystemClock.elapsedRealtime() } }, ): ChronometerState { val state = remember(timeSource, startTimeMillis) { ChronometerState(timeSource, startTimeMillis) } val lifecycleOwner = LocalLifecycleOwner.current Loading @@ -69,25 +66,3 @@ fun rememberChronometerState(timeSource: TimeSource, startTimeMillis: Long): Chr return state } /** * A composable chronometer that displays elapsed time with constrained width. The width of the text * is only allowed to increase. This ensures there is no visual jitter when individual digits in the * text change due to the timer ticking. */ @Composable fun ChronometerText( startTimeMillis: Long, modifier: Modifier = Modifier, color: Color = Color.Unspecified, style: TextStyle = LocalTextStyle.current, timeSource: TimeSource = remember { TimeSource { SystemClock.elapsedRealtime() } }, ) { val state = rememberChronometerState(timeSource, startTimeMillis) Text( text = state.currentTimeText, style = style, color = color, modifier = modifier.neverDecreaseWidth(), ) }