UI text: revised 문서 반영 — 전체 텍스트 통일

[Placement]
- Alignment Complete → Start Scanning
- sensor → VesiScan (초기 안내)
- Raise/Lower the sensor → Slide up/down
- Move left/right → Slide left/right
- Fine-tune → Optimizing, Checking LR → Centering
- Optimal position! → In position!
- Position lost/detached → Restart above pubic bone.
- Past optimum → Too far, Lost signal → Signal lost

[Donut]
- Void/Catheterize → Voided/Catheterized
- Auto → Auto Scan, Stop → Stop Scan, Spot → Single Scan
- Voiding recorded → Recorded
- 한글 다이얼로그 → 영어 (Disconnect and remove pairing.)
- Sensor Position Issue → Position lost, Go to Alignment → Realign

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 13:58:27 +09:00
parent 75b10c2f77
commit ddd2f79380
2 changed files with 47 additions and 47 deletions
@@ -949,7 +949,7 @@ fun PiezoMonitoringView(appState: AppState) {
lastVolumeMl = 0.0
maxVolumeMl = 0.0
resetMeasurement()
android.widget.Toast.makeText(context, "Voiding recorded", android.widget.Toast.LENGTH_SHORT).show()
android.widget.Toast.makeText(context, "Recorded", android.widget.Toast.LENGTH_SHORT).show()
},
enabled = !isSpotInProgress && !isAutoMeasuring,
modifier = Modifier.weight(1.3f).height(btnHeight),
@@ -960,8 +960,8 @@ fun PiezoMonitoringView(appState: AppState) {
)
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("Void /", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
Text("Catheterization", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
Text("Voided", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
Text("Catheterized", fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
}
}
@@ -979,9 +979,9 @@ fun PiezoMonitoringView(appState: AppState) {
)
) {
if (isAutoMeasuring) {
Text("Stop", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
Text("Stop Scan", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
} else {
Text("Automatic", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
Text("Auto Scan", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
}
}
@@ -1032,7 +1032,7 @@ fun PiezoMonitoringView(appState: AppState) {
if (isSpotInProgress) {
CircularProgressIndicator(color = Color.White, modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
} else {
Text("Spot", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
Text("Single Scan", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
}
}
}
@@ -1286,7 +1286,7 @@ fun PiezoMonitoringView(appState: AppState) {
AlertDialog(
onDismissRequest = { showDisconnectConfirm = false },
title = { Text("Delete Pairing") },
text = { Text("기기 연결을 해제하고 페어링 정보를 삭제합니다.") },
text = { Text("Disconnect and remove pairing.") },
confirmButton = {
TextButton(onClick = {
showDisconnectConfirm = false; showSettings = false
@@ -1328,14 +1328,14 @@ fun PiezoMonitoringView(appState: AppState) {
if (showRealignPrompt) {
AlertDialog(
onDismissRequest = { showRealignPrompt = false },
title = { Text("Sensor Position Issue") },
text = { Text("The sensor may have shifted from the optimal position. Please re-run Sensor Alignment to ensure accurate measurements.") },
title = { Text("Position lost") },
text = { Text("Sensor may have shifted. Restart from alignment.") },
confirmButton = {
Button(onClick = {
showRealignPrompt = false
autoFailCount = 0
appState.currentScreen = com.example.medilightv2android.AppScreen.PLACEMENT_GUIDE
}) { Text("Go to Alignment") }
}) { Text("Realign") }
},
dismissButton = {
TextButton(onClick = { showRealignPrompt = false; autoFailCount = 0 }) {
@@ -120,7 +120,7 @@ fun PlacementGuideView(appState: AppState) {
lastHintChangeMs = 0L
lastGuidePhase = PlacementPhase.VERTICAL
phaseHoldScans = 0
directionHint = "Place the sensor above the pubic bone, then press Start"
directionHint = "Place VesiScan above the pubic bone, then press Start"
directionIcon = ""
lastCv = Double.NaN
for (i in 0 until 6) { channelDetected[i] = false; channelUrineLen[i] = 0 }
@@ -225,8 +225,8 @@ fun PlacementGuideView(appState: AppState) {
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")) {
if (hint.startsWith("Slide") || hint.startsWith("Optimizing") ||
hint.startsWith("Centering") || hint.startsWith("Adjust")) {
append(dots)
}
if (appState.isDevMode && !lastCv.isNaN()) {
@@ -602,7 +602,7 @@ fun PlacementGuideView(appState: AppState) {
val detachResult = if (fullCh.size >= 6) DetachmentDetection.detect(buffers) else null
if (detachResult != null && detachResult.isDetached) {
directionHint = "Sensor detached. Place above pubic bone, then press Start"
directionHint = "Sensor detached. Restart above pubic bone."
directionIcon = "" // 화살표 없음
placementScore = 0
isContinuousMode = false
@@ -690,7 +690,7 @@ fun PlacementGuideView(appState: AppState) {
// GREEN hold 중이면 힌트 강제 유지
if (greenHeld) {
directionHint = "Optimal position!"
directionHint = "In position!"
directionIcon = "checkmark.circle"
placementPhase = PlacementPhase.GREEN
if (!guideResult.cv.isNaN()) lastCv = guideResult.cv
@@ -707,7 +707,7 @@ fun PlacementGuideView(appState: AppState) {
greenFailCount++
if (greenFailCount < 3) {
// 아직 이탈 안 함 — GREEN 유지
directionHint = "Optimal position!"
directionHint = "In position!"
directionIcon = "checkmark.circle"
placementPhase = PlacementPhase.GREEN
} else {
@@ -716,7 +716,7 @@ fun PlacementGuideView(appState: AppState) {
greenLockedAtMs = 0L
greenFailCount = 0
if (lastLedMode != 5) { bleManager.sendLedMode(5); lastLedMode = 5 }
directionHint = "Position lost. Place sensor above pubic bone, then press Start"
directionHint = "Position lost. Restart above pubic bone."
directionIcon = "" // 화살표 없음
placementScore = 10
placementPhase = PlacementPhase.VERTICAL
@@ -810,7 +810,7 @@ fun PlacementGuideView(appState: AppState) {
}
}
// Alignment Complete button (스캔 진행 중에만)
// Start Scanning button (스캔 진행 중에만)
if (!waitingForStart) Button(
onClick = {
isContinuousMode = false
@@ -828,7 +828,7 @@ fun PlacementGuideView(appState: AppState) {
) {
Icon(Icons.Filled.CheckCircle, contentDescription = null, tint = Color.White)
Spacer(modifier = Modifier.width(8.dp))
Text("Alignment Complete", fontSize = 16.sp, fontWeight = FontWeight.Bold, color = Color.White)
Text("Start Scanning", fontSize = 16.sp, fontWeight = FontWeight.Bold, color = Color.White)
}
// Skip button
@@ -1234,7 +1234,7 @@ private fun computePlacementGuide(
val detectedCount = detected.count { it }
if (detectedCount == 0) {
return PlacementGuideResult("Raise the sensor up", "arrow.up", 0,
return PlacementGuideResult("Slide up", "arrow.up", 0,
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.VERTICAL)
}
@@ -1259,9 +1259,9 @@ private fun computePlacementGuide(
// Phase 1: nothing detected — start instruction
if (centerDetected == 0) {
val hint = if (vs.everSawAllFour)
"Lost signal — slide back up ↑"
"Signal lost — slide up ↑"
else
"Place sensor near navel, slide slowly down ↓"
"Start near navel, slide down slowly ↓"
val icon = if (vs.everSawAllFour) "arrow.up" else "arrow.down"
return PlacementGuideResult(hint, icon, 5,
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.VERTICAL)
@@ -1270,7 +1270,7 @@ private fun computePlacementGuide(
// Phase 4: was at all-4, now lost a channel → overshoot (boundary)
if (vs.everSawAllFour && centerDetected < prev && centerDetected < 4) {
vs.boundaryHit = true
return PlacementGuideResult("Past optimum — slide back up ↑", "arrow.up", 50,
return PlacementGuideResult("Too far — slide up ↑", "arrow.up", 50,
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.VERTICAL)
}
@@ -1290,9 +1290,9 @@ private fun computePlacementGuide(
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.GREEN)
} else {
val lrHint = when {
l4 > 0 && l5 > 0 && l4 > l5 -> "Move left ←"
l4 > 0 && l5 > 0 && l5 > l4 -> "Move right →"
else -> "Checking left/right balance..."
l4 > 0 && l5 > 0 && l4 > l5 -> "Slide left ←"
l4 > 0 && l5 > 0 && l5 > l4 -> "Slide right →"
else -> "Centering"
}
val lrIcon = when {
l4 > 0 && l5 > 0 && l4 > l5 -> "arrow.left"
@@ -1328,13 +1328,13 @@ private fun computePlacementGuide(
val hint: String; val icon: String
when {
(ch0det || ch1det) && !ch2det && !ch3det -> {
hint = "Raise the sensor up"; icon = "arrow.up"
hint = "Slide up"; icon = "arrow.up"
}
(ch3det || ch2det) && !ch0det && !ch1det -> {
hint = "Lower the sensor down"; icon = "arrow.down"
hint = "Slide down"; icon = "arrow.down"
}
else -> {
hint = "Raise the sensor up"; icon = "arrow.up"
hint = "Slide up"; icon = "arrow.up"
}
}
return PlacementGuideResult(hint, icon, centerDetected * 10,
@@ -1379,7 +1379,7 @@ private fun computePlacementGuide(
val ch5ok = detected.getOrElse(5) { false }
// 항상 LATERAL 단계를 거침 — 전환 시 항상 Checking 표시
val lrHint = "Checking left/right balance..."
val lrHint = "Centering"
val lrIcon = "checkmark.circle"
val score = (40 + ((1.0 - kotlin.math.abs(gradient) / gradientThr) * 20).toInt())
.coerceIn(40, 60)
@@ -1396,16 +1396,16 @@ private fun computePlacementGuide(
val ch4ok = detected.getOrElse(4) { false }
val ch5ok = detected.getOrElse(5) { false }
// 항상 LATERAL 단계를 거침
return PlacementGuideResult("Checking left/right balance...",
return PlacementGuideResult("Centering",
"checkmark.circle", 50,
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.LATERAL)
} else if (gradient > 0) {
val intensity = if (gradient > 0.8) "Lower the sensor down" else "Lower the sensor slightly"
val intensity = if (gradient > 0.8) "Slide down" else "Slide down slightly"
return PlacementGuideResult(intensity, "arrow.down",
(20 + centerDetected * 5).coerceAtMost(35),
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.VERTICAL)
} else {
val intensity = if (gradient < -0.8) "Raise the sensor up" else "Raise the sensor slightly"
val intensity = if (gradient < -0.8) "Slide up" else "Slide up slightly"
return PlacementGuideResult(intensity, "arrow.up",
(20 + centerDetected * 5).coerceAtMost(35),
phase = PlacementPhase.VERTICAL, nextPhase = PlacementPhase.VERTICAL)
@@ -1443,10 +1443,10 @@ private fun computePlacementGuide(
phase = PlacementPhase.LATERAL, nextPhase = PlacementPhase.GREEN)
}
return if (lateralOffsetMm > 0) {
PlacementGuideResult("Move right →", "arrow.right", 45,
PlacementGuideResult("Slide right →", "arrow.right", 45,
phase = PlacementPhase.LATERAL, nextPhase = PlacementPhase.LATERAL)
} else {
PlacementGuideResult("Move left ←", "arrow.left", 45,
PlacementGuideResult("Slide left ←", "arrow.left", 45,
phase = PlacementPhase.LATERAL, nextPhase = PlacementPhase.LATERAL)
}
}
@@ -1454,12 +1454,12 @@ private fun computePlacementGuide(
// 한쪽만 detect → 반대쪽으로 이동 (잡히는 쪽의 반대로)
// ch4(왼쪽)만 잡힘 = 기기가 오른쪽 치우침 = 왼쪽으로
if (ch4det && !ch5det) {
return PlacementGuideResult("Move left ←", "arrow.left", 40,
return PlacementGuideResult("Slide left ←", "arrow.left", 40,
phase = PlacementPhase.LATERAL, nextPhase = PlacementPhase.LATERAL)
}
// ch5(오른쪽)만 잡힘 = 기기가 왼쪽 치우침 = 오른쪽으로
if (ch5det && !ch4det) {
return PlacementGuideResult("Move right →", "arrow.right", 40,
return PlacementGuideResult("Slide right →", "arrow.right", 40,
phase = PlacementPhase.LATERAL, nextPhase = PlacementPhase.LATERAL)
}
if (!ch4det && !ch5det) {
@@ -1549,7 +1549,7 @@ private fun computePlacementGuide(
if (isPass) {
val score = ((1.0 - cv / cvThr).coerceIn(0.0, 1.0) * 100).toInt().coerceAtLeast(70)
return PlacementGuideResult(
"Optimal position!",
"In position!",
"checkmark.circle", score, cv, true, lrDev, lrPass,
phase = PlacementPhase.GREEN, nextPhase = PlacementPhase.GREEN)
} else {
@@ -1567,25 +1567,25 @@ private fun computePlacementGuide(
when {
// ch4/ch5 중 하나만 빠짐 → 반대 방향 안내
!lrPass && !ch4det && ch5det -> {
adjustHint = "Move left ←"; adjustIcon = "arrow.left"
adjustHint = "Slide left ←"; adjustIcon = "arrow.left"
}
!lrPass && ch4det && !ch5det -> {
adjustHint = "Move right →"; adjustIcon = "arrow.right"
adjustHint = "Slide right →"; adjustIcon = "arrow.right"
}
!lrPass && !ch4det && !ch5det -> {
adjustHint = "Adjust left or right"; adjustIcon = "arrow.right"
}
!lrPass && lrDev > DEFAULT_LR_DEV_THR -> {
adjustHint = "Move left ←"; adjustIcon = "arrow.left"
adjustHint = "Slide left ←"; adjustIcon = "arrow.left"
}
!lrPass && lrDev < -DEFAULT_LR_DEV_THR -> {
adjustHint = "Move right →"; adjustIcon = "arrow.right"
adjustHint = "Slide right →"; adjustIcon = "arrow.right"
}
gradient > 0.3 -> {
adjustHint = "Lower the sensor down"; adjustIcon = "arrow.down"
adjustHint = "Slide down"; adjustIcon = "arrow.down"
}
gradient < -0.3 -> {
adjustHint = "Raise the sensor up"; adjustIcon = "arrow.up"
adjustHint = "Slide up"; adjustIcon = "arrow.up"
}
else -> {
// 방향 애매 + CV 미달 → ch별 len 분석으로 방향 제시
@@ -1596,13 +1596,13 @@ private fun computePlacementGuide(
// 최소 채널이 최대의 60% 미만 → 약한 쪽으로 안내
if (minCh <= 1) {
// ch0/ch1 약함 → 위로
adjustHint = "Raise the sensor slightly"; adjustIcon = "arrow.up"
adjustHint = "Slide up slightly"; adjustIcon = "arrow.up"
} else {
// ch2/ch3 약함 → 아래로
adjustHint = "Lower the sensor slightly"; adjustIcon = "arrow.down"
adjustHint = "Slide down slightly"; adjustIcon = "arrow.down"
}
} else {
adjustHint = "Fine-tune position"; adjustIcon = "checkmark.circle"
adjustHint = "Optimizing"; adjustIcon = "checkmark.circle"
}
}
}