Compare commits
7 commits
0935cd88d4
...
5639ebd4cd
Author | SHA1 | Date | |
---|---|---|---|
5639ebd4cd | |||
d1e7b60378 | |||
2a318d551c | |||
3a873725f2 | |||
1334014c04 | |||
06bc8a839e | |||
2b2a2c2f5a |
4 changed files with 143 additions and 38 deletions
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) },
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -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>
|
Loading…
Add table
Reference in a new issue