diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index decedb2..99794b1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,7 @@ tools:targetApi="31"> diff --git a/app/src/main/java/com/example/tvcontroller/ui/views/CameraView.kt b/app/src/main/java/com/example/tvcontroller/ui/views/CameraView.kt index 940e886..6f584f4 100644 --- a/app/src/main/java/com/example/tvcontroller/ui/views/CameraView.kt +++ b/app/src/main/java/com/example/tvcontroller/ui/views/CameraView.kt @@ -1,10 +1,17 @@ package com.example.tvcontroller.ui.views +import android.content.res.Configuration +import android.util.Log import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.dp import com.example.tvcontroller.ui.components.CameraPreview import org.webrtc.EglBase @@ -12,11 +19,16 @@ import org.webrtc.VideoTrack @Composable fun CameraView(eglBaseContext: EglBase.Context, videoTrack: VideoTrack) { + val configuration = LocalConfiguration.current + val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + var ratio = if (isLandscape) 16/9f else 9/16f Box( modifier = Modifier - .fillMaxSize() - .padding(all = 16.dp), + .fillMaxSize(), + contentAlignment = Alignment.Center ) { - CameraPreview(eglBaseContext = eglBaseContext, videoTrack = videoTrack, modifier = Modifier.fillMaxSize()) + Box(modifier = if (isLandscape) Modifier.aspectRatio(ratio).fillMaxHeight() else Modifier.aspectRatio(ratio).fillMaxWidth()) { + CameraPreview(eglBaseContext = eglBaseContext, videoTrack = videoTrack, modifier = Modifier.fillMaxSize()) + } } } diff --git a/app/src/main/java/com/example/tvcontroller/ui/views/MainView.kt b/app/src/main/java/com/example/tvcontroller/ui/views/MainView.kt index a03688e..0641de0 100644 --- a/app/src/main/java/com/example/tvcontroller/ui/views/MainView.kt +++ b/app/src/main/java/com/example/tvcontroller/ui/views/MainView.kt @@ -1,16 +1,28 @@ package com.example.tvcontroller.ui.views +import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationRail +import androidx.compose.material3.NavigationRailItem import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -26,6 +38,13 @@ import com.example.tvcontroller.ui.views.MainViewModel.Companion.CAMERA_VIEW import com.example.tvcontroller.ui.views.MainViewModel.Companion.REMOTE_VIEW import com.example.tvcontroller.ui.views.MainViewModel.Companion.SETTINGS_VIEW +private data class NavigationItem( + var onClick: () -> Unit = {}, + var icon: @Composable () -> Unit = {}, + var label: @Composable () -> Unit = {}, + var selected: Boolean = false +) + @Composable fun MainView( deviceService: DeviceService, @@ -41,54 +60,91 @@ fun MainView( val baselineCamera24 = painterResource(R.drawable.baseline_camera_24) val baselineRemote24 = painterResource(R.drawable.baseline_settings_remote_24) val baselineSettings24 = painterResource(R.drawable.baseline_settings_24) - Scaffold(modifier = Modifier.fillMaxSize(), bottomBar = { - NavigationBar { - NavigationBarItem( - onClick = { navController.navigate(CAMERA_VIEW) }, icon = { - Icon( - baselineCamera24, contentDescription = "Camera" - ) - }, label = { Text("Camera") }, selected = currentView == CAMERA_VIEW - ) - NavigationBarItem( - onClick = { navController.navigate(REMOTE_VIEW) }, icon = { - Icon( - baselineRemote24, contentDescription = "Remote" - ) - }, label = { Text("Remote") }, selected = currentView == REMOTE_VIEW - ) - NavigationBarItem( - onClick = { navController.navigate(SETTINGS_VIEW) }, - icon = { - Icon( - baselineSettings24, contentDescription = "Settings" - ) - }, - label = { Text("Settings") }, - selected = currentView == SETTINGS_VIEW - ) - } - }) { innerPadding -> - NavHost( - navController = navController, - startDestination = viewModel.currentView.value, - modifier = Modifier.padding(innerPadding) - ) { - composable(route = CAMERA_VIEW) { - CameraView( - eglBaseContext = cameraService.eglBaseContext, - videoTrack = webRtcService.videoTrack - ) - } - composable(route = REMOTE_VIEW) { - RemoteView( - controllerService = controllerService - ) - } - composable(route = SETTINGS_VIEW) { - SettingsView( - deviceService = deviceService, bluetoothService = bluetoothService - ) + val configuration = LocalConfiguration.current + val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + + val navigationItems = listOf( + NavigationItem( + onClick = { navController.navigate(CAMERA_VIEW) }, + icon = { Icon(baselineCamera24, contentDescription = "Camera") }, + label = { Text("Camera") }, + selected = currentView == CAMERA_VIEW + ), NavigationItem( + onClick = { navController.navigate(REMOTE_VIEW) }, + icon = { Icon(baselineRemote24, contentDescription = "Remote") }, + label = { Text("Remote") }, + selected = currentView == REMOTE_VIEW + ), NavigationItem( + onClick = { navController.navigate(SETTINGS_VIEW) }, + icon = { Icon(baselineSettings24, contentDescription = "Settings") }, + label = { Text("Settings") }, + selected = currentView == SETTINGS_VIEW + ) + ) + Surface(modifier = Modifier.fillMaxSize()) { + Scaffold( + modifier = Modifier + .fillMaxHeight(), + bottomBar = { + if (!isLandscape) { + NavigationBar { + navigationItems.forEach { item -> + NavigationBarItem( + onClick = item.onClick, + icon = item.icon, + label = item.label, + selected = item.selected, + ) + } + } + } + }) { innerPadding -> + Row(Modifier.padding(innerPadding)) { + if (isLandscape) { + NavigationRail( + modifier = Modifier + .fillMaxHeight() + .width(64.dp) + ) { + Column( + modifier = Modifier + .fillMaxHeight(), + verticalArrangement = Arrangement.spacedBy( + 12.dp, Alignment.CenterVertically + ) + ) { + navigationItems.forEach { item -> + NavigationRailItem( + onClick = item.onClick, + icon = item.icon, + label = item.label, + selected = item.selected, + ) + } + } + } + } + NavHost( + navController = navController, + startDestination = viewModel.currentView.value, + ) { + composable(route = CAMERA_VIEW) { + CameraView( + eglBaseContext = cameraService.eglBaseContext, + videoTrack = webRtcService.videoTrack + ) + } + composable(route = REMOTE_VIEW) { + RemoteView( + controllerService = controllerService + ) + } + composable(route = SETTINGS_VIEW) { + SettingsView( + deviceService = deviceService, bluetoothService = bluetoothService + ) + } + } } } }