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.content.Intent
import android.net.Uri import android.net.Uri
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable 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.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize 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.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ElevatedButton import androidx.compose.material3.ElevatedButton
@@ -17,13 +23,65 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.res.painterResource 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.dp
import androidx.compose.ui.unit.sp 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 @Composable
fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier) { 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))) context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
} }
fun Modifier.onClick(onClick: () -> Unit): Modifier = composed { //fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
clickable(remember { MutableInteractionSource() }, null) { onClick() } // clickable(remember { MutableInteractionSource() }, null) { onClick() }
} //}
@@ -110,7 +110,7 @@ fun FilterDialog(
Slider( Slider(
value = hoursValue.intValue.toFloat(), value = hoursValue.intValue.toFloat(),
onValueChange = { hoursValue.intValue = it.toInt() }, onValueChange = { hoursValue.intValue = it.toInt() },
valueRange = 1f..168f, valueRange = 1f..96f,
colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant) colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant)
) )
Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.Bottom) { Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.Bottom) {
@@ -133,7 +133,7 @@ fun FilterDialog(
Slider( Slider(
value = elevationValue.intValue.toFloat(), value = elevationValue.intValue.toFloat(),
onValueChange = { elevationValue.intValue = it.toInt() }, onValueChange = { elevationValue.intValue = it.toInt() },
valueRange = 0f..90f, valueRange = 0f..60f,
colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant) colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant)
) )
LazyVerticalGrid( LazyVerticalGrid(
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width 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.foundation.lazy.items
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@@ -27,8 +25,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource 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.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow 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.MainTheme
import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator
import com.rtbishop.look4sat.presentation.components.PullRefreshState 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.pullRefresh
import com.rtbishop.look4sat.presentation.components.rememberPullRefreshState import com.rtbishop.look4sat.presentation.components.rememberPullRefreshState
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@@ -56,58 +53,22 @@ fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
}) })
val toggleDialog = { uiState.takeAction(PassesAction.ToggleFilterDialog) } val toggleDialog = { uiState.takeAction(PassesAction.ToggleFilterDialog) }
if (uiState.isDialogShown) { 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)) uiState.takeAction(PassesAction.ApplyFilter(hours, elevation, modes))
} }
} }
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { 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) 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) @Preview(showBackground = true)
@Composable @Composable
private fun PassPreview() { private fun PassPreview() {
@@ -120,7 +81,9 @@ private fun PassPreview() {
} }
@Composable @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(color = MaterialTheme.colorScheme.background, modifier = modifier) {
Surface(modifier = Modifier Surface(modifier = Modifier
.padding(bottom = 2.dp) .padding(bottom = 2.dp)
@@ -189,7 +152,10 @@ private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: M
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
val deepTime = stringResource(id = R.string.pass_placeholder) 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( LinearProgressIndicator(
progress = if (pass.isDeepSpace) 1f else pass.progress, progress = if (pass.isDeepSpace) 1f else pass.progress,
modifier = modifier modifier = modifier
@@ -197,7 +163,10 @@ private fun Pass(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: M
.padding(top = 3.dp), .padding(top = 3.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface 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) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
private fun PassesCard( 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()) { ElevatedCard(modifier = Modifier.fillMaxSize()) {
Box(Modifier.pullRefresh(refreshState)) { Box(Modifier.pullRefresh(refreshState)) {
@@ -17,6 +17,11 @@
*/ */
package com.rtbishop.look4sat.presentation.radar package com.rtbishop.look4sat.presentation.radar
import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.domain.predict.OrbitalPos 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.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
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.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -23,45 +21,22 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.presentation.components.TimerBar
@Composable @Composable
fun RadarScreen() { fun RadarScreen() {
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory) 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)) { Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
ElevatedCard(modifier = Modifier.height(52.dp)) { TimerBar(id, name, "88:88:88", R.drawable.ic_notifications) {}
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)
)
}
}
ElevatedCard( ElevatedCard(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -124,7 +124,7 @@ class RadarViewModel(
val elevation = orbitalPos.elevation.toDegrees().round(1) val elevation = orbitalPos.elevation.toDegrees().round(1)
networkReporter.reportRotation(server, port, azimuth, elevation) 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.enableR8.fullMode=true
android.nonFinalResIds=true android.nonFinalResIds=true
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.suppressUnsupportedCompileSdk=34
android.useAndroidX=true android.useAndroidX=true
kotlin.code.style=official kotlin.code.style=official
kotlin.daemon.jvm.options=-Xmx4g kotlin.daemon.jvm.options=-Xmx4g