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 4 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
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,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 @@ -22,5 +22,11 @@ package org.eclipse.kuksa.companion
import android.app.Application
import dagger.hilt.android.HiltAndroidApp

const val PREVIEW_WIDTH_DP = 400
const val PREVIEW_HEIGHT_DP = 900

const val SHEET_EXPANDED_HEIGHT = 300
const val SHEET_COLLAPSED_HEIGHT = 50

@HiltAndroidApp
class CompanionApplication : Application()
41 changes: 15 additions & 26 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,8 @@ 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.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 Down Expand Up @@ -142,32 +138,25 @@ 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,
doorControlViewModel = doorControlViewModel,
temperatureViewModel = temperatureViewModel,
lightControlViewModel = lightControlViewModel,
wheelPressureViewModel = wheelPressureViewModel,
settingsViewModel = settingsViewModel,
windowSizeClass = windowSizeClass,
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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.runtime.Composable
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
wba2hi marked this conversation as resolved.
Show resolved Hide resolved
fun Configuration.getWindowSizeClass(): WindowSizeClass {
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,93 @@
/*
* 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.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.constraintlayout.compose.ConstrainScope
import androidx.constraintlayout.compose.ConstrainedLayoutReference
import org.eclipse.kuksa.companion.feature.door.view.horizontalMarginAnchorToDoor
import org.eclipse.kuksa.companion.feature.door.view.verticalMarginAnchorToBackDoor
import org.eclipse.kuksa.companion.feature.door.view.verticalMarginAnchorToDoor

fun ConstrainScope.alignDriverFrontDoor(
Chrylo marked this conversation as resolved.
Show resolved Hide resolved
windowSizeClass: WindowSizeClass,
anchorPoint: ConstrainedLayoutReference,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
end.linkTo(anchorPoint.start, horizontalMarginAnchorToDoor)
top.linkTo(anchorPoint.bottom, verticalMarginAnchorToDoor)
} else {
end.linkTo(anchorPoint.start, verticalMarginAnchorToDoor)
bottom.linkTo(anchorPoint.top, horizontalMarginAnchorToDoor)
}
}

fun ConstrainScope.alignPassengerFrontDoor(
windowSizeClass: WindowSizeClass,
anchorPoint: ConstrainedLayoutReference,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
start.linkTo(anchorPoint.end, horizontalMarginAnchorToDoor)
top.linkTo(anchorPoint.bottom, verticalMarginAnchorToDoor)
} else {
end.linkTo(anchorPoint.start, verticalMarginAnchorToDoor)
top.linkTo(anchorPoint.bottom, horizontalMarginAnchorToDoor)
}
}

fun ConstrainScope.alignDriverBackDoor(
windowSizeClass: WindowSizeClass,
anchorPoint: ConstrainedLayoutReference,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
end.linkTo(anchorPoint.start, horizontalMarginAnchorToDoor)
top.linkTo(anchorPoint.bottom, verticalMarginAnchorToBackDoor)
} else {
end.linkTo(anchorPoint.start, verticalMarginAnchorToBackDoor)
bottom.linkTo(anchorPoint.top, horizontalMarginAnchorToDoor)
}
}

fun ConstrainScope.alignPassengerBackDoor(
windowSizeClass: WindowSizeClass,
anchorPoint: ConstrainedLayoutReference,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
start.linkTo(anchorPoint.end, horizontalMarginAnchorToDoor)
top.linkTo(anchorPoint.bottom, verticalMarginAnchorToBackDoor)
} else {
end.linkTo(anchorPoint.start, verticalMarginAnchorToBackDoor)
top.linkTo(anchorPoint.bottom, horizontalMarginAnchorToDoor)
}
}

fun ConstrainScope.alignTrunk(
windowSizeClass: WindowSizeClass,
anchorPoint: ConstrainedLayoutReference,
) {
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
centerHorizontallyTo(anchorPoint)
bottom.linkTo(parent.bottom)
} else {
centerVerticallyTo(anchorPoint)
start.linkTo(parent.start)
}
}
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,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.getWindowSizeClass
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 AdaptiveConnectionStatusViewPreview_Disconnected() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.DISCONNECTED

val windowSizeClass = LocalConfiguration.current.getWindowSizeClass()
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 AdaptiveConnectionStatusViewPreview_Connecting() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.CONNECTING

val windowSizeClass = LocalConfiguration.current.getWindowSizeClass()
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 AdaptiveConnectionStatusViewPreview_Connected() {
val viewModel = ConnectionStatusViewModel()
viewModel.connectionState = ConnectionStatusViewModel.ConnectionState.CONNECTED

val windowSizeClass = LocalConfiguration.current.getWindowSizeClass()
Box {
AdaptiveConnectionStatusView(viewModel = viewModel, windowSizeClass)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import kotlinx.coroutines.delay
import org.eclipse.kuksa.companion.feature.connection.viewModel.ConnectionStatusViewModel.ConnectionState
import kotlin.time.Duration.Companion.milliseconds

private const val MAX_NUMBER_OF_DOTS = 3
wba2hi marked this conversation as resolved.
Show resolved Hide resolved
private val DelayDuration = 500.milliseconds

@Composable
fun animateLoadingText(
connectionState: ConnectionState,
wba2hi marked this conversation as resolved.
Show resolved Hide resolved
text: String,
): String {
var animatedText = text
if (connectionState == ConnectionState.CONNECTING) {
val numberOfDots = remember {
mutableIntStateOf(0)
}
repeat(numberOfDots.intValue) {
animatedText += "."
}
LaunchedEffect(Unit) {
while (true) {
if (numberOfDots.intValue < MAX_NUMBER_OF_DOTS) {
numberOfDots.intValue += 1
} else {
numberOfDots.intValue = 0
}
delay(DelayDuration)
}
}
}
return animatedText
}
Loading
Loading