Auto commit Sat Apr 4 08:01:01 AM CDT 2026

This commit is contained in:
Tretzi
2026-04-04 08:01:01 -05:00
parent 11445d10dd
commit f10df4813f
3 changed files with 74 additions and 2 deletions

View File

@@ -104,6 +104,7 @@ import com.mindmachine.mvp.session.flashIntervalMsToSeconds
import com.mindmachine.mvp.session.flashIntervalSecondsToMs import com.mindmachine.mvp.session.flashIntervalSecondsToMs
import com.mindmachine.mvp.session.formatDuration import com.mindmachine.mvp.session.formatDuration
import com.mindmachine.mvp.session.sessionProgressFraction import com.mindmachine.mvp.session.sessionProgressFraction
import com.mindmachine.mvp.session.shouldRequireStopConfirmation
import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault
import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@@ -113,6 +114,11 @@ import java.util.Locale
private const val SESSION_ENTRY_HOME = "home" private const val SESSION_ENTRY_HOME = "home"
private const val SESSION_ENTRY_SETUP = "setup" private const val SESSION_ENTRY_SETUP = "setup"
private enum class StopConfirmationAction {
BACK,
STOP_BUTTON,
}
private val MindMachineColors = darkColorScheme( private val MindMachineColors = darkColorScheme(
primary = Color(0xFF8AB4FF), primary = Color(0xFF8AB4FF),
onPrimary = Color(0xFF001B3D), onPrimary = Color(0xFF001B3D),
@@ -483,8 +489,14 @@ fun ActiveSessionScreen(vm: MainViewModel, onFinish: () -> Unit, onBackToEntry:
val ui by vm.ui.collectAsStateWithLifecycle() val ui by vm.ui.collectAsStateWithLifecycle()
if (ui.runtimeState == RuntimeState.COMPLETED) onFinish() if (ui.runtimeState == RuntimeState.COMPLETED) onFinish()
var stopConfirmationAction by remember { mutableStateOf<StopConfirmationAction?>(null) }
BackHandler { BackHandler {
onBackToEntry() if (shouldRequireStopConfirmation(ui.runtimeState)) {
stopConfirmationAction = StopConfirmationAction.BACK
} else {
onBackToEntry()
}
} }
val isVisualMode = true val isVisualMode = true
@@ -633,7 +645,17 @@ fun ActiveSessionScreen(vm: MainViewModel, onFinish: () -> Unit, onBackToEntry:
} else { } else {
Button(onClick = { vm.resume() }, modifier = Modifier.fillMaxWidth()) { Text("Resume") } Button(onClick = { vm.resume() }, modifier = Modifier.fillMaxWidth()) { Text("Resume") }
} }
OutlinedButton(onClick = { vm.stop(); onFinish() }, modifier = Modifier.fillMaxWidth()) { Text("Stop") } OutlinedButton(
onClick = {
if (shouldRequireStopConfirmation(ui.runtimeState)) {
stopConfirmationAction = StopConfirmationAction.STOP_BUTTON
} else {
vm.stop()
onFinish()
}
},
modifier = Modifier.fillMaxWidth()
) { Text("Stop") }
if (ui.interruptionReason != null) { if (ui.interruptionReason != null) {
Text(ui.interruptionReason!!, color = Color.White) Text(ui.interruptionReason!!, color = Color.White)
if (ui.runtimeState == RuntimeState.INTERRUPTED) { if (ui.runtimeState == RuntimeState.INTERRUPTED) {
@@ -645,6 +667,36 @@ fun ActiveSessionScreen(vm: MainViewModel, onFinish: () -> Unit, onBackToEntry:
} }
} }
} }
if (stopConfirmationAction != null) {
AlertDialog(
onDismissRequest = { stopConfirmationAction = null },
title = { Text("End session?") },
text = { Text("Your current session will stop and return to the previous screen.") },
confirmButton = {
TextButton(
onClick = {
when (stopConfirmationAction) {
StopConfirmationAction.BACK -> onBackToEntry()
StopConfirmationAction.STOP_BUTTON -> {
vm.stop()
onFinish()
}
null -> Unit
}
stopConfirmationAction = null
}
) {
Text("End session", color = Color(0xFFFF5252))
}
},
dismissButton = {
TextButton(onClick = { stopConfirmationAction = null }) {
Text("Keep running")
}
}
)
}
} }
@Composable @Composable

View File

@@ -11,3 +11,10 @@ fun sessionProgressFraction(durationSec: Int, remainingSec: Int): Float {
val elapsed = (total - remainingSec).coerceIn(0, total) val elapsed = (total - remainingSec).coerceIn(0, total)
return elapsed.toFloat() / total.toFloat() return elapsed.toFloat() / total.toFloat()
} }
fun shouldRequireStopConfirmation(runtimeState: RuntimeState): Boolean {
return runtimeState == RuntimeState.COUNTDOWN ||
runtimeState == RuntimeState.RUNNING ||
runtimeState == RuntimeState.PAUSED ||
runtimeState == RuntimeState.INTERRUPTED
}

View File

@@ -2,6 +2,7 @@ package com.mindmachine.mvp
import com.mindmachine.mvp.domain.RuntimeState import com.mindmachine.mvp.domain.RuntimeState
import com.mindmachine.mvp.session.sessionProgressFraction import com.mindmachine.mvp.session.sessionProgressFraction
import com.mindmachine.mvp.session.shouldRequireStopConfirmation
import com.mindmachine.mvp.session.shouldRevealSystemBarsOnTap import com.mindmachine.mvp.session.shouldRevealSystemBarsOnTap
import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault
import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen
@@ -53,4 +54,16 @@ class ActiveSessionUiTest {
assertTrue(sessionProgressFraction(durationSec = 600, remainingSec = 800) == 0f) assertTrue(sessionProgressFraction(durationSec = 600, remainingSec = 800) == 0f)
assertTrue(sessionProgressFraction(durationSec = 600, remainingSec = -10) == 1f) assertTrue(sessionProgressFraction(durationSec = 600, remainingSec = -10) == 1f)
} }
@Test
fun stop_confirmation_is_required_only_while_session_is_active_or_paused() {
assertTrue(shouldRequireStopConfirmation(RuntimeState.COUNTDOWN))
assertTrue(shouldRequireStopConfirmation(RuntimeState.RUNNING))
assertTrue(shouldRequireStopConfirmation(RuntimeState.PAUSED))
assertTrue(shouldRequireStopConfirmation(RuntimeState.INTERRUPTED))
assertFalse(shouldRequireStopConfirmation(RuntimeState.IDLE))
assertFalse(shouldRequireStopConfirmation(RuntimeState.COMPLETED))
assertFalse(shouldRequireStopConfirmation(RuntimeState.STOPPED))
}
} }