Compare commits

...

7 commits

4 changed files with 143 additions and 38 deletions

View file

@ -41,6 +41,7 @@ import ru.nm17.narodmon.ui.pages.SensorsPage
import ru.nm17.narodmon.ui.theme.NarodMonTheme import ru.nm17.narodmon.ui.theme.NarodMonTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun AppNavHost() { fun AppNavHost() {
val navController = rememberNavController() val navController = rememberNavController()

View file

@ -8,7 +8,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsChannel import io.ktor.client.statement.bodyAsChannel
import io.ktor.utils.io.jvm.javaio.toInputStream import io.ktor.utils.io.jvm.javaio.toInputStream
@ -22,7 +22,7 @@ import java.io.InputStream
const val mapSize = 32768 const val mapSize = 32768
val client = HttpClient(CIO) val client = HttpClient(OkHttp)
val tileStreamProvider = TileStreamProvider { row, col, zoom -> val tileStreamProvider = TileStreamProvider { row, col, zoom ->
requestTile(row, col, zoom) requestTile(row, col, zoom)
} }

View file

@ -1,35 +1,85 @@
package ru.nm17.narodmon.ui.pages package ru.nm17.narodmon.ui.pages
import androidx.compose.foundation.clickable
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.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding 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.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChip
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SearchBar
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.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.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
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.navigation.NavController import androidx.navigation.NavController
import ru.nm17.narodmon.R import ru.nm17.narodmon.R
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
enum class SensorsFilter { data class SensorFilter(
All, Thermometer, Camera, val stringRes: Int,
} val code: Int,
var enabled: MutableState<Boolean> = mutableStateOf(false),
)
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
@Composable @Composable
fun SensorsPage(navController: NavController) { fun SensorsPage(navController: NavController) {
var filter by remember { mutableStateOf(SensorsFilter.All) } var searchQuery by remember { mutableStateOf("") }
var searchActive by remember { mutableStateOf(false) }
var filterShown 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 scrConfig = LocalConfiguration.current val scrConfig = LocalConfiguration.current
val mapHeight = scrConfig.screenHeightDp / 3 val mapHeight = scrConfig.screenHeightDp / 3
@ -41,45 +91,74 @@ fun SensorsPage(navController: NavController) {
TileMap(modifier = Modifier.height(mapHeight.dp)) TileMap(modifier = Modifier.height(mapHeight.dp))
SearchBar(
query = searchQuery,
active = searchActive,
onActiveChange = { active -> searchActive = active },
onQueryChange = { query -> searchQuery = query },
onSearch = { searchActive = false },
placeholder = { Text(stringResource(R.string.search)) },
modifier = Modifier.fillMaxWidth()
) {}
Row( Row(
modifier = Modifier.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(horizontal = 8.dp),
) { ) {
SensorsFilterChip( AssistChip(
name = stringResource(R.string.sensors_filter_all), onClick = { filterShown = true },
checkFilter = { filter == SensorsFilter.All }, label = { Text(text = stringResource(R.string.sensors_filter)) },
updateFilter = { filter = SensorsFilter.All },
) )
SensorsFilterChip( AssistChip(
name = stringResource(R.string.sensors_filter_temp), onClick = { },
checkFilter = { filter == SensorsFilter.Thermometer }, label = { Text(text = stringResource(R.string.sensors_sorting)) },
updateFilter = { filter = SensorsFilter.Thermometer },
) )
SensorsFilterChip( FilterChip(
name = stringResource(R.string.sensors_filter_camera), selected = filterMine,
checkFilter = { filter == SensorsFilter.Camera }, onClick = { filterMine = !filterMine },
updateFilter = { filter = SensorsFilter.Camera }, label = { Text(text = stringResource(R.string.sensors_mine)) },
)
}
}
}
if (filterShown) {
ModalBottomSheet(onDismissRequest = { filterShown = false }) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = stringResource(R.string.sensors_filter_title),
fontSize = 24.sp,
fontWeight = FontWeight(500),
) )
} }
//Text(mapVM.state.scroll.toString()) LazyColumn(
//Text(mapVM.state.scale.toString()) modifier = Modifier.padding(horizontal = 4.dp),
) {
items(filterItems) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Checkbox(
checked = it.enabled.value,
onCheckedChange = { checked ->
it.enabled.value = checked
},
)
Text(
text = stringResource(id = it.stringRes),
modifier = Modifier.clickable {
it.enabled.value = !it.enabled.value
}
)
}
}
}
} }
} }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SensorsFilterChip(
name: String,
checkFilter: () -> Boolean,
updateFilter: () -> Unit,
) {
FilterChip(
selected = checkFilter(),
onClick = updateFilter,
label = { Text(name) },
)
} }

View file

@ -15,7 +15,32 @@
<string name="agreement_dialog_title">Примите необходимые соглашения</string> <string name="agreement_dialog_title">Примите необходимые соглашения</string>
<string name="sensors_page_title">Сенсоры</string> <string name="sensors_page_title">Сенсоры</string>
<string name="waiting_for_user_agreement">Ожидаю соглашение пользователя</string> <string name="waiting_for_user_agreement">Ожидаю соглашение пользователя</string>
<string name="sensors_filter_all">Все</string> <string name="search">Поиск</string>
<string name="sensors_filter_temp">Термометры</string> <string name="sensors_filter">Фильтр</string>
<string name="sensors_filter_camera">Камеры</string> <string name="sensors_sorting">Сортировка</string>
<string name="sensors_mine">Мои</string>
<string name="filter_temp_dew_point">Температура точки росы</string>
<string name="filter_temp">Температура воздуха</string>
<string name="filter_temp_water">Температура воды</string>
<string name="filter_temp_ground">Температура почвы</string>
<string name="filter_humidity">Влажность</string>
<string name="filter_pressure">Давление</string>
<string name="filter_lightness">Освещённость</string>
<string name="filter_uv">УФ-индекс</string>
<string name="filter_radiation">Радиация</string>
<string name="filter_rainfall">Осадки</string>
<string name="filter_dust">Запылённость</string>
<string name="filter_wind_speed">Скорость ветра</string>
<string name="filter_wind_direction">Направление ветра</string>
<string name="filter_concentration">Концентрация</string>
<string name="filter_power">Мощность</string>
<string name="filter_voltage">Напряжение</string>
<string name="filter_amperage">Сила тока</string>
<string name="filter_energy">Энергия</string>
<string name="filter_battery">% батареи</string>
<string name="filter_rxtx">Rx/Tx трафик</string>
<string name="filter_signal">Сигнал в dBm</string>
<string name="filter_water_meter">Счётчик воды</string>
<string name="filter_time">Время работы</string>
<string name="sensors_filter_title">Тип датчиков</string>
</resources> </resources>