UI: 힌트 위치 이동 + 버튼 텍스트 + Alignment 비활성 + Bladder Capacity

#1 Placement 힌트 메시지: 몸 아래 → Step 아래/몸 위로 이동
#2 버튼 텍스트: Catheterize→Catheterization, Auto→Automatic, 글자 크기 UP
#3 Alignment Complete: GREEN(Optimal)일 때만 활성 (Skip과 차별화)
#4 Max Volume → Bladder Capacity (설정+Personalization 모두)
- Bladdy 도넛 내 위치 3% 위로 보정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 11:51:27 +09:00
parent fab018f19e
commit 75b10c2f77
3 changed files with 40 additions and 40 deletions
@@ -900,11 +900,11 @@ fun PiezoMonitoringView(appState: AppState) {
lineWidth = donutLineWidth, lineWidth = donutLineWidth,
size = donutSize size = donutSize
) )
// Bladdy + 볼륨 (정중앙) // Bladdy + 볼륨 (약간 위로 보정)
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
modifier = Modifier.matchParentSize() modifier = Modifier.matchParentSize().offset(y = -(donutSize * 0.03f))
) { ) {
BladdyRiveView(urgency = urgency, size = bladdySize) BladdyRiveView(urgency = urgency, size = bladdySize)
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
@@ -960,8 +960,8 @@ fun PiezoMonitoringView(appState: AppState) {
) )
) { ) {
Column(horizontalAlignment = Alignment.CenterHorizontally) { Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("Void /", fontSize = 12.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary) Text("Void /", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
Text("Catheterize", fontSize = 12.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary) Text("Catheterization", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
} }
} }
@@ -979,9 +979,9 @@ fun PiezoMonitoringView(appState: AppState) {
) )
) { ) {
if (isAutoMeasuring) { if (isAutoMeasuring) {
Text("Stop", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = Color.White) Text("Stop", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
} else { } else {
Text("Auto", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = Color.White) Text("Automatic", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
} }
} }
@@ -1032,7 +1032,7 @@ fun PiezoMonitoringView(appState: AppState) {
if (isSpotInProgress) { if (isSpotInProgress) {
CircularProgressIndicator(color = Color.White, modifier = Modifier.size(18.dp), strokeWidth = 2.dp) CircularProgressIndicator(color = Color.White, modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
} else { } else {
Text("Spot", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = Color.White) Text("Spot", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
} }
} }
} }
@@ -1098,7 +1098,7 @@ fun PiezoMonitoringView(appState: AppState) {
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
// Max Volume // Max Volume
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Text("Max Volume", fontSize = 14.sp, fontWeight = FontWeight.SemiBold) Text("Bladder Capacity", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Text("${appState.piezoSettings.maxVolume} mL", fontSize = 14.sp, fontWeight = FontWeight.Bold, color = MlPrimary) Text("${appState.piezoSettings.maxVolume} mL", fontSize = 14.sp, fontWeight = FontWeight.Bold, color = MlPrimary)
} }
@@ -217,6 +217,34 @@ fun PlacementGuideView(appState: AppState) {
} }
} }
// ── 가이드 텍스트 (Step 아래, 몸 위) ──
val hintGreen = isGreenZone
val hintBg = if (hintGreen) Color(0xFF4CAF50).copy(alpha = 0.12f) else Color(0xFFFFF3E0)
val hintFg = if (hintGreen) Color(0xFF4CAF50) else Color(0xFFFF9800)
val dots = ".".repeat((scanCount % 3) + 1)
val displayHint = buildString {
val hint = directionHint.ifEmpty { " " }
append(hint)
if (hint.startsWith("Raise") || hint.startsWith("Lower") || hint.startsWith("Move") ||
hint.startsWith("Fine-tune") || hint.startsWith("Checking") || hint.startsWith("Adjust")) {
append(dots)
}
if (appState.isDevMode && !lastCv.isNaN()) {
append(" (CV=${"%.3f".format(lastCv)})")
}
}
Text(
text = displayHint,
fontSize = 15.sp,
fontWeight = FontWeight.SemiBold,
color = hintFg,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.background(hintBg, RoundedCornerShape(12.dp))
.padding(12.dp)
)
// ── 하복부 Canvas 실루엣 + 센서 + 방향 가이드 ── // ── 하복부 Canvas 실루엣 + 센서 + 방향 가이드 ──
Box( Box(
modifier = Modifier modifier = Modifier
@@ -382,35 +410,7 @@ fun PlacementGuideView(appState: AppState) {
} }
// ── 가이드 텍스트 (일러스트 아래, 항상 표시) ── // (힌트 텍스트는 Step 아래, 몸 위에 배치됨)
val hintGreen = isGreenZone
val hintBg = if (hintGreen) Color(0xFF4CAF50).copy(alpha = 0.12f) else Color(0xFFFFF3E0)
val hintFg = if (hintGreen) Color(0xFF4CAF50) else Color(0xFFFF9800)
// 방향 힌트에 점 순환 (. / .. / ...) — 업데이트 중임을 시각적으로 표시
val dots = ".".repeat((scanCount % 3) + 1)
val displayHint = buildString {
val hint = directionHint.ifEmpty { " " }
append(hint)
// 방향 안내 중일 때만 점 추가 (Optimal, Place sensor 등은 제외)
if (hint.startsWith("Raise") || hint.startsWith("Lower") || hint.startsWith("Move") ||
hint.startsWith("Fine-tune") || hint.startsWith("Checking")) {
append(dots)
}
if (appState.isDevMode && !lastCv.isNaN()) {
append(" (CV=${"%.3f".format(lastCv)})")
}
}
Text(
text = displayHint,
fontSize = 15.sp,
fontWeight = FontWeight.SemiBold,
color = hintFg,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.background(hintBg, RoundedCornerShape(12.dp))
.padding(12.dp)
)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
@@ -816,7 +816,7 @@ fun PlacementGuideView(appState: AppState) {
isContinuousMode = false isContinuousMode = false
appState.placementComplete() appState.placementComplete()
}, },
enabled = isLocked || detectedCount >= 4, enabled = isLocked, // GREEN(Optimal)일 때만 활성
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(52.dp), .height(52.dp),
@@ -146,9 +146,9 @@ private fun SensorPositionStep(appState: AppState) {
@Composable @Composable
private fun MaxVolumeStep(appState: AppState) { private fun MaxVolumeStep(appState: AppState) {
Column(horizontalAlignment = Alignment.CenterHorizontally) { Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("Maximum Volume", fontSize = 24.sp, fontWeight = FontWeight.Bold) Text("Bladder Capacity", fontSize = 24.sp, fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text("Set your maximum bladder capacity", fontSize = 14.sp, color = MlSecondaryText) Text("Set your maximum bladder capacity (mL)", fontSize = 14.sp, color = MlSecondaryText)
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Row(verticalAlignment = Alignment.Bottom) { Row(verticalAlignment = Alignment.Bottom) {