Provide current time as composition local
This commit is contained in:
parent
cf0b34857f
commit
08e736f5d1
@ -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() }
|
||||
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -167,8 +167,7 @@ fun ClockStylePreference(
|
||||
) {
|
||||
Clock(
|
||||
style = styles[it],
|
||||
layout = layout,
|
||||
time = System.currentTimeMillis()
|
||||
layout = layout
|
||||
)
|
||||
}
|
||||
HorizontalPagerIndicator(pagerState = pagerState)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user