Polish editors, previews, persistence and docs
Cross-platform refinements to appearance/battery/charger editors, tabs and navigation, plus persistence, screenshot previews and CLAUDE.md docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,8 +19,10 @@ import androidx.compose.material.icons.outlined.BatteryChargingFull
|
||||
import androidx.compose.material.icons.outlined.BatteryFull
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.LibraryBooks
|
||||
import androidx.compose.material.icons.outlined.Speed
|
||||
import androidx.compose.material.icons.outlined.Warning
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -63,6 +65,7 @@ fun BatteriesTab(
|
||||
state: DetailState,
|
||||
onEditBattery: (String) -> Unit,
|
||||
onNewBattery: () -> Unit,
|
||||
onOpenLibrary: () -> Unit,
|
||||
onDeleteBattery: (SavedBattery) -> Unit,
|
||||
) {
|
||||
val batteries = state.batteries
|
||||
@@ -73,11 +76,15 @@ fun BatteriesTab(
|
||||
subtitle = stringResource(R.string.battery_onboarding_subtitle),
|
||||
primaryLabel = stringResource(R.string.battery_empty_create),
|
||||
onPrimary = onNewBattery,
|
||||
secondaryLabel = stringResource(R.string.loads_empty_library),
|
||||
onSecondary = onOpenLibrary,
|
||||
images = listOf(R.drawable.onboarding_battery),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val m = state.metrics
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
StatsHeader {
|
||||
Text(stringResource(R.string.battery_bank_header_title), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold)
|
||||
@@ -101,12 +108,20 @@ fun BatteriesTab(
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn(Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues(bottom = 24.dp)) {
|
||||
LazyColumn(Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues(bottom = 96.dp)) {
|
||||
items(batteries, key = { it.id }) { battery ->
|
||||
BatteryRow(battery, onClick = { onEditBattery(battery.id) }, onDelete = { onDeleteBattery(battery) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedFloatingActionButton(
|
||||
onClick = onOpenLibrary,
|
||||
icon = { Icon(Icons.Outlined.LibraryBooks, contentDescription = null) },
|
||||
text = { Text(stringResource(R.string.loads_library_button)) },
|
||||
modifier = Modifier.align(Alignment.BottomEnd).padding(24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -90,6 +91,9 @@ fun BatteryEditorScreen(systemId: String, batteryId: String?, onBack: () -> Unit
|
||||
title = {
|
||||
Text(s.name, fontWeight = FontWeight.SemiBold, modifier = Modifier.clickable { showAppearance = true })
|
||||
},
|
||||
actions = {
|
||||
TextButton(onClick = onBack) { Text(stringResource(R.string.action_save)) }
|
||||
},
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
|
||||
@@ -81,6 +81,9 @@ fun ChargerEditorScreen(systemId: String, chargerId: String?, onBack: () -> Unit
|
||||
IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = stringResource(R.string.action_back)) }
|
||||
},
|
||||
title = { Text(s.name, fontWeight = FontWeight.SemiBold, modifier = Modifier.clickable { showAppearance = true }) },
|
||||
actions = {
|
||||
TextButton(onClick = onBack) { Text(stringResource(R.string.action_save)) }
|
||||
},
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
|
||||
@@ -2,6 +2,7 @@ package app.voltplan.cable.ui.chargers
|
||||
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
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
|
||||
@@ -15,7 +16,9 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material.icons.outlined.BatteryChargingFull
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.LibraryBooks
|
||||
import androidx.compose.material.icons.outlined.Speed
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -55,6 +58,7 @@ fun ChargersTab(
|
||||
state: DetailState,
|
||||
onEditCharger: (String) -> Unit,
|
||||
onNewCharger: () -> Unit,
|
||||
onOpenLibrary: () -> Unit,
|
||||
onDeleteCharger: (SavedCharger) -> Unit,
|
||||
) {
|
||||
val chargers = state.chargers
|
||||
@@ -65,11 +69,15 @@ fun ChargersTab(
|
||||
subtitle = stringResource(R.string.chargers_onboarding_subtitle),
|
||||
primaryLabel = stringResource(R.string.chargers_onboarding_primary),
|
||||
onPrimary = onNewCharger,
|
||||
secondaryLabel = stringResource(R.string.loads_empty_library),
|
||||
onSecondary = onOpenLibrary,
|
||||
images = listOf(R.drawable.onboarding_charger),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val m = state.metrics
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
StatsHeader {
|
||||
Text(stringResource(R.string.chargers_summary_title), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold)
|
||||
@@ -85,12 +93,20 @@ fun ChargersTab(
|
||||
SummaryMetric(Icons.Outlined.Bolt, "${Fmt.number(m.totalChargerPower)} W", stringResource(R.string.chargers_metric_power), SysPink)
|
||||
}
|
||||
}
|
||||
LazyColumn(Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues(bottom = 24.dp)) {
|
||||
LazyColumn(Modifier.fillMaxSize(), contentPadding = androidx.compose.foundation.layout.PaddingValues(bottom = 96.dp)) {
|
||||
items(chargers, key = { it.id }) { charger ->
|
||||
ChargerRow(charger, onClick = { onEditCharger(charger.id) }, onDelete = { onDeleteCharger(charger) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedFloatingActionButton(
|
||||
onClick = onOpenLibrary,
|
||||
icon = { Icon(Icons.Outlined.LibraryBooks, contentDescription = null) },
|
||||
text = { Text(stringResource(R.string.loads_library_button)) },
|
||||
modifier = Modifier.align(Alignment.BottomEnd).padding(24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -3,18 +3,17 @@ package app.voltplan.cable.ui.components
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
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.RowScope
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -69,6 +68,7 @@ fun AppearanceEditorSheet(
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 20.dp)
|
||||
.padding(bottom = 24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
@@ -113,55 +113,41 @@ fun AppearanceEditorSheet(
|
||||
extra?.invoke()
|
||||
|
||||
Text("Icon", style = MaterialTheme.typography.titleSmall)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(5),
|
||||
modifier = Modifier.fillMaxWidth().heightForRows(icons.size, 5),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
userScrollEnabled = false,
|
||||
) {
|
||||
items(icons) { symbol ->
|
||||
val selected = symbol == icon
|
||||
Box(
|
||||
Modifier
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(if (selected) selectedColor else MaterialTheme.colorScheme.surfaceVariant)
|
||||
.clickable { icon = symbol },
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
sfSymbol(symbol),
|
||||
contentDescription = symbol,
|
||||
tint = if (selected) Color.White else MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
}
|
||||
GridRows(items = icons, columns = 5) { symbol ->
|
||||
val selected = symbol == icon
|
||||
Box(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(if (selected) selectedColor else MaterialTheme.colorScheme.surfaceVariant)
|
||||
.clickable { icon = symbol },
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
sfSymbol(symbol),
|
||||
contentDescription = symbol,
|
||||
tint = if (selected) Color.White else MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Text("Color", style = MaterialTheme.typography.titleSmall)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(6),
|
||||
modifier = Modifier.fillMaxWidth().heightForRows(curatedColorNames.size, 6),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
userScrollEnabled = false,
|
||||
) {
|
||||
items(curatedColorNames) { colorName ->
|
||||
val c = componentColor(colorName)
|
||||
Box(
|
||||
Modifier
|
||||
.aspectRatio(1f)
|
||||
.clip(CircleShape)
|
||||
.background(c)
|
||||
.border(2.dp, if (colorName == color) Color.White else Color.Transparent, CircleShape)
|
||||
.clickable { color = colorName },
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (colorName == color) {
|
||||
Icon(Icons.Filled.Check, contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp))
|
||||
}
|
||||
GridRows(items = curatedColorNames, columns = 6) { colorName ->
|
||||
val c = componentColor(colorName)
|
||||
Box(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.aspectRatio(1f)
|
||||
.clip(CircleShape)
|
||||
.background(c)
|
||||
.border(2.dp, if (colorName == color) Color.White else Color.Transparent, CircleShape)
|
||||
.clickable { color = colorName },
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (colorName == color) {
|
||||
Icon(Icons.Filled.Check, contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,8 +155,25 @@ fun AppearanceEditorSheet(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Modifier.heightForRows(itemCount: Int, columns: Int): Modifier {
|
||||
val rows = (itemCount + columns - 1) / columns
|
||||
// ~56dp per cell including spacing; gives a non-scrolling grid inside the sheet.
|
||||
return this.height((rows * 56).dp)
|
||||
/**
|
||||
* Lays out [items] in a non-lazy grid of fixed [columns], sizing to its content so it can live
|
||||
* inside a vertically scrolling container without a fixed height. Empty trailing cells are padded
|
||||
* with spacers so cells keep equal widths on the final row.
|
||||
*/
|
||||
@Composable
|
||||
private fun <T> GridRows(
|
||||
items: List<T>,
|
||||
columns: Int,
|
||||
cell: @Composable RowScope.(T) -> Unit,
|
||||
) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
items.chunked(columns).forEach { rowItems ->
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier.fillMaxWidth()) {
|
||||
rowItems.forEach { cell(it) }
|
||||
repeat(columns - rowItems.size) {
|
||||
androidx.compose.foundation.layout.Spacer(Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,9 @@ fun CalculatorScreen(systemId: String, loadId: String?, onBack: () -> Unit) {
|
||||
Text(s.loadName, fontWeight = FontWeight.SemiBold, modifier = Modifier.padding(start = 8.dp))
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
TextButton(onClick = onBack) { Text(stringResource(R.string.action_save)) }
|
||||
},
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
|
||||
@@ -69,6 +69,7 @@ fun ComponentsTab(
|
||||
onPrimary = onNewLoad,
|
||||
secondaryLabel = stringResource(R.string.loads_empty_library),
|
||||
onSecondary = onOpenLibrary,
|
||||
images = listOf(R.drawable.onboarding_coffee, R.drawable.onboarding_router, R.drawable.onboarding_charger),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import app.voltplan.cable.ui.batteries.BatteryEditorScreen
|
||||
import app.voltplan.cable.ui.bom.BillOfMaterialsScreen
|
||||
import app.voltplan.cable.library.ComponentLibraryType
|
||||
import app.voltplan.cable.ui.chargers.ChargerEditorScreen
|
||||
import app.voltplan.cable.ui.library.ComponentLibraryScreen
|
||||
import app.voltplan.cable.ui.loads.CalculatorScreen
|
||||
@@ -22,11 +23,17 @@ object Routes {
|
||||
const val BATTERY = "battery/{systemId}?batteryId={batteryId}"
|
||||
const val CHARGER = "charger/{systemId}?chargerId={chargerId}"
|
||||
const val BOM = "bom/{systemId}"
|
||||
const val LIBRARY = "library?systemId={systemId}"
|
||||
const val LIBRARY = "library?systemId={systemId}&type={type}"
|
||||
const val SETTINGS = "settings"
|
||||
|
||||
fun system(id: String) = "system/$id"
|
||||
fun library(systemId: String? = null) = "library" + (systemId?.let { "?systemId=$it" } ?: "")
|
||||
fun library(systemId: String? = null, type: String = "load"): String {
|
||||
val params = buildList {
|
||||
systemId?.let { add("systemId=$it") }
|
||||
add("type=$type")
|
||||
}
|
||||
return "library?" + params.joinToString("&")
|
||||
}
|
||||
fun calculator(systemId: String, loadId: String? = null) =
|
||||
"calculator/$systemId" + (loadId?.let { "?loadId=$it" } ?: "")
|
||||
fun battery(systemId: String, batteryId: String? = null) =
|
||||
@@ -64,7 +71,7 @@ fun CableNavHost() {
|
||||
onEditCharger = { id -> nav.navigate(Routes.charger(systemId, id)) },
|
||||
onNewCharger = { nav.navigate(Routes.charger(systemId)) },
|
||||
onOpenBom = { nav.navigate(Routes.bom(systemId)) },
|
||||
onOpenLibrary = { nav.navigate(Routes.library(systemId)) },
|
||||
onOpenLibrary = { type -> nav.navigate(Routes.library(systemId, type.typeValue)) },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -122,15 +129,27 @@ fun CableNavHost() {
|
||||
|
||||
composable(
|
||||
Routes.LIBRARY,
|
||||
arguments = listOf(navArgument("systemId") { type = NavType.StringType; nullable = true; defaultValue = null }),
|
||||
arguments = listOf(
|
||||
navArgument("systemId") { type = NavType.StringType; nullable = true; defaultValue = null },
|
||||
navArgument("type") { type = NavType.StringType; nullable = true; defaultValue = "load" },
|
||||
),
|
||||
) { entry ->
|
||||
ComponentLibraryScreen(
|
||||
targetSystemId = entry.arguments?.getString("systemId"),
|
||||
libraryType = ComponentLibraryType.fromArg(entry.arguments?.getString("type")),
|
||||
onBack = { nav.popBackStack() },
|
||||
onOpenSystem = { systemId ->
|
||||
nav.popBackStack()
|
||||
nav.navigate(Routes.system(systemId))
|
||||
},
|
||||
onOpenBatteryEditor = { systemId, batteryId ->
|
||||
nav.popBackStack()
|
||||
nav.navigate(Routes.battery(systemId, batteryId))
|
||||
},
|
||||
onOpenChargerEditor = { systemId, chargerId ->
|
||||
nav.popBackStack()
|
||||
nav.navigate(Routes.charger(systemId, chargerId))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ fun OverviewTab(
|
||||
onAddCharger: () -> Unit,
|
||||
onOpenLibrary: () -> Unit,
|
||||
onOpenBom: () -> Unit,
|
||||
onSelectLoads: () -> Unit,
|
||||
onSelectBatteries: () -> Unit,
|
||||
onSelectChargers: () -> Unit,
|
||||
onSetRuntimeGoal: (Double?) -> Unit,
|
||||
onSetChargeGoal: (Double?) -> Unit,
|
||||
) {
|
||||
@@ -104,9 +107,9 @@ fun OverviewTab(
|
||||
}
|
||||
}
|
||||
|
||||
LoadsCard(state, m, onAddLoad, onOpenLibrary)
|
||||
BatteriesCard(state, m, onAddBattery)
|
||||
ChargersCard(state, m, onAddCharger)
|
||||
LoadsCard(state, m, onAddLoad, onOpenLibrary, onSelectLoads)
|
||||
BatteriesCard(state, m, onAddBattery, onSelectBatteries)
|
||||
ChargersCard(state, m, onAddCharger, onSelectChargers)
|
||||
}
|
||||
|
||||
goalEditor?.let { kind ->
|
||||
@@ -163,9 +166,10 @@ private fun MetricRow(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OverviewCard(title: String, content: @Composable () -> Unit) {
|
||||
private fun OverviewCard(title: String, onClick: (() -> Unit)? = null, content: @Composable () -> Unit) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.then(if (onClick != null) Modifier.clickable { onClick() } else Modifier),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f),
|
||||
) {
|
||||
@@ -177,8 +181,8 @@ private fun OverviewCard(title: String, content: @Composable () -> Unit) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadsCard(state: DetailState, m: SystemMetrics, onAddLoad: () -> Unit, onOpenLibrary: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.loads_overview_header_title)) {
|
||||
private fun LoadsCard(state: DetailState, m: SystemMetrics, onAddLoad: () -> Unit, onOpenLibrary: () -> Unit, onSelect: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.loads_overview_header_title), onClick = if (state.loads.isEmpty()) null else onSelect) {
|
||||
if (state.loads.isEmpty()) {
|
||||
Text(stringResource(R.string.overview_loads_empty_title), fontWeight = FontWeight.Medium)
|
||||
Text(stringResource(R.string.overview_loads_empty_subtitle), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
@@ -196,8 +200,8 @@ private fun LoadsCard(state: DetailState, m: SystemMetrics, onAddLoad: () -> Uni
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BatteriesCard(state: DetailState, m: SystemMetrics, onAddBattery: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.battery_bank_header_title)) {
|
||||
private fun BatteriesCard(state: DetailState, m: SystemMetrics, onAddBattery: () -> Unit, onSelect: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.battery_bank_header_title), onClick = if (state.batteries.isEmpty()) null else onSelect) {
|
||||
if (state.batteries.isEmpty()) {
|
||||
Text(stringResource(R.string.battery_empty_title), fontWeight = FontWeight.Medium)
|
||||
Button(onClick = onAddBattery) { Text(stringResource(R.string.battery_empty_create)) }
|
||||
@@ -212,8 +216,8 @@ private fun BatteriesCard(state: DetailState, m: SystemMetrics, onAddBattery: ()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ChargersCard(state: DetailState, m: SystemMetrics, onAddCharger: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.overview_chargers_header_title)) {
|
||||
private fun ChargersCard(state: DetailState, m: SystemMetrics, onAddCharger: () -> Unit, onSelect: () -> Unit) {
|
||||
OverviewCard(stringResource(R.string.overview_chargers_header_title), onClick = if (state.chargers.isEmpty()) null else onSelect) {
|
||||
if (state.chargers.isEmpty()) {
|
||||
Text(stringResource(R.string.overview_chargers_empty_title), fontWeight = FontWeight.Medium)
|
||||
Text(stringResource(R.string.overview_chargers_empty_subtitle), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
@@ -16,7 +17,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
import androidx.compose.material.icons.outlined.ChevronRight
|
||||
import androidx.compose.material.icons.outlined.AutoAwesome
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material3.Button
|
||||
@@ -46,6 +46,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import app.voltplan.cable.R
|
||||
import app.voltplan.cable.ui.components.OnboardingCarousel
|
||||
import app.voltplan.cable.ui.sfSymbol
|
||||
import app.voltplan.cable.ui.theme.componentColor
|
||||
|
||||
@@ -174,7 +175,10 @@ private fun SystemsOnboarding(modifier: Modifier = Modifier, onCreate: (String)
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(Icons.Outlined.AutoAwesome, contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(48.dp))
|
||||
OnboardingCarousel(
|
||||
images = listOf(R.drawable.onboarding_van, R.drawable.onboarding_cabin, R.drawable.onboarding_boat),
|
||||
modifier = Modifier.fillMaxWidth().height(220.dp),
|
||||
)
|
||||
Spacer(Modifier.size(16.dp))
|
||||
Text(stringResource(R.string.onboarding_systems_title), style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.SemiBold)
|
||||
Spacer(Modifier.size(8.dp))
|
||||
|
||||
Reference in New Issue
Block a user