mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Optimized common composables and satellite selection
This commit is contained in:
1 parent
706c912b13
commit
45eb6915c2
2 files changed
+136
-150
No files matched your search
+38
-19
@@ -40,11 +40,23 @@ class SelectionRepo(
|
|||||||
private val currentItems = MutableStateFlow<List<SatItem>>(emptyList())
|
private val currentItems = MutableStateFlow<List<SatItem>>(emptyList())
|
||||||
private val currentTypes = MutableStateFlow(settingsRepo.selectedTypes.value)
|
private val currentTypes = MutableStateFlow(settingsRepo.selectedTypes.value)
|
||||||
private val currentQuery = MutableStateFlow("")
|
private val currentQuery = MutableStateFlow("")
|
||||||
|
|
||||||
|
// Resolve type IDs once when types change, then filter items reactively.
|
||||||
|
// The HashSet gives O(1) catnum lookups instead of O(n) with a List.
|
||||||
private val itemsWithTypes = currentTypes.flatMapLatest { types: List<String> ->
|
private val itemsWithTypes = currentTypes.flatMapLatest { types: List<String> ->
|
||||||
currentItems.map { items -> items.filterByTypes(types) }
|
val catnumSet: Set<Int>? = if (types.isEmpty()) {
|
||||||
|
null // null = no filtering
|
||||||
|
} else {
|
||||||
|
val ids = settingsRepo.getSatelliteTypesIds(types)
|
||||||
|
if (ids.isEmpty()) null else ids.toHashSet()
|
||||||
|
}
|
||||||
|
currentItems.map { items ->
|
||||||
|
if (catnumSet == null) items else items.filter { it.catnum in catnumSet }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val itemsWithQuery = currentQuery.flatMapLatest { query ->
|
private val itemsWithQuery = currentQuery.flatMapLatest { query ->
|
||||||
itemsWithTypes.map { items -> items.filterByQuery(query) }
|
itemsWithTypes.map { items -> filterByQuery(items, query) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCurrentTypes() = currentTypes.value
|
override fun getCurrentTypes() = currentTypes.value
|
||||||
@@ -54,7 +66,7 @@ class SelectionRepo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getEntriesFlow() = withContext(dispatcher) {
|
override suspend fun getEntriesFlow() = withContext(dispatcher) {
|
||||||
val selectedIds = settingsRepo.selectedIds.value
|
val selectedIds = settingsRepo.selectedIds.value.toHashSet()
|
||||||
currentItems.value = localSource.getEntriesList().map { item ->
|
currentItems.value = localSource.getEntriesList().map { item ->
|
||||||
item.copy(isSelected = item.catnum in selectedIds)
|
item.copy(isSelected = item.catnum in selectedIds)
|
||||||
}
|
}
|
||||||
@@ -66,17 +78,19 @@ class SelectionRepo(
|
|||||||
settingsRepo.setSelectedTypes(types)
|
settingsRepo.setSelectedTypes(types)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setQuery(query: String) = withContext(dispatcher) {
|
override suspend fun setQuery(query: String) {
|
||||||
currentQuery.value = query
|
currentQuery.value = query
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setSelection(selectAll: Boolean) = withContext(dispatcher) {
|
override suspend fun setSelection(selectAll: Boolean) = withContext(dispatcher) {
|
||||||
setSelection(itemsWithQuery.first().map { item -> item.catnum }, selectAll)
|
val visibleIds = itemsWithQuery.first().mapTo(HashSet()) { it.catnum }
|
||||||
|
setSelection(visibleIds, selectAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setSelection(ids: List<Int>, isTicked: Boolean) = withContext(dispatcher) {
|
override suspend fun setSelection(ids: List<Int>, isTicked: Boolean) = withContext(dispatcher) {
|
||||||
|
val idSet = ids.toHashSet()
|
||||||
currentItems.value = currentItems.value.map { item ->
|
currentItems.value = currentItems.value.map { item ->
|
||||||
if (item.catnum in ids) item.copy(isSelected = isTicked) else item
|
if (item.catnum in idSet) item.copy(isSelected = isTicked) else item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,19 +99,24 @@ class SelectionRepo(
|
|||||||
settingsRepo.setSelectedIds(currentSelection)
|
settingsRepo.setSelectedIds(currentSelection)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun List<SatItem>.filterByTypes(types: List<String>) = withContext(dispatcher) {
|
/**
|
||||||
if (types.isEmpty()) return@withContext this@filterByTypes
|
* Bulk selection using a pre-built Set for O(1) lookups.
|
||||||
val catnums = settingsRepo.getSatelliteTypesIds(types)
|
*/
|
||||||
if (catnums.isEmpty()) return@withContext this@filterByTypes
|
private suspend fun setSelection(idSet: Set<Int>, isTicked: Boolean) = withContext(dispatcher) {
|
||||||
return@withContext this@filterByTypes.filter { item -> item.catnum in catnums }
|
currentItems.value = currentItems.value.map { item ->
|
||||||
}
|
if (item.catnum in idSet) item.copy(isSelected = isTicked) else item
|
||||||
|
|
||||||
private suspend fun List<SatItem>.filterByQuery(query: String) = withContext(dispatcher) {
|
|
||||||
if (query.isBlank()) return@withContext this@filterByQuery
|
|
||||||
return@withContext try {
|
|
||||||
this@filterByQuery.filter { it.catnum == query.toInt() }
|
|
||||||
} catch (_: Exception) {
|
|
||||||
this@filterByQuery.filter { item -> item.name.lowercase().contains(query.lowercase()) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters items by query. Uses toIntOrNull() instead of exception-based flow,
|
||||||
|
* and lowercases the query once up front instead of per-item.
|
||||||
|
*/
|
||||||
|
private fun filterByQuery(items: List<SatItem>, query: String): List<SatItem> {
|
||||||
|
if (query.isBlank()) return items
|
||||||
|
val catnum = query.toIntOrNull()
|
||||||
|
if (catnum != null) return items.filter { it.catnum == catnum }
|
||||||
|
val lowerQuery = query.lowercase()
|
||||||
|
return items.filter { it.name.lowercase().contains(lowerQuery) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+98
-131
@@ -76,19 +76,23 @@ private fun TopBarPreview() = MainTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopBar(content: @Composable (RowScope.() -> Unit)) {
|
fun TopBar(content: @Composable RowScope.() -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.height(48.dp),
|
modifier = Modifier.height(48.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) { content() }
|
content = content
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RowScope.TimerRow(timeString: String, isTimeAos: Boolean) {
|
fun RowScope.TimerRow(timeString: String, isTimeAos: Boolean) {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
val aosColor = if (isTimeAos) colorScheme.primary else colorScheme.onSurface
|
val (aosColor, losColor) = if (isTimeAos) {
|
||||||
val losColor = if (!isTimeAos) colorScheme.primary else colorScheme.onSurface
|
colorScheme.primary to colorScheme.onSurface
|
||||||
|
} else {
|
||||||
|
colorScheme.onSurface to colorScheme.primary
|
||||||
|
}
|
||||||
ElevatedCard(modifier = Modifier.weight(1f)) {
|
ElevatedCard(modifier = Modifier.weight(1f)) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
@@ -100,7 +104,7 @@ fun RowScope.TimerRow(timeString: String, isTimeAos: Boolean) {
|
|||||||
text = timeString,
|
text = timeString,
|
||||||
fontSize = 32.sp,
|
fontSize = 32.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = colorScheme.primary
|
||||||
)
|
)
|
||||||
Text(text = "LOS", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = losColor)
|
Text(text = "LOS", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = losColor)
|
||||||
}
|
}
|
||||||
@@ -124,13 +128,11 @@ fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
|
|||||||
verticalArrangement = Arrangement.spacedBy((-2).dp),
|
verticalArrangement = Arrangement.spacedBy((-2).dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
// .background(color = MaterialTheme.colorScheme.background)
|
|
||||||
.padding(start = 6.dp, top = 1.dp, end = 6.dp, bottom = 0.dp)
|
.padding(start = 6.dp, top = 1.dp, end = 6.dp, bottom = 0.dp)
|
||||||
) {
|
) {
|
||||||
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
text = "$passSatId - ",
|
text = "${stringResource(R.string.pass_satId, pass.catNum)} - ",
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
@@ -144,7 +146,7 @@ fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
|
|||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_elevation),
|
painter = painterResource(R.drawable.ic_elevation),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
@@ -160,47 +162,30 @@ fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
|
|||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Row(
|
Text(
|
||||||
modifier = Modifier.weight(1f),
|
text = sdfTime.format(Date(pass.aosTime)),
|
||||||
horizontalArrangement = Arrangement.Start,
|
fontSize = 15.sp,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
)
|
||||||
Text(
|
|
||||||
text = sdfTime.format(Date(pass.aosTime)),
|
|
||||||
fontSize = 15.sp,
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_altitude),
|
painter = painterResource(R.drawable.ic_altitude),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Text(
|
Text(text = "${pass.altitude} km", fontSize = 15.sp)
|
||||||
text = "${pass.altitude} km",
|
|
||||||
fontSize = 15.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
horizontalArrangement = Arrangement.End,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(
|
|
||||||
id = R.string.pass_aosLos,
|
|
||||||
pass.aosAzimuth.toInt(),
|
|
||||||
pass.losAzimuth.toInt()
|
|
||||||
),
|
|
||||||
fontSize = 15.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.pass_aosLos, pass.aosAzimuth.toInt(), pass.losAzimuth.toInt()),
|
||||||
|
fontSize = 15.sp,
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,34 +194,41 @@ fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
|
|||||||
@Composable
|
@Composable
|
||||||
fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier) {
|
fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier) {
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onClick = { onClick() }, colors = ButtonDefaults.buttonColors(
|
onClick = onClick,
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant
|
contentColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
), shape = MaterialTheme.shapes.small, modifier = modifier,
|
),
|
||||||
|
shape = MaterialTheme.shapes.small,
|
||||||
|
modifier = modifier,
|
||||||
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp)
|
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp)
|
||||||
) { Text(text = text, fontSize = 16.sp, textAlign = TextAlign.Center) }
|
) { Text(text = text, fontSize = 16.sp, textAlign = TextAlign.Center) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun IconCard(action: () -> Unit, resId: Int, modifier: Modifier = Modifier) {
|
fun IconCard(action: () -> Unit, resId: Int, modifier: Modifier = Modifier) {
|
||||||
val clickableMod = Modifier.clickable { action() }
|
|
||||||
ElevatedCard(modifier = Modifier.size(48.dp)) {
|
ElevatedCard(modifier = Modifier.size(48.dp)) {
|
||||||
Box(modifier = clickableMod.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(
|
||||||
Icon(painter = painterResource(resId), contentDescription = null, modifier = modifier)
|
modifier = Modifier
|
||||||
}
|
.clickable(onClick = action)
|
||||||
|
.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) { Icon(painter = painterResource(resId), contentDescription = null, modifier = modifier) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PrimaryIconCard(modifier: Modifier = Modifier, resId: Int, onClick: () -> Unit) {
|
fun PrimaryIconCard(modifier: Modifier = Modifier, resId: Int, onClick: () -> Unit) {
|
||||||
val clickableMod = modifier.clickable { onClick() }
|
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
modifier = Modifier.size(102.dp, 48.dp),
|
modifier = Modifier.size(102.dp, 48.dp),
|
||||||
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.primary)
|
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.primary)
|
||||||
) {
|
) {
|
||||||
Box(modifier = clickableMod.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(
|
||||||
Icon(painter = painterResource(id = resId), contentDescription = null)
|
modifier = modifier
|
||||||
}
|
.clickable(onClick = onClick)
|
||||||
|
.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) { Icon(painter = painterResource(resId), contentDescription = null) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,56 +254,56 @@ fun EmptyListCard(message: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultPass(): OrbitalPass {
|
private val defaultOrbitalData = OrbitalData(
|
||||||
val orbitalData = OrbitalData(
|
name = """ ¯\_(ツ)_/¯ ⚠️""",
|
||||||
""" ¯\_(ツ)_/¯ ⚠️""",
|
epoch = 0.0, meanmo = 0.0, eccn = 0.0, incl = 0.0,
|
||||||
0.0,
|
raan = 0.0, argper = 0.0, meanan = 0.0, catnum = 0, bstar = 0.0
|
||||||
0.0,
|
)
|
||||||
0.0,
|
|
||||||
0.0,
|
fun getDefaultPass(): OrbitalPass = OrbitalPass(
|
||||||
0.0,
|
aosTime = 0L, aosAzimuth = 0.0, losTime = Long.MAX_VALUE, losAzimuth = 0.0,
|
||||||
0.0,
|
altitude = 0, maxElevation = 0.0, orbitalObject = NearEarthObject(defaultOrbitalData), progress = 0f
|
||||||
0.0,
|
)
|
||||||
0,
|
|
||||||
0.0
|
|
||||||
)
|
|
||||||
val satellite = NearEarthObject(orbitalData)
|
|
||||||
return OrbitalPass(0L, 0.0, Long.MAX_VALUE, 0.0, 0, 0.0, satellite, 0f)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SharedDialog(
|
fun SharedDialog(
|
||||||
title: String, onCancel: () -> Unit, onAccept: () -> Unit, content: @Composable () -> Unit
|
title: String, onCancel: () -> Unit, onAccept: () -> Unit, content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val padding = LocalSpacing.current.large
|
DialogShell(title = title, titleFontSize = 16, onDismissRequest = onCancel) {
|
||||||
Dialog(onDismissRequest = { onCancel() }) {
|
content()
|
||||||
ElevatedCard {
|
Row(modifier = Modifier.padding(start = it, bottom = it, end = it)) {
|
||||||
Column(
|
CardButton(onClick = onCancel, text = stringResource(R.string.btn_cancel))
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
verticalArrangement = Arrangement.spacedBy(padding)
|
CardButton(onClick = onAccept, text = stringResource(R.string.btn_accept))
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = title,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
modifier = Modifier.padding(start = padding, top = padding, end = padding)
|
|
||||||
)
|
|
||||||
content()
|
|
||||||
Row(modifier = Modifier.padding(start = padding, bottom = padding, end = padding)) {
|
|
||||||
CardButton(onClick = onCancel, text = stringResource(id = R.string.btn_cancel))
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
CardButton(onClick = onAccept, text = stringResource(id = R.string.btn_accept))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InfoDialog(title: String, text: String, onDismiss: () -> Unit) {
|
fun InfoDialog(title: String, text: String, onDismiss: () -> Unit) {
|
||||||
|
DialogShell(title = title, titleFontSize = 18, onDismissRequest = {}) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
modifier = Modifier.padding(horizontal = it)
|
||||||
|
)
|
||||||
|
Row(modifier = Modifier.padding(start = it, bottom = it, end = it)) {
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
CardButton(onClick = onDismiss, text = stringResource(R.string.btn_accept))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DialogShell(
|
||||||
|
title: String,
|
||||||
|
titleFontSize: Int,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
content: @Composable (padding: androidx.compose.ui.unit.Dp) -> Unit
|
||||||
|
) {
|
||||||
val padding = LocalSpacing.current.large
|
val padding = LocalSpacing.current.large
|
||||||
Dialog(onDismissRequest = {}) {
|
Dialog(onDismissRequest = onDismissRequest) {
|
||||||
ElevatedCard {
|
ElevatedCard {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
@@ -319,54 +311,36 @@ fun InfoDialog(title: String, text: String, onDismiss: () -> Unit) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
fontSize = 18.sp,
|
fontSize = titleFontSize.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier.padding(start = padding, top = padding, end = padding)
|
modifier = Modifier.padding(start = padding, top = padding, end = padding)
|
||||||
)
|
)
|
||||||
Text(
|
content(padding)
|
||||||
text = text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
modifier = Modifier.padding(horizontal = padding)
|
|
||||||
)
|
|
||||||
Row(modifier = Modifier.padding(start = padding, bottom = padding, end = padding)) {
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
CardButton(
|
|
||||||
onClick = onDismiss,
|
|
||||||
text = stringResource(id = R.string.btn_accept)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun hasEnoughHeight(): Boolean {
|
fun hasEnoughHeight(): Boolean =
|
||||||
return currentWindowAdaptiveInfo().windowSizeClass.isHeightAtLeastBreakpoint(480)
|
currentWindowAdaptiveInfo().windowSizeClass.isHeightAtLeastBreakpoint(480)
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun hasEnoughWidth(): Boolean {
|
fun hasEnoughWidth(): Boolean =
|
||||||
return currentWindowAdaptiveInfo().windowSizeClass.isWidthAtLeastBreakpoint(600)
|
currentWindowAdaptiveInfo().windowSizeClass.isWidthAtLeastBreakpoint(600)
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun isVerticalLayout(): Boolean {
|
fun isVerticalLayout(): Boolean = !hasEnoughWidth()
|
||||||
return currentWindowAdaptiveInfo().windowSizeClass.isWidthAtLeastBreakpoint(600).not()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Modifier.infiniteMarquee(): Modifier {
|
fun Modifier.infiniteMarquee(): Modifier =
|
||||||
return basicMarquee(iterations = Int.MAX_VALUE, spacing = MarqueeSpacing(16.dp))
|
basicMarquee(iterations = Int.MAX_VALUE, spacing = MarqueeSpacing(16.dp))
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Modifier.layoutPadding(): Modifier {
|
fun Modifier.layoutPadding(): Modifier {
|
||||||
val statusBarMod = this.statusBarsPadding()
|
|
||||||
val spacing = LocalSpacing.current.extraSmall
|
val spacing = LocalSpacing.current.extraSmall
|
||||||
return statusBarMod.padding(start = spacing, top = 0.dp, end = spacing, bottom = spacing)
|
return statusBarsPadding().padding(start = spacing, top = 0.dp, end = spacing, bottom = spacing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -375,15 +349,15 @@ fun ScreenColumn(
|
|||||||
floatingBar: @Composable () -> Unit = {},
|
floatingBar: @Composable () -> Unit = {},
|
||||||
content: @Composable (Boolean) -> Unit = {}
|
content: @Composable (Boolean) -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val isVerticalLayout = isVerticalLayout()
|
val isVertical = isVerticalLayout()
|
||||||
Surface(color = MaterialTheme.colorScheme.background) {
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
Box(modifier = Modifier.layoutPadding(), contentAlignment = Alignment.BottomCenter) {
|
Box(modifier = Modifier.layoutPadding(), contentAlignment = Alignment.BottomCenter) {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(LocalSpacing.current.extraSmall)) {
|
Column(verticalArrangement = Arrangement.spacedBy(LocalSpacing.current.extraSmall)) {
|
||||||
topBar(isVerticalLayout)
|
topBar(isVertical)
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
color = MaterialTheme.colorScheme.surfaceContainer
|
color = MaterialTheme.colorScheme.surfaceContainer
|
||||||
) { content(isVerticalLayout) }
|
) { content(isVertical) }
|
||||||
}
|
}
|
||||||
floatingBar()
|
floatingBar()
|
||||||
}
|
}
|
||||||
@@ -394,21 +368,14 @@ fun ScreenColumn(
|
|||||||
fun TopBar(
|
fun TopBar(
|
||||||
isVerticalLayout: Boolean,
|
isVerticalLayout: Boolean,
|
||||||
startAction: @Composable () -> Unit,
|
startAction: @Composable () -> Unit,
|
||||||
topInfo: @Composable (RowScope.() -> Unit),
|
topInfo: @Composable RowScope.() -> Unit,
|
||||||
bottomInfo: @Composable (RowScope.() -> Unit),
|
bottomInfo: @Composable RowScope.() -> Unit,
|
||||||
endAction: @Composable () -> Unit
|
endAction: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val topBarRow = @Composable { content: @Composable RowScope.() -> Unit ->
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.height(48.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) { content() }
|
|
||||||
}
|
|
||||||
if (isVerticalLayout) {
|
if (isVerticalLayout) {
|
||||||
topBarRow { startAction().also { topInfo() }.also { endAction() } }
|
TopBar { startAction(); topInfo(); endAction() }
|
||||||
topBarRow { bottomInfo() }
|
TopBar { bottomInfo() }
|
||||||
} else {
|
} else {
|
||||||
topBarRow { startAction().also { topInfo() }.also { bottomInfo() }.also { endAction() } }
|
TopBar { startAction(); topInfo(); bottomInfo(); endAction() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user