Ir al contenido

Navegación y flujo de pantallas

Toda la navegación vive en dos variables de estado dentro de RacingCardsApp:

var current by rememberSaveable { mutableStateOf(Destination.Gallery) }
var isEditingCard by rememberSaveable { mutableStateOf(false) }
val cards = remember { mutableStateListOf<RacingCard>() }
var selectedCard by remember { mutableStateOf<RacingCard?>(null) }
  • current — cuál de las 3 tabs de la barra inferior está activa (Destination.Gallery, .Create o .Details).
  • isEditingCard — un booleano que, cuando es true, reemplaza cualquier pantalla actual por EditScreen en modo edición (no es una tab; es un overlay sobre la navegación normal).
  • cards / selectedCard — el “backend en memoria”: la lista de cartas creadas y cuál está seleccionada para ver/editar.

El árbol de decisión que arma la pantalla visible es:

when {
isEditingCard -> EditScreen(/* editar selectedCard */)
else -> when (current) {
Destination.Gallery -> GalleryScreen(...)
Destination.Details -> DetailsScreen(...)
Destination.Create -> EditScreen(/* isNewCard = true */)
}
}

Es decir: EditScreen se reutiliza tanto para “Create” (tab, isNewCard = true) como para “editar una carta existente” (isEditingCard = true, fuera del sistema de tabs).

Estados de navegación de RacingCardsApp

stateDiagram-v2
  [*] --> SystemSplash

  SystemSplash: Splash del sistema (Theme.Starting)
  LoadingScreen: LoadingScreen (Compose, ~1.1s)
  Gallery: Destination.Gallery
  Details: Destination.Details
  CreateNew: Destination.Create (EditScreen, isNewCard=true)
  RollOverlay: PerformanceRollOverlay (rifa de stats)
  EditExisting: isEditingCard=true (EditScreen)

  SystemSplash --> LoadingScreen
  LoadingScreen --> Gallery: delay(1100ms)

  Gallery --> Details: tap en una carta
  Gallery --> CreateNew: tab "Create"
  Details --> Gallery: back / eliminar
  Details --> EditExisting: tap en editar (lápiz)
  Details --> CreateNew: tab "Create"

  CreateNew --> Gallery: back
  CreateNew --> RollOverlay: check (guardar)
  RollOverlay --> Gallery: onFinished (carta guardada)

  EditExisting --> Details: back
  EditExisting --> Details: check (guardar, sin re-rifar stats)
Sección titulada «Detalle del flujo “Create → Roll → Gallery”»

Crear una carta nueva es el flujo más largo de la app: el formulario no navega a otra pantalla al guardar, sino que se transforma en la animación de rifa (rolling = true dentro del mismo EditScreen), y sólo al terminar esa animación se llama a onSave, que es lo que efectivamente navega de vuelta a la Gallery.

Secuencia: crear una carta nueva

sequenceDiagram
  actor U as Usuario
  participant App as RacingCardsApp
  participant Edit as EditScreen
  participant Roll as PerformanceRollOverlay
  participant Roller as PerformanceRoller

  U->>App: tap tab "Create"
  App->>Edit: EditScreen(card=blank, isNewCard=true)
  U->>Edit: completa nombre, clase, color, badge, foto
  U->>Edit: tap check (guardar)
  Edit->>Edit: rolling = true
  Edit->>Roller: rollStats()
  Roller-->>Edit: CardStats aleatorias
  Edit->>Roller: tierFor(stats)
  Roller-->>Edit: rareza "S".."D"
  Edit->>Roll: PerformanceRollOverlay(finalStats, finalTier)
  Roll->>Roll: anima cada stat (slot machine, ~4x cascada)
  Roll->>Roll: muestra chip de rareza + pulso del auto
  Roll->>App: onFinished() -> onSave(card)
  App->>App: cards.add(card); current = Gallery
  App-->>U: vuelve a Gallery con la carta nueva
  • No hay pila de navegación (back stack). Volver es siempre una transición explícita a un destino fijo (onBack = { current = Destination.Gallery }), no un popBackStack(). Esto es posible porque el grafo de pantallas es plano: nunca hay más de un nivel de profundidad real.
  • isEditingCard no es parte de Destination a propósito: editar una carta existente puede iniciarse desde Details, así que modelarlo como una tab más obligaría a inventar un destino sin ícono en la barra inferior.
  • El tab Create está marcado con isEmphasized = true en Destination.kt, lo que le da un fondo circular amarillo permanente en la barra inferior — independiente de si está seleccionado — para que “crear” destaque como la acción principal de la app.