diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/personalization/AutoScanIntervalSetupView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/personalization/AutoScanIntervalSetupView.kt index cdbd134..0bd272e 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/personalization/AutoScanIntervalSetupView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/personalization/AutoScanIntervalSetupView.kt @@ -27,14 +27,19 @@ import com.example.medilightv2android.ui.theme.* import kotlin.math.roundToInt /** - * Auto Scan Interval 설정 화면. + * Scan Interval 설정 화면. * * 흐름: PiezoPersonalization(MaxCapacity + CatheterThreshold) - * → 본 화면 (Auto Scan Interval) + * → 본 화면 (Scan Interval) * → PlacementGuide → PiezoMonitoring * - * 600~5000ms 범위, 200ms 단위 snap. PiezoMonitoring의 in-monitoring settings에서 - * 같은 슬라이더로 측정 중에도 조정 가능. + * 단위 토글 (SEC/MIN): + * - SEC 모드: 0.6 ~ 5.0 s (0.2s step) — 짧은 간격, 실시간 모니터링 + * - MIN 모드: 1 ~ 10 min (30s step) — 장시간 측정, 배터리 절약 + * - 모드 전환 시 최소값(SEC=0.6s / MIN=1min)으로 reset + * 최소 600ms 고정 (펌웨어 응답 시간 + 안전 마진). + * + * PiezoMonitoring의 in-monitoring settings는 SEC 슬라이더만 유지 (회의 결정). */ @Composable fun AutoScanIntervalSetupView(appState: AppState) { @@ -105,6 +110,11 @@ fun AutoScanIntervalSetupView(appState: AppState) { @Composable private fun AutoScanIntervalCard(appState: AppState) { + // 단위 모드 — 현재 저장된 ms 값으로 기본 모드 추론 (60000ms 미만 = SEC) + var unitMode by remember { + mutableStateOf(if (appState.piezoSettings.autoScanIntervalMs < 60000) "sec" else "min") + } + Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), @@ -114,45 +124,74 @@ private fun AutoScanIntervalCard(appState: AppState) { modifier = Modifier.padding(horizontal = 20.dp, vertical = 24.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Auto Scan Interval", fontSize = 34.sp, fontWeight = FontWeight.ExtraBold) + Text("Scan Interval", fontSize = 34.sp, fontWeight = FontWeight.ExtraBold) Spacer(modifier = Modifier.height(8.dp)) - Text("Auto scan 사이클 간격 — 짧을수록 빠른 갱신, 길수록 안정", + Text("측정 간격 조절", fontSize = 13.sp, color = MlSecondaryText) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(16.dp)) + // SEC / MIN 토글 + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + UnitToggleButton(label = "SEC", selected = unitMode == "sec") { + if (unitMode != "sec") { + unitMode = "sec" + appState.piezoSettings = appState.piezoSettings.copy(autoScanIntervalMs = 600) + } + } + UnitToggleButton(label = "MIN", selected = unitMode == "min") { + if (unitMode != "min") { + unitMode = "min" + appState.piezoSettings = appState.piezoSettings.copy(autoScanIntervalMs = 60000) + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + // 현재 값 표시 (모드에 따라 sec/min 변환) + val currentMs = appState.piezoSettings.autoScanIntervalMs Row(verticalAlignment = Alignment.Bottom) { - Text("${appState.piezoSettings.autoScanIntervalMs}", fontSize = 64.sp, + val displayValue = if (unitMode == "sec") "%.1f".format(currentMs / 1000.0) + else "%.1f".format(currentMs / 60000.0) + Text(displayValue, fontSize = 64.sp, fontWeight = FontWeight.ExtraBold, color = MlPrimary) Spacer(modifier = Modifier.width(8.dp)) - Text("ms", fontSize = 24.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText, + Text(if (unitMode == "sec") "s" else "min", + fontSize = 24.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText, modifier = Modifier.padding(bottom = 12.dp)) } Spacer(modifier = Modifier.height(12.dp)) + // 스테퍼 — 모드별 step 크기 + val stepMs = if (unitMode == "sec") 200 else 30_000 + val minMs = if (unitMode == "sec") 600 else 60_000 + val maxMs = if (unitMode == "sec") 5_000 else 600_000 Row(horizontalArrangement = Arrangement.spacedBy(32.dp)) { StepperButton(icon = Icons.Default.Remove) { - val next = (appState.piezoSettings.autoScanIntervalMs - 200).coerceIn(600, 5000) + val next = (currentMs - stepMs).coerceIn(minMs, maxMs) appState.piezoSettings = appState.piezoSettings.copy(autoScanIntervalMs = next) } StepperButton(icon = Icons.Default.Add) { - val next = (appState.piezoSettings.autoScanIntervalMs + 200).coerceIn(600, 5000) + val next = (currentMs + stepMs).coerceIn(minMs, maxMs) appState.piezoSettings = appState.piezoSettings.copy(autoScanIntervalMs = next) } } Spacer(modifier = Modifier.height(12.dp)) + // 슬라이더 — 모드별 범위/snap + val stepCount = ((maxMs - minMs) / stepMs) - 1 // Slider steps는 양 끝점 사이 점 개수 Slider( - value = appState.piezoSettings.autoScanIntervalMs.toFloat(), + value = currentMs.toFloat(), onValueChange = { - val snapped = ((it / 200f).roundToInt() * 200).coerceIn(600, 5000) + val snapped = ((it / stepMs).roundToInt() * stepMs).coerceIn(minMs, maxMs) appState.piezoSettings = appState.piezoSettings.copy(autoScanIntervalMs = snapped) }, - valueRange = 600f..5000f, - steps = 21, + valueRange = minMs.toFloat()..maxMs.toFloat(), + steps = stepCount.coerceAtLeast(0), modifier = Modifier.padding(horizontal = 24.dp), colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary) ) @@ -160,6 +199,21 @@ private fun AutoScanIntervalCard(appState: AppState) { } } +@Composable +private fun UnitToggleButton(label: String, selected: Boolean, onClick: () -> Unit) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(8.dp)) + .background(if (selected) MlPrimary else Color.Gray.copy(alpha = 0.15f)) + .clickable(onClick = onClick) + .padding(horizontal = 24.dp, vertical = 8.dp), + contentAlignment = Alignment.Center + ) { + Text(label, fontSize = 14.sp, fontWeight = FontWeight.Bold, + color = if (selected) Color.White else Color.Black) + } +} + @Composable private fun StepperButton(icon: androidx.compose.ui.graphics.vector.ImageVector, onClick: () -> Unit) { Box(