mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
feat(ui): top-right 日程按钮 — add current/next pass to system calendar on radar and passes pages
Restores the original repo's calendar function (ic_calendar → AddToCalendar via CalendarContract ACTION_INSERT) to the top-right of both pages, replacing the map buttons: - Radar page: back to upstream's addToCalendar (current pass name/aos/los). - Passes page: new PassesAction.AddToCalendar wired through PassesViewModel + container.provideAddToCalendar() (next pass name/aos/los); left button back to the pass filter (reverts the earlier radios-button swap). The map button is gone from both top bars — the map is now a bottom-nav tab. Also drops the now-dead openMapRequest/navigateToMap navigation chain in NavRoot/MainScreen that only the radar map button used.
This commit is contained in:
1 parent
14b98cc7b1
commit
d56392f3c6
5 files changed
+34
-38
No files matched your search
@@ -51,7 +51,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -94,16 +93,11 @@ import com.rtbishop.look4sat.feature.status.SatStatusDestination
|
||||
fun NavRoot(deeplink: String? = null) {
|
||||
val rootBackStack = rememberNavBackStack(Screen.Passes)
|
||||
val deeplinkResolver = DeeplinkResolver()
|
||||
var openMapRequest by remember { mutableIntStateOf(0) }
|
||||
LaunchedEffect(deeplink) {
|
||||
deeplink?.let { rootBackStack.add(deeplinkResolver.resolve(it)) }
|
||||
}
|
||||
val navigateBack: () -> Unit = { rootBackStack.removeLastOrNull() }
|
||||
val navigateToRadar: () -> Unit = { rootBackStack.add(RadarDestination) }
|
||||
val navigateToMap: () -> Unit = {
|
||||
while (rootBackStack.size > 1) rootBackStack.removeAt(rootBackStack.size - 1)
|
||||
openMapRequest += 1
|
||||
}
|
||||
// Incoming screen slides in from the right, outgoing drifts left at 1/3 speed (API35+ style)
|
||||
val pushTransition = slideInHorizontally(tween(300)) { it } togetherWith
|
||||
slideOutHorizontally(tween(300)) { -it / 3 }
|
||||
@@ -124,9 +118,7 @@ fun NavRoot(deeplink: String? = null) {
|
||||
entryProvider = entryProvider {
|
||||
entry<Screen.Passes> {
|
||||
MainScreen(
|
||||
navigateToRadar = navigateToRadar,
|
||||
openMapRequest = openMapRequest,
|
||||
onOpenMapRequestHandled = { openMapRequest = 0 }
|
||||
navigateToRadar = navigateToRadar
|
||||
)
|
||||
}
|
||||
entry<RadarDestination> {
|
||||
@@ -134,7 +126,7 @@ fun NavRoot(deeplink: String? = null) {
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
RadarDestination(navigateUp = navigateBack, navigateToMap = navigateToMap)
|
||||
RadarDestination(navigateUp = navigateBack)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,23 +135,11 @@ fun NavRoot(deeplink: String? = null) {
|
||||
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
navigateToRadar: () -> Unit = {},
|
||||
openMapRequest: Int = 0,
|
||||
onOpenMapRequestHandled: () -> Unit = {}
|
||||
navigateToRadar: () -> Unit = {}
|
||||
) {
|
||||
val backStack = rememberNavBackStack(Screen.Passes)
|
||||
val currentKey = backStack.lastOrNull()
|
||||
val navigateBack: () -> Unit = { backStack.removeLastOrNull() }
|
||||
val navigateToMap: () -> Unit = {
|
||||
while (backStack.size > 1) backStack.removeAt(backStack.size - 1)
|
||||
backStack.add(Screen.Map)
|
||||
}
|
||||
LaunchedEffect(openMapRequest) {
|
||||
if (openMapRequest > 0) {
|
||||
navigateToMap()
|
||||
onOpenMapRequestHandled()
|
||||
}
|
||||
}
|
||||
val fadeTransition = fadeIn(animationSpec = tween(350)) togetherWith fadeOut(animationSpec = tween(350))
|
||||
// Map sits at position 4 from the left, matching the upstream nav order
|
||||
// (Satellites, Passes, AMSAT/Status, Map, ...), with the fork's Mutual tab
|
||||
|
||||
@@ -156,7 +156,7 @@ private fun PassesScreen(
|
||||
TopBar(
|
||||
isVerticalLayout = isVerticalLayout,
|
||||
startAction = {
|
||||
IconCard(action = { onAction(PassesAction.ToggleRadiosDialog) }, resId = R.drawable.ic_radios)
|
||||
IconCard(action = { onAction(PassesAction.TogglePassesDialog) }, resId = R.drawable.ic_filter)
|
||||
},
|
||||
topInfo = {
|
||||
TimerRow(timeString = uiState.nextTime, isTimeAos = uiState.isNextTimeAos)
|
||||
@@ -165,7 +165,19 @@ private fun PassesScreen(
|
||||
NextPassRow(pass = uiState.nextPass, isUtc = uiState.isUtc)
|
||||
},
|
||||
endAction = {
|
||||
IconCard(action = { onAction(PassesAction.TogglePassesDialog) }, resId = R.drawable.ic_filter)
|
||||
// 日程功能: 把下个过境写入系统日历 (原仓库雷达页的 addToCalendar).
|
||||
IconCard(
|
||||
action = {
|
||||
onAction(
|
||||
PassesAction.AddToCalendar(
|
||||
uiState.nextPass.name,
|
||||
uiState.nextPass.aosTime,
|
||||
uiState.nextPass.losTime
|
||||
)
|
||||
)
|
||||
},
|
||||
resId = R.drawable.ic_calendar
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -61,4 +61,6 @@ sealed interface PassesAction {
|
||||
data object ToggleRadiosDialog : PassesAction
|
||||
data class FocusCatNum(val catNum: Int) : PassesAction
|
||||
data object ClearFocus : PassesAction
|
||||
/** 日程功能: 把下个过境写入系统日历 (ic_calendar 按钮). */
|
||||
data class AddToCalendar(val name: String, val aosTime: Long, val losTime: Long) : PassesAction
|
||||
}
|
||||
+7
-2
@@ -28,6 +28,7 @@ import com.rtbishop.look4sat.core.domain.predict.OrbitalPass
|
||||
import com.rtbishop.look4sat.core.domain.repository.IMainContainer
|
||||
import com.rtbishop.look4sat.core.domain.repository.ISatelliteRepo
|
||||
import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo
|
||||
import com.rtbishop.look4sat.core.domain.usecase.IAddToCalendar
|
||||
import com.rtbishop.look4sat.core.domain.utility.round
|
||||
import com.rtbishop.look4sat.core.domain.utility.toTimerString
|
||||
import com.rtbishop.look4sat.core.presentation.getDefaultPass
|
||||
@@ -46,7 +47,8 @@ import java.util.TimeZone
|
||||
|
||||
class PassesViewModel(
|
||||
private val satelliteRepo: ISatelliteRepo,
|
||||
private val settingsRepo: ISettingsRepo
|
||||
private val settingsRepo: ISettingsRepo,
|
||||
private val addToCalendar: IAddToCalendar
|
||||
) : ViewModel() {
|
||||
|
||||
private val defaultPass = getDefaultPass()
|
||||
@@ -151,6 +153,8 @@ class PassesViewModel(
|
||||
_uiState.update { it.copy(isRadiosDialogShown = !it.isRadiosDialogShown) }
|
||||
is PassesAction.FocusCatNum -> _uiState.update { it.copy(focusedCatNum = action.catNum) }
|
||||
PassesAction.ClearFocus -> _uiState.update { it.copy(focusedCatNum = null) }
|
||||
is PassesAction.AddToCalendar ->
|
||||
addToCalendar(action.name, action.aosTime, action.losTime)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,7 +349,8 @@ class PassesViewModel(
|
||||
initializer {
|
||||
PassesViewModel(
|
||||
satelliteRepo = container.satelliteRepo,
|
||||
settingsRepo = container.settingsRepo
|
||||
settingsRepo = container.settingsRepo,
|
||||
addToCalendar = container.provideAddToCalendar()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ private enum class RadarPage(val title: String) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RadarDestination(navigateUp: () -> Unit, navigateToMap: () -> Unit) {
|
||||
fun RadarDestination(navigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val container = (context.applicationContext as IContainerProvider).getMainContainer()
|
||||
val viewModel: RadarViewModel = viewModel(factory = RadarViewModel.factory(container))
|
||||
@@ -96,12 +96,6 @@ fun RadarDestination(navigateUp: () -> Unit, navigateToMap: () -> Unit) {
|
||||
}
|
||||
navigateUp()
|
||||
}
|
||||
val navigateToMapAndClearMutual = {
|
||||
if (container.mutualPassData.value.endTime > 0L) {
|
||||
container.setMutualPassData(MutualPassData())
|
||||
}
|
||||
navigateToMap()
|
||||
}
|
||||
LaunchedEffect(mutualData.endTime) {
|
||||
if (mutualData.endTime <= 0L) return@LaunchedEffect
|
||||
while (true) {
|
||||
@@ -127,7 +121,7 @@ fun RadarDestination(navigateUp: () -> Unit, navigateToMap: () -> Unit) {
|
||||
viewModel.onAction(RadarAction.SstvPermissionResult(granted))
|
||||
viewModel.onAction(RadarAction.CwPermissionResult(granted))
|
||||
}
|
||||
RadarScreen(uiState, viewModel::onAction, navigateUpAndClearMutual, navigateToMapAndClearMutual, mutualData, requestMicPermission = {
|
||||
RadarScreen(uiState, viewModel::onAction, navigateUpAndClearMutual, mutualData, requestMicPermission = {
|
||||
permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
|
||||
})
|
||||
}
|
||||
@@ -137,11 +131,14 @@ private fun RadarScreen(
|
||||
uiState: RadarState,
|
||||
onAction: (RadarAction) -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
navigateToMap: () -> Unit,
|
||||
mutualData: MutualPassData,
|
||||
requestMicPermission: () -> Unit
|
||||
) {
|
||||
val upcomingPass = uiState.currentPass ?: getDefaultPass()
|
||||
// 日程功能: 把当前过境写入系统日历(原仓库的 addToCalendar, ic_calendar 按钮)
|
||||
val addToCalendar: () -> Unit = {
|
||||
uiState.currentPass?.let { onAction(RadarAction.AddToCalendar(it.name, it.aosTime, it.losTime)) }
|
||||
}
|
||||
// Station-B overlay: full track line (only where B's elevation > 0) + live position dot
|
||||
// at the current moment, same display mode as the local station.
|
||||
val trackB = remember(mutualData.trackSamples) {
|
||||
@@ -177,7 +174,7 @@ private fun RadarScreen(
|
||||
TopBar {
|
||||
IconCard(action = navigateUp, resId = R.drawable.ic_back)
|
||||
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isTimeAos)
|
||||
IconCard(action = navigateToMap, resId = R.drawable.ic_map)
|
||||
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
|
||||
}
|
||||
TopBar { NextPassRow(pass = upcomingPass, isUtc = uiState.isUtc) }
|
||||
} else {
|
||||
@@ -185,7 +182,7 @@ private fun RadarScreen(
|
||||
IconCard(action = navigateUp, resId = R.drawable.ic_back)
|
||||
TimerRow(timeString = uiState.currentTime, isTimeAos = uiState.isTimeAos)
|
||||
NextPassRow(pass = upcomingPass, modifier = Modifier.weight(1f), isUtc = uiState.isUtc)
|
||||
IconCard(action = navigateToMap, resId = R.drawable.ic_map)
|
||||
IconCard(action = addToCalendar, resId = R.drawable.ic_calendar)
|
||||
}
|
||||
}
|
||||
if (isVertical) {
|
||||
|
||||
Reference in new issue
Block a user