Ir al contenido

Gallery

GalleryScreen es el destino de arranque de la app (Destination.Gallery, primera tab) y muestra todas las cartas creadas, en grilla de 2 columnas o en lista de 1 columna con panel de estadísticas expandido.

Auto de ejemplo 1Auto de ejemplo 2
@Composable
fun GalleryScreen(
modifier: Modifier = Modifier,
cards: List<RacingCard> = emptyList(),
onCardClick: (RacingCard) -> Unit = {},
onDeleteCard: (RacingCard) -> Unit = {},
)

Es una pantalla sin estado propio de datos: recibe la lista de cartas ya lista desde RacingCardsApp y sólo reporta intenciones (onCardClick, onDeleteCard) hacia arriba. Su único estado local es de presentación:

var filter by rememberSaveable { mutableStateOf(CardOptions.filters.first()) }
var layout by rememberSaveable { mutableStateOf(CardLayout.Grid) }
CenterAlignedTopAppBar("MY CARDS")
└── LazyVerticalGrid(columns = 2 en Grid, 1 en List)
├── FilterBar (dropdown de clase + toggle Grid/List)
├── si cards está vacío → EmptyGalleryState
└── si no → por cada carta:
├── modo Grid → GalleryGridItem (CardArtwork compacto, aspect 6:7)
└── modo List → GalleryListItem (SwipeToDismissBox + panel de stats)

GalleryGridItem es sólo un CardArtwork compacto (aspectRatio = 6f/7f) dentro de la celda de la grilla — toda la “personalidad” de la carta (viñeta de color, roundel de número, badge, chips) viene heredada de ArtworkFace.

GalleryListItem envuelve cada fila en un SwipeToDismissBox de Material 3: deslizar de derecha a izquierda revela un fondo rojo (BrandRed) con un ícono de papelera y, al superar el umbral, dispara onDeleteCard directamente — sin diálogo de confirmación (a diferencia del botón “Eliminar tarjeta” de Details, que sí confirma).

val dismissState = rememberSwipeToDismissBoxState(
confirmValueChange = { value ->
if (value == SwipeToDismissBoxValue.EndToStart) { onDelete(); true } else false
},
)

Cada fila en modo lista además muestra el panel de 4 estadísticas (StatItem × 4) que en modo grid no cabe, así que el modo lista es estrictamente más informativo que el modo grid, a costa de densidad.

Si cards está vacía, ambos modos colapsan al mismo EmptyGalleryState: un ícono de auto en un círculo amarillo + "No cars yet" / "Tap Create to add your first car.", usando el componente compartido EmptyState.

Interacción dentro de Gallery

flowchart TD
  A[GalleryScreen] --> B{cards vacío?}
  B -->|sí| C[EmptyGalleryState]
  B -->|no| D{layout}
  D -->|Grid| E[GalleryGridItem por carta]
  D -->|List| F[GalleryListItem por carta]
  E -->|tap| G["onCardClick(card) -> Details"]
  F -->|tap| G
  F -->|swipe end-to-start| H["onDeleteCard(card)"]