From 50272cd6a6ef87fd1229a19217b31dc2250bbdb4 Mon Sep 17 00:00:00 2001 From: Tretzi Date: Wed, 15 Apr 2026 09:44:17 -0500 Subject: [PATCH] Setup UX: allow Start w/ unsaved changes; hide delete for built-ins --- .../java/com/mindmachine/mvp/MainActivity.kt | 40 ++++++++++--------- .../mindmachine/mvp/session/MainViewModel.kt | 9 ++++- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/mindmachine/mvp/MainActivity.kt b/app/src/main/java/com/mindmachine/mvp/MainActivity.kt index 7ea16e4..1b411bd 100644 --- a/app/src/main/java/com/mindmachine/mvp/MainActivity.kt +++ b/app/src/main/java/com/mindmachine/mvp/MainActivity.kt @@ -319,21 +319,23 @@ fun App(vm: MainViewModel = viewModel(), billingManager: solutions.tretter.mindm modifier = Modifier.size(38.dp) ) } - Box( - modifier = Modifier - .size(24.dp) - .clickable { - confirmDeleteProgramId = p.id - confirmDeleteProgramName = p.name - }, - contentAlignment = Alignment.Center - ) { - Icon( - imageVector = Icons.Filled.Delete, - contentDescription = "Delete ${p.name}", - tint = Color(0xFFFF5252), - modifier = Modifier.fillMaxSize() - ) + if (p.id in ui.deletableProgramIds) { + Box( + modifier = Modifier + .size(24.dp) + .clickable { + confirmDeleteProgramId = p.id + confirmDeleteProgramName = p.name + }, + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Filled.Delete, + contentDescription = "Delete ${p.name}", + tint = Color(0xFFFF5252), + modifier = Modifier.fillMaxSize() + ) + } } } } @@ -527,12 +529,14 @@ fun SetupScreen( Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { 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") } - } 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) Spacer(Modifier.height(8.dp)) diff --git a/app/src/main/java/com/mindmachine/mvp/session/MainViewModel.kt b/app/src/main/java/com/mindmachine/mvp/session/MainViewModel.kt index 02d8c13..1a3353c 100644 --- a/app/src/main/java/com/mindmachine/mvp/session/MainViewModel.kt +++ b/app/src/main/java/com/mindmachine/mvp/session/MainViewModel.kt @@ -34,6 +34,9 @@ data class UiState( val selectedPreset: SessionPreset = Presets.builtIn.first(), val config: SessionConfig = Presets.builtIn.first().toConfig(), + // Only user-saved programs (including customizations of built-ins) are deletable. + val deletableProgramIds: Set = emptySet(), + // Timeline program (curves) used for both editing + runtime modulation. val timeline: TimelineEditorState = TimelineProgramFactory.fromPreset(Presets.builtIn.first()), val savedProgramName: String = Presets.builtIn.first().name, @@ -101,6 +104,7 @@ class MainViewModel( combine(settingsRepository.settings, userProgramRepository.userPrograms) { settings, userPrograms -> settings to userPrograms }.collect { (settings, userPrograms) -> + val userProgramIds = userPrograms.map { it.id }.toSet() val builtInPrograms = Presets.builtIn.map { preset -> userPrograms.firstOrNull { it.id == preset.id } ?: UserProgramEntity( id = preset.id, @@ -121,7 +125,9 @@ class MainViewModel( description = it.description, timeline = it.timeline, 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, savedTimelineSignature = savedSignature, hasUnsavedChanges = isDirty(selectedPreset.name, nextTimeline, savedName, savedSignature), + deletableProgramIds = userProgramIds, ) } }