diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9be7f7e..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,6 +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")
+ implementation("com.github.bumptech.glide:compose:1.0.0-alpha.1")
+
+
}
\ 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/WebCamItem.kt b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamItem.kt
new file mode 100644
index 0000000..1bf1928
--- /dev/null
+++ b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamItem.kt
@@ -0,0 +1,74 @@
+package ru.nm17.narodmon.ui.webCamsScreen
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
+import com.bumptech.glide.integration.compose.GlideImage
+import ru.nm17.narodmon.ui.iosevkaFamily
+
+@OptIn(ExperimentalGlideComposeApi::class)
+@Composable
+fun WebCamItem(webCamEntity: WebCamUiEntity) {
+ Box(
+ modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
+ contentAlignment = Alignment.BottomStart
+ ) {
+ GlideImage(
+ model = webCamEntity.imageUrl,
+ contentDescription = webCamEntity.name,
+ contentScale = ContentScale.FillHeight,
+ modifier = Modifier
+ .clip(RoundedCornerShape(8.dp))
+ .height(240.dp)
+ .fillMaxWidth()
+ )
+ Row(
+ modifier = Modifier
+ .clip(
+ RoundedCornerShape(bottomEnd = 8.dp, bottomStart = 8.dp)
+ )
+ .background(Color(0f, 0f, 0f, 0.55f))
+ .padding(start = 16.dp, end = 16.dp, bottom = 12.dp, top = 8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Column {
+ Text(
+ text = webCamEntity.time,
+ color = Color.White,
+ fontFamily = iosevkaFamily
+ )
+ Text(
+ text = webCamEntity.name,
+ color = Color.White,
+ maxLines = 1,
+ fontFamily = iosevkaFamily
+ )
+
+ }
+ Text(
+ text = "${webCamEntity.distance} км",
+ color = Color.White,
+ fontFamily = iosevkaFamily,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.End
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamUiEntity.kt b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamUiEntity.kt
new file mode 100644
index 0000000..e17a48e
--- /dev/null
+++ b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamUiEntity.kt
@@ -0,0 +1,13 @@
+package ru.nm17.narodmon.ui.webCamsScreen
+
+import android.graphics.Bitmap
+import androidx.compose.ui.graphics.ImageBitmap
+
+data class WebCamUiEntity(
+ val id: Int,
+ val name: String,
+ val distance: Int,
+ val location: String,
+ val time: String,
+ val imageUrl: String
+)
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
new file mode 100644
index 0000000..38a4a3a
--- /dev/null
+++ b/app/src/main/java/ru/nm17/narodmon/ui/webCamsScreen/WebCamsScreen.kt
@@ -0,0 +1,62 @@
+package ru.nm17.narodmon.ui.webCamsScreen
+
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
+import ru.nm17.narodmon.ui.theme.NarodMonTheme
+
+@Composable
+fun WebCamsScreen(navController: NavController) {
+
+ var webCams by remember {
+ mutableStateOf(
+ listOf(
+ WebCamUiEntity(
+ 1,
+ "Крутая камера",
+ 1,
+ "Улица Пушкина, дом Калатушкина, кватира под номером 5",
+ "12:45",
+ "https://images-webcams.windy.com/51/1559159251/current/preview/1559159251.jpg?1686320054"
+ ),
+ WebCamUiEntity(
+ 2,
+ "Крутая камера 2",
+ 2,
+ "Улица Пушкина, дом Калатушкина, кватира под номером 5",
+ "12:45",
+ "https://images-webcams.windy.com/51/1559159251/current/preview/1559159251.jpg?1686320054"
+ ),
+ WebCamUiEntity(
+ 3,
+ "Крутая камера 3",
+ 3,
+ "Улица Пушкина, дом Калатушкина, кватира под номером 5",
+ "12:45",
+ "https://images-webcams.windy.com/51/1559159251/current/preview/1559159251.jpg?1686320054"
+ )
+ )
+ )
+ } // TODO источник камер
+
+ LazyColumn() {
+ items(webCams) {
+ WebCamItem(webCamEntity = it)
+ }
+ }
+}
+
+@Preview
+@Composable
+fun PreviewWebCams() {
+ NarodMonTheme {
+ 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