From 0c41debb8fabb56105fcaefe8cbdf3240090e9d1 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Mon, 19 Feb 2024 13:16:34 +0100 Subject: [PATCH 1/2] feature: Move Stateful Data into ViewModels closes: #55 --- app/src/main/AndroidManifest.xml | 2 +- .../eclipse/kuksa/companion/MainActivity.kt | 118 +++++------------- .../application/ApplicationViewModel.kt | 31 +++++ .../{ => application}/CompanionApplication.kt | 10 +- .../door/surface/DoorVehicleSceneThread.kt | 7 +- .../door/surface/DoorVehicleSurface.kt | 2 + .../feature/door/view/DoorControlView.kt | 4 +- .../feature/door/view/DoorOverlayView.kt | 4 +- .../door/viewModel/DoorControlViewModel.kt | 35 ++++-- .../feature/home/view/AdaptiveAppScreen.kt | 4 +- .../feature/light/view/LightOverlayView.kt | 4 +- .../light/viewmodel/LightControlViewModel.kt | 14 +++ .../navigation/view/AdaptiveNavigationView.kt | 4 +- .../feature/sheet/view/AdaptiveSheetView.kt | 4 +- .../feature/sheet/view/SideSheetView.kt | 6 +- .../view/TemperatureOverlayView.kt | 4 +- .../viewmodel/TemperatureViewModel.kt | 15 +++ .../pressure/view/WheelPressureOverlayView.kt | 4 +- .../viewmodel/WheelPressureViewModel.kt | 15 +++ 19 files changed, 164 insertions(+), 123 deletions(-) create mode 100644 app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt rename app/src/main/kotlin/org/eclipse/kuksa/companion/{ => application}/CompanionApplication.kt (73%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 07f0fec..eb46c43 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,7 +23,7 @@ () { - override fun onSpecificationChanged(vssSpecification: VssDoor) { - doorVehicleScene.updateDoors(vssSpecification) - } - - override fun onPostFilterError(throwable: Throwable) { - Log.e(TAG, "Failed to subscribe to specification: $throwable") - } - } - private val vssTrunkListener = object : FilteredVssSpecificationListener() { - override fun onSpecificationChanged(vssSpecification: VssTrunk) { - doorVehicleScene.updateTrunk(vssSpecification) - } - - override fun onPostFilterError(throwable: Throwable) { - Log.e(TAG, "Failed to subscribe to specification: $throwable") - } - } - private val vssTemperatureListener = object : FilteredVssSpecificationListener() { - override fun onSpecificationChanged(vssSpecification: VssHvac) { - temperatureViewModel.hvac = vssSpecification - } - - override fun onPostFilterError(throwable: Throwable) { - Log.e(TAG, "Failed to subscribe to specification: $throwable") - } - } - private val vssWheelPressureListener = object : FilteredVssSpecificationListener() { - override fun onSpecificationChanged(vssSpecification: VssAxle) { - wheelPressureViewModel.axle = vssSpecification - } - - override fun onPostFilterError(throwable: Throwable) { - Log.e(TAG, "Failed to subscribe to specification: $throwable") - } - } - - private val vssLightListener = object : FilteredVssSpecificationListener() { - override fun onSpecificationChanged(vssSpecification: VssLights) { - lightControlViewModel.vssLight = vssSpecification - } - - override fun onPostFilterError(throwable: Throwable) { - Log.e(TAG, "Failed to subscribe to specification: $throwable") - } - } - // region: Lifecycle @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) override fun onCreate(savedInstanceState: Bundle?) { @@ -177,6 +120,21 @@ class MainActivity : ComponentActivity() { override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) + doorControlViewModel.doorVehicleSceneDelegate = object : DoorVehicleScene { + override fun updateDoors(door: VssDoor) { + doorVehicleScene.updateDoors(door) + } + + override fun updateTrunk(trunk: VssTrunk) { + doorVehicleScene.updateTrunk(trunk) + } + } + + applicationViewModel.disconnectListener = DisconnectListener { + applicationViewModel.dataBrokerConnection = null + connectionStatusViewModel.connectionState = ConnectionState.DISCONNECTED + } + connectionStatusViewModel.onClickReconnect = { connectToDataBroker { subscribe() @@ -238,14 +196,6 @@ class MainActivity : ComponentActivity() { doorVehicleSurface.stopRendering() } - override fun onDestroy() { - super.onDestroy() - - dataBrokerConnection?.disconnectListeners?.unregister(disconnectListener) - - unsubscribe() - } - // endregion private fun updatePlannedTemperature(plannedTemperature: Int) { @@ -265,25 +215,25 @@ class MainActivity : ComponentActivity() { private fun subscribe() { dataBrokerConnection?.apply { - disconnectListeners.register(disconnectListener) + disconnectListeners.register(applicationViewModel.disconnectListener) - subscribe(VssDoor(), listener = vssDoorListener) - subscribe(VssTrunk(), listener = vssTrunkListener) - subscribe(VssHvac(), listener = vssTemperatureListener) - subscribe(VssAxle(), listener = vssWheelPressureListener) - subscribe(VssLights(), listener = vssLightListener) + subscribe(VssDoor(), listener = doorControlViewModel.vssDoorListener) + subscribe(VssTrunk(), listener = doorControlViewModel.vssTrunkListener) + subscribe(VssHvac(), listener = temperatureViewModel.vssTemperatureListener) + subscribe(VssAxle(), listener = wheelPressureViewModel.vssWheelPressureListener) + subscribe(VssLights(), listener = lightControlViewModel.vssLightListener) } } private fun unsubscribe() { dataBrokerConnection?.apply { - disconnectListeners.unregister(disconnectListener) + disconnectListeners.unregister(applicationViewModel.disconnectListener) - unsubscribe(VssDoor(), listener = vssDoorListener) - unsubscribe(VssTrunk(), listener = vssTrunkListener) - unsubscribe(VssHvac(), listener = vssTemperatureListener) - unsubscribe(VssAxle(), listener = vssWheelPressureListener) - unsubscribe(VssLights(), listener = vssLightListener) + unsubscribe(VssDoor(), listener = doorControlViewModel.vssDoorListener) + unsubscribe(VssTrunk(), listener = doorControlViewModel.vssTrunkListener) + unsubscribe(VssHvac(), listener = temperatureViewModel.vssTemperatureListener) + unsubscribe(VssAxle(), listener = wheelPressureViewModel.vssWheelPressureListener) + unsubscribe(VssLights(), listener = lightControlViewModel.vssLightListener) } } diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt new file mode 100644 index 0000000..f675e92 --- /dev/null +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023-2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.companion.application + +import androidx.lifecycle.ViewModel +import org.eclipse.kuksa.DataBrokerConnection +import org.eclipse.kuksa.DisconnectListener +import kotlin.properties.Delegates + +class ApplicationViewModel : ViewModel() { + var dataBrokerConnection: DataBrokerConnection? = null + + var disconnectListener: DisconnectListener by Delegates.notNull() +} diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/CompanionApplication.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/application/CompanionApplication.kt similarity index 73% rename from app/src/main/kotlin/org/eclipse/kuksa/companion/CompanionApplication.kt rename to app/src/main/kotlin/org/eclipse/kuksa/companion/application/CompanionApplication.kt index 8551eba..b70f35a 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/CompanionApplication.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/application/CompanionApplication.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023-2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,19 +17,15 @@ * */ -package org.eclipse.kuksa.companion +package org.eclipse.kuksa.companion.application import android.app.Application import dagger.hilt.android.HiltAndroidApp -import org.eclipse.kuksa.DataBrokerConnection const val PREVIEW_WIDTH_DP = 400 const val PREVIEW_HEIGHT_DP = 900 const val SHEET_EXPANDED_HEIGHT = 350 -const val SHEET_COLLAPSED_HEIGHT = 50 @HiltAndroidApp -class CompanionApplication : Application() { - var dataBrokerConnection: DataBrokerConnection? = null -} +class CompanionApplication : Application() diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSceneThread.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSceneThread.kt index 30a1df8..82e2507 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSceneThread.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSceneThread.kt @@ -185,8 +185,6 @@ class DoorVehicleSceneThread( // region: VehicleScene override fun updateDoors(door: VssDoor) { - viewModel.updateDoors(door) - addRunnableToThreadQueue { door.findProperties(VssDoor.VssRow1.VssPassengerSide.VssIsOpen::class).apply { doorRow1DriverSide = getOrDefault(doorRow1DriverSide.vssPath, doorRow1DriverSide) @@ -198,8 +196,9 @@ class DoorVehicleSceneThread( } override fun updateTrunk(trunk: VssTrunk) { - viewModel.updateTrunk(trunk) - doorTrunkRear = trunk.findProperty(VssTrunk.VssRear.VssIsOpen()) + addRunnableToThreadQueue { + doorTrunkRear = trunk.findProperty(VssTrunk.VssRear.VssIsOpen()) + } } // endregion diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSurface.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSurface.kt index df7b382..c80d843 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSurface.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/door/surface/DoorVehicleSurface.kt @@ -48,6 +48,8 @@ class DoorVehicleSurface : AndroidRamsesSurface() { + override fun onSpecificationChanged(vssSpecification: VssDoor) { + door = vssSpecification + doorVehicleSceneDelegate?.updateDoors(vssSpecification) + } + + override fun onPostFilterError(throwable: Throwable) { + Log.e(TAG, "Failed to subscribe to specification: $throwable") + } + } + val vssTrunkListener = object : FilteredVssSpecificationListener() { + override fun onSpecificationChanged(vssSpecification: VssTrunk) { + trunk = vssSpecification + doorVehicleSceneDelegate?.updateTrunk(vssSpecification) + } + + override fun onPostFilterError(throwable: Throwable) { + Log.e(TAG, "Failed to subscribe to specification: $throwable") + } + } + var onClickOpenAll: () -> Unit = {} var onClickCloseAll: () -> Unit = {} @@ -45,14 +72,6 @@ class DoorControlViewModel(application: Application) : AndroidViewModel(applicat var door: VssDoor by mutableStateOf(VssDoor()) private set - fun updateDoors(door: VssDoor) { - this.door = door - } - - fun updateTrunk(trunk: VssTrunk) { - this.trunk = trunk - } - @DrawableRes fun fetchLockDrawable(isLocked: Boolean): Int { return if (isLocked) { diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt index 8473611..c08a419 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt @@ -38,8 +38,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.connection.repository.ConnectionInfoRepository import org.eclipse.kuksa.companion.feature.connection.view.HorizontalConnectionStatusView diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/view/LightOverlayView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/view/LightOverlayView.kt index 5269995..5bb07a6 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/view/LightOverlayView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/view/LightOverlayView.kt @@ -33,9 +33,9 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.R +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.home.view.AdaptiveFlowColumnRow import org.eclipse.kuksa.companion.feature.light.viewmodel.LightControlViewModel diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/viewmodel/LightControlViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/viewmodel/LightControlViewModel.kt index a89d0ad..6085f10 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/viewmodel/LightControlViewModel.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/light/viewmodel/LightControlViewModel.kt @@ -19,17 +19,31 @@ package org.eclipse.kuksa.companion.feature.light.viewmodel +import android.util.Log import androidx.annotation.DrawableRes import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel +import org.eclipse.kuksa.VssSpecificationListener import org.eclipse.kuksa.companion.R +import org.eclipse.kuksa.companion.extension.TAG +import org.eclipse.kuksa.companion.listener.FilteredVssSpecificationListener import org.eclipse.kuksa.vss.VssLights import org.eclipse.kuksa.vsscore.model.VssProperty class LightControlViewModel : ViewModel() { + var vssLightListener: VssSpecificationListener = object : FilteredVssSpecificationListener() { + override fun onSpecificationChanged(vssSpecification: VssLights) { + vssLight = vssSpecification + } + + override fun onPostFilterError(throwable: Throwable) { + Log.e(TAG, "Failed to subscribe to specification: $throwable") + } + } + var onClickToggleLight: (VssProperty) -> Unit = { } var vssLight: VssLights by mutableStateOf(VssLights()) diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/navigation/view/AdaptiveNavigationView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/navigation/view/AdaptiveNavigationView.kt index aae5eee..e535a01 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/navigation/view/AdaptiveNavigationView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/navigation/view/AdaptiveNavigationView.kt @@ -25,8 +25,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.navigation.NavigationPage import org.eclipse.kuksa.companion.feature.navigation.viewmodel.NavigationViewModel diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/AdaptiveSheetView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/AdaptiveSheetView.kt index 7f16ddc..6997557 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/AdaptiveSheetView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/AdaptiveSheetView.kt @@ -27,8 +27,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass /** diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/SideSheetView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/SideSheetView.kt index 8b0ac3b..9f63aaa 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/SideSheetView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/sheet/view/SideSheetView.kt @@ -47,10 +47,10 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.constraintlayout.compose.ConstraintLayout import androidx.coordinatorlayout.widget.CoordinatorLayout import com.google.android.material.sidesheet.SideSheetBehavior -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.R -import org.eclipse.kuksa.companion.SHEET_EXPANDED_HEIGHT +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.SHEET_EXPANDED_HEIGHT import org.eclipse.kuksa.companion.feature.connection.repository.ConnectionInfoRepository import org.eclipse.kuksa.companion.feature.settings.view.SettingsView import org.eclipse.kuksa.companion.feature.settings.viewModel.SettingsViewModel diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/view/TemperatureOverlayView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/view/TemperatureOverlayView.kt index f0867b8..aa639e8 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/view/TemperatureOverlayView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/view/TemperatureOverlayView.kt @@ -32,8 +32,8 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.temperature.viewmodel.TemperatureViewModel import org.eclipse.kuksa.companion.ramses.DriverBackDoorAnchor diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/viewmodel/TemperatureViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/viewmodel/TemperatureViewModel.kt index fd22765..8f11bd7 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/viewmodel/TemperatureViewModel.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/temperature/viewmodel/TemperatureViewModel.kt @@ -19,6 +19,7 @@ package org.eclipse.kuksa.companion.feature.temperature.viewmodel +import android.util.Log import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -26,13 +27,27 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.graphics.Color import androidx.lifecycle.ViewModel +import org.eclipse.kuksa.VssSpecificationListener import org.eclipse.kuksa.companion.extension.LightBlue +import org.eclipse.kuksa.companion.extension.TAG +import org.eclipse.kuksa.companion.listener.FilteredVssSpecificationListener import org.eclipse.kuksa.vss.VssHvac private const val MIN_TEMP_OK = 17F private const val MIN_TEMP_WARM = 25F class TemperatureViewModel : ViewModel() { + var vssTemperatureListener: VssSpecificationListener = + object : FilteredVssSpecificationListener() { + override fun onSpecificationChanged(vssSpecification: VssHvac) { + hvac = vssSpecification + } + + override fun onPostFilterError(throwable: Throwable) { + Log.e(TAG, "Failed to subscribe to specification: $throwable") + } + } + val minTemperature = 10 val maxTemperature = 35 diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/view/WheelPressureOverlayView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/view/WheelPressureOverlayView.kt index e61cf11..a423c63 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/view/WheelPressureOverlayView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/view/WheelPressureOverlayView.kt @@ -33,8 +33,8 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout -import org.eclipse.kuksa.companion.PREVIEW_HEIGHT_DP -import org.eclipse.kuksa.companion.PREVIEW_WIDTH_DP +import org.eclipse.kuksa.companion.application.PREVIEW_HEIGHT_DP +import org.eclipse.kuksa.companion.application.PREVIEW_WIDTH_DP import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.wheel.pressure.viewmodel.WheelPressureViewModel import org.eclipse.kuksa.companion.ramses.DriverBackDoorAnchor diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/viewmodel/WheelPressureViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/viewmodel/WheelPressureViewModel.kt index f28cf5e..b64d72a 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/viewmodel/WheelPressureViewModel.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/wheel/pressure/viewmodel/WheelPressureViewModel.kt @@ -19,14 +19,29 @@ package org.eclipse.kuksa.companion.feature.wheel.pressure.viewmodel +import android.util.Log import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel +import org.eclipse.kuksa.VssSpecificationListener +import org.eclipse.kuksa.companion.extension.TAG +import org.eclipse.kuksa.companion.listener.FilteredVssSpecificationListener import org.eclipse.kuksa.vss.VssAxle class WheelPressureViewModel : ViewModel() { + var vssWheelPressureListener: VssSpecificationListener = + object : FilteredVssSpecificationListener() { + override fun onSpecificationChanged(vssSpecification: VssAxle) { + axle = vssSpecification + } + + override fun onPostFilterError(throwable: Throwable) { + Log.e(TAG, "Failed to subscribe to specification: $throwable") + } + } + var axle by mutableStateOf(VssAxle()) val pressureLeftFront by derivedStateOf { From 8417d535a933a9c10f124103bef62bf38a64d8ab Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 22 Feb 2024 07:22:55 +0100 Subject: [PATCH 2/2] chore: Move Logic from ApplicationViewModel into ConnectionViewModel --- .../eclipse/kuksa/companion/MainActivity.kt | 47 +++++-------------- .../application/ApplicationViewModel.kt | 31 ------------ .../view/HorizontalConnectionStatusView.kt | 12 ++--- ...tusViewModel.kt => ConnectionViewModel.kt} | 15 +++++- .../feature/home/view/AdaptiveAppScreen.kt | 10 ++-- 5 files changed, 37 insertions(+), 78 deletions(-) delete mode 100644 app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt rename app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/{ConnectionStatusViewModel.kt => ConnectionViewModel.kt} (65%) diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt index d8f95b2..93a980f 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt @@ -32,13 +32,11 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import org.eclipse.kuksa.DataBrokerConnection import org.eclipse.kuksa.DataBrokerException -import org.eclipse.kuksa.DisconnectListener -import org.eclipse.kuksa.companion.application.ApplicationViewModel import org.eclipse.kuksa.companion.extension.TAG import org.eclipse.kuksa.companion.feature.connection.factory.DataBrokerConnectorFactory import org.eclipse.kuksa.companion.feature.connection.repository.ConnectionInfoRepository -import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel -import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel.ConnectionState +import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionViewModel +import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionViewModel.ConnectionState import org.eclipse.kuksa.companion.feature.door.surface.DoorVehicleScene import org.eclipse.kuksa.companion.feature.door.surface.DoorVehicleSurface import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel @@ -74,8 +72,7 @@ class MainActivity : ComponentActivity() { private lateinit var doorVehicleScene: DoorVehicleScene private val doorVehicleSurface = DoorVehicleSurface() - private val applicationViewModel: ApplicationViewModel by viewModels() - private val connectionStatusViewModel: ConnectionStatusViewModel by viewModels() + private val connectionViewModel: ConnectionViewModel by viewModels() private val navigationViewModel: NavigationViewModel by viewModels() private val doorControlViewModel: DoorControlViewModel by viewModels() private val temperatureViewModel: TemperatureViewModel by viewModels() @@ -85,11 +82,11 @@ class MainActivity : ComponentActivity() { private val dataBrokerConnectorFactory = DataBrokerConnectorFactory() - // storing the connection in the Application keeps the Connection alive on orientation changes + // storing the connection in the ViewModel keeps the Connection alive on orientation changes private var dataBrokerConnection: DataBrokerConnection? - get() = applicationViewModel.dataBrokerConnection + get() = connectionViewModel.dataBrokerConnection set(value) { - applicationViewModel.dataBrokerConnection = value + connectionViewModel.dataBrokerConnection = value } // region: Lifecycle @@ -104,7 +101,7 @@ class MainActivity : ComponentActivity() { KuksaCompanionTheme { AdaptiveAppScreen( callback = doorVehicleSurface, - connectionStatusViewModel = connectionStatusViewModel, + connectionViewModel = connectionViewModel, navigationViewModel = navigationViewModel, doorControlViewModel = doorControlViewModel, temperatureViewModel = temperatureViewModel, @@ -130,12 +127,7 @@ class MainActivity : ComponentActivity() { } } - applicationViewModel.disconnectListener = DisconnectListener { - applicationViewModel.dataBrokerConnection = null - connectionStatusViewModel.connectionState = ConnectionState.DISCONNECTED - } - - connectionStatusViewModel.onClickReconnect = { + connectionViewModel.onClickReconnect = { connectToDataBroker { subscribe() } @@ -215,8 +207,6 @@ class MainActivity : ComponentActivity() { private fun subscribe() { dataBrokerConnection?.apply { - disconnectListeners.register(applicationViewModel.disconnectListener) - subscribe(VssDoor(), listener = doorControlViewModel.vssDoorListener) subscribe(VssTrunk(), listener = doorControlViewModel.vssTrunkListener) subscribe(VssHvac(), listener = temperatureViewModel.vssTemperatureListener) @@ -225,18 +215,6 @@ class MainActivity : ComponentActivity() { } } - private fun unsubscribe() { - dataBrokerConnection?.apply { - disconnectListeners.unregister(applicationViewModel.disconnectListener) - - unsubscribe(VssDoor(), listener = doorControlViewModel.vssDoorListener) - unsubscribe(VssTrunk(), listener = doorControlViewModel.vssTrunkListener) - unsubscribe(VssHvac(), listener = temperatureViewModel.vssTemperatureListener) - unsubscribe(VssAxle(), listener = wheelPressureViewModel.vssWheelPressureListener) - unsubscribe(VssLights(), listener = lightControlViewModel.vssLightListener) - } - } - private fun updateSpecification( vararg specifications: VssSpecification, fields: List = listOf(Field.FIELD_VALUE), @@ -254,8 +232,7 @@ class MainActivity : ComponentActivity() { private fun connectToDataBroker(onConnected: () -> Unit = {}) { // dataBrokerConnection is already established e.g. after an orientation change - if (dataBrokerConnection != null) { - onConnected() + if (connectionViewModel.connectionState == ConnectionState.CONNECTED) { return } @@ -265,15 +242,15 @@ class MainActivity : ComponentActivity() { try { Log.d(TAG, "Connecting to DataBroker ${connectionInfo.host}:${connectionInfo.port}") - connectionStatusViewModel.connectionState = ConnectionState.CONNECTING + connectionViewModel.connectionState = ConnectionState.CONNECTING val context = this@MainActivity val dataBrokerConnector = dataBrokerConnectorFactory.create(context, connectionInfo) dataBrokerConnection = dataBrokerConnector.connect() - connectionStatusViewModel.connectionState = ConnectionState.CONNECTED + connectionViewModel.connectionState = ConnectionState.CONNECTED onConnected() } catch (e: DataBrokerException) { Log.w(TAG, "Connection to DataBroker failed: ", e) - connectionStatusViewModel.connectionState = ConnectionState.DISCONNECTED + connectionViewModel.connectionState = ConnectionState.DISCONNECTED } } } diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt deleted file mode 100644 index f675e92..0000000 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/application/ApplicationViewModel.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023-2024 Contributors to the Eclipse Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -package org.eclipse.kuksa.companion.application - -import androidx.lifecycle.ViewModel -import org.eclipse.kuksa.DataBrokerConnection -import org.eclipse.kuksa.DisconnectListener -import kotlin.properties.Delegates - -class ApplicationViewModel : ViewModel() { - var dataBrokerConnection: DataBrokerConnection? = null - - var disconnectListener: DisconnectListener by Delegates.notNull() -} diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/view/HorizontalConnectionStatusView.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/view/HorizontalConnectionStatusView.kt index a69485f..481d51b 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/view/HorizontalConnectionStatusView.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/view/HorizontalConnectionStatusView.kt @@ -42,8 +42,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.eclipse.kuksa.companion.R -import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel -import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel.ConnectionState +import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionViewModel +import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionViewModel.ConnectionState val StatusBarHeight = 50.dp private val iconSize = 30.dp @@ -52,7 +52,7 @@ private val paddingEnd = 5.dp @Composable fun HorizontalConnectionStatusView( - viewModel: ConnectionStatusViewModel, + viewModel: ConnectionViewModel, modifier: Modifier = Modifier, ) { val connectionState = viewModel.connectionState @@ -113,7 +113,7 @@ fun HorizontalConnectionStatusView( @Preview @Composable private fun HorizontalDisconnectedPreview() { - val viewModel = ConnectionStatusViewModel() + val viewModel = ConnectionViewModel() viewModel.connectionState = ConnectionState.DISCONNECTED HorizontalConnectionStatusView(viewModel = viewModel) @@ -122,7 +122,7 @@ private fun HorizontalDisconnectedPreview() { @Preview @Composable private fun HorizontalConnectingPreview() { - val viewModel = ConnectionStatusViewModel() + val viewModel = ConnectionViewModel() viewModel.connectionState = ConnectionState.CONNECTING HorizontalConnectionStatusView(viewModel = viewModel) } @@ -130,7 +130,7 @@ private fun HorizontalConnectingPreview() { @Preview @Composable private fun HorizontalConnectedPreview() { - val viewModel = ConnectionStatusViewModel() + val viewModel = ConnectionViewModel() viewModel.connectionState = ConnectionState.CONNECTED HorizontalConnectionStatusView(viewModel = viewModel) } diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionStatusViewModel.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionViewModel.kt similarity index 65% rename from app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionStatusViewModel.kt rename to app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionViewModel.kt index 78bd3b9..1741ae3 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionStatusViewModel.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/connection/viewModel/ConnectionViewModel.kt @@ -23,8 +23,11 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel +import org.eclipse.kuksa.DataBrokerConnection +import org.eclipse.kuksa.DisconnectListener +import kotlin.properties.Delegates -class ConnectionStatusViewModel : ViewModel() { +class ConnectionViewModel : ViewModel() { enum class ConnectionState { DISCONNECTED, CONNECTING, @@ -34,4 +37,14 @@ class ConnectionStatusViewModel : ViewModel() { var onClickReconnect: () -> Unit = { } var connectionState by mutableStateOf(ConnectionState.DISCONNECTED) + + var dataBrokerConnection: DataBrokerConnection? by Delegates.observable(null) { _, oldValue, newValue -> + oldValue?.disconnectListeners?.unregister(disconnectListener) + newValue?.disconnectListeners?.register(disconnectListener) + } + + private var disconnectListener: DisconnectListener = DisconnectListener { + dataBrokerConnection = null + connectionState = ConnectionState.DISCONNECTED + } } diff --git a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt index c08a419..29c0706 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/companion/feature/home/view/AdaptiveAppScreen.kt @@ -44,7 +44,7 @@ import org.eclipse.kuksa.companion.extension.windowSizeClass import org.eclipse.kuksa.companion.feature.connection.repository.ConnectionInfoRepository import org.eclipse.kuksa.companion.feature.connection.view.HorizontalConnectionStatusView import org.eclipse.kuksa.companion.feature.connection.view.StatusBarHeight -import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel +import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionViewModel import org.eclipse.kuksa.companion.feature.door.view.DoorControlView import org.eclipse.kuksa.companion.feature.door.view.DoorOverlayView import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel @@ -75,7 +75,7 @@ private const val Z_INDEX_ERROR = 2F @Composable fun AdaptiveAppScreen( callback: SurfaceHolder.Callback, - connectionStatusViewModel: ConnectionStatusViewModel, + connectionViewModel: ConnectionViewModel, navigationViewModel: NavigationViewModel, doorControlViewModel: DoorControlViewModel, temperatureViewModel: TemperatureViewModel, @@ -115,10 +115,10 @@ fun AdaptiveAppScreen( ) { Box { var connectionStatusViewPaddingValues = PaddingValues(0.dp) - if (connectionStatusViewModel.connectionState != ConnectionStatusViewModel.ConnectionState.CONNECTED) { + if (connectionViewModel.connectionState != ConnectionViewModel.ConnectionState.CONNECTED) { connectionStatusViewPaddingValues = PaddingValues(top = StatusBarHeight) HorizontalConnectionStatusView( - connectionStatusViewModel, + connectionViewModel, Modifier .zIndex(Z_INDEX_ERROR), ) @@ -201,7 +201,7 @@ private fun AdaptiveAppScreenPreview() { val repository = ConnectionInfoRepository(context) AdaptiveAppScreen( callback, - ConnectionStatusViewModel(), + ConnectionViewModel(), NavigationViewModel().apply { selectedNavigationIndex = NavigationPage.SETTINGS.ordinal selectedNavigationPage = NavigationPage.SETTINGS