Added more tweaks to components and dependencies

This commit is contained in:
Arty Bishop committed 2025-12-27 15:02:14 +00:00
1 parent fb8053ef60
commit 266fbfed1f
7 files changed
+135 -90

No files matched your search

@@ -1,9 +1,6 @@
package com.rtbishop.look4sat.presentation package com.rtbishop.look4sat.presentation
import androidx.compose.foundation.background
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
@@ -39,11 +36,7 @@ fun MainScreen(navController: NavHostController = rememberNavController()) {
openMap = { navController.navigate(Screen.Map.route) }, openMap = { navController.navigate(Screen.Map.route) },
openSettings = { navController.navigate(Screen.Settings.route) } openSettings = { navController.navigate(Screen.Settings.route) }
) )
NavHost( NavHost(navController = navController, startDestination = Screen.Passes.route) {
navController = navController,
startDestination = Screen.Passes.route,
modifier = Modifier.background(color = MaterialTheme.colorScheme.background)
) {
satellitesDestination { navController.navigateUp() } satellitesDestination { navController.navigateUp() }
passesDestination(navActions) passesDestination(navActions)
radarDestination { navController.navigateUp() } radarDestination { navController.navigateUp() }
@@ -1,9 +1,12 @@
package com.rtbishop.look4sat.presentation.common package com.rtbishop.look4sat.presentation.common
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.MarqueeSpacing import androidx.compose.foundation.MarqueeSpacing
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -18,12 +21,15 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ElevatedButton import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.FilledIconButton
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
@@ -98,17 +104,17 @@ fun RowScope.TimerRow(timeString: String, isTimeAos: Boolean) {
@Composable @Composable
@Preview(showBackground = true) @Preview(showBackground = true)
private fun NextPassRowPreview() = MainTheme { private fun NextPassRowPreview() = MainTheme {
NextPassRow(pass = getDefaultPass()) TopBar { NextPassRow(pass = getDefaultPass()) }
} }
@Composable @Composable
fun NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) { fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier) {
ElevatedCard(modifier = modifier.height(48.dp)) { ElevatedCard(modifier = modifier.height(48.dp).weight(1f)) {
Column( Column(
verticalArrangement = Arrangement.spacedBy((-2).dp), verticalArrangement = Arrangement.spacedBy((-2).dp),
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(color = MaterialTheme.colorScheme.surface) // .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) val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
@@ -319,58 +325,86 @@ fun Modifier.layoutPadding(): Modifier {
} }
@Composable @Composable
fun ScreenColumn(floatingBar: @Composable () -> Unit = {}, content: @Composable (Boolean) -> Unit) { fun ScreenColumn(
Box(contentAlignment = Alignment.BottomCenter) { topBar: @Composable (Boolean) -> Unit = {},
Column( floatingBar: @Composable () -> Unit = {},
modifier = Modifier.layoutPadding(), content: @Composable (Boolean) -> Unit = {}
verticalArrangement = Arrangement.spacedBy(LocalSpacing.current.extraSmall) ) {
) { content(isVerticalLayout()) } val surfaceCorners = LocalSpacing.current.large
floatingBar() val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
} val isVerticalLayout = windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT
} Surface(color = MaterialTheme.colorScheme.background) {
Box(modifier = Modifier.layoutPadding(), contentAlignment = Alignment.BottomCenter) {
@Composable Column(verticalArrangement = Arrangement.spacedBy(LocalSpacing.current.extraSmall)) {
fun PrimaryButton(action: () -> Unit, resId: Int, modifier: Modifier = Modifier) { topBar(isVerticalLayout)
val clickableMod = modifier.clickable { action() } Surface(
val colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary) modifier = Modifier.fillMaxSize(),
ElevatedCard(modifier = Modifier.size(96.dp, 48.dp), colors = colors, shape = MaterialTheme.shapes.large) { shape = RoundedCornerShape(topStart = surfaceCorners, topEnd = surfaceCorners),
Box(modifier = clickableMod.fillMaxSize(), contentAlignment = Alignment.Center) { color = MaterialTheme.colorScheme.surfaceContainer
Icon(painter = painterResource(resId), contentDescription = null) ) { content(isVerticalLayout) }
}
floatingBar()
} }
} }
} }
@Composable @Composable
fun SecondaryButton(action: () -> Unit, resId: Int, modifier: Modifier = Modifier) { fun TopBar(
val clickableMod = modifier.clickable { action() } isVerticalLayout: Boolean,
ElevatedCard(modifier = Modifier.size(48.dp), shape = MaterialTheme.shapes.large) { startAction: @Composable () -> Unit,
Box(modifier = clickableMod.fillMaxSize(), contentAlignment = Alignment.Center) { topInfo: @Composable (RowScope.() -> Unit),
Icon(painter = painterResource(resId), contentDescription = null) bottomInfo: @Composable (RowScope.() -> 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) {
topBarRow { startAction().also { topInfo() }.also { endAction() } }
topBarRow { bottomInfo() }
} else {
topBarRow { startAction().also { topInfo() }.also { bottomInfo() }.also { endAction() } }
} }
} }
@Composable @Composable
fun FloatingBar( fun FloatingBar(
startAction: () -> Unit, startIconResId: Int, visible: Boolean,
centerAction: () -> Unit, centerIconResId: Int, startAction: @Composable () -> Unit,
endAction: () -> Unit, endIconResId: Int centerAction: @Composable () -> Unit,
endAction: @Composable () -> Unit
) { ) {
val spacing = LocalSpacing.current val spacing = LocalSpacing.current
Surface( AnimatedVisibility(visible = visible, enter = fadeIn(tween(250)), exit = fadeOut(tween(250))) {
color = MaterialTheme.colorScheme.background, Surface(
shape = MaterialTheme.shapes.extraLarge, modifier = Modifier.padding(bottom = spacing.large),
modifier = Modifier.padding(bottom = spacing.medium) shape = CircleShape,
.border(width = 1.dp, color = MaterialTheme.colorScheme.surfaceVariant, shape = MaterialTheme.shapes.extraLarge) color = MaterialTheme.colorScheme.background,
) { border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.surfaceVariant)
Row(
horizontalArrangement = Arrangement.spacedBy(spacing.medium),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = spacing.large, vertical = spacing.medium)
) { ) {
SecondaryButton(action = startAction, resId = startIconResId) Row(
PrimaryButton(action = centerAction, resId = centerIconResId) modifier = Modifier.padding(horizontal = spacing.medium, vertical = spacing.small),
SecondaryButton(action = endAction, resId = endIconResId) horizontalArrangement = Arrangement.spacedBy(spacing.extraSmall),
verticalAlignment = Alignment.CenterVertically
) { startAction().also { centerAction() }.also { endAction() } }
} }
} }
} }
@Composable
fun PrimaryAction(action: () -> Unit, resId: Int, descResId: Int) {
FilledIconButton(onClick = action, modifier = Modifier.width(72.dp)) {
Icon(painterResource(resId), stringResource(descResId))
}
}
@Composable
fun SecondaryAction(action: () -> Unit, resId: Int, descResId: Int) {
IconButton(onClick = action) {
Icon(painterResource(resId), stringResource(descResId))
}
}
@@ -114,7 +114,7 @@ private fun MapScreen(uiState: State<MapState>, mapView: MapView) {
TimerRow(timeString = timeString, isTimeAos = isTimeAos) TimerRow(timeString = timeString, isTimeAos = isTimeAos)
IconCard(action = selectNext, resId = R.drawable.ic_arrow) IconCard(action = selectNext, resId = R.drawable.ic_arrow)
} }
NextPassRow(pass = uiState.value.orbitalPass) TopBar { NextPassRow(pass = uiState.value.orbitalPass) }
} else { } else {
TopBar { TopBar {
IconCard(action = selectPrev, resId = R.drawable.ic_arrow, modifier = rotateMod) IconCard(action = selectPrev, resId = R.drawable.ic_arrow, modifier = rotateMod)
@@ -1,9 +1,5 @@
package com.rtbishop.look4sat.presentation.passes package com.rtbishop.look4sat.presentation.passes
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@@ -59,7 +55,9 @@ import com.rtbishop.look4sat.presentation.common.FloatingBar
import com.rtbishop.look4sat.presentation.common.IconCard import com.rtbishop.look4sat.presentation.common.IconCard
import com.rtbishop.look4sat.presentation.common.InfoDialog import com.rtbishop.look4sat.presentation.common.InfoDialog
import com.rtbishop.look4sat.presentation.common.NextPassRow import com.rtbishop.look4sat.presentation.common.NextPassRow
import com.rtbishop.look4sat.presentation.common.PrimaryAction
import com.rtbishop.look4sat.presentation.common.ScreenColumn import com.rtbishop.look4sat.presentation.common.ScreenColumn
import com.rtbishop.look4sat.presentation.common.SecondaryAction
import com.rtbishop.look4sat.presentation.common.TimerRow import com.rtbishop.look4sat.presentation.common.TimerRow
import com.rtbishop.look4sat.presentation.common.TopBar import com.rtbishop.look4sat.presentation.common.TopBar
import com.rtbishop.look4sat.presentation.common.infiniteMarquee import com.rtbishop.look4sat.presentation.common.infiniteMarquee
@@ -88,7 +86,11 @@ private fun PassesScreen(uiState: PassesState, navActions: NavActions) {
val showPassesDialog = { uiState.takeAction(PassesAction.TogglePassesDialog) } val showPassesDialog = { uiState.takeAction(PassesAction.TogglePassesDialog) }
val showRadiosDialog = { uiState.takeAction(PassesAction.ToggleRadiosDialog) } val showRadiosDialog = { uiState.takeAction(PassesAction.ToggleRadiosDialog) }
if (uiState.isPassesDialogShown) { if (uiState.isPassesDialogShown) {
PassesDialog(hours = uiState.hours, elevation = uiState.elevation, cancel = showPassesDialog) { hours, elevation -> PassesDialog(
hours = uiState.hours,
elevation = uiState.elevation,
cancel = showPassesDialog
) { hours, elevation ->
uiState.takeAction(PassesAction.FilterPasses(hours, elevation)) uiState.takeAction(PassesAction.FilterPasses(hours, elevation))
} }
} }
@@ -107,36 +109,51 @@ private fun PassesScreen(uiState: PassesState, navActions: NavActions) {
} }
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
ScreenColumn( ScreenColumn(
floatingBar = { PassesFloatingBar(gridState.isScrolling(), navActions) } topBar = { isVerticalLayout ->
) { isVerticalLayout -> TopBar(
if (isVerticalLayout) { isVerticalLayout = isVerticalLayout,
TopBar { startAction = {
IconCard(action = { showPassesDialog() }, resId = R.drawable.ic_filter) IconCard(action = showPassesDialog, resId = R.drawable.ic_filter)
TimerRow(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos) },
IconCard(action = { showRadiosDialog() }, resId = R.drawable.ic_satellite) topInfo = {
} TimerRow(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos)
NextPassRow(pass = uiState.nextPass) },
} else { bottomInfo = {
TopBar { NextPassRow(pass = uiState.nextPass)
IconCard(action = { showPassesDialog() }, resId = R.drawable.ic_filter) },
TimerRow(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos) endAction = {
NextPassRow(pass = uiState.nextPass, modifier = Modifier.weight(1f)) IconCard(action = showRadiosDialog, resId = R.drawable.ic_satellite)
IconCard(action = { showRadiosDialog() }, resId = R.drawable.ic_satellite) }
} )
},
floatingBar = {
PassesFloatingBar(visible = gridState.isScrolling(), actions = navActions)
} }
PassesList(uiState.isRefreshing, uiState.itemsList, navActions.openRadar, refreshList, gridState) ) { isVerticalLayout ->
PassesList(
isRefreshing = uiState.isRefreshing,
passes = uiState.itemsList,
navigateToRadar = navActions.openRadar,
refreshPasses = refreshList,
gridState = gridState
)
} }
} }
@Composable @Composable
private fun PassesFloatingBar(visible: Boolean, navActions: NavActions) { private fun PassesFloatingBar(visible: Boolean, actions: NavActions) {
AnimatedVisibility(visible = visible, enter = fadeIn(tween(250)), exit = fadeOut(tween(250))) { FloatingBar(
FloatingBar( visible = visible,
startAction = navActions.openSettings, startIconResId = R.drawable.ic_settings, startAction = {
centerAction = navActions.openSatellites, centerIconResId = R.drawable.ic_sputnik, SecondaryAction(actions.openSettings, R.drawable.ic_settings, R.string.btn_settings)
endAction = navActions.openMap, endIconResId = R.drawable.ic_map },
) centerAction = {
} PrimaryAction(actions.openSatellites, R.drawable.ic_sputnik, R.string.btn_satellites)
},
endAction = {
SecondaryAction(actions.openMap, R.drawable.ic_map, R.string.btn_map)
}
)
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -88,7 +88,7 @@ private fun RadarScreen(uiState: RadarState, navigateUp: () -> Unit) {
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos) TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isCurrentTimeAos)
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar) IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
} }
NextPassRow(pass = upcomingPass) TopBar { NextPassRow(pass = upcomingPass) }
} else { } else {
TopBar { TopBar {
IconCard(action = navigateUp, resId = R.drawable.ic_back) IconCard(action = navigateUp, resId = R.drawable.ic_back)
+3 -3
View File
@@ -5,16 +5,16 @@ kotlin = "2.2.20"
androidx-core-ktx = "1.17.0" androidx-core-ktx = "1.17.0"
androidx-core-splashscreen = "1.0.1" androidx-core-splashscreen = "1.0.1"
androidx-room = "2.8.1" androidx-room = "2.8.2"
compose-bom = "2025.09.01" compose-bom = "2025.10.00"
compose-activity = "1.11.0" compose-activity = "1.11.0"
compose-lifecycle = "2.9.4" compose-lifecycle = "2.9.4"
compose-navigation = "2.9.5" compose-navigation = "2.9.5"
other-coroutines = "1.10.2" other-coroutines = "1.10.2"
other-json = "20250517" other-json = "20250517"
other-okhttp = "5.1.0" other-okhttp = "5.2.1"
other-osmdroid = "6.1.20" other-osmdroid = "6.1.20"
test-junit4 = "4.13.2" test-junit4 = "4.13.2"
+2 -1
View File
@@ -1,6 +1,7 @@
#Sat Oct 11 13:47:56 BST 2025
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME