diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 63a6902..f29eafc 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -9,20 +9,20 @@ val keystoreProperties = Properties ()
keystoreProperties . load ( FileInputStream ( rootProject . file ("keystore.properties") ) )
plugins {
- id ("com.android.application") . version ("8.8.0")
- id ("org.jetbrains.kotlin.android") . version ("2.1.10")
- id ("org.jetbrains.kotlin.plugin.compose") . version ("2.1.10")
- id ("org.jetbrains.kotlin.plugin.serialization") . version ("2.1.10")
+ id ("com.android.application") . version ("8.7.2")
+ id ("org.jetbrains.kotlin.android") . version ("2.0.0")
+ id ("org.jetbrains.kotlin.plugin.compose") . version ("2.0.0")
+ id ("org.jetbrains.kotlin.plugin.serialization") . version ("2.0.0")
}
android {
namespace = "com.kernelmaft.zanbur"
- compileSdk = 35
+ compileSdk = 34
defaultConfig {
applicationId = "com.kernelmaft.zanbur"
- minSdk = 35
- targetSdk = 35
+ minSdk = 31
+ targetSdk = 34
versionCode = 1
versionName = "1.0"
}
@@ -47,11 +47,10 @@ android {
}
}
compileOptions {
- // Required even though we don't have any Java sources because it needs to match Kotlin's JVM version
- targetCompatibility = JavaVersion . VERSION_23
+ targetCompatibility = JavaVersion . VERSION_11
}
kotlinOptions {
- jvmTarget = "23"
+ jvmTarget = "11"
}
buildFeatures {
compose = true
@@ -61,18 +60,19 @@ android {
dependencies {
// Android runtime libraries
implementation ( "com.google.android.material" , "material" , "1.12.0" )
- implementation ( "androidx.activity" , "activity-compose" , "1.10.0" )
- implementation ( "androidx.core" , "core-ktx" , "1.15.0" )
+ implementation ( "androidx.activity" , "activity-compose" , "1.9.3" )
+ implementation ( "androidx.core" , "core-ktx" , "1.13.1" )
implementation ( "androidx.compose.material3" , "material3" , "1.3.1" )
- implementation ( "androidx.compose.ui" , "ui" , "1.7.7" )
- implementation ( "androidx.compose.ui" , "ui-graphics" , "1.7.7" )
- debugImplementation ( "androidx.compose.ui" , "ui-tooling" , "1.7.7" )
+ implementation ( "androidx.compose.ui" , "ui" , "1.7.5" )
+ implementation ( "androidx.compose.ui" , "ui-graphics" , "1.7.5" )
+ debugImplementation ( "androidx.compose.ui" , "ui-tooling" , "1.7.5" )
+ 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.10.1" )
- implementation ( "org.jetbrains.kotlinx" , "kotlinx-serialization-json" , "1.8.0" )
+ implementation ( "org.jetbrains.kotlinx" , "kotlinx-coroutines-android" , "1.9.0" )
+ implementation ( "org.jetbrains.kotlinx" , "kotlinx-serialization-json" , "1.7.3" )
// Other libraries
- implementation ( "io.github.davidepianca98" , "kmqtt-common" , "1.0.0" )
- implementation ( "io.github.davidepianca98" , "kmqtt-client" , "1.0.0" )
+ implementation ( "io.github.davidepianca98" , "kmqtt-common" , "0.4.8" )
+ implementation ( "io.github.davidepianca98" , "kmqtt-client" , "0.4.8" )
}
tasks . withType ( KotlinCompile :: class ) . all {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 90a24a3..1acccf6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,14 +4,17 @@
+ android:supportsRtl = "true"
+ android:theme = "@style/Theme.Zanbur" >
+ android:name = ".MainActivity"
+ android:exported = "true"
+ android:label = "@string/title_activity_main"
+ android:theme = "@style/Theme.Zanbur" >
diff --git a/app/src/main/java/com/kernelmaft/zanbur/app-state.kt b/app/src/main/java/com/kernelmaft/zanbur/app-state.kt
new file mode 100644
index 0000000..52c4991
--- /dev/null
+++ b/app/src/main/java/com/kernelmaft/zanbur/app-state.kt
@@ -0,0 +1,25 @@
+package com.kernelmaft.zanbur
+
+
+
+object AppState {
+ val groups : List get () = groupsAsMutable
+ private var groupsAsMutable : List = emptyList ()
+
+ private val subscribers : MutableList < ( List ) -> Unit > = mutableListOf ()
+
+ fun subscribe ( subscriber : ( List ) -> Unit ) = subscribers . add (subscriber)
+
+ fun addGroup ( group : Group ) {
+ groupsAsMutable += group
+ subscribers . forEach { it (groups) }
+ }
+
+ fun setCurrentScene ( groupId : Int , scene : Scene ) {
+ groupsAsMutable = groupsAsMutable . mapIndexed { index , group ->
+ if ( index == groupId ) group . copy ( currentScene = scene )
+ else group
+ }
+ subscribers . forEach { it (groups) }
+ }
+}
diff --git a/app/src/main/java/com/kernelmaft/zanbur/common/app-state.kt b/app/src/main/java/com/kernelmaft/zanbur/common/app-state.kt
deleted file mode 100644
index 6abdb42..0000000
--- a/app/src/main/java/com/kernelmaft/zanbur/common/app-state.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.kernelmaft.zanbur.common
-
-
-
-enum class ChangeSource { Local , Remote }
-
-typealias CurrentSceneSubscriber = ( Group , Scene , ChangeSource ) -> Unit
-typealias GroupAddedSubscriber = ( Group , ChangeSource ) -> Unit
-
-object AppState {
- private val currentSceneSubscribers : MutableList = mutableListOf ()
- private val groupAddedSubscribers : MutableList = mutableListOf ()
-
- 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 ( 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/ui/components.kt b/app/src/main/java/com/kernelmaft/zanbur/components.kt
similarity index 94%
rename from app/src/main/java/com/kernelmaft/zanbur/ui/components.kt
rename to app/src/main/java/com/kernelmaft/zanbur/components.kt
index 03fc6ac..e2d54e9 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/ui/components.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/components.kt
@@ -1,4 +1,4 @@
-package com.kernelmaft.zanbur.ui
+package com.kernelmaft.zanbur
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Center
@@ -9,7 +9,6 @@ import androidx.compose.material3.ButtonDefaults.shape
import androidx.compose.runtime.*
import androidx.compose.ui.*
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
-import com.kernelmaft.zanbur.common.*
diff --git a/app/src/main/java/com/kernelmaft/zanbur/common/config.kt b/app/src/main/java/com/kernelmaft/zanbur/config.kt
similarity index 92%
rename from app/src/main/java/com/kernelmaft/zanbur/common/config.kt
rename to app/src/main/java/com/kernelmaft/zanbur/config.kt
index 3e4ddda..ef1f384 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/common/config.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/config.kt
@@ -1,4 +1,4 @@
-package com.kernelmaft.zanbur.common
+package com.kernelmaft.zanbur
diff --git a/app/src/main/java/com/kernelmaft/zanbur/main.kt b/app/src/main/java/com/kernelmaft/zanbur/main.kt
new file mode 100644
index 0000000..769890f
--- /dev/null
+++ b/app/src/main/java/com/kernelmaft/zanbur/main.kt
@@ -0,0 +1,65 @@
+package com.kernelmaft.zanbur
+
+import android.os.*
+import androidx.activity.compose.*
+import androidx.compose.foundation.layout.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.*
+import androidx.compose.ui.unit.*
+import androidx.datastore.preferences.core.*
+import androidx.lifecycle.*
+import kotlinx.coroutines.*
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.flow.*
+
+
+
+class MainActivity : EdgeToEdgeActivity () {
+ override fun onCreate ( savedInstanceState : Bundle ? ) {
+ super . onCreate (savedInstanceState)
+
+ Config . groups . forEach { AppState . addGroup (it) }
+
+ var groups by mutableStateOf ( AppState . groups )
+ AppState . subscribe { groups = it }
+
+ lifecycleScope . launch (IO) {
+ val prefs = dataStore . data . firstOrNull ()
+ if ( prefs != null ) {
+ val savedSceneName = prefs [ stringPreferencesKey ("scene") ]
+ if ( savedSceneName != null ) {
+ val savedScene = AppState . groups [0] . scenes . find { it . name == savedSceneName }
+ if ( savedScene != null ) {
+ AppState . setCurrentScene ( 0 , savedScene )
+ }
+ }
+ }
+ }
+
+ setContent {
+ AppFrame {
+ Column ( Modifier . width ( 300 . dp ) ) {
+ groups . forEach { group ->
+ SceneSwitcher (group) {
+ AppState . setCurrentScene ( group . id , it )
+ publishSceneChange ( group , it )
+ }
+ }
+ }
+ }
+ }
+
+ MqttClient . run (lifecycleScope)
+ }
+
+ override fun onStop () {
+ super . onStop ()
+
+ val currentScene = AppState . groups [0] . currentScene
+ if ( currentScene != null ) lifecycleScope . launch (IO) {
+ applicationContext . dataStore . edit {
+ it [ stringPreferencesKey ("scene") ] = currentScene . name
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/kernelmaft/zanbur/network/mqtt.kt b/app/src/main/java/com/kernelmaft/zanbur/mqtt.kt
similarity index 70%
rename from app/src/main/java/com/kernelmaft/zanbur/network/mqtt.kt
rename to app/src/main/java/com/kernelmaft/zanbur/mqtt.kt
index 212d73a..5d633ac 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/network/mqtt.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/mqtt.kt
@@ -1,16 +1,16 @@
-package com.kernelmaft.zanbur.network
+package com.kernelmaft.zanbur
-import com.kernelmaft.zanbur.common.Config.MQTT_SERVER_HOST
-import com.kernelmaft.zanbur.common.Config.MQTT_SERVER_PORT
-import com.kernelmaft.zanbur.common.Config.MQTT_TOPIC
-import io.github.davidepianca98.*
-import io.github.davidepianca98.mqtt.*
-import io.github.davidepianca98.mqtt.MQTTVersion.*
-import io.github.davidepianca98.mqtt.packets.Qos.*
-import io.github.davidepianca98.mqtt.packets.mqtt.*
+import MQTTClient
+import com.kernelmaft.zanbur.Config.MQTT_SERVER_HOST
+import com.kernelmaft.zanbur.Config.MQTT_SERVER_PORT
+import com.kernelmaft.zanbur.Config.MQTT_TOPIC
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.serialization.json.*
+import mqtt.*
+import mqtt.MQTTVersion.*
+import mqtt.packets.Qos.*
+import mqtt.packets.mqtt.*
diff --git a/app/src/main/java/com/kernelmaft/zanbur/common/ontology.kt b/app/src/main/java/com/kernelmaft/zanbur/ontology.kt
similarity index 83%
rename from app/src/main/java/com/kernelmaft/zanbur/common/ontology.kt
rename to app/src/main/java/com/kernelmaft/zanbur/ontology.kt
index 86e8a1c..4bec33e 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/common/ontology.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/ontology.kt
@@ -1,4 +1,4 @@
-package com.kernelmaft.zanbur.common
+package com.kernelmaft.zanbur
diff --git a/app/src/main/java/com/kernelmaft/zanbur/persistence.kt b/app/src/main/java/com/kernelmaft/zanbur/persistence.kt
new file mode 100644
index 0000000..9110f71
--- /dev/null
+++ b/app/src/main/java/com/kernelmaft/zanbur/persistence.kt
@@ -0,0 +1,10 @@
+package com.kernelmaft.zanbur
+
+import android.content.*
+import androidx.datastore.core.*
+import androidx.datastore.preferences.*
+import androidx.datastore.preferences.core.*
+
+
+
+val Context . dataStore : DataStore by preferencesDataStore ("state")
diff --git a/app/src/main/java/com/kernelmaft/zanbur/ui/theme.kt b/app/src/main/java/com/kernelmaft/zanbur/theme.kt
similarity index 94%
rename from app/src/main/java/com/kernelmaft/zanbur/ui/theme.kt
rename to app/src/main/java/com/kernelmaft/zanbur/theme.kt
index 0da4c53..8a95cbc 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/ui/theme.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/theme.kt
@@ -1,4 +1,4 @@
-package com.kernelmaft.zanbur.ui
+package com.kernelmaft.zanbur
import android.os.*
import androidx.activity.*
@@ -29,6 +29,7 @@ open class EdgeToEdgeActivity : ComponentActivity () {
override fun onCreate ( savedInstanceState : Bundle ? ) {
super . onCreate (savedInstanceState)
+ enableEdgeToEdge ()
actionBar ?. hide ()
}
}
diff --git a/app/src/main/java/com/kernelmaft/zanbur/ui/compose-state.kt b/app/src/main/java/com/kernelmaft/zanbur/ui/compose-state.kt
deleted file mode 100644
index 212f254..0000000
--- a/app/src/main/java/com/kernelmaft/zanbur/ui/compose-state.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.kernelmaft.zanbur.ui
-
-import androidx.compose.runtime.*
-import com.kernelmaft.zanbur.common.*
-
-
-
-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/ui/main-activity.kt b/app/src/main/java/com/kernelmaft/zanbur/ui/main-activity.kt
deleted file mode 100644
index 147fd0c..0000000
--- a/app/src/main/java/com/kernelmaft/zanbur/ui/main-activity.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.kernelmaft.zanbur.ui
-
-import android.os.*
-import androidx.activity.compose.*
-import androidx.compose.foundation.layout.*
-import androidx.compose.ui.*
-import androidx.compose.ui.unit.*
-import androidx.lifecycle.*
-import com.kernelmaft.zanbur.common.*
-import com.kernelmaft.zanbur.common.ChangeSource.*
-import com.kernelmaft.zanbur.network.*
-
-
-
-class MainActivity : EdgeToEdgeActivity () {
- override fun onCreate ( savedInstanceState : Bundle ? ) {
- super . onCreate (savedInstanceState)
-
- val groups = createGroupsComposeState ()
-
- 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 ) ) {
- groups . value . forEach { group ->
- SceneSwitcher (group) { newScene ->
- AppState . setCurrentScene ( group , newScene , Local )
- }
- }
- }
- }
- }
-
- MqttClient . run (lifecycleScope)
- }
-}
diff --git a/app/src/main/java/com/kernelmaft/zanbur/network/zigbee2mqtt.kt b/app/src/main/java/com/kernelmaft/zanbur/zigbee2mqtt.kt
similarity index 77%
rename from app/src/main/java/com/kernelmaft/zanbur/network/zigbee2mqtt.kt
rename to app/src/main/java/com/kernelmaft/zanbur/zigbee2mqtt.kt
index e59269f..0dc2d88 100644
--- a/app/src/main/java/com/kernelmaft/zanbur/network/zigbee2mqtt.kt
+++ b/app/src/main/java/com/kernelmaft/zanbur/zigbee2mqtt.kt
@@ -1,7 +1,6 @@
-package com.kernelmaft.zanbur.network
+package com.kernelmaft.zanbur
-import com.kernelmaft.zanbur.common.*
-import com.kernelmaft.zanbur.common.Config.MQTT_TOPIC
+import com.kernelmaft.zanbur.Config.MQTT_TOPIC
import kotlinx.serialization.*
import kotlinx.serialization.json.*
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..30feaa0
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+ Zanbur
+ Zanbur
+
+
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..ced7955
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,8 @@
+
+
+
+
+