Merge branch 'master' into request-entities
This commit is contained in:
commit
5d501d201d
20 changed files with 613 additions and 245 deletions
|
@ -74,63 +74,44 @@ dependencies {
|
||||||
debugImplementation(libs.ui.tooling)
|
debugImplementation(libs.ui.tooling)
|
||||||
debugImplementation(libs.ui.test.manifest)
|
debugImplementation(libs.ui.test.manifest)
|
||||||
|
|
||||||
|
|
||||||
|
//-- Navigation
|
||||||
val nav_version = "2.5.3"
|
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-fragment-ktx:$nav_version")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
|
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
|
||||||
|
|
||||||
// Feature module Support
|
|
||||||
implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")
|
implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")
|
||||||
|
|
||||||
// Testing Navigation
|
|
||||||
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
|
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
|
||||||
|
|
||||||
// Jetpack Compose Integration
|
|
||||||
implementation("androidx.navigation:navigation-compose:$nav_version")
|
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)
|
// To use Kotlin annotation processing tool (kapt)
|
||||||
//kapt("androidx.room:room-compiler:$room_version")
|
//kapt("androidx.room:room-compiler:$room_version")
|
||||||
// To use Kotlin Symbol Processing (KSP)
|
// To use Kotlin Symbol Processing (KSP)
|
||||||
|
val room_version = "2.5.1"
|
||||||
|
|
||||||
ksp("androidx.room:room-compiler:$room_version")
|
ksp("androidx.room:room-compiler:$room_version")
|
||||||
|
annotationProcessor("androidx.room:room-compiler:$room_version")
|
||||||
// optional - Kotlin Extensions and Coroutines support for Room
|
implementation("androidx.room:room-runtime:$room_version")
|
||||||
implementation("androidx.room:room-ktx:$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")
|
implementation("androidx.room:room-guava:$room_version")
|
||||||
|
|
||||||
// optional - Test helpers
|
|
||||||
testImplementation("androidx.room:room-testing:$room_version")
|
testImplementation("androidx.room:room-testing:$room_version")
|
||||||
|
|
||||||
// optional - Paging 3 Integration
|
|
||||||
implementation("androidx.room:room-paging:$room_version")
|
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"
|
val ktor_version = "2.3.1"
|
||||||
implementation("io.ktor:ktor-client-core:$ktor_version")
|
implementation("io.ktor:ktor-client-core:$ktor_version")
|
||||||
implementation("io.ktor:ktor-client-cio:$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(platform("dev.forkhandles:forkhandles-bom:2.6.0.0"))
|
||||||
implementation("dev.forkhandles:result4k")
|
implementation("dev.forkhandles:result4k")
|
||||||
|
|
||||||
implementation("io.ktor:ktor-client-core:2.3.1")
|
implementation("io.ktor:ktor-client-core:2.3.1")
|
||||||
implementation("io.ktor:ktor-client-okhttp:2.3.1")
|
implementation("io.ktor:ktor-client-okhttp:2.3.1")
|
||||||
|
|
||||||
implementation("androidx.security:security-crypto-ktx:1.1.0-alpha06")
|
implementation("androidx.security:security-crypto-ktx:1.1.0-alpha06")
|
||||||
|
|
||||||
|
|
||||||
// For Identity Credential APIs
|
// For Identity Credential APIs
|
||||||
implementation("androidx.security:security-identity-credential:1.0.0-alpha03")
|
implementation("androidx.security:security-identity-credential:1.0.0-alpha03")
|
||||||
|
|
||||||
|
@ -143,6 +124,14 @@ dependencies {
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
|
|
||||||
// Map Compose library
|
|
||||||
|
//-- Map Compose library
|
||||||
implementation("ovh.plrapps:mapcompose:2.7.1")
|
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")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,27 +1,16 @@
|
||||||
@file:OptIn(
|
|
||||||
ExperimentalMaterial3Api::class, ExperimentalMaterial3Api::class,
|
|
||||||
ExperimentalMaterial3Api::class
|
|
||||||
)
|
|
||||||
|
|
||||||
package ru.nm17.narodmon
|
package ru.nm17.narodmon
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
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.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -33,64 +22,17 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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.room.Room
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ru.nm17.narodmon.db.AppDatabase
|
import ru.nm17.narodmon.db.AppDatabase
|
||||||
import ru.nm17.narodmon.db.entities.KVSetting
|
import ru.nm17.narodmon.db.entities.KVSetting
|
||||||
import ru.nm17.narodmon.ui.dialogs.AgreementDialog
|
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
|
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() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -153,11 +95,7 @@ class MainActivity : ComponentActivity() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AppNavHost()
|
AppNavHost()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A surface container using the 'background' color from the theme
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
30
app/src/main/java/ru/nm17/narodmon/ui/navHost/AppNavHost.kt
Normal file
30
app/src/main/java/ru/nm17/narodmon/ui/navHost/AppNavHost.kt
Normal file
|
@ -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()
|
||||||
|
}
|
83
app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreen.kt
Normal file
83
app/src/main/java/ru/nm17/narodmon/ui/navHost/MainScreen.kt
Normal file
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package ru.nm17.narodmon.ui.sensorsScreen
|
package ru.nm17.narodmon.ui.sensorsScreen
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
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.LazyRow
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
import androidx.compose.material.icons.outlined.Settings
|
||||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
|
||||||
import androidx.compose.material.icons.rounded.Check
|
import androidx.compose.material.icons.rounded.Check
|
||||||
import androidx.compose.material.icons.rounded.Person
|
|
||||||
import androidx.compose.material3.BottomSheetScaffold
|
import androidx.compose.material3.BottomSheetScaffold
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilterChip
|
import androidx.compose.material3.FilterChip
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.SearchBar
|
import androidx.compose.material3.SearchBar
|
||||||
import androidx.compose.material3.SearchBarDefaults
|
import androidx.compose.material3.SearchBarDefaults
|
||||||
import androidx.compose.material3.SheetValue
|
import androidx.compose.material3.SheetValue
|
||||||
import androidx.compose.material3.Text
|
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.material3.rememberBottomSheetScaffoldState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -45,28 +37,23 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.rememberNavController
|
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.R
|
||||||
import ru.nm17.narodmon.db.entities.SensorType
|
import ru.nm17.narodmon.db.entities.SensorType
|
||||||
import ru.nm17.narodmon.ui.dialogs.FilterSensorsDialog
|
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.dialogs.SortSensorsDialog
|
||||||
|
import ru.nm17.narodmon.ui.elements.SensorItem
|
||||||
import ru.nm17.narodmon.ui.elements.TileMap
|
import ru.nm17.narodmon.ui.elements.TileMap
|
||||||
import ru.nm17.narodmon.ui.entities.SensorEntity
|
import ru.nm17.narodmon.ui.entities.SensorEntity
|
||||||
import ru.nm17.narodmon.ui.entities.SensorSortingUiEntity
|
import ru.nm17.narodmon.ui.entities.SensorSortingUiEntity
|
||||||
import ru.nm17.narodmon.ui.entities.SortingTypes
|
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.theme.NarodMonTheme
|
||||||
import ru.nm17.narodmon.ui.toChipTitle
|
import ru.nm17.narodmon.ui.toChipTitle
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SensorsScreen(navController: NavController) {
|
fun SensorsScreen(outerNavController: NavController) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
var searchQuery by remember { mutableStateOf("") }
|
var searchQuery by remember { mutableStateOf("") }
|
||||||
var searchActive by remember { mutableStateOf(false) }
|
var searchActive by remember { mutableStateOf(false) }
|
||||||
|
@ -119,15 +106,11 @@ fun SensorsScreen(navController: NavController) {
|
||||||
mutableStateOf(SheetHeight.ExtraExpanded)
|
mutableStateOf(SheetHeight.ExtraExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
BottomSheetScaffold(
|
BottomSheetScaffold(modifier = Modifier.fillMaxSize(), sheetPeekHeight = when (sheetHeight) {
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
sheetPeekHeight = when (sheetHeight) {
|
|
||||||
SheetHeight.ExtraExpanded -> 256.dp
|
SheetHeight.ExtraExpanded -> 256.dp
|
||||||
SheetHeight.Expanded -> 128.dp
|
SheetHeight.Expanded -> 128.dp
|
||||||
SheetHeight.Hidden -> 0.dp
|
SheetHeight.Hidden -> 0.dp
|
||||||
},
|
}, scaffoldState = scaffoldState, sheetContent = {
|
||||||
scaffoldState = scaffoldState,
|
|
||||||
sheetContent = {
|
|
||||||
AnimatedVisibility(visible = scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded) {
|
AnimatedVisibility(visible = scaffoldState.bottomSheetState.currentValue == SheetValue.Expanded) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = searchQuery,
|
value = searchQuery,
|
||||||
|
@ -168,8 +151,7 @@ fun SensorsScreen(navController: NavController) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
FilterChip(
|
FilterChip(selected = sortingType.sortingType != SortingTypes.DISTANCE,
|
||||||
selected = sortingType.sortingType != SortingTypes.DISTANCE,
|
|
||||||
onClick = { sortingShow = true },
|
onClick = { sortingShow = true },
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
|
@ -191,8 +173,7 @@ fun SensorsScreen(navController: NavController) {
|
||||||
else sortingType.stringRes
|
else sortingType.stringRes
|
||||||
).toChipTitle(),
|
).toChipTitle(),
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
@ -202,8 +183,7 @@ fun SensorsScreen(navController: NavController) {
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
if (filterMine) {
|
if (filterMine) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Rounded.Check,
|
Icons.Rounded.Check, contentDescription = ""
|
||||||
contentDescription = ""
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -219,8 +199,7 @@ fun SensorsScreen(navController: NavController) {
|
||||||
SensorItem(sensor)
|
SensorItem(sensor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}) {
|
||||||
) {
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
SearchBar(
|
SearchBar(
|
||||||
query = searchQuery,
|
query = searchQuery,
|
||||||
|
@ -231,18 +210,24 @@ fun SensorsScreen(navController: NavController) {
|
||||||
},
|
},
|
||||||
onQueryChange = { query -> searchQuery = query },
|
onQueryChange = { query -> searchQuery = query },
|
||||||
onSearch = { searchActive = false },
|
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
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = if (!searchActive) 8.dp else 0.dp,
|
horizontal = if (!searchActive) 8.dp else 0.dp,
|
||||||
vertical = if (!searchActive) 16.dp else 0.dp
|
|
||||||
)
|
)
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
TileMap(
|
TileMap(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize()
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
) {
|
||||||
sheetHeight =
|
sheetHeight =
|
||||||
SheetHeight.Expanded // TODO придумать, чтобы менялось на SheetHeight.ExtraExpanded после взаимодействия с картой
|
SheetHeight.Expanded // TODO придумать, чтобы менялось на SheetHeight.ExtraExpanded после взаимодействия с картой
|
||||||
|
@ -251,25 +236,18 @@ fun SensorsScreen(navController: NavController) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sortingShow) {
|
if (sortingShow) {
|
||||||
SortSensorsDialog(
|
SortSensorsDialog(sortingType, onApply = {
|
||||||
sortingType,
|
|
||||||
onApply = {
|
|
||||||
sortingType = it
|
sortingType = it
|
||||||
sortingShow = false
|
sortingShow = false
|
||||||
},
|
}, onDismissRequest = {
|
||||||
onDismissRequest = {
|
|
||||||
sortingShow = false
|
sortingShow = false
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (filterShow) {
|
if (filterShow) {
|
||||||
FilterSensorsDialog(
|
FilterSensorsDialog(onApply = {
|
||||||
onApply = {
|
|
||||||
// TODO применение фильтров
|
// TODO применение фильтров
|
||||||
filterShow = false
|
filterShow = false
|
||||||
},
|
}, onDismissRequest = { filterShow = false })
|
||||||
onDismissRequest = { filterShow = false }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
app/src/main/java/ru/nm17/narodmon/ui/settings/Settings.kt
Normal file
12
app/src/main/java/ru/nm17/narodmon/ui/settings/Settings.kt
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
@ -27,14 +28,14 @@ private val LightColorScheme = lightColorScheme(
|
||||||
tertiary = Pink80
|
tertiary = Pink80
|
||||||
|
|
||||||
/* Other default colors to override
|
/* Other default colors to override
|
||||||
background = Color(0xFFFFFBFE),
|
background = Color(0xFFFFFBFE),
|
||||||
surface = Color(0xFFFFFBFE),
|
surface = Color(0xFFFFFBFE),
|
||||||
onPrimary = Color.White,
|
onPrimary = Color.White,
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
onTertiary = Color.White,
|
onTertiary = Color.White,
|
||||||
onBackground = Color(0xFF1C1B1F),
|
onBackground = Color(0xFF1C1B1F),
|
||||||
onSurface = Color(0xFF1C1B1F),
|
onSurface = Color(0xFF1C1B1F),
|
||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -57,8 +58,10 @@ fun NarodMonTheme(
|
||||||
if (!view.isInEditMode) {
|
if (!view.isInEditMode) {
|
||||||
SideEffect {
|
SideEffect {
|
||||||
val window = (view.context as Activity).window
|
val window = (view.context as Activity).window
|
||||||
window.statusBarColor = colorScheme.primary.toArgb()
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
|
window.statusBarColor = Color.Transparent.toArgb()
|
||||||
|
|
||||||
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
5
app/src/main/res/drawable/ic_home.xml
Normal file
5
app/src/main/res/drawable/ic_home.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,5.69l5,4.5V18h-2v-6H9v6H7v-7.81l5,-4.5M12,3L2,12h3v8h6v-6h2v6h6v-8h3L12,3z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_message.xml
Normal file
5
app/src/main/res/drawable/ic_message.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:autoMirrored="true" android:height="24dp"
|
||||||
|
android:tint="#000000" android:viewportHeight="24"
|
||||||
|
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M4,4h16v12L5.17,16L4,17.17L4,4m0,-2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2L4,2zM6,12h12v2L6,14v-2zM6,9h12v2L6,11L6,9zM6,6h12v2L6,8L6,6z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_settings.xml
Normal file
5
app/src/main/res/drawable/ic_settings.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98 0,0.33 0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM17.45,11.27c0.04,0.31 0.05,0.52 0.05,0.73 0,0.21 -0.02,0.43 -0.05,0.73l-0.14,1.13 0.89,0.7 1.08,0.84 -0.7,1.21 -1.27,-0.51 -1.04,-0.42 -0.9,0.68c-0.43,0.32 -0.84,0.56 -1.25,0.73l-1.06,0.43 -0.16,1.13 -0.2,1.35h-1.4l-0.19,-1.35 -0.16,-1.13 -1.06,-0.43c-0.43,-0.18 -0.83,-0.41 -1.23,-0.71l-0.91,-0.7 -1.06,0.43 -1.27,0.51 -0.7,-1.21 1.08,-0.84 0.89,-0.7 -0.14,-1.13c-0.03,-0.31 -0.05,-0.54 -0.05,-0.74s0.02,-0.43 0.05,-0.73l0.14,-1.13 -0.89,-0.7 -1.08,-0.84 0.7,-1.21 1.27,0.51 1.04,0.42 0.9,-0.68c0.43,-0.32 0.84,-0.56 1.25,-0.73l1.06,-0.43 0.16,-1.13 0.2,-1.35h1.39l0.19,1.35 0.16,1.13 1.06,0.43c0.43,0.18 0.83,0.41 1.23,0.71l0.91,0.7 1.06,-0.43 1.27,-0.51 0.7,1.21 -1.07,0.85 -0.89,0.7 0.14,1.13zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_webcam.xml
Normal file
5
app/src/main/res/drawable/ic_webcam.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15,8v8H5V8h10m1,-2H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4V7c0,-0.55 -0.45,-1 -1,-1z"/>
|
||||||
|
</vector>
|
|
@ -52,4 +52,10 @@
|
||||||
<string name="apply">Применить</string>
|
<string name="apply">Применить</string>
|
||||||
<string name="sort_by_distance_desc">От дальних к ближним</string>
|
<string name="sort_by_distance_desc">От дальних к ближним</string>
|
||||||
<string name="cancel1">Отменить</string>
|
<string name="cancel1">Отменить</string>
|
||||||
|
<string name="webcams">Веб-камеры</string>
|
||||||
|
<string name="messages">Сообщения</string>
|
||||||
|
<string name="settings">Настройки</string>
|
||||||
|
<string name="search_sensors">Поиск датчиков</string>
|
||||||
|
<string name="about_app">О приложении</string>
|
||||||
|
<string name="debug_menu">Debug-меню</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Reference in a new issue