@Composable
fun StudioCard(app: App, onOpen: () -> Unit) {
var pressed by remember { mutableStateOf(false) }
val scale by animateFloatAsState(if (pressed) 0.98f else 1f)
Card(
modifier = Modifier
.fillMaxWidth()
.graphicsLayer { scaleX = scale; scaleY = scale }
.clickable(onClick = onOpen),
shape = MaterialTheme.shapes.extraLarge,
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AppIcon(app.icon, size = 56.dp)
Spacer(Modifier.width(16.dp))
Column {
Text(app.name, style = MaterialTheme.typography.titleLarge)
Text(app.tagline, color = MaterialTheme.colorScheme.onSurfaceVariant)
}
}
}
}
// Small details, shipped carefully.
class ReleaseViewModel(private val repo: AppRepository) : ViewModel() {
val apps = repo.observeApps()
.map { list -> list.sortedBy { it.name } }
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun refresh() = viewModelScope.launch { repo.sync() }
}
@Composable
fun StudioCard(app: App, onOpen: () -> Unit) {
var pressed by remember { mutableStateOf(false) }
val scale by animateFloatAsState(if (pressed) 0.98f else 1f)
Card(
modifier = Modifier
.fillMaxWidth()
.graphicsLayer { scaleX = scale; scaleY = scale }
.clickable(onClick = onOpen),
shape = MaterialTheme.shapes.extraLarge,
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AppIcon(app.icon, size = 56.dp)
Spacer(Modifier.width(16.dp))
Column {
Text(app.name, style = MaterialTheme.typography.titleLarge)
Text(app.tagline, color = MaterialTheme.colorScheme.onSurfaceVariant)
}
}
}
}
// Small details, shipped carefully.
class ReleaseViewModel(private val repo: AppRepository) : ViewModel() {
val apps = repo.observeApps()
.map { list -> list.sortedBy { it.name } }
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun refresh() = viewModelScope.launch { repo.sync() }
}