diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideCurrentTime.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideCurrentTime.kt index 80013074..a00b0c66 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideCurrentTime.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideCurrentTime.kt @@ -1,13 +1,9 @@ package de.mm20.launcher2.ui.base -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.snap -import androidx.compose.animation.core.tween +import android.os.Handler +import android.os.Looper +import android.os.SystemClock +import android.util.Log import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -16,13 +12,15 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.awaitCancellation import java.time.Instant import java.time.ZoneId +import kotlin.math.max + /** * Provide the current time (in millis) to the LocalTime composition local. @@ -31,64 +29,38 @@ import java.time.ZoneId @Composable fun ProvideCurrentTime(content: @Composable () -> Unit) { - val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current var time by remember { mutableLongStateOf(System.currentTimeMillis()) } - val secondsAnimation = remember { Animatable(0f) } - - LaunchedEffect(time) { - val currentTime = System.currentTimeMillis() - val seconds = Instant - .ofEpochMilli(currentTime) - .atZone(ZoneId.systemDefault()).second - val millis = (currentTime % 1000).toInt() - secondsAnimation.animateTo(seconds.toFloat() + millis / 1000f, snap()) - secondsAnimation.animateTo( - 60f, - tween( - (60 - seconds) * 1000 - millis, - delayMillis = millis, - easing = LinearEasing - ) - ) - } - - val lifecycleOwner = LocalLifecycleOwner.current LaunchedEffect(null) { - lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { - val dateTime = Instant.ofEpochMilli(System.currentTimeMillis()) - .atZone(ZoneId.systemDefault()) - .withSecond(0) - .withNano(0) + val handler = Handler(Looper.getMainLooper()) + val runnable = object : Runnable { + override fun run() { + val dateTime = Instant.now().atZone(ZoneId.systemDefault()) - time = dateTime.toEpochSecond() * 1000 + time = dateTime.toEpochSecond() * 1000 - val receiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - val dt = Instant.ofEpochMilli(System.currentTimeMillis()) - .atZone(ZoneId.systemDefault()) - .withSecond(0) - .withNano(0) - time = dt.toEpochSecond() * 1000 - } + val millis = dateTime.nano / 1000000L + var next = 1000L - millis + if (next <= 200L) next += 1000L + + handler.postDelayed(this, 1000 - millis) } - context.registerReceiver(receiver, IntentFilter().apply { - addAction(Intent.ACTION_TIME_CHANGED) - addAction(Intent.ACTION_TIME_TICK) - }) - + } + lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { + handler.post(runnable) try { awaitCancellation() - } finally { - context.unregisterReceiver(receiver) + } catch (e: CancellationException) { + handler.removeCallbacks(runnable) } } } CompositionLocalProvider( - LocalTime provides time + secondsAnimation.value.toInt() * 1000, + LocalTime provides time, content = content ) }