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.preferences.Settings
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.base.BaseActivity
|
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.base.ProvideSettings
|
||||||
import de.mm20.launcher2.ui.component.NavBarEffects
|
import de.mm20.launcher2.ui.component.NavBarEffects
|
||||||
import de.mm20.launcher2.ui.ktx.animateTo
|
import de.mm20.launcher2.ui.ktx.animateTo
|
||||||
@ -72,77 +73,79 @@ class LauncherActivity : BaseActivity() {
|
|||||||
LocalSnackbarHostState provides snackbarHostState
|
LocalSnackbarHostState provides snackbarHostState
|
||||||
) {
|
) {
|
||||||
LauncherTheme {
|
LauncherTheme {
|
||||||
ProvideSettings {
|
ProvideCurrentTime {
|
||||||
val lightStatus by viewModel.lightStatusBar.observeAsState(false)
|
ProvideSettings {
|
||||||
val lightNav by viewModel.lightNavBar.observeAsState(false)
|
val lightStatus by viewModel.lightStatusBar.observeAsState(false)
|
||||||
val hideStatus by viewModel.hideStatusBar.observeAsState(false)
|
val lightNav by viewModel.lightNavBar.observeAsState(false)
|
||||||
val hideNav by viewModel.hideNavBar.observeAsState(false)
|
val hideStatus by viewModel.hideStatusBar.observeAsState(false)
|
||||||
val dimBackground by viewModel.dimBackground.observeAsState(false)
|
val hideNav by viewModel.hideNavBar.observeAsState(false)
|
||||||
val layout by viewModel.layout.observeAsState(null)
|
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) {
|
LaunchedEffect(null) {
|
||||||
homeTransitionManager
|
homeTransitionManager
|
||||||
.currentTransition
|
.currentTransition
|
||||||
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
|
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
|
||||||
.collect {
|
.collect {
|
||||||
enterTransition.value = 0f
|
enterTransition.value = 0f
|
||||||
enterTransition.animateTo(1f)
|
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 -> {}
|
|
||||||
}
|
}
|
||||||
SnackbarHost(
|
|
||||||
snackbarHostState,
|
LaunchedEffect(hideStatus) {
|
||||||
|
systemUiController.isStatusBarVisible = !hideStatus
|
||||||
|
}
|
||||||
|
LaunchedEffect(hideNav) {
|
||||||
|
systemUiController.isNavigationBarVisible = !hideNav
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.navigationBarsPadding()
|
.fillMaxSize()
|
||||||
.imePadding()
|
.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.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockStyle
|
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockStyle
|
||||||
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetLayout
|
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.ClockWidgetVM
|
||||||
import de.mm20.launcher2.ui.launcher.widgets.clock.clocks.*
|
import de.mm20.launcher2.ui.launcher.widgets.clock.clocks.*
|
||||||
import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider
|
import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider
|
||||||
@ -31,15 +29,12 @@ fun ClockWidget(
|
|||||||
) {
|
) {
|
||||||
val viewModel: ClockWidgetVM = viewModel()
|
val viewModel: ClockWidgetVM = viewModel()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
|
||||||
val time by viewModel.time.collectAsState(System.currentTimeMillis())
|
|
||||||
val layout by viewModel.layout.observeAsState()
|
val layout by viewModel.layout.observeAsState()
|
||||||
val clockStyle by viewModel.clockStyle.observeAsState()
|
val clockStyle by viewModel.clockStyle.observeAsState()
|
||||||
|
val time = LocalTime.current
|
||||||
|
|
||||||
LaunchedEffect(null) {
|
LaunchedEffect(time) {
|
||||||
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
viewModel.updateTime(time)
|
||||||
viewModel.onActive(context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val partProvider by viewModel.getActivePart(LocalContext.current).collectAsState(null)
|
val partProvider by viewModel.getActivePart(LocalContext.current).collectAsState(null)
|
||||||
@ -66,7 +61,7 @@ fun ClockWidget(
|
|||||||
viewModel.launchClockApp(context)
|
viewModel.launchClockApp(context)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Clock(clockStyle, ClockWidgetLayout.Vertical, time)
|
Clock(clockStyle, ClockWidgetLayout.Vertical)
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicZone(
|
DynamicZone(
|
||||||
@ -114,7 +109,7 @@ fun ClockWidget(
|
|||||||
viewModel.launchClockApp(context)
|
viewModel.launchClockApp(context)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Clock(clockStyle, ClockWidgetLayout.Horizontal, time)
|
Clock(clockStyle, ClockWidgetLayout.Horizontal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,8 +123,8 @@ fun ClockWidget(
|
|||||||
fun Clock(
|
fun Clock(
|
||||||
style: ClockStyle?,
|
style: ClockStyle?,
|
||||||
layout: ClockWidgetLayout,
|
layout: ClockWidgetLayout,
|
||||||
time: Long
|
|
||||||
) {
|
) {
|
||||||
|
val time = LocalTime.current
|
||||||
when (style) {
|
when (style) {
|
||||||
ClockStyle.DigitalClock1 -> DigitalClock1(time, layout)
|
ClockStyle.DigitalClock1 -> DigitalClock1(time, layout)
|
||||||
ClockStyle.DigitalClock2 -> DigitalClock2(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 layout = dataStore.data.map { it.clockWidget.layout }.asLiveData()
|
||||||
val clockStyle = dataStore.data.map { it.clockWidget.clockStyle }.asLiveData()
|
val clockStyle = dataStore.data.map { it.clockWidget.clockStyle }.asLiveData()
|
||||||
|
|
||||||
private fun getTime(context: Context): Flow<Long> = callbackFlow {
|
fun updateTime(time: Long) {
|
||||||
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) {
|
|
||||||
partProviders.value.forEach { it.setTime(time) }
|
partProviders.value.forEach { it.setTime(time) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +76,4 @@ class ClockWidgetVM : ViewModel(), KoinComponent {
|
|||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
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)
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) {
|
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.compose.ui.unit.em
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.preferences.Settings
|
import de.mm20.launcher2.preferences.Settings
|
||||||
|
import de.mm20.launcher2.ui.base.LocalTime
|
||||||
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidgetVM
|
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidgetVM
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@ -29,15 +30,9 @@ class DatePartProvider: PartProvider {
|
|||||||
emit(1)
|
emit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val time = MutableStateFlow(System.currentTimeMillis())
|
|
||||||
|
|
||||||
override fun setTime(time: Long) {
|
|
||||||
this.time.value = time
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) {
|
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 verticalLayout = layout == Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|||||||
@ -167,8 +167,7 @@ fun ClockStylePreference(
|
|||||||
) {
|
) {
|
||||||
Clock(
|
Clock(
|
||||||
style = styles[it],
|
style = styles[it],
|
||||||
layout = layout,
|
layout = layout
|
||||||
time = System.currentTimeMillis()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
HorizontalPagerIndicator(pagerState = pagerState)
|
HorizontalPagerIndicator(pagerState = pagerState)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user