diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 153e5da..8247bdc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -74,63 +74,44 @@ dependencies { debugImplementation(libs.ui.tooling) debugImplementation(libs.ui.test.manifest) + + //-- Navigation val nav_version = "2.5.3" - // Java language implementation - implementation("androidx.navigation:navigation-fragment:$nav_version") - implementation("androidx.navigation:navigation-ui:$nav_version") - - // Kotlin implementation("androidx.navigation:navigation-fragment-ktx:$nav_version") implementation("androidx.navigation:navigation-ui-ktx:$nav_version") - - // Feature module Support implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version") - - // Testing Navigation androidTestImplementation("androidx.navigation:navigation-testing:$nav_version") - - // Jetpack Compose Integration implementation("androidx.navigation:navigation-compose:$nav_version") - val room_version = "2.5.1" - - implementation("androidx.room:room-runtime:$room_version") - annotationProcessor("androidx.room:room-compiler:$room_version") + //-- Room // To use Kotlin annotation processing tool (kapt) //kapt("androidx.room:room-compiler:$room_version") // To use Kotlin Symbol Processing (KSP) + val room_version = "2.5.1" + ksp("androidx.room:room-compiler:$room_version") - - // optional - Kotlin Extensions and Coroutines support for Room + annotationProcessor("androidx.room:room-compiler:$room_version") + implementation("androidx.room:room-runtime:$room_version") implementation("androidx.room:room-ktx:$room_version") - - // optional - Guava support for Room, including Optional and ListenableFuture implementation("androidx.room:room-guava:$room_version") - - // optional - Test helpers testImplementation("androidx.room:room-testing:$room_version") - - // optional - Paging 3 Integration implementation("androidx.room:room-paging:$room_version") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") - - // Ktor + //-- Ktor val ktor_version = "2.3.1" implementation("io.ktor:ktor-client-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version") - + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation(platform("dev.forkhandles:forkhandles-bom:2.6.0.0")) implementation("dev.forkhandles:result4k") - implementation("io.ktor:ktor-client-core:2.3.1") implementation("io.ktor:ktor-client-okhttp:2.3.1") - implementation("androidx.security:security-crypto-ktx:1.1.0-alpha06") + // For Identity Credential APIs implementation("androidx.security:security-identity-credential:1.0.0-alpha03") @@ -143,10 +124,14 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") - // Map Compose library + + //-- Map Compose library implementation("ovh.plrapps:mapcompose:2.7.1") - // Glide - implementation ("com.github.bumptech.glide:glide:4.14.2") + + //-- Glide + implementation("com.github.bumptech.glide:glide:4.14.2") implementation("com.github.bumptech.glide:compose:1.0.0-alpha.1") - } \ No newline at end of file + + +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/MainActivity.kt b/app/src/main/java/ru/nm17/narodmon/MainActivity.kt index 72011a6..fb62ffc 100644 --- a/app/src/main/java/ru/nm17/narodmon/MainActivity.kt +++ b/app/src/main/java/ru/nm17/narodmon/MainActivity.kt @@ -1,27 +1,16 @@ -@file:OptIn( - ExperimentalMaterial3Api::class, ExperimentalMaterial3Api::class, - ExperimentalMaterial3Api::class -) + package ru.nm17.narodmon import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Person -import androidx.compose.material.icons.rounded.Add -import androidx.compose.material.icons.rounded.Menu -import androidx.compose.material3.BottomAppBar import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -33,64 +22,17 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController import androidx.room.Room -import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKeys import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import ru.nm17.narodmon.db.AppDatabase import ru.nm17.narodmon.db.entities.KVSetting import ru.nm17.narodmon.ui.dialogs.AgreementDialog -import ru.nm17.narodmon.ui.sensorsScreen.SensorsScreen +import ru.nm17.narodmon.ui.navHost.AppNavHost import ru.nm17.narodmon.ui.theme.NarodMonTheme -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun AppNavHost() { - val navController = rememberNavController() - val coScope = rememberCoroutineScope() - NavHost(navController = navController, startDestination = "sensors") { - composable("agreement") { - - } - - composable("sensors") { - Scaffold(bottomBar = { - BottomAppBar(actions = { - Image( - Icons.Rounded.Menu, - contentDescription = null - ) - }, floatingActionButton = { - FloatingActionButton(onClick = { /*TODO*/ }) { - Image( - Icons.Rounded.Add, - contentDescription = "" - ) - } - }, - contentPadding = PaddingValues(start = 16.dp) - ) - }) { - Column(modifier = Modifier.padding(it)) { - SensorsScreen(navController) - } - } - - } - } - - /*...*/ - -} - class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -153,11 +95,7 @@ class MainActivity : ComponentActivity() { } } else { AppNavHost() - } - - // A surface container using the 'background' color from the theme - } } } diff --git a/app/src/main/java/ru/nm17/narodmon/ui/elements/SettingsItem.kt b/app/src/main/java/ru/nm17/narodmon/ui/elements/SettingsItem.kt new file mode 100644 index 0000000..daf382f --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/elements/SettingsItem.kt @@ -0,0 +1,50 @@ +package ru.nm17.narodmon.ui.elements + +import androidx.annotation.StringRes +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import ru.nm17.narodmon.R + +/** + * Кнопка, которая нужна для настроек. + * @param titleId Id заголовка кнопки + * @param leadingItem Заполнить, когда нужно вставить Composable перед заголовком(например [Icon], [FilterCheckbox] или [Switch] + */ +@Composable +fun SettingsItem( + @StringRes titleId: Int, + leadingItem: @Composable (() -> Unit)? = null, + onClick: () -> Unit = {} +) { + Row(modifier = Modifier.padding(16.dp)) { + if (leadingItem != null) { + leadingItem.invoke() + Spacer(modifier = Modifier.size(16.dp)) + } + Column(modifier = Modifier + .fillMaxWidth() + .clickable { onClick.invoke() }) { + Text(text = stringResource(id = titleId)) + } + } + +} + +@Preview(showBackground = true) +@Composable +fun PreviewSettingsItem() { + SettingsItem(R.string.about_app) {} +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/messagesScreen/MessagesScreen.kt b/app/src/main/java/ru/nm17/narodmon/ui/messagesScreen/MessagesScreen.kt new file mode 100644 index 0000000..f2c8b8f --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/messagesScreen/MessagesScreen.kt @@ -0,0 +1,16 @@ +package ru.nm17.narodmon.ui.messagesScreen + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + +@Composable +fun MessagesScreen() { + Text(text = "todo") +} + +@Preview +@Composable +fun PreviewMessagesScreen() { + MessagesScreen() +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/navHost/AppNavHost.kt b/app/src/main/java/ru/nm17/narodmon/ui/navHost/AppNavHost.kt new file mode 100644 index 0000000..9697fa4 --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/navHost/AppNavHost.kt @@ -0,0 +1,30 @@ +package ru.nm17.narodmon.ui.navHost + +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import ru.nm17.narodmon.ui.settings.SettingsNavigation + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppNavHost() { + val navController = rememberNavController() + NavHost(navController = navController, startDestination = "main") { + composable("main") { + MainScreen(navController) + } + composable("settings") { + SettingsNavigation() + } + } +} + +@Preview +@Composable +fun PreviewAppNavHost() { + AppNavHost() +} diff --git a/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreen.kt b/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreen.kt new file mode 100644 index 0000000..d2569b2 --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreen.kt @@ -0,0 +1,83 @@ +package ru.nm17.narodmon.ui.navHost + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavController +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import ru.nm17.narodmon.ui.sensorsScreen.SensorsScreen +import ru.nm17.narodmon.ui.theme.NarodMonTheme +import ru.nm17.narodmon.ui.webCamsScreen.WebCamsScreen + + +val items = listOf( + MainScreenSealed.Sensors, + MainScreenSealed.Webcams, + MainScreenSealed.Messages +) + +@Composable +fun MainScreen(outerNavController: NavController) { + val navController = rememberNavController() + + Scaffold( + bottomBar = { + NavigationBar { + + items.forEach { screen -> + NavigationBarItem( + selected = navController.currentDestination?.route == screen.route, + onClick = { + navController.navigate(screen.route) { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + }, + label = { Text(text = stringResource(id = screen.resourceId)) }, + icon = { + Icon( + painter = painterResource(id = screen.iconId), + contentDescription = "" + ) + }) + } + } + }, + modifier = Modifier.fillMaxSize() + ) { + NavHost( + navController, + startDestination = MainScreenSealed.Sensors.route, + Modifier.padding(it) + ) { + composable(MainScreenSealed.Sensors.route) { + SensorsScreen(outerNavController) + } + composable(MainScreenSealed.Webcams.route) { WebCamsScreen(navController) } + composable(MainScreenSealed.Messages.route) { } + } + } +} + +@Preview +@Composable +fun PreviewMainScreen() { + NarodMonTheme { + MainScreen(rememberNavController()) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreenSealed.kt b/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreenSealed.kt new file mode 100644 index 0000000..89fcdde --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreenSealed.kt @@ -0,0 +1,18 @@ +package ru.nm17.narodmon.ui.navHost + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import ru.nm17.narodmon.R + +sealed class MainScreenSealed( + val route: String, + @StringRes val resourceId: Int, + @DrawableRes val iconId: Int +) { + object Sensors : MainScreenSealed("sensors", R.string.sensors_page_title, R.drawable.ic_home) + object Webcams : MainScreenSealed("webcams", R.string.webcams, R.drawable.ic_webcam) + + object Messages : MainScreenSealed("messages", R.string.messages, R.drawable.ic_message) + + object Settings : MainScreenSealed("settings", R.string.settings, R.drawable.ic_settings) +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/sensorsScreen/SensorsScreen.kt b/app/src/main/java/ru/nm17/narodmon/ui/sensorsScreen/SensorsScreen.kt index d40161b..8ded59d 100644 --- a/app/src/main/java/ru/nm17/narodmon/ui/sensorsScreen/SensorsScreen.kt +++ b/app/src/main/java/ru/nm17/narodmon/ui/sensorsScreen/SensorsScreen.kt @@ -1,8 +1,6 @@ package ru.nm17.narodmon.ui.sensorsScreen -import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxHeight @@ -13,29 +11,23 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material.icons.rounded.ArrowDropDown +import androidx.compose.material.icons.outlined.Settings import androidx.compose.material.icons.rounded.Check -import androidx.compose.material.icons.rounded.Person import androidx.compose.material3.BottomSheetScaffold import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.SearchBar import androidx.compose.material3.SearchBarDefaults import androidx.compose.material3.SheetValue import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.material3.TextFieldColors -import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -45,28 +37,23 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import ovh.plrapps.mapcompose.core.debounce import ru.nm17.narodmon.R import ru.nm17.narodmon.db.entities.SensorType import ru.nm17.narodmon.ui.dialogs.FilterSensorsDialog -import ru.nm17.narodmon.ui.elements.SensorItem import ru.nm17.narodmon.ui.dialogs.SortSensorsDialog +import ru.nm17.narodmon.ui.elements.SensorItem import ru.nm17.narodmon.ui.elements.TileMap import ru.nm17.narodmon.ui.entities.SensorEntity import ru.nm17.narodmon.ui.entities.SensorSortingUiEntity import ru.nm17.narodmon.ui.entities.SortingTypes +import ru.nm17.narodmon.ui.navHost.MainScreenSealed import ru.nm17.narodmon.ui.theme.NarodMonTheme import ru.nm17.narodmon.ui.toChipTitle -@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun SensorsScreen(navController: NavController) { - val coroutineScope = rememberCoroutineScope() +fun SensorsScreen(outerNavController: NavController) { var searchQuery by remember { mutableStateOf("") } var searchActive by remember { mutableStateOf(false) } @@ -119,108 +106,100 @@ fun SensorsScreen(navController: NavController) { mutableStateOf(SheetHeight.ExtraExpanded) } - BottomSheetScaffold( - modifier = Modifier.fillMaxSize(), - sheetPeekHeight = when (sheetHeight) { - SheetHeight.ExtraExpanded -> 256.dp - SheetHeight.Expanded -> 128.dp - SheetHeight.Hidden -> 0.dp - }, - scaffoldState = scaffoldState, - sheetContent = { - AnimatedVisibility(visible = scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded) { - OutlinedTextField( - value = searchQuery, - onValueChange = { searchQuery = it }, - placeholder = { Text(stringResource(R.string.search)) }, - shape = SearchBarDefaults.inputFieldShape, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp, vertical = 8.dp) - ) - } - - LazyRow( - horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally), + BottomSheetScaffold(modifier = Modifier.fillMaxSize(), sheetPeekHeight = when (sheetHeight) { + SheetHeight.ExtraExpanded -> 256.dp + SheetHeight.Expanded -> 128.dp + SheetHeight.Hidden -> 0.dp + }, scaffoldState = scaffoldState, sheetContent = { + AnimatedVisibility(visible = scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded) { + OutlinedTextField( + value = searchQuery, + onValueChange = { searchQuery = it }, + placeholder = { Text(stringResource(R.string.search)) }, + shape = SearchBarDefaults.inputFieldShape, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), - ) { - item { - FilterChip( - selected = false, - onClick = { filterShow = true }, - leadingIcon = { - Icon( - painter = painterResource(id = R.drawable.ic_filter), - contentDescription = stringResource(id = R.string.sensors_filter) - ) - }, - trailingIcon = { -// Icon( -// Icons.Filled.ArrowDropDown, -// "", -// tint = MaterialTheme.colorScheme.onBackground -// ) - }, + .padding(horizontal = 8.dp, vertical = 8.dp) + ) + } - label = { Text(text = stringResource(R.string.sensors_filter)) }, - ) - } - item { - FilterChip( - selected = sortingType.sortingType != SortingTypes.DISTANCE, - onClick = { sortingShow = true }, - leadingIcon = { - Icon( - painter = painterResource(id = R.drawable.ic_sort), - contentDescription = stringResource(id = R.string.sensors_sorting) - ) - }, - trailingIcon = { + LazyRow( + horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) { + item { + FilterChip( + selected = false, + onClick = { filterShow = true }, + leadingIcon = { + Icon( + painter = painterResource(id = R.drawable.ic_filter), + contentDescription = stringResource(id = R.string.sensors_filter) + ) + }, + trailingIcon = { // Icon( // Icons.Filled.ArrowDropDown, // "", // tint = MaterialTheme.colorScheme.onBackground // ) - }, - label = { - Text( - text = stringResource( - if (sortingType.sortingType == SortingTypes.DISTANCE) R.string.sensors_sorting - else sortingType.stringRes - ).toChipTitle(), + }, + + label = { Text(text = stringResource(R.string.sensors_filter)) }, + ) + } + item { + FilterChip(selected = sortingType.sortingType != SortingTypes.DISTANCE, + onClick = { sortingShow = true }, + leadingIcon = { + Icon( + painter = painterResource(id = R.drawable.ic_sort), + contentDescription = stringResource(id = R.string.sensors_sorting) + ) + }, + trailingIcon = { +// Icon( +// Icons.Filled.ArrowDropDown, +// "", +// tint = MaterialTheme.colorScheme.onBackground +// ) + }, + label = { + Text( + text = stringResource( + if (sortingType.sortingType == SortingTypes.DISTANCE) R.string.sensors_sorting + else sortingType.stringRes + ).toChipTitle(), + ) + }) + } + + item { + FilterChip( + selected = filterMine, + onClick = { filterMine = !filterMine }, + leadingIcon = { + if (filterMine) { + Icon( + Icons.Rounded.Check, contentDescription = "" ) } - ) - } - - item { - FilterChip( - selected = filterMine, - onClick = { filterMine = !filterMine }, - leadingIcon = { - if (filterMine) { - Icon( - Icons.Rounded.Check, - contentDescription = "" - ) - } - }, - label = { Text(text = stringResource(R.string.sensors_mine)) }, - ) - } - } - - LazyColumn( - modifier = Modifier.fillMaxHeight(), - ) { - items(sensorEntities) { sensor -> - SensorItem(sensor) - } + }, + label = { Text(text = stringResource(R.string.sensors_mine)) }, + ) } } - ) { + + LazyColumn( + modifier = Modifier.fillMaxHeight(), + ) { + items(sensorEntities) { sensor -> + SensorItem(sensor) + } + } + }) { Box(modifier = Modifier.fillMaxSize()) { SearchBar( query = searchQuery, @@ -231,18 +210,24 @@ fun SensorsScreen(navController: NavController) { }, onQueryChange = { query -> searchQuery = query }, onSearch = { searchActive = false }, - placeholder = { Text(stringResource(R.string.search)) }, + placeholder = { Text(stringResource(R.string.search_sensors)) }, + trailingIcon = { + IconButton(onClick = { outerNavController.navigate(MainScreenSealed.Settings.route) }) { + Icon( + Icons.Outlined.Settings, + contentDescription = stringResource(R.string.settings) + ) + } + }, modifier = Modifier .fillMaxWidth() .padding( horizontal = if (!searchActive) 8.dp else 0.dp, - vertical = if (!searchActive) 16.dp else 0.dp ) ) {} TileMap( - modifier = Modifier - .fillMaxSize() + modifier = Modifier.fillMaxSize() ) { sheetHeight = SheetHeight.Expanded // TODO придумать, чтобы менялось на SheetHeight.ExtraExpanded после взаимодействия с картой @@ -251,25 +236,18 @@ fun SensorsScreen(navController: NavController) { } } if (sortingShow) { - SortSensorsDialog( - sortingType, - onApply = { - sortingType = it - sortingShow = false - }, - onDismissRequest = { - sortingShow = false - } - ) + SortSensorsDialog(sortingType, onApply = { + sortingType = it + sortingShow = false + }, onDismissRequest = { + sortingShow = false + }) } if (filterShow) { - FilterSensorsDialog( - onApply = { - // TODO применение фильтров - filterShow = false - }, - onDismissRequest = { filterShow = false } - ) + FilterSensorsDialog(onApply = { + // TODO применение фильтров + filterShow = false + }, onDismissRequest = { filterShow = false }) } } diff --git a/app/src/main/java/ru/nm17/narodmon/ui/settings/Settings.kt b/app/src/main/java/ru/nm17/narodmon/ui/settings/Settings.kt new file mode 100644 index 0000000..6ff326e --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/settings/Settings.kt @@ -0,0 +1,12 @@ +package ru.nm17.narodmon.ui.settings + +import androidx.annotation.StringRes +import ru.nm17.narodmon.R + +sealed class Settings(val route: String, @StringRes val resourceId: Int) { + + object Main : Settings("settings_main", R.string.settings) + object AboutApp : Settings("settings_about_app", R.string.about_app) + + object Debug : Settings("settings_debug_menu", R.string.debug_menu) +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsNavigation.kt b/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsNavigation.kt new file mode 100644 index 0000000..f8cc7a2 --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsNavigation.kt @@ -0,0 +1,39 @@ +package ru.nm17.narodmon.ui.settings + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingsNavigation() { + val navController = rememberNavController() + Scaffold(topBar = { + TopAppBar(title = { Text(text = navController.currentDestination?.route ?: "") }) + }) { + NavHost( + navController = navController, + startDestination = Settings.Main.route, + modifier = Modifier.padding(it) + ) { + composable(Settings.Main.route) { SettingsScreen(navController) } + composable(Settings.AboutApp.route) { } + composable(Settings.Debug.route) { } + } + + } +} + +@Preview +@Composable +fun PreviewSettingsNavigation() { + SettingsNavigation() +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsScreen.kt b/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsScreen.kt new file mode 100644 index 0000000..fb75ba0 --- /dev/null +++ b/app/src/main/java/ru/nm17/narodmon/ui/settings/SettingsScreen.kt @@ -0,0 +1,37 @@ +package ru.nm17.narodmon.ui.settings + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController +import ru.nm17.narodmon.R +import ru.nm17.narodmon.ui.elements.SettingsItem +import ru.nm17.narodmon.ui.theme.NarodMonTheme + +@Composable +fun SettingsScreen(navController: NavController) { + LazyColumn(modifier = Modifier.fillMaxSize()) { + item { + SettingsItem(titleId = R.string.debug_menu) { + navController.navigate(Settings.Debug.route) + } + } + item { + SettingsItem(R.string.about_app) { + navController.navigate(Settings.AboutApp.route) + } + } + + } +} + +@Preview(showBackground = true, showSystemUi = false) +@Composable +fun PreviewSettingsScreen() { + NarodMonTheme { + SettingsScreen(rememberNavController()) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/theme/Theme.kt b/app/src/main/java/ru/nm17/narodmon/ui/theme/Theme.kt index 666d520..4b5a002 100644 --- a/app/src/main/java/ru/nm17/narodmon/ui/theme/Theme.kt +++ b/app/src/main/java/ru/nm17/narodmon/ui/theme/Theme.kt @@ -10,15 +10,16 @@ import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 ) private val LightColorScheme = lightColorScheme( @@ -26,23 +27,23 @@ private val LightColorScheme = lightColorScheme( secondary = PurpleGrey80, tertiary = Pink80 - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ + /* Other default colors to override +background = Color(0xFFFFFBFE), +surface = Color(0xFFFFFBFE), +onPrimary = Color.White, +onSecondary = Color.White, +onTertiary = Color.White, +onBackground = Color(0xFF1C1B1F), +onSurface = Color(0xFF1C1B1F), +*/ ) @Composable fun NarodMonTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, - content: @Composable () -> Unit + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit ) { val colorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { @@ -57,14 +58,16 @@ fun NarodMonTheme( if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + WindowCompat.setDecorFitsSystemWindows(window, false) + window.statusBarColor = Color.Transparent.toArgb() + + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme } } MaterialTheme( - colorScheme = colorScheme, - typography = Typography, - content = content + colorScheme = colorScheme, + typography = Typography, + content = content ) } \ No newline at end of file diff --git a/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamsScreen.kt b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamsScreen.kt index 98298b9..38a4a3a 100644 --- a/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamsScreen.kt +++ b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamsScreen.kt @@ -1,6 +1,5 @@ package ru.nm17.narodmon.ui.webCamsScreen -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable @@ -8,13 +7,13 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.viewinterop.AndroidView +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController import ru.nm17.narodmon.ui.theme.NarodMonTheme @Composable -fun WebCamsScreen() { +fun WebCamsScreen(navController: NavController) { var webCams by remember { mutableStateOf( @@ -58,6 +57,6 @@ fun WebCamsScreen() { @Composable fun PreviewWebCams() { NarodMonTheme { - WebCamsScreen() + WebCamsScreen(rememberNavController()) } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 0000000..3cdad40 --- /dev/null +++ b/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_message.xml b/app/src/main/res/drawable/ic_message.xml new file mode 100644 index 0000000..dfb81a6 --- /dev/null +++ b/app/src/main/res/drawable/ic_message.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..c624d19 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_webcam.xml b/app/src/main/res/drawable/ic_webcam.xml new file mode 100644 index 0000000..a6fd65e --- /dev/null +++ b/app/src/main/res/drawable/ic_webcam.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ac3adf6..9e74ffa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,4 +52,10 @@ Применить От дальних к ближним Отменить + Веб-камеры + Сообщения + Настройки + Поиск датчиков + О приложении + Debug-меню \ No newline at end of file