Introduce subscription-based state, remove DataStore stopgap
This commit is contained in:
parent
8413cf7ae7
commit
87eb947936
4 changed files with 49 additions and 44 deletions
|
@ -66,7 +66,6 @@ dependencies {
|
||||||
implementation ( "androidx.compose.ui" , "ui" , "1.7.6" )
|
implementation ( "androidx.compose.ui" , "ui" , "1.7.6" )
|
||||||
implementation ( "androidx.compose.ui" , "ui-graphics" , "1.7.6" )
|
implementation ( "androidx.compose.ui" , "ui-graphics" , "1.7.6" )
|
||||||
debugImplementation ( "androidx.compose.ui" , "ui-tooling" , "1.7.6" )
|
debugImplementation ( "androidx.compose.ui" , "ui-tooling" , "1.7.6" )
|
||||||
implementation ( "androidx.datastore" , "datastore-preferences" , "1.1.1" )
|
|
||||||
implementation ( "androidx.lifecycle" , "lifecycle-runtime-ktx" , "2.8.7" )
|
implementation ( "androidx.lifecycle" , "lifecycle-runtime-ktx" , "2.8.7" )
|
||||||
implementation ( "org.jetbrains.kotlinx" , "kotlinx-coroutines-android" , "1.9.0" )
|
implementation ( "org.jetbrains.kotlinx" , "kotlinx-coroutines-android" , "1.9.0" )
|
||||||
implementation ( "org.jetbrains.kotlinx" , "kotlinx-serialization-json" , "1.7.3" )
|
implementation ( "org.jetbrains.kotlinx" , "kotlinx-serialization-json" , "1.7.3" )
|
||||||
|
|
|
@ -1,26 +1,31 @@
|
||||||
package com.kernelmaft.zanbur
|
package com.kernelmaft.zanbur
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
|
|
||||||
|
|
||||||
|
enum class ChangeSource { Local , Remote }
|
||||||
|
|
||||||
|
typealias CurrentSceneSubscriber = ( Group , Scene , ChangeSource ) -> Unit
|
||||||
|
typealias GroupAddedSubscriber = ( Group , ChangeSource ) -> Unit
|
||||||
|
|
||||||
object AppState {
|
object AppState {
|
||||||
// The index of a group in this list is always equal to its ID
|
private val currentSceneSubscribers : MutableList <CurrentSceneSubscriber> = mutableListOf ()
|
||||||
val groups : State < List <Group> > get () = groupsAsMutable
|
private val groupAddedSubscribers : MutableList <GroupAddedSubscriber> = mutableListOf ()
|
||||||
private val groupsAsMutable : MutableState < List <Group> > = mutableStateOf ( emptyList () )
|
|
||||||
|
|
||||||
fun setCurrentScene ( groupId : Int , scene : Scene ) {
|
fun setCurrentScene ( group : Group , newScene : Scene , source : ChangeSource ) {
|
||||||
groupsAsMutable . value = groupsAsMutable . value . mapIndexed { index , group ->
|
for ( subscriber in currentSceneSubscribers ) {
|
||||||
if ( index == groupId ) group . copy ( currentScene = scene )
|
subscriber ( group , newScene , source )
|
||||||
else group
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun subscribeToCurrentScene ( subscriber : CurrentSceneSubscriber ) {
|
||||||
|
currentSceneSubscribers . add (subscriber)
|
||||||
|
}
|
||||||
|
|
||||||
fun addGroup ( group : Group ) {
|
fun addGroup ( newGroup : Group , source : ChangeSource ) {
|
||||||
val newGroups = groupsAsMutable . value . toMutableList ()
|
for ( subscriber in groupAddedSubscribers ) {
|
||||||
// Wow this is sooo much better than Java
|
subscriber ( newGroup , source )
|
||||||
if ( newGroups . getOrNull ( group . id ) != null ) newGroups . removeAt ( group . id )
|
}
|
||||||
newGroups . add ( group . id , group )
|
}
|
||||||
groupsAsMutable . value = newGroups
|
fun subscribeToGroupAdded ( subscriber : GroupAddedSubscriber ) {
|
||||||
|
groupAddedSubscribers . add (subscriber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
app/src/main/java/com/kernelmaft/zanbur/compose-state.kt
Normal file
21
app/src/main/java/com/kernelmaft/zanbur/compose-state.kt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package com.kernelmaft.zanbur
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun createGroupsComposeState () : MutableState < List <Group> > {
|
||||||
|
val groups : MutableState < List <Group> > = mutableStateOf ( emptyList () )
|
||||||
|
|
||||||
|
AppState . subscribeToGroupAdded { newGroup , _ ->
|
||||||
|
groups . value = groups . value . plus (newGroup)
|
||||||
|
}
|
||||||
|
AppState . subscribeToCurrentScene { group , newScene , source ->
|
||||||
|
groups . value = groups . value . map { when ( it . id ) {
|
||||||
|
group . id -> it . copy ( currentScene = newScene )
|
||||||
|
else -> it
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups
|
||||||
|
}
|
|
@ -5,40 +5,31 @@ import androidx.activity.compose.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.ui.*
|
import androidx.compose.ui.*
|
||||||
import androidx.compose.ui.unit.*
|
import androidx.compose.ui.unit.*
|
||||||
import androidx.datastore.preferences.*
|
|
||||||
import androidx.datastore.preferences.core.*
|
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import kotlinx.coroutines.*
|
import com.kernelmaft.zanbur.ChangeSource.*
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
|
||||||
import kotlinx.coroutines.flow.*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : EdgeToEdgeActivity () {
|
class MainActivity : EdgeToEdgeActivity () {
|
||||||
val dataStore = PreferenceDataStoreFactory . create { preferencesDataStoreFile ("state") }
|
|
||||||
|
|
||||||
override fun onCreate ( savedInstanceState : Bundle ? ) {
|
override fun onCreate ( savedInstanceState : Bundle ? ) {
|
||||||
super . onCreate (savedInstanceState)
|
super . onCreate (savedInstanceState)
|
||||||
|
|
||||||
Config . groups . forEach { AppState . addGroup (it) }
|
val groups = createGroupsComposeState ()
|
||||||
|
|
||||||
lifecycleScope . launch (IO) {
|
AppState . subscribeToCurrentScene { group , newScene , source ->
|
||||||
val prefs = dataStore . data . firstOrNull ()
|
if ( source == Local ) {
|
||||||
val savedSceneName = prefs ?. get ( stringPreferencesKey ("scene") )
|
publishSceneChange ( group , newScene )
|
||||||
if ( savedSceneName != null ) {
|
|
||||||
val savedScene = AppState . groups . value [0] . scenes
|
|
||||||
. find { it . name == savedSceneName }
|
|
||||||
savedScene ?. let { AppState . setCurrentScene ( 0 , it ) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config . groups . forEach { AppState . addGroup ( it , Remote ) }
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
AppFrame {
|
AppFrame {
|
||||||
Column ( Modifier . width ( 300 . dp ) ) {
|
Column ( Modifier . width ( 300 . dp ) ) {
|
||||||
AppState . groups . value . forEach { group ->
|
groups . value . forEach { group ->
|
||||||
SceneSwitcher (group) { newScene ->
|
SceneSwitcher (group) { newScene ->
|
||||||
AppState . setCurrentScene ( group . id , newScene )
|
AppState . setCurrentScene ( group , newScene , Local )
|
||||||
publishSceneChange ( group , newScene )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,15 +38,4 @@ class MainActivity : EdgeToEdgeActivity () {
|
||||||
|
|
||||||
MqttClient . run (lifecycleScope)
|
MqttClient . run (lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop () {
|
|
||||||
super . onStop ()
|
|
||||||
|
|
||||||
val currentScene = AppState . groups . value [0] . currentScene
|
|
||||||
if ( currentScene != null ) lifecycleScope . launch (IO) {
|
|
||||||
dataStore . edit {
|
|
||||||
it [ stringPreferencesKey ("scene") ] = currentScene . name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue