Compare commits

..

No commits in common. "2a6bfb205c34fb5e7892019311484168f9af0167" and "4c3584d63c864a42e174cb5dcc9aaf975b2f81bf" have entirely different histories.

14 changed files with 226 additions and 346 deletions

View file

@ -106,6 +106,12 @@ dependencies {
// optional - Kotlin Extensions and Coroutines support for Room // optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version") 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 // optional - Guava support for Room, including Optional and ListenableFuture
implementation("androidx.room:room-guava:$room_version") implementation("androidx.room:room-guava:$room_version")

View file

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

View file

@ -1,119 +0,0 @@
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

@ -1,97 +0,0 @@
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

@ -1,21 +0,0 @@
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

@ -1,11 +0,0 @@
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

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

View file

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

View file

@ -1,13 +0,0 @@
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,17 +11,20 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AssistChip import androidx.compose.material3.AssistChip
import androidx.compose.material3.Card
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
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.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.SearchBar import androidx.compose.material3.SearchBar
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -29,24 +32,53 @@ 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.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavController import androidx.navigation.NavController
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.bottomSheets.FilterSensorsBottomSheet
import ru.nm17.narodmon.ui.bottomSheets.SortSensorsBottomSheet
import ru.nm17.narodmon.ui.elements.GenericNavScaffold import ru.nm17.narodmon.ui.elements.GenericNavScaffold
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.SensorFilterUiEntity
import ru.nm17.narodmon.ui.entities.SortingTypes
import ru.nm17.narodmon.ui.iosevkaFamily 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 @ExperimentalMaterial3Api
@Composable @Composable
@ -54,18 +86,61 @@ fun SensorsPage(navController: NavController) {
var searchQuery by remember { mutableStateOf("") } var searchQuery by remember { mutableStateOf("") }
var searchActive by remember { mutableStateOf(false) } var searchActive by remember { mutableStateOf(false) }
var sortingShow by remember { mutableStateOf(false) } var sortingShow by remember { mutableStateOf(false) }
var sortingType by remember { mutableStateOf(SortingTypes.DISTANCE) } 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 filterShow by remember { mutableStateOf(false) } var filterShow by remember { mutableStateOf(false) }
var filterMine 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 sensorEntities = remember { val sensors = remember {
mutableListOf( mutableListOf(
// TODO: загружать датчики с сервера. Этот список -- для макета // TODO: загружать датчики с сервера. Этот список -- для макета
SensorEntity( Sensor(
0, 0,
SensorType(0, "temp", "C"), SensorType(0, "temp", "C"),
"device0", 0, "device0", 0,
@ -74,7 +149,7 @@ fun SensorsPage(navController: NavController) {
"Москва", 0.4, "Москва", 0.4,
20.0, "C", 1686142800, 20.0, "C", 1686142800,
), ),
SensorEntity( Sensor(
1, 1,
SensorType(4, "humidity", "%"), SensorType(4, "humidity", "%"),
"device1", 0, "device1", 0,
@ -83,7 +158,7 @@ fun SensorsPage(navController: NavController) {
"Подмосковье", 1.1, "Подмосковье", 1.1,
39.0, "%", 1686142800, 39.0, "%", 1686142800,
), ),
SensorEntity( Sensor(
2, 2,
SensorType(11, "wind speed", "m/s"), SensorType(11, "wind speed", "m/s"),
"device2", 1, "device2", 1,
@ -112,9 +187,7 @@ fun SensorsPage(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)) },
modifier = Modifier modifier = Modifier.fillMaxWidth()
.fillMaxWidth()
.padding(horizontal = if (!searchActive) 8.dp else 0.dp)
) {} ) {}
Row( Row(
@ -123,23 +196,11 @@ fun SensorsPage(navController: NavController) {
) { ) {
AssistChip( AssistChip(
onClick = { filterShow = true }, 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)) }, label = { Text(text = stringResource(R.string.sensors_filter)) },
) )
AssistChip( AssistChip(
onClick = { sortingShow = true }, 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)) }, label = { Text(text = stringResource(R.string.sensors_sorting)) },
) )
@ -155,7 +216,7 @@ fun SensorsPage(navController: NavController) {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxHeight(), modifier = Modifier.fillMaxHeight(),
) { ) {
items(sensorEntities) { sensor -> items(sensors) { sensor ->
SensorItem(sensor) SensorItem(sensor)
} }
} }
@ -163,42 +224,105 @@ fun SensorsPage(navController: NavController) {
} }
if (filterShow) { if (filterShow) {
FilterSensorsBottomSheet( ModalBottomSheet(onDismissRequest = { filterShow = false }) {
onApply = { Row(
// TODO применение фильтров horizontalArrangement = Arrangement.Center,
filterShow = false modifier = Modifier.fillMaxWidth(),
}, ) {
onDismissRequest = { filterShow = false } Text(
text = stringResource(R.string.sensors_filter_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
) )
} }
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) { if (sortingShow) {
SortSensorsBottomSheet( ModalBottomSheet(onDismissRequest = { sortingShow = false }) {
onApply = { s -> Row(
sortingType = s horizontalArrangement = Arrangement.Center,
sortingShow = false modifier = Modifier.fillMaxWidth(),
}, ) {
onDismissRequest = { sortingShow = false }) 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,
)
}
}
}
} }
} }
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
@Composable @Composable
fun SensorItem(sensorEntity: SensorEntity) { fun SensorItem(sensor: Sensor) {
ListItem( ListItem(
overlineContent = { Text(text = "${sensorEntity.deviceName} от ${sensorEntity.deviceOwner}") }, overlineContent = { Text(text = "${sensor.deviceName} от ${sensor.deviceOwner}") },
headlineContent = { Text(text = sensorEntity.type.name) }, headlineContent = { Text(text = sensor.type.name) },
supportingContent = { Text(text = sensorEntity.name) }, supportingContent = { Text(text = sensor.name) },
trailingContent = { trailingContent = {
Column( Column(
horizontalAlignment = Alignment.End, horizontalAlignment = Alignment.End,
) { ) {
Text(text = "${sensorEntity.distance} km") Text(text = "${sensor.distance} km")
ElevatedCard( ElevatedCard(
shape = RectangleShape, shape = RectangleShape,
) { ) {
Text( Text(
text = "${sensorEntity.value} ${sensorEntity.unit}", text = "${sensor.value} ${sensor.unit}",
fontFamily = iosevkaFamily, fontFamily = iosevkaFamily,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
fontSize = 14.sp, fontSize = 14.sp,
@ -212,12 +336,9 @@ fun SensorItem(sensorEntity: SensorEntity) {
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
@Composable @Composable
fun FilterCheckbox(checked: Boolean, stringRes: Int, onCheckedChange: () -> Unit) { fun FilterCheckbox(checked: Boolean, onCheckedChange: () -> Unit, stringRes: Int) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable { onCheckedChange() }
) { ) {
Checkbox( Checkbox(
checked = checked, checked = checked,
@ -225,6 +346,7 @@ fun FilterCheckbox(checked: Boolean, stringRes: Int, onCheckedChange: () -> Unit
) )
Text( Text(
text = stringResource(id = stringRes), text = stringResource(id = stringRes),
modifier = Modifier.clickable { onCheckedChange() },
) )
} }
} }
@ -232,16 +354,16 @@ fun FilterCheckbox(checked: Boolean, stringRes: Int, onCheckedChange: () -> Unit
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
@Composable @Composable
fun FilterRadioButton(selected: Boolean, onClick: () -> Unit, stringRes: Int) { fun FilterRadioButton(selected: Boolean, onClick: () -> Unit, stringRes: Int) {
Row( Row (
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable { onClick.invoke() }
) { ) {
RadioButton( RadioButton(
selected = selected, selected = selected,
onClick = onClick, onClick = onClick,
) )
Text(text = stringResource(id = stringRes)) Text(
text = stringResource(id = stringRes),
modifier = Modifier.clickable { onClick() },
)
} }
} }

View file

@ -1,5 +0,0 @@
<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

@ -1,5 +0,0 @@
<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

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