Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Optimize Views for Landscape #48

Merged
merged 29 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
86538dc
feature: Optimize Views for Landscape
wba2hi Jan 22, 2024
c782435
chore: Fix Lint Issues
wba2hi Feb 1, 2024
2c96f1f
chore: Move Library into .toml
wba2hi Feb 1, 2024
e175561
chore: Fix z-indexes of Views
wba2hi Feb 1, 2024
8c0796b
chore: Change ConfigurationExtension from fun to val
wba2hi Feb 6, 2024
c2cebd5
chore: Decouple animateLoadingText Logic from ConnectionState
wba2hi Feb 6, 2024
3b12807
chore: Rename Method Name of Previews
wba2hi Feb 6, 2024
d4c7613
chore: Replace VerticalText with Extension
wba2hi Feb 6, 2024
549396f
chore: Save NavigationBar Tab Information
wba2hi Feb 6, 2024
3f4ad10
chore: Align Naming
wba2hi Feb 6, 2024
2915a7d
chore: Re-Add BottomSheet
wba2hi Feb 6, 2024
09f79d5
chore: Replace ConstraintScopeExtension with RamsesAnchor
wba2hi Feb 7, 2024
6df5250
chore: Change Size of NavigationBarIcons
wba2hi Feb 7, 2024
3a82419
chore: Add SideSheet to Landscape Mode
wba2hi Feb 8, 2024
c30add3
chore: Fix Lint Findings
wba2hi Feb 8, 2024
3db8d9d
chore: Disable KTLint Naming Rule
wba2hi Feb 8, 2024
98d3520
chore: Keep Connection Alive on Orientation Change
wba2hi Feb 8, 2024
c6a4bb8
chore: Remove Legacy Code
wba2hi Feb 8, 2024
46c86f2
chore: Remove onSideSheetInitialised Callback
wba2hi Feb 8, 2024
2b780a8
chore: Remove Unused Resources
wba2hi Feb 8, 2024
a3be81b
chore: Change isBottomSheetEnabled to more generic isSheetEnabled
wba2hi Feb 8, 2024
6caf440
chore: Center NavigationRail
wba2hi Feb 9, 2024
696eec9
chore: Add Rounded Corner to SideSheet
wba2hi Feb 9, 2024
2142677
chore: Change Navigation Labels and add Padding
wba2hi Feb 9, 2024
f0088e3
chore: Correctly Register DisconnectListener on Orientation Change
wba2hi Feb 9, 2024
7ecb21c
chore: Align Feature Folder Structure
wba2hi Feb 9, 2024
7b6fbb3
chore: Use Early Return if SideSheet is disabled
wba2hi Feb 9, 2024
a2927ed
chore: Align Subscribe and Unsubscribe
wba2hi Feb 12, 2024
4fbc622
Merge branch 'main' into feature-20
wba2hi Feb 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ ktlint_standard_annotation = disabled # false positive with @JvmOverloads and de
ktlint_function_naming_ignore_when_annotated_with = Composable
ktlint_standard_multiline-expression-wrapping = disabled
ktlint_standard_string-template-indent = disabled
ktlint_standard_property-naming = disabled
4 changes: 4 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.androidx.lifecycle.runtime.compose)

implementation(libs.material)

implementation(libs.ramses.aar)

testImplementation(libs.junit)
Expand All @@ -142,6 +144,8 @@ dependencies {

implementation(libs.hilt.android)
kapt(libs.hilt.android.compiler)

implementation(libs.androidx.material3.window.size.clazz)
}

// Allow references to generated code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ package org.eclipse.kuksa.companion

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()
class CompanionApplication : Application() {
var dataBrokerConnection: DataBrokerConnection? = null
}
68 changes: 38 additions & 30 deletions app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
Expand All @@ -45,12 +45,9 @@ import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel.C
import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel.Companion.DOOR_ALL_OPEN
import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel.Companion.TRUNK_CLOSED
import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel.Companion.TRUNK_OPEN
import org.eclipse.kuksa.companion.feature.home.view.HOME_SCREEN
import org.eclipse.kuksa.companion.feature.home.view.RamsesView
import org.eclipse.kuksa.companion.feature.home.view.homeScreen
import org.eclipse.kuksa.companion.feature.home.view.AdaptiveAppScreen
import org.eclipse.kuksa.companion.feature.home.view.navigation.NavigationViewModel
import org.eclipse.kuksa.companion.feature.light.viewmodel.LightControlViewModel
import org.eclipse.kuksa.companion.feature.settings.navigation.navigateToSettingsScreen
import org.eclipse.kuksa.companion.feature.settings.navigation.settingsScreen
import org.eclipse.kuksa.companion.feature.settings.viewModel.SettingsViewModel
import org.eclipse.kuksa.companion.feature.temperature.viewmodel.TemperatureViewModel
import org.eclipse.kuksa.companion.feature.wheel.pressure.viewmodel.WheelPressureViewModel
Expand All @@ -71,16 +68,21 @@ import javax.inject.Inject
@AndroidEntryPoint
@VssDefinition("vss_rel_4.0.yaml")
class MainActivity : ComponentActivity() {
private val companionApplication
get() = applicationContext as CompanionApplication

@Inject
lateinit var connectionInfoRepository: ConnectionInfoRepository

private lateinit var doorVehicleScene: DoorVehicleScene

private val disconnectListener = DisconnectListener {
dataBrokerConnection = null
connectionStatusViewModel.connectionState = ConnectionState.DISCONNECTED
}

private val connectionStatusViewModel: ConnectionStatusViewModel by viewModels()
private val navigationViewModel: NavigationViewModel by viewModels()

private val doorControlViewModel: DoorControlViewModel by viewModels()
private val temperatureViewModel: TemperatureViewModel by viewModels()
Expand All @@ -89,7 +91,13 @@ class MainActivity : ComponentActivity() {

private val settingsViewModel: SettingsViewModel by viewModels()

private var dataBrokerConnection: DataBrokerConnection? = null
// storing the connection in the Application keeps the Connection alive on orientation changes
private var dataBrokerConnection: DataBrokerConnection?
wba2hi marked this conversation as resolved.
Show resolved Hide resolved
get() = companionApplication.dataBrokerConnection
set(value) {
companionApplication.dataBrokerConnection = value
}

private val dataBrokerConnectorFactory = DataBrokerConnectorFactory()

private val doorVehicleSurface = DoorVehicleSurface()
Expand Down Expand Up @@ -142,32 +150,26 @@ class MainActivity : ComponentActivity() {
}

// region: Lifecycle
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

doorVehicleScene = doorVehicleSurface.loadScene(doorControlViewModel)

setContent {
val windowSizeClass = calculateWindowSizeClass(activity = this@MainActivity)
KuksaCompanionTheme {
val navController = rememberNavController()
RamsesView(callback = doorVehicleSurface)
NavHost(navController, startDestination = HOME_SCREEN) {
homeScreen(
connectionStatusViewModel = connectionStatusViewModel,
doorControlViewModel = doorControlViewModel,
temperatureViewModel = temperatureViewModel,
lightControlViewModel = lightControlViewModel,
wheelPressureViewModel = wheelPressureViewModel,
onNavigateToSettingsScreen = { navController.navigateToSettingsScreen() },
)

settingsScreen(
settingsViewModel = settingsViewModel,
onNavigateBack = {
navController.navigateUp()
},
)
}
AdaptiveAppScreen(
callback = doorVehicleSurface,
connectionStatusViewModel = connectionStatusViewModel,
navigationViewModel = navigationViewModel,
doorControlViewModel = doorControlViewModel,
temperatureViewModel = temperatureViewModel,
lightControlViewModel = lightControlViewModel,
wheelPressureViewModel = wheelPressureViewModel,
settingsViewModel = settingsViewModel,
windowSizeClass = windowSizeClass,
)
}
}
}
Expand Down Expand Up @@ -263,6 +265,8 @@ class MainActivity : ComponentActivity() {

private fun subscribe() {
dataBrokerConnection?.apply {
disconnectListeners.register(disconnectListener)

subscribe(VssDoor(), listener = vssDoorListener)
subscribe(VssTrunk(), listener = vssTrunkListener)
subscribe(VssHvac(), listener = vssTemperatureListener)
Expand Down Expand Up @@ -297,6 +301,12 @@ class MainActivity : ComponentActivity() {
}

private fun connectToDataBroker(onConnected: () -> Unit = {}) {
// dataBrokerConnection is already established e.g. after an orientation change
if (dataBrokerConnection != null) {
onConnected()
Chrylo marked this conversation as resolved.
Show resolved Hide resolved
return
}

lifecycleScope.launch {
val connectionInfo = connectionInfoRepository.connectionInfoFlow.first()

Expand All @@ -306,9 +316,7 @@ class MainActivity : ComponentActivity() {
connectionStatusViewModel.connectionState = ConnectionState.CONNECTING
val context = this@MainActivity
val dataBrokerConnector = dataBrokerConnectorFactory.create(context, connectionInfo)
dataBrokerConnection = dataBrokerConnector.connect().apply {
disconnectListeners.register(disconnectListener)
}
dataBrokerConnection = dataBrokerConnector.connect()
connectionStatusViewModel.connectionState = ConnectionState.CONNECTED
onConnected()
} catch (e: DataBrokerException) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 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.extension

import android.content.res.Configuration
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
val Configuration.windowSizeClass: WindowSizeClass
get() {
val screenWidth = screenWidthDp
val screenHeight = screenHeightDp
val size = DpSize(screenWidth.dp, screenHeight.dp)
return WindowSizeClass.calculateFromSize(size)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 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.extension

import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha

fun Modifier.isVisible(isVisible: Boolean): Modifier {
val alpha = if (isVisible) 1F else 0F

return then(Modifier.alpha(alpha))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 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.extension

fun String.convertToVerticalString(): String {
wba2hi marked this conversation as resolved.
Show resolved Hide resolved
if (isEmpty()) return this

val charArray = toCharArray()
val builder = StringBuilder()
charArray.forEach {
builder.appendLine(it)
}

return builder.toString().dropLast(1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2023 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.feature.connection.view

import androidx.compose.foundation.layout.Box
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
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.extension.windowSizeClass
import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel

@Composable
fun AdaptiveConnectionStatusView(
viewModel: ConnectionStatusViewModel,
windowSizeClass: WindowSizeClass,
modifier: Modifier = Modifier,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
Chrylo marked this conversation as resolved.
Show resolved Hide resolved
HorizontalConnectionStatusView(viewModel, modifier)
} else {
VerticalConnectionStatusView(viewModel, modifier)
}
}

@Preview(widthDp = PREVIEW_WIDTH_DP, heightDp = PREVIEW_HEIGHT_DP)
@Preview(widthDp = PREVIEW_HEIGHT_DP, heightDp = PREVIEW_WIDTH_DP)
@Composable
private fun AdaptiveDisconnectedPreview() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.DISCONNECTED

val windowSizeClass = LocalConfiguration.current.windowSizeClass
Box {
AdaptiveConnectionStatusView(viewModel = viewModel, windowSizeClass)
}
}

@Preview(widthDp = PREVIEW_WIDTH_DP, heightDp = PREVIEW_HEIGHT_DP)
@Preview(widthDp = PREVIEW_HEIGHT_DP, heightDp = PREVIEW_WIDTH_DP)
@Composable
private fun AdaptiveConnectingPreview() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.CONNECTING

val windowSizeClass = LocalConfiguration.current.windowSizeClass
Box {
AdaptiveConnectionStatusView(viewModel = viewModel, windowSizeClass)
}
}

@Preview(widthDp = PREVIEW_WIDTH_DP, heightDp = PREVIEW_HEIGHT_DP)
@Preview(widthDp = PREVIEW_HEIGHT_DP, heightDp = PREVIEW_WIDTH_DP)
@Composable
private fun AdaptiveConnectedStatusPreview() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.CONNECTED

val windowSizeClass = LocalConfiguration.current.windowSizeClass
Box {
AdaptiveConnectionStatusView(viewModel = viewModel, windowSizeClass)
}
}
Loading
Loading