From 87eb947936aa5d339c664c8b11899d029ed9c369 Mon Sep 17 00:00:00 2001 From: Reinout Meliesie Date: Thu, 19 Dec 2024 18:49:22 +0100 Subject: [PATCH] Introduce subscription-based state, remove DataStore stopgap --- app/build.gradle.kts | 1 - .../java/com/kernelmaft/zanbur/app-state.kt | 33 +++++++++------- .../com/kernelmaft/zanbur/compose-state.kt | 21 ++++++++++ .../main/java/com/kernelmaft/zanbur/main.kt | 38 +++++-------------- 4 files changed, 49 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/com/kernelmaft/zanbur/compose-state.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index eca2e77..aa064e8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -66,7 +66,6 @@ dependencies { implementation ( "androidx.compose.ui" , "ui" , "1.7.6" ) implementation ( "androidx.compose.ui" , "ui-graphics" , "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 ( "org.jetbrains.kotlinx" , "kotlinx-coroutines-android" , "1.9.0" ) implementation ( "org.jetbrains.kotlinx" , "kotlinx-serialization-json" , "1.7.3" ) diff --git a/app/src/main/java/com/kernelmaft/zanbur/app-state.kt b/app/src/main/java/com/kernelmaft/zanbur/app-state.kt index ae77a76..41e2d98 100644 --- a/app/src/main/java/com/kernelmaft/zanbur/app-state.kt +++ b/app/src/main/java/com/kernelmaft/zanbur/app-state.kt @@ -1,26 +1,31 @@ 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 { - // The index of a group in this list is always equal to its ID - val groups : State < List > get () = groupsAsMutable - private val groupsAsMutable : MutableState < List > = mutableStateOf ( emptyList () ) + private val currentSceneSubscribers : MutableList = mutableListOf () + private val groupAddedSubscribers : MutableList = mutableListOf () - fun setCurrentScene ( groupId : Int , scene : Scene ) { - groupsAsMutable . value = groupsAsMutable . value . mapIndexed { index , group -> - if ( index == groupId ) group . copy ( currentScene = scene ) - else group + fun setCurrentScene ( group : Group , newScene : Scene , source : ChangeSource ) { + for ( subscriber in currentSceneSubscribers ) { + subscriber ( group , newScene , source ) } } + fun subscribeToCurrentScene ( subscriber : CurrentSceneSubscriber ) { + currentSceneSubscribers . add (subscriber) + } - fun addGroup ( group : Group ) { - val newGroups = groupsAsMutable . value . toMutableList () - // Wow this is sooo much better than Java - if ( newGroups . getOrNull ( group . id ) != null ) newGroups . removeAt ( group . id ) - newGroups . add ( group . id , group ) - groupsAsMutable . value = newGroups + fun addGroup ( newGroup : Group , source : ChangeSource ) { + for ( subscriber in groupAddedSubscribers ) { + subscriber ( newGroup , source ) + } + } + fun subscribeToGroupAdded ( subscriber : GroupAddedSubscriber ) { + groupAddedSubscribers . add (subscriber) } } diff --git a/app/src/main/java/com/kernelmaft/zanbur/compose-state.kt b/app/src/main/java/com/kernelmaft/zanbur/compose-state.kt new file mode 100644 index 0000000..bd2a3e3 --- /dev/null +++ b/app/src/main/java/com/kernelmaft/zanbur/compose-state.kt @@ -0,0 +1,21 @@ +package com.kernelmaft.zanbur + +import androidx.compose.runtime.* + + + +fun createGroupsComposeState () : MutableState < List > { + val groups : MutableState < List > = 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 +} diff --git a/app/src/main/java/com/kernelmaft/zanbur/main.kt b/app/src/main/java/com/kernelmaft/zanbur/main.kt index 5e5a914..5d12e11 100644 --- a/app/src/main/java/com/kernelmaft/zanbur/main.kt +++ b/app/src/main/java/com/kernelmaft/zanbur/main.kt @@ -5,40 +5,31 @@ import androidx.activity.compose.* import androidx.compose.foundation.layout.* import androidx.compose.ui.* import androidx.compose.ui.unit.* -import androidx.datastore.preferences.* -import androidx.datastore.preferences.core.* import androidx.lifecycle.* -import kotlinx.coroutines.* -import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.flow.* +import com.kernelmaft.zanbur.ChangeSource.* class MainActivity : EdgeToEdgeActivity () { - val dataStore = PreferenceDataStoreFactory . create { preferencesDataStoreFile ("state") } - override fun onCreate ( savedInstanceState : Bundle ? ) { super . onCreate (savedInstanceState) - Config . groups . forEach { AppState . addGroup (it) } + val groups = createGroupsComposeState () - lifecycleScope . launch (IO) { - val prefs = dataStore . data . firstOrNull () - val savedSceneName = prefs ?. get ( stringPreferencesKey ("scene") ) - if ( savedSceneName != null ) { - val savedScene = AppState . groups . value [0] . scenes - . find { it . name == savedSceneName } - savedScene ?. let { AppState . setCurrentScene ( 0 , it ) } + AppState . subscribeToCurrentScene { group , newScene , source -> + if ( source == Local ) { + publishSceneChange ( group , newScene ) } } + Config . groups . forEach { AppState . addGroup ( it , Remote ) } + setContent { AppFrame { Column ( Modifier . width ( 300 . dp ) ) { - AppState . groups . value . forEach { group -> + groups . value . forEach { group -> SceneSwitcher (group) { newScene -> - AppState . setCurrentScene ( group . id , newScene ) - publishSceneChange ( group , newScene ) + AppState . setCurrentScene ( group , newScene , Local ) } } } @@ -47,15 +38,4 @@ class MainActivity : EdgeToEdgeActivity () { 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 - } - } - } }