Added shared TimerBar composable function

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:45 +00:00
1 parent 4b63882c70
commit a52788e72f
8 files changed
+111 -93

No files matched your search

@@ -4,11 +4,17 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ElevatedButton
@@ -17,13 +23,65 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
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.composed
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.MainTheme
@Composable
@Preview(showBackground = true)
private fun TimerBarPreview() {
MainTheme { TimerBar(45555, "Satellite", "88:88:88", R.drawable.ic_filter) {} }
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TimerBar(id: Int, name: String, time: String, iconId: Int, action: () -> Unit) {
val barHeightMod = Modifier.height(48.dp)
val maxSizeMod = Modifier.fillMaxSize()
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
ElevatedCard(modifier = barHeightMod.weight(1f)) {
Row(
modifier = maxSizeMod.padding(horizontal = 6.dp, vertical = 4.dp),
verticalAlignment = Alignment.Top
) {
Text(
text = "Id:$id - ",
modifier = Modifier.width(82.dp),
textAlign = TextAlign.End,
color = MaterialTheme.colorScheme.primary
)
Text(
text = name,
fontWeight = FontWeight.Medium,
modifier = Modifier.basicMarquee(iterations = Int.MAX_VALUE)
)
}
}
ElevatedCard(modifier = barHeightMod) {
Text(
text = time,
fontSize = 32.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),
style = TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = false))
)
}
CardIcon(onClick = { action() }, iconId = iconId)
}
}
@Composable
fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier) {
@@ -60,6 +118,6 @@ fun gotoUrl(context: Context, url: String) {
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
clickable(remember { MutableInteractionSource() }, null) { onClick() }
}
//fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
// clickable(remember { MutableInteractionSource() }, null) { onClick() }
//}
@@ -110,7 +110,7 @@ fun FilterDialog(
Slider(
value = hoursValue.intValue.toFloat(),
onValueChange = { hoursValue.intValue = it.toInt() },
valueRange = 1f..168f,
valueRange = 1f..96f,
colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant)
)
Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.Bottom) {
@@ -133,7 +133,7 @@ fun FilterDialog(
Slider(
value = elevationValue.intValue.toFloat(),
onValueChange = { elevationValue.intValue = it.toInt() },
valueRange = 0f..90f,
valueRange = 0f..60f,
colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant)
)
LazyVerticalGrid(
@@ -9,7 +9,6 @@ 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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -17,7 +16,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
@@ -27,8 +25,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
@@ -42,6 +38,7 @@ import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator
import com.rtbishop.look4sat.presentation.components.PullRefreshState
import com.rtbishop.look4sat.presentation.components.TimerBar
import com.rtbishop.look4sat.presentation.components.pullRefresh
import com.rtbishop.look4sat.presentation.components.rememberPullRefreshState
import java.text.SimpleDateFormat
@@ -56,58 +53,22 @@ fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
})
val toggleDialog = { uiState.takeAction(PassesAction.ToggleFilterDialog) }
if (uiState.isDialogShown) {
FilterDialog(uiState.hours, uiState.elevation, uiState.modes, toggleDialog) { hours, elevation, modes ->
FilterDialog(uiState.hours, uiState.elevation, uiState.modes, toggleDialog
) { hours, elevation, modes ->
uiState.takeAction(PassesAction.ApplyFilter(hours, elevation, modes))
}
}
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
TopBar(nextId = uiState.nextId, nextName = uiState.nextName, nextTime = uiState.nextTime, toggleDialog)
TimerBar(
id = uiState.nextId,
name = uiState.nextName,
time = uiState.nextTime,
iconId = R.drawable.ic_filter
) { toggleDialog() }
PassesCard(refreshState, uiState.isRefreshing, uiState.itemsList, navToRadar)
}
}
@Composable
@Preview(showBackground = true)
private fun TopBarPreview() {
MainTheme { TopBar(nextId = 45555, nextName = "Stuff", nextTime = "88:88:88") {} }
}
@Composable
private fun TopBar(nextId: Int, nextName: String, nextTime: String, toggleDialog: () -> Unit) {
ElevatedCard(modifier = Modifier.height(48.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize()
) {
Icon(
painter = painterResource(id = R.drawable.ic_sputnik),
contentDescription = null,
modifier = Modifier.padding(12.dp)
)
Column(verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f)) {
Text(
text = "AOS - Id:$nextId",
color = MaterialTheme.colorScheme.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(text = nextName, fontWeight = FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
Text(
text = nextTime,
fontSize = 32.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
style = TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = false))
)
IconButton(onClick = { toggleDialog() }) {
Icon(painter = painterResource(id = R.drawable.ic_filter), contentDescription = null)
}
}
}
}
@Preview(showBackground = true)
@Composable
private fun PassPreview() {
@@ -120,7 +81,9 @@ private fun PassPreview() {
}
@Composable
private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: Modifier = Modifier) {
private fun Pass(
pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: Modifier = Modifier
) {
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
Surface(modifier = Modifier
.padding(bottom = 2.dp)
@@ -189,7 +152,10 @@ private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: M
modifier = Modifier.fillMaxWidth()
) {
val deepTime = stringResource(id = R.string.pass_placeholder)
Text(text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.aosTime)), fontSize = 15.sp)
Text(
text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.aosTime)),
fontSize = 15.sp
)
LinearProgressIndicator(
progress = if (pass.isDeepSpace) 1f else pass.progress,
modifier = modifier
@@ -197,7 +163,10 @@ private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: M
.padding(top = 3.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface
)
Text(text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.losTime)), fontSize = 15.sp)
Text(
text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.losTime)),
fontSize = 15.sp
)
}
}
}
@@ -207,7 +176,10 @@ private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: M
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun PassesCard(
refreshState: PullRefreshState, isRefreshing: Boolean, passes: List<OrbitalPass>, navToRadar: (Int, Long) -> Unit
refreshState: PullRefreshState,
isRefreshing: Boolean,
passes: List<OrbitalPass>,
navToRadar: (Int, Long) -> Unit
) {
ElevatedCard(modifier = Modifier.fillMaxSize()) {
Box(Modifier.pullRefresh(refreshState)) {
@@ -17,6 +17,11 @@
*/
package com.rtbishop.look4sat.presentation.radar
import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.domain.predict.OrbitalPos
data class RadarData(val orbitalPos: OrbitalPos, val satTrack: List<OrbitalPos> = emptyList())
data class RadarData(
val orbitalPass: OrbitalPass,
val orbitalPos: OrbitalPos,
val satTrack: List<OrbitalPos> = emptyList()
)
@@ -6,13 +6,11 @@ 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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -23,45 +21,22 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.presentation.components.TimerBar
@Composable
fun RadarScreen() {
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory)
val currentPass = viewModel.getPass().collectAsState(null)
val currentPass = viewModel.getPass().collectAsState(null).value
val id = currentPass?.catNum ?: 99999
val name = currentPass?.name ?: "Satellite"
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
ElevatedCard(modifier = Modifier.height(52.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize()
) {
IconButton(onClick = {}) {
Icon(painter = painterResource(id = R.drawable.ic_filter), contentDescription = null)
}
Column(verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f)) {
Text(text = "Null")
Text(text = "Null")
}
Text(
text = "00:00:00",
fontSize = 36.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
textAlign = TextAlign.End,
modifier = Modifier
.weight(1f)
.padding(bottom = 2.dp, end = 8.dp)
)
}
}
TimerBar(id, name, "88:88:88", R.drawable.ic_notifications) {}
ElevatedCard(
modifier = Modifier
.fillMaxSize()
@@ -124,7 +124,7 @@ class RadarViewModel(
val elevation = orbitalPos.elevation.toDegrees().round(1)
networkReporter.reportRotation(server, port, azimuth, elevation)
}
radarData.value = RadarData(orbitalPos, track)
radarData.value = RadarData(orbitalPass, orbitalPos, track)
}
}
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z" />
</vector>
-1
View File
@@ -2,7 +2,6 @@ android.enableJetifier=false
android.enableR8.fullMode=true
android.nonFinalResIds=true
android.nonTransitiveRClass=true
android.suppressUnsupportedCompileSdk=34
android.useAndroidX=true
kotlin.code.style=official
kotlin.daemon.jvm.options=-Xmx4g