Фикс #10 #15
|
@ -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")
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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(
|
||||
DarkCat09 marked this conversation as resolved
|
||||
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
|
||||
|
||||
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) {
|
||||
mezhendosina marked this conversation as resolved
Outdated
nm17
commented
Также, надо понять нужно ли контроллер навигационный выносить за параметр. Возможно, это остатки моего кода, поэтому можешь это не исправлять. Также, надо понять нужно ли контроллер навигационный выносить за параметр. Возможно, это остатки моего кода, поэтому можешь это не исправлять.
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
fun SensorsScreen(outerNavController: NavController) {
|
||||
|
||||
mezhendosina marked this conversation as resolved
Outdated
nm17
commented
Функция экрана датчиков становится оооочень большой. Я могу принять, но при условии что потом создашь отдельный ПР для рефакторинга этой функции, либо можешь исправить в этом пр. Функция экрана датчиков становится оооочень большой. Я могу принять, но при условии что потом создашь отдельный ПР для рефакторинга этой функции, либо можешь исправить в этом пр.
mezhendosina
commented
Надо убрать onSettingsClick. Оно же тоже к навигатору обращаться в итоге будет Надо убрать onSettingsClick. Оно же тоже к навигатору обращаться в итоге будет
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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,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
|
||||
)
|
||||
}
|
|
@ -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) {
|
||||
nm17 marked this conversation as resolved
nm17
commented
Также тут под вопросом вынос контроллера. Также тут под вопросом вынос контроллера.
DarkCat09
commented
В студии подсвечивается как unused. Да, это в твоём коде экрана датчиков было, мы и копируем)) В студии подсвечивается как unused. Да, это в твоём коде экрана датчиков было, мы и копируем))
mezhendosina
commented
Он вынесен, чтобы можно было из веб-камер уйти в полноэкранное меню просмотра камеры Он вынесен, чтобы можно было из веб-камер уйти в полноэкранное меню просмотра камеры
|
||||
|
||||
var webCams by remember {
|
||||
mutableStateOf(
|
||||
|
@ -58,6 +57,6 @@ fun WebCamsScreen() {
|
|||
@Composable
|
||||
fun PreviewWebCams() {
|
||||
NarodMonTheme {
|
||||
WebCamsScreen()
|
||||
WebCamsScreen(rememberNavController())
|
||||
}
|
||||
}
|
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"/>
|
||||
nm17 marked this conversation as resolved
nm17
commented
А в Material Icon Library нет этих иконок? Было бы супер, если бы мы могли без своих обойтись https://developer.android.com/jetpack/compose/graphics/images/material А в Material Icon Library нет этих иконок? Было бы супер, если бы мы могли без своих обойтись
https://developer.android.com/jetpack/compose/graphics/images/material
https://developer.android.com/reference/kotlin/androidx/compose/material/icons/package-summary
DarkCat09
commented
Официальный список — https://fonts.google.com/icons Сейчас посмотрел, все нужные иконки имеются. > А в Material Icon Library нет этих иконок? Было бы супер, если бы мы могли без своих обойтись
Официальный список — https://fonts.google.com/icons
При выборе иконки там даже есть код для Compose.
Сейчас посмотрел, все нужные иконки имеются.
mezhendosina
commented
Дак я оттуда и брал))0) Дак я оттуда и брал))0)
DarkCat09
commented
А, вижу. Раньше была вкладка с Jetpack Compose, убрали походу. Вот так надо: https://developer.android.com/reference/kotlin/androidx/compose/material/icons/Icons.Outlined
вместо использования своей SVGшки.
Прям во всех стилях (Filled, Outlined, Rounded) нету? Проверить сейчас негде. > Дак я оттуда и брал))0)
А, вижу. Раньше была вкладка с Jetpack Compose, убрали походу.
Вот так надо: https://developer.android.com/reference/kotlin/androidx/compose/material/icons/Icons.Outlined
```kotlin
Icons.Outlined.Home
```
вместо использования своей SVGшки.
> Там нет как минимум иконки камеры
Прям во всех стилях (Filled, Outlined, Rounded) нету? Проверить сейчас негде.
Если так, то печально.
Можем посмотреть альтернативные библиотеки для Compose с теми же материал-диазайновыми иконками.
|
||||
</vector>
|
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
|
@ -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
|
@ -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="sort_by_distance_desc">От дальних к ближним</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>
|
Интересное решение