Provide current time as composition local

This commit is contained in:
MM20 2022-06-15 17:46:53 +02:00
parent cf0b34857f
commit 08e736f5d1
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
7 changed files with 120 additions and 118 deletions

View File

@ -0,0 +1,40 @@
package de.mm20.launcher2.ui.base
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
@Composable
fun ProvideCurrentTime(content: @Composable () -> Unit) {
val context = LocalContext.current
var time by remember { mutableStateOf(System.currentTimeMillis()) }
DisposableEffect(null) {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
time = System.currentTimeMillis()
Log.d("MM20", "Time Changed: $time")
}
}
context.registerReceiver(receiver, IntentFilter().apply {
addAction(Intent.ACTION_TIME_TICK)
addAction(Intent.ACTION_TIME_CHANGED)
})
onDispose {
context.unregisterReceiver(receiver)
}
}
CompositionLocalProvider(
LocalTime provides time,
content = content
)
}
val LocalTime = compositionLocalOf { System.currentTimeMillis() }

View File

@ -35,6 +35,7 @@ import de.mm20.launcher2.icons.DynamicIconController
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.base.BaseActivity
import de.mm20.launcher2.ui.base.ProvideCurrentTime
import de.mm20.launcher2.ui.base.ProvideSettings
import de.mm20.launcher2.ui.component.NavBarEffects
import de.mm20.launcher2.ui.ktx.animateTo
@ -72,77 +73,79 @@ class LauncherActivity : BaseActivity() {
LocalSnackbarHostState provides snackbarHostState
) {
LauncherTheme {
ProvideSettings {
val lightStatus by viewModel.lightStatusBar.observeAsState(false)
val lightNav by viewModel.lightNavBar.observeAsState(false)
val hideStatus by viewModel.hideStatusBar.observeAsState(false)
val hideNav by viewModel.hideNavBar.observeAsState(false)
val dimBackground by viewModel.dimBackground.observeAsState(false)
val layout by viewModel.layout.observeAsState(null)
ProvideCurrentTime {
ProvideSettings {
val lightStatus by viewModel.lightStatusBar.observeAsState(false)
val lightNav by viewModel.lightNavBar.observeAsState(false)
val hideStatus by viewModel.hideStatusBar.observeAsState(false)
val hideNav by viewModel.hideNavBar.observeAsState(false)
val dimBackground by viewModel.dimBackground.observeAsState(false)
val layout by viewModel.layout.observeAsState(null)
val systemUiController = rememberSystemUiController()
val systemUiController = rememberSystemUiController()
val enterTransition = remember { mutableStateOf(1f) }
val enterTransition = remember { mutableStateOf(1f) }
LaunchedEffect(null) {
homeTransitionManager
.currentTransition
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
.collect {
enterTransition.value = 0f
enterTransition.animateTo(1f)
}
}
LaunchedEffect(hideStatus) {
systemUiController.isStatusBarVisible = !hideStatus
}
LaunchedEffect(hideNav) {
systemUiController.isNavigationBarVisible = !hideNav
}
Box(
modifier = Modifier
.fillMaxSize()
.background(if (dimBackground) Color.Black.copy(alpha = 0.30f) else Color.Transparent),
contentAlignment = Alignment.BottomCenter
) {
NavBarEffects(modifier = Modifier.fillMaxSize())
when (layout) {
Settings.AppearanceSettings.Layout.PullDown -> {
PullDownScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = 0.5f + enterTransition.value * 0.5f
scaleY = 0.5f + enterTransition.value * 0.5f
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
}
Settings.AppearanceSettings.Layout.Pager -> {
PagerScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = enterTransition.value
scaleY = enterTransition.value
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
}
else -> {}
LaunchedEffect(null) {
homeTransitionManager
.currentTransition
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
.collect {
enterTransition.value = 0f
enterTransition.animateTo(1f)
}
}
SnackbarHost(
snackbarHostState,
LaunchedEffect(hideStatus) {
systemUiController.isStatusBarVisible = !hideStatus
}
LaunchedEffect(hideNav) {
systemUiController.isNavigationBarVisible = !hideNav
}
Box(
modifier = Modifier
.navigationBarsPadding()
.imePadding()
)
.fillMaxSize()
.background(if (dimBackground) Color.Black.copy(alpha = 0.30f) else Color.Transparent),
contentAlignment = Alignment.BottomCenter
) {
NavBarEffects(modifier = Modifier.fillMaxSize())
when (layout) {
Settings.AppearanceSettings.Layout.PullDown -> {
PullDownScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = 0.5f + enterTransition.value * 0.5f
scaleY = 0.5f + enterTransition.value * 0.5f
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
}
Settings.AppearanceSettings.Layout.Pager -> {
PagerScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = enterTransition.value
scaleY = enterTransition.value
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
}
else -> {}
}
SnackbarHost(
snackbarHostState,
modifier = Modifier
.navigationBarsPadding()
.imePadding()
)
}
}
}
}

View File

@ -14,13 +14,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockStyle
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetLayout
import de.mm20.launcher2.ui.base.LocalTime
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidgetVM
import de.mm20.launcher2.ui.launcher.widgets.clock.clocks.*
import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider
@ -31,15 +29,12 @@ fun ClockWidget(
) {
val viewModel: ClockWidgetVM = viewModel()
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val time by viewModel.time.collectAsState(System.currentTimeMillis())
val layout by viewModel.layout.observeAsState()
val clockStyle by viewModel.clockStyle.observeAsState()
val time = LocalTime.current
LaunchedEffect(null) {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewModel.onActive(context)
}
LaunchedEffect(time) {
viewModel.updateTime(time)
}
val partProvider by viewModel.getActivePart(LocalContext.current).collectAsState(null)
@ -66,7 +61,7 @@ fun ClockWidget(
viewModel.launchClockApp(context)
}
) {
Clock(clockStyle, ClockWidgetLayout.Vertical, time)
Clock(clockStyle, ClockWidgetLayout.Vertical)
}
DynamicZone(
@ -114,7 +109,7 @@ fun ClockWidget(
viewModel.launchClockApp(context)
}
) {
Clock(clockStyle, ClockWidgetLayout.Horizontal, time)
Clock(clockStyle, ClockWidgetLayout.Horizontal)
}
}
}
@ -128,8 +123,8 @@ fun ClockWidget(
fun Clock(
style: ClockStyle?,
layout: ClockWidgetLayout,
time: Long
) {
val time = LocalTime.current
when (style) {
ClockStyle.DigitalClock1 -> DigitalClock1(time, layout)
ClockStyle.DigitalClock2 -> DigitalClock2(time, layout)

View File

@ -67,23 +67,7 @@ class ClockWidgetVM : ViewModel(), KoinComponent {
val layout = dataStore.data.map { it.clockWidget.layout }.asLiveData()
val clockStyle = dataStore.data.map { it.clockWidget.clockStyle }.asLiveData()
private fun getTime(context: Context): Flow<Long> = callbackFlow {
trySendBlocking(System.currentTimeMillis())
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
trySendBlocking(System.currentTimeMillis())
}
}
context.registerReceiver(receiver, IntentFilter().apply {
addAction(Intent.ACTION_TIME_TICK)
addAction(Intent.ACTION_TIME_CHANGED)
})
awaitClose {
context.unregisterReceiver(receiver)
}
}
private fun updatePartsTime(time: Long) {
fun updateTime(time: Long) {
partProviders.value.forEach { it.setTime(time) }
}
@ -92,11 +76,4 @@ class ClockWidgetVM : ViewModel(), KoinComponent {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
})
}
suspend fun onActive(context: Context) {
getTime(context).collectLatest {
time.value = it
updatePartsTime(it)
}
}
}

View File

@ -53,13 +53,6 @@ class BatteryPartProvider : PartProvider {
}
}
private val time = MutableStateFlow(System.currentTimeMillis())
override fun setTime(time: Long) {
super.setTime(time)
this.time.value = time
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) {

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.em
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.base.LocalTime
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidgetVM
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
@ -29,15 +30,9 @@ class DatePartProvider: PartProvider {
emit(1)
}
private val time = MutableStateFlow(System.currentTimeMillis())
override fun setTime(time: Long) {
this.time.value = time
}
@Composable
override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) {
val time by this.time.collectAsState(System.currentTimeMillis())
val time = LocalTime.current
val verticalLayout = layout == Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical
val context = LocalContext.current
TextButton(

View File

@ -167,8 +167,7 @@ fun ClockStylePreference(
) {
Clock(
style = styles[it],
layout = layout,
time = System.currentTimeMillis()
layout = layout
)
}
HorizontalPagerIndicator(pagerState = pagerState)