Compare commits

...

11 commits

14 changed files with 346 additions and 226 deletions

View file

@ -106,12 +106,6 @@ dependencies {
// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version")
// optional - RxJava2 support for Room
implementation("androidx.room:room-rxjava2:$room_version")
// optional - RxJava3 support for Room
implementation("androidx.room:room-rxjava3:$room_version")
// optional - Guava support for Room, including Optional and ListenableFuture
implementation("androidx.room:room-guava:$room_version")

View file

@ -132,23 +132,7 @@ class MainActivity : ComponentActivity() {
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Composable
fun NavHolderEl() {
//NavHost(navController = NavHostController(N), graph =)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
NarodMonTheme {
Greeting("Android")
}
}

View file

@ -0,0 +1,119 @@
package ru.nm17.narodmon.ui.bottomSheets
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ru.nm17.narodmon.R
import ru.nm17.narodmon.ui.entities.SensorFilterUiEntity
import ru.nm17.narodmon.ui.pages.FilterCheckbox
import ru.nm17.narodmon.ui.theme.NarodMonTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSensorsBottomSheet(
onApply: (filters: List<SensorFilterUiEntity>) -> Unit,
onDismissRequest: () -> Unit
) {
val filterItems = remember {
listOf(
/* TODO:
* Заменить `code` на настоящее значение
* либо динамически его подгружать из ответа АПИ
* (см. /appInit, ключ в жсоне: types.type) */
SensorFilterUiEntity(R.string.filter_temp, 0),
SensorFilterUiEntity(R.string.filter_temp_water, 1),
SensorFilterUiEntity(R.string.filter_temp_ground, 2),
SensorFilterUiEntity(R.string.filter_temp_dew_point, 3),
SensorFilterUiEntity(R.string.filter_humidity, 4),
SensorFilterUiEntity(R.string.filter_pressure, 5),
SensorFilterUiEntity(R.string.filter_lightness, 6),
SensorFilterUiEntity(R.string.filter_uv, 7),
SensorFilterUiEntity(R.string.filter_radiation, 8),
SensorFilterUiEntity(R.string.filter_rainfall, 9),
SensorFilterUiEntity(R.string.filter_dust, 10),
SensorFilterUiEntity(R.string.filter_wind_speed, 11),
SensorFilterUiEntity(R.string.filter_wind_direction, 12),
SensorFilterUiEntity(R.string.filter_concentration, 13),
SensorFilterUiEntity(R.string.filter_power, 14),
SensorFilterUiEntity(R.string.filter_voltage, 15),
SensorFilterUiEntity(R.string.filter_amperage, 16),
SensorFilterUiEntity(R.string.filter_energy, 17),
SensorFilterUiEntity(R.string.filter_battery, 18),
SensorFilterUiEntity(R.string.filter_rxtx, 19),
SensorFilterUiEntity(R.string.filter_signal, 20),
SensorFilterUiEntity(R.string.filter_water_meter, 21),
SensorFilterUiEntity(R.string.filter_time, 22),
)
}
ModalBottomSheet(
onDismissRequest = { onDismissRequest.invoke() },
sheetState = SheetState(true)
) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.sensors_filter_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
)
}
Box(contentAlignment = Alignment.BottomCenter) {
LazyColumn(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth(),
) {
items(filterItems) {
FilterCheckbox(
checked = it.enabled.value,
stringRes = it.stringRes,
) { it.enabled.value = !it.enabled.value }
}
}
Button(
onClick = { onApply.invoke(filterItems) },
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 64.dp)
) {
Text(text = stringResource(id = R.string.apply))
}
}
}
}
@Preview
@Composable
fun PreviewSensorFilterBottomSheet() {
NarodMonTheme {
FilterSensorsBottomSheet({}) {
}
}
}

View file

@ -0,0 +1,97 @@
package ru.nm17.narodmon.ui.bottomSheets
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
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.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ru.nm17.narodmon.R
import ru.nm17.narodmon.ui.entities.SensorSortingUiEntity
import ru.nm17.narodmon.ui.entities.SortingTypes
import ru.nm17.narodmon.ui.pages.FilterRadioButton
import ru.nm17.narodmon.ui.theme.NarodMonTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SortSensorsBottomSheet(
onApply: (sortingType: SortingTypes) -> Unit,
onDismissRequest: () -> Unit
) {
var sortingType by remember { mutableStateOf(SortingTypes.DISTANCE) }
val sortingTypes = remember {
listOf(
SensorSortingUiEntity(R.string.sort_by_name, SortingTypes.NAME),
SensorSortingUiEntity(R.string.sort_by_name_desc, SortingTypes.NAME_DESC),
SensorSortingUiEntity(R.string.sort_by_distance, SortingTypes.DISTANCE),
SensorSortingUiEntity(R.string.sort_by_distance_desc, SortingTypes.DISTANCE_DESC),
SensorSortingUiEntity(R.string.sort_by_type, SortingTypes.TYPE),
SensorSortingUiEntity(R.string.sort_by_type_desc, SortingTypes.TYPE_DESC),
SensorSortingUiEntity(R.string.sort_update_time, SortingTypes.UPD_TIME),
)
}
ModalBottomSheet(
onDismissRequest = { onDismissRequest.invoke() },
sheetState = SheetState(true)
) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.sensors_sort_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
)
}
LazyColumn(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth(),
) {
items(sortingTypes) {
FilterRadioButton(
selected = (sortingType == it.sortingType),
onClick = { sortingType = it.sortingType },
stringRes = it.stringRes,
)
}
}
Button(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 64.dp, vertical = 8.dp),
onClick = {
onApply.invoke(sortingType)
}) {
Text(text = stringResource(R.string.apply))
}
}
}
@Preview
@Composable
fun PreviewSortBottomSheet() {
NarodMonTheme {
SortSensorsBottomSheet(onApply = {}) {}
}
}

View file

@ -0,0 +1,21 @@
package ru.nm17.narodmon.ui.entities
import ru.nm17.narodmon.db.entities.SensorType
data class SensorEntity(
// TODO: Вынести в отдельный класс, и явно не в директорию `ui`
val id: Int,
val type: SensorType,
val deviceName: String,
val deviceOwner: Int,
val name: String,
val favorite: Boolean,
val public: Boolean,
val mine: Boolean,
val location: String,
val distance: Double, // километры
val value: Double,
val unit: String,
val changed: Int,
)

View file

@ -0,0 +1,11 @@
package ru.nm17.narodmon.ui.entities
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
data class SensorFilterUiEntity(
// TODO: Можно попробовать объединить с db/SensorType.kt
val stringRes: Int,
val code: Int,
var enabled: MutableState<Boolean> = mutableStateOf(false),
)

View file

@ -0,0 +1,7 @@
package ru.nm17.narodmon.ui.entities
data class SensorSortingUiEntity(
val stringRes: Int,
val sortingType: SortingTypes,
)

View file

@ -0,0 +1 @@
package ru.nm17.narodmon.ui.entities

View file

@ -0,0 +1,13 @@
package ru.nm17.narodmon.ui.entities
enum class SortingTypes {
DISTANCE,
DISTANCE_DESC,
TYPE,
TYPE_DESC,
UPD_TIME,
NAME,
NAME_DESC,
VALUE,
VALUE_DESC
}

View file

@ -11,20 +11,17 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Card
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Divider
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.RadioButton
import androidx.compose.material3.SearchBar
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
@ -32,53 +29,24 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import ru.nm17.narodmon.R
import ru.nm17.narodmon.db.entities.SensorType
import ru.nm17.narodmon.ui.bottomSheets.FilterSensorsBottomSheet
import ru.nm17.narodmon.ui.bottomSheets.SortSensorsBottomSheet
import ru.nm17.narodmon.ui.elements.GenericNavScaffold
import ru.nm17.narodmon.ui.elements.TileMap
import ru.nm17.narodmon.ui.entities.SensorEntity
import ru.nm17.narodmon.ui.entities.SensorFilterUiEntity
import ru.nm17.narodmon.ui.entities.SortingTypes
import ru.nm17.narodmon.ui.iosevkaFamily
data class Sensor(
// TODO: Вынести в отдельный класс, и явно не в директорию `ui`
val id: Int,
val type: SensorType,
val deviceName: String,
val deviceOwner: Int,
val name: String,
val favorite: Boolean,
val public: Boolean,
val mine: Boolean,
val location: String,
val distance: Double, // километры
val value: Double,
val unit: String,
val changed: Int,
)
data class SensorFilter(
// TODO: Можно попробовать объединить с db/SensorType.kt
val stringRes: Int,
val code: Int,
var enabled: MutableState<Boolean> = mutableStateOf(false),
)
data class SensorSortingItem(
val stringRes: Int,
val sortingType: SortingType,
)
enum class SortingType {
DISTANCE, TYPE, UPD_TIME,
NAME, VALUE,
}
@ExperimentalMaterial3Api
@Composable
@ -86,61 +54,18 @@ fun SensorsPage(navController: NavController) {
var searchQuery by remember { mutableStateOf("") }
var searchActive by remember { mutableStateOf(false) }
var sortingShow by remember { mutableStateOf(false) }
var sortingType by remember { mutableStateOf(SortingType.DISTANCE) }
var sortingDesc by remember { mutableStateOf(false) }
var sortingMine by remember { mutableStateOf(false) }
var sortingFav by remember { mutableStateOf(false) }
val sortingTypes = remember {
listOf(
SensorSortingItem(R.string.sort_distance, SortingType.DISTANCE),
SensorSortingItem(R.string.sort_type, SortingType.TYPE),
SensorSortingItem(R.string.sort_update_time, SortingType.UPD_TIME),
SensorSortingItem(R.string.sort_name, SortingType.NAME),
SensorSortingItem(R.string.sort_value, SortingType.VALUE),
)
}
var sortingShow by remember { mutableStateOf(false) }
var sortingType by remember { mutableStateOf(SortingTypes.DISTANCE) }
var filterShow by remember { mutableStateOf(false) }
var filterMine by remember { mutableStateOf(false) }
val filterItems = remember {
listOf(
/* TODO:
* Заменить `code` на настоящее значение
* либо динамически его подгружать из ответа АПИ
* (см. /appInit, ключ в жсоне: types.type) */
SensorFilter(R.string.filter_temp, 0),
SensorFilter(R.string.filter_temp_water, 1),
SensorFilter(R.string.filter_temp_ground, 2),
SensorFilter(R.string.filter_temp_dew_point, 3),
SensorFilter(R.string.filter_humidity, 4),
SensorFilter(R.string.filter_pressure, 5),
SensorFilter(R.string.filter_lightness, 6),
SensorFilter(R.string.filter_uv, 7),
SensorFilter(R.string.filter_radiation, 8),
SensorFilter(R.string.filter_rainfall, 9),
SensorFilter(R.string.filter_dust, 10),
SensorFilter(R.string.filter_wind_speed, 11),
SensorFilter(R.string.filter_wind_direction, 12),
SensorFilter(R.string.filter_concentration, 13),
SensorFilter(R.string.filter_power, 14),
SensorFilter(R.string.filter_voltage, 15),
SensorFilter(R.string.filter_amperage, 16),
SensorFilter(R.string.filter_energy, 17),
SensorFilter(R.string.filter_battery, 18),
SensorFilter(R.string.filter_rxtx, 19),
SensorFilter(R.string.filter_signal, 20),
SensorFilter(R.string.filter_water_meter, 21),
SensorFilter(R.string.filter_time, 22),
)
}
val sensors = remember {
val sensorEntities = remember {
mutableListOf(
// TODO: загружать датчики с сервера. Этот список -- для макета
Sensor(
SensorEntity(
0,
SensorType(0, "temp", "C"),
"device0", 0,
@ -149,7 +74,7 @@ fun SensorsPage(navController: NavController) {
"Москва", 0.4,
20.0, "C", 1686142800,
),
Sensor(
SensorEntity(
1,
SensorType(4, "humidity", "%"),
"device1", 0,
@ -158,7 +83,7 @@ fun SensorsPage(navController: NavController) {
"Подмосковье", 1.1,
39.0, "%", 1686142800,
),
Sensor(
SensorEntity(
2,
SensorType(11, "wind speed", "m/s"),
"device2", 1,
@ -187,7 +112,9 @@ fun SensorsPage(navController: NavController) {
onQueryChange = { query -> searchQuery = query },
onSearch = { searchActive = false },
placeholder = { Text(stringResource(R.string.search)) },
modifier = Modifier.fillMaxWidth()
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = if (!searchActive) 8.dp else 0.dp)
) {}
Row(
@ -196,11 +123,23 @@ fun SensorsPage(navController: NavController) {
) {
AssistChip(
onClick = { filterShow = true },
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_filter),
contentDescription = stringResource(id = R.string.sensors_filter)
)
},
label = { Text(text = stringResource(R.string.sensors_filter)) },
)
AssistChip(
onClick = { sortingShow = true },
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_sort),
contentDescription = stringResource(id = R.string.sensors_sorting)
)
},
label = { Text(text = stringResource(R.string.sensors_sorting)) },
)
@ -216,7 +155,7 @@ fun SensorsPage(navController: NavController) {
LazyColumn(
modifier = Modifier.fillMaxHeight(),
) {
items(sensors) { sensor ->
items(sensorEntities) { sensor ->
SensorItem(sensor)
}
}
@ -224,105 +163,42 @@ fun SensorsPage(navController: NavController) {
}
if (filterShow) {
ModalBottomSheet(onDismissRequest = { filterShow = false }) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.sensors_filter_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
FilterSensorsBottomSheet(
onApply = {
// TODO применение фильтров
filterShow = false
},
onDismissRequest = { filterShow = false }
)
}
LazyColumn(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth(),
) {
items(filterItems) {
FilterCheckbox(
checked = it.enabled.value,
onCheckedChange = { it.enabled.value = !it.enabled.value },
stringRes = it.stringRes,
)
}
}
}
}
if (sortingShow) {
ModalBottomSheet(onDismissRequest = { sortingShow = false }) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.sensors_sort_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
)
}
LazyColumn(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth(),
) {
items(sortingTypes) {
FilterRadioButton(
selected = (sortingType == it.sortingType),
onClick = { sortingType = it.sortingType },
stringRes = it.stringRes,
)
}
item {
FilterCheckbox(
checked = sortingDesc,
onCheckedChange = { sortingDesc = !sortingDesc },
stringRes = R.string.sort_option_desc,
)
}
item {
FilterCheckbox(
checked = sortingFav,
onCheckedChange = { sortingFav = !sortingFav },
stringRes = R.string.sort_option_fav,
)
}
item {
FilterCheckbox(
checked = sortingMine,
onCheckedChange = { sortingMine = !sortingMine },
stringRes = R.string.sort_option_mine,
)
}
}
}
SortSensorsBottomSheet(
onApply = { s ->
sortingType = s
sortingShow = false
},
onDismissRequest = { sortingShow = false })
}
}
@ExperimentalMaterial3Api
@Composable
fun SensorItem(sensor: Sensor) {
fun SensorItem(sensorEntity: SensorEntity) {
ListItem(
overlineContent = { Text(text = "${sensor.deviceName} от ${sensor.deviceOwner}") },
headlineContent = { Text(text = sensor.type.name) },
supportingContent = { Text(text = sensor.name) },
overlineContent = { Text(text = "${sensorEntity.deviceName} от ${sensorEntity.deviceOwner}") },
headlineContent = { Text(text = sensorEntity.type.name) },
supportingContent = { Text(text = sensorEntity.name) },
trailingContent = {
Column(
horizontalAlignment = Alignment.End,
) {
Text(text = "${sensor.distance} km")
Text(text = "${sensorEntity.distance} km")
ElevatedCard(
shape = RectangleShape,
) {
Text(
text = "${sensor.value} ${sensor.unit}",
text = "${sensorEntity.value} ${sensorEntity.unit}",
fontFamily = iosevkaFamily,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
@ -336,9 +212,12 @@ fun SensorItem(sensor: Sensor) {
@ExperimentalMaterial3Api
@Composable
fun FilterCheckbox(checked: Boolean, onCheckedChange: () -> Unit, stringRes: Int) {
fun FilterCheckbox(checked: Boolean, stringRes: Int, onCheckedChange: () -> Unit) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable { onCheckedChange() }
) {
Checkbox(
checked = checked,
@ -346,7 +225,6 @@ fun FilterCheckbox(checked: Boolean, onCheckedChange: () -> Unit, stringRes: Int
)
Text(
text = stringResource(id = stringRes),
modifier = Modifier.clickable { onCheckedChange() },
)
}
}
@ -354,16 +232,16 @@ fun FilterCheckbox(checked: Boolean, onCheckedChange: () -> Unit, stringRes: Int
@ExperimentalMaterial3Api
@Composable
fun FilterRadioButton(selected: Boolean, onClick: () -> Unit, stringRes: Int) {
Row (
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable { onClick.invoke() }
) {
RadioButton(
selected = selected,
onClick = onClick,
)
Text(
text = stringResource(id = stringRes),
modifier = Modifier.clickable { onClick() },
)
Text(text = stringResource(id = stringRes))
}
}

View 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="M7,6h10l-5.01,6.3L7,6zM4.25,5.61C6.27,8.2 10,13 10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-6c0,0 3.72,-4.8 5.74,-7.39C20.25,4.95 19.78,4 18.95,4H5.04C4.21,4 3.74,4.95 4.25,5.61z"/>
</vector>

View 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="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
</vector>

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Sensors">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>

View file

@ -1,7 +1,6 @@
<resources>
<string name="app_name">Народный Мониторинг</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="accept_agreements">Я принимаю соглашения</string>
<string name="exit">Выйти</string>
<string name="agreement_dialog_text">
@ -18,7 +17,7 @@
<string name="search">Поиск</string>
<string name="sensors_filter">Фильтр</string>
<string name="sensors_sorting">Сортировка</string>
<string name="sensors_mine">Мои</string>
<string name="sensors_mine">Мои датчики</string>
<string name="filter_temp_dew_point">Температура точки росы</string>
<string name="filter_temp">Температура воздуха</string>
<string name="filter_temp_water">Температура воды</string>
@ -43,13 +42,13 @@
<string name="filter_water_meter">Счётчик воды</string>
<string name="filter_time">Время работы</string>
<string name="sensors_filter_title">Тип датчиков</string>
<string name="sort_distance">Расстояние</string>
<string name="sort_type">Тип датчика</string>
<string name="sort_update_time">Время последнего обновления</string>
<string name="sort_name">Название</string>
<string name="sort_value">Данные</string>
<string name="sort_option_desc">По убыванию</string>
<string name="sort_option_fav">Избранные сверху</string>
<string name="sort_option_mine">Мои датчики сверху</string>
<string name="sensors_sort_title">Сортировка</string>
<string name="sort_by_distance">От ближних к дальним</string>
<string name="sort_by_type">По типу (от А до Я)</string>
<string name="sort_by_type_desc">По типу (от Я до А)</string>
<string name="sort_by_name">По названию (от А до Я)</string>
<string name="sort_by_name_desc">По названию (от Я до А)</string>
<string name="sensors_sort_title">Сортировка датчиков</string>
<string name="sort_update_time">По времени обновления</string>
<string name="apply">Применить</string>
<string name="sort_by_distance_desc">От дальних к ближним</string>
</resources>