Setup UX: allow Start w/ unsaved changes; hide delete for built-ins

This commit is contained in:
Tretzi
2026-04-15 09:44:17 -05:00
parent 14dd04413b
commit 50272cd6a6
2 changed files with 30 additions and 19 deletions

View File

@@ -319,6 +319,7 @@ fun App(vm: MainViewModel = viewModel(), billingManager: solutions.tretter.mindm
modifier = Modifier.size(38.dp) modifier = Modifier.size(38.dp)
) )
} }
if (p.id in ui.deletableProgramIds) {
Box( Box(
modifier = Modifier modifier = Modifier
.size(24.dp) .size(24.dp)
@@ -340,6 +341,7 @@ fun App(vm: MainViewModel = viewModel(), billingManager: solutions.tretter.mindm
} }
} }
} }
}
AdBanner( AdBanner(
enabled = !ui.settings.noAds, enabled = !ui.settings.noAds,
@@ -527,12 +529,14 @@ fun SetupScreen(
Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
if (hasUnsavedChanges) { if (hasUnsavedChanges) {
OutlinedButton(onClick = { vm.saveCurrentProgram(programName) }, modifier = Modifier.weight(1f).height(52.dp)) { OutlinedButton(
onClick = { vm.saveCurrentProgram(programName) },
modifier = Modifier.weight(1f).height(52.dp)
) {
Text("Save") Text("Save")
} }
} else {
Button(onClick = onStart, modifier = Modifier.weight(1f).height(52.dp)) { Text("Start") }
} }
Button(onClick = onStart, modifier = Modifier.weight(1f).height(52.dp)) { Text("Start") }
} }
if (ui.error != null) Text(ui.error!!, color = if (ui.error!!.startsWith("Saved")) Color(0xFF72E39A) else MaterialTheme.colorScheme.error) if (ui.error != null) Text(ui.error!!, color = if (ui.error!!.startsWith("Saved")) Color(0xFF72E39A) else MaterialTheme.colorScheme.error)
Spacer(Modifier.height(8.dp)) Spacer(Modifier.height(8.dp))

View File

@@ -34,6 +34,9 @@ data class UiState(
val selectedPreset: SessionPreset = Presets.builtIn.first(), val selectedPreset: SessionPreset = Presets.builtIn.first(),
val config: SessionConfig = Presets.builtIn.first().toConfig(), val config: SessionConfig = Presets.builtIn.first().toConfig(),
// Only user-saved programs (including customizations of built-ins) are deletable.
val deletableProgramIds: Set<String> = emptySet(),
// Timeline program (curves) used for both editing + runtime modulation. // Timeline program (curves) used for both editing + runtime modulation.
val timeline: TimelineEditorState = TimelineProgramFactory.fromPreset(Presets.builtIn.first()), val timeline: TimelineEditorState = TimelineProgramFactory.fromPreset(Presets.builtIn.first()),
val savedProgramName: String = Presets.builtIn.first().name, val savedProgramName: String = Presets.builtIn.first().name,
@@ -101,6 +104,7 @@ class MainViewModel(
combine(settingsRepository.settings, userProgramRepository.userPrograms) { settings, userPrograms -> combine(settingsRepository.settings, userProgramRepository.userPrograms) { settings, userPrograms ->
settings to userPrograms settings to userPrograms
}.collect { (settings, userPrograms) -> }.collect { (settings, userPrograms) ->
val userProgramIds = userPrograms.map { it.id }.toSet()
val builtInPrograms = Presets.builtIn.map { preset -> val builtInPrograms = Presets.builtIn.map { preset ->
userPrograms.firstOrNull { it.id == preset.id } ?: UserProgramEntity( userPrograms.firstOrNull { it.id == preset.id } ?: UserProgramEntity(
id = preset.id, id = preset.id,
@@ -121,7 +125,9 @@ class MainViewModel(
description = it.description, description = it.description,
timeline = it.timeline, timeline = it.timeline,
sortOrder = it.sortOrder, sortOrder = it.sortOrder,
isUserProgram = true, // Deletable only when the user explicitly saved it (either custom program,
// or a customized built-in stored in the user program store).
isUserProgram = it.id in userProgramIds,
) )
} }
@@ -142,6 +148,7 @@ class MainViewModel(
savedProgramName = savedName, savedProgramName = savedName,
savedTimelineSignature = savedSignature, savedTimelineSignature = savedSignature,
hasUnsavedChanges = isDirty(selectedPreset.name, nextTimeline, savedName, savedSignature), hasUnsavedChanges = isDirty(selectedPreset.name, nextTimeline, savedName, savedSignature),
deletableProgramIds = userProgramIds,
) )
} }
} }