From 7581b05b97ce1a35752eeb111a51e2e9f5508afb Mon Sep 17 00:00:00 2001 From: Ray <154766448+damontecres@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:25:36 -0500 Subject: [PATCH] Move time tracking into a CompositionLocal (#493) ## Description Creates a `CompositionLocal` which tracks the current time in a single place and is usable anywhere in the app. Can be used such as: ```kotlin val now = LocalClock.current.now val details = remember(item, now) { // Create detail strings based the item and current time // This will be recomposed/updated whenever the time changes } ``` ### Related issues Related to #475 --- .../damontecres/wholphin/MainActivity.kt | 17 ++++---- .../wholphin/ui/components/TimeDisplay.kt | 19 +-------- .../wholphin/ui/util/LocalClock.kt | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/github/damontecres/wholphin/ui/util/LocalClock.kt diff --git a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt index ef90f38a..52a63020 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt @@ -47,6 +47,7 @@ import com.github.damontecres.wholphin.ui.launchIO import com.github.damontecres.wholphin.ui.nav.ApplicationContent import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.theme.WholphinTheme +import com.github.damontecres.wholphin.ui.util.ProvideLocalClock import com.github.damontecres.wholphin.util.DebugLogTree import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers @@ -222,13 +223,15 @@ class MainActivity : AppCompatActivity() { ) } } - ApplicationContent( - user = current?.user, - server = current?.server, - navigationManager = navigationManager, - preferences = preferences, - modifier = Modifier.fillMaxSize(), - ) + ProvideLocalClock { + ApplicationContent( + user = current?.user, + server = current?.server, + navigationManager = navigationManager, + preferences = preferences, + modifier = Modifier.fillMaxSize(), + ) + } } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/TimeDisplay.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/TimeDisplay.kt index 54c2d75c..79bd2f73 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/TimeDisplay.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/TimeDisplay.kt @@ -3,33 +3,18 @@ package com.github.damontecres.wholphin.ui.components import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text -import com.github.damontecres.wholphin.ui.TimeFormatter -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import java.time.LocalTime +import com.github.damontecres.wholphin.ui.util.LocalClock @Composable fun BoxScope.TimeDisplay(modifier: Modifier = Modifier) { - var now by remember { mutableStateOf(LocalTime.now()) } - LaunchedEffect(Unit) { - while (isActive) { - now = LocalTime.now() - delay(1000L) - } - } Text( - text = TimeFormatter.format(now), + text = LocalClock.current.timeString, fontSize = 18.sp, color = MaterialTheme.colorScheme.onSurface, modifier = diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/util/LocalClock.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/util/LocalClock.kt new file mode 100644 index 00000000..53cd4d9b --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/util/LocalClock.kt @@ -0,0 +1,42 @@ +package com.github.damontecres.wholphin.ui.util + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import com.github.damontecres.wholphin.ui.TimeFormatter +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import java.time.LocalDateTime + +val LocalClock = compositionLocalOf { throw IllegalStateException() } + +/** + * Represents the current time + */ +data class Clock( + /** + * The current [LocalDateTime] + */ + val now: LocalDateTime, + /** + * The current time formatted as a string with [TimeFormatter] + */ + val timeString: String, +) + +@Composable +fun ProvideLocalClock(content: @Composable () -> Unit) { + var clock by remember { mutableStateOf(LocalDateTime.now().let { Clock(it, TimeFormatter.format(it)) }) } + LaunchedEffect(Unit) { + while (isActive) { + clock = LocalDateTime.now().let { Clock(it, TimeFormatter.format(it)) } + delay(1_000) + } + } + CompositionLocalProvider(LocalClock provides clock, content) +}