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.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()
)
}
} }
} }
} }

View File

@ -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)

View File

@ -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)
}
}
} }

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) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
override fun Component(layout: Settings.ClockWidgetSettings.ClockWidgetLayout) { 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.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(

View File

@ -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)