From d8a725b21b04a6f03d39265dd662efab57374623 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Wed, 22 Apr 2026 17:23:46 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=8F=84=EB=84=9B=EC=B0=A8=ED=8A=B8=20r?= =?UTF-8?q?ecomposition=20=EB=B2=84=EA=B7=B8=20+=20Spot=20=EB=A1=B1?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=8A=A4=20=EC=9E=90=EB=8F=99=EC=B8=A1?= =?UTF-8?q?=EC=A0=95=20+=20BV=204=EC=B1=84=EB=84=90(CH0~CH3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bladderLevel.copy() 할당으로 Compose recomposition 트리거 (도넛차트 실시간 갱신) - Spot 버튼: Button→Box+detectTapGestures (탭=단일, 롱프레스=30초 자동측정) - startAutoMeasure() + LaunchedEffect 30초 반복 루프 - BV 추정 CH0~CH4(5ch)→CH0~CH3(4ch) 세로 채널만 사용 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../views/monitoring/PiezoMonitoringView.kt | 93 +++++++++++-------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index c017178..b96e43c 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -8,6 +8,8 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape @@ -109,10 +111,10 @@ fun PiezoMonitoringView(appState: AppState) { if (validChannels.isNotEmpty()) { val analysisResult = analyzer.analyzeMultiChannel(validChannels) - // Build walls list for BV estimation (5 channels) - val walls: MutableList?> = MutableList(5) { null } + // Build walls list for BV estimation (CH0~CH3, 세로 4채널만) + val walls: MutableList?> = MutableList(4) { null } for (ch in analysisResult.channels) { - if (ch.channel < 5 && ch.result != null) { + if (ch.channel < 4 && ch.result != null) { walls[ch.channel] = Pair(ch.result.ant, ch.result.post) } } @@ -142,7 +144,7 @@ fun PiezoMonitoringView(appState: AppState) { val maxVol = appState.piezoSettings.maxVolume.toDouble() val pct = if (maxVol > 0) (lastVolumeMl / maxVol).coerceAtMost(1.0) else 0.0 val level = (pct * BladderLevel.MAX_LEVEL).toInt().coerceIn(1, BladderLevel.MAX_LEVEL) - appState.bladderLevel.currentLevel = level + appState.bladderLevel = appState.bladderLevel.copy(currentLevel = level) } isMeasuring = false measureRetryCount = 0 @@ -183,10 +185,25 @@ fun PiezoMonitoringView(appState: AppState) { isMeasuring = false } + fun startAutoMeasure() { + isAutoMeasuring = true + measure() + } + fun stopAutoMeasure() { isAutoMeasuring = false } + // Auto-measure: repeat every 30s while active + LaunchedEffect(isAutoMeasuring) { + if (isAutoMeasuring) { + while (isAutoMeasuring) { + kotlinx.coroutines.delay(30_000) + if (isAutoMeasuring && !isMeasuring) measure() + } + } + } + // Setup disconnect handling LaunchedEffect(Unit) { bleManager.onUnexpectedDisconnect = { @@ -634,44 +651,46 @@ fun PiezoMonitoringView(appState: AppState) { Text("Catheterize", fontSize = 16.sp, fontWeight = FontWeight.SemiBold, color = MlPrimary) } - // Spot button - Button( - onClick = { - if (isAutoMeasuring) stopAutoMeasure() - else if (!isMeasuring) measure() - }, - modifier = Modifier.weight(1f).height(56.dp), - shape = RoundedCornerShape(16.dp), - colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent), - contentPadding = PaddingValues(), - enabled = !isMeasuring || isAutoMeasuring - ) { - Box( - modifier = Modifier.fillMaxSize().background( + // Spot button (tap = single, long press = auto 30s) + Box( + modifier = Modifier + .weight(1f) + .height(56.dp) + .clip(RoundedCornerShape(16.dp)) + .background( Brush.horizontalGradient( if (isAutoMeasuring) listOf(Color.Red, Color(0xFFFF9500)) else urgency.gradientColors - ), - RoundedCornerShape(16.dp) - ), - contentAlignment = Alignment.Center - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - if (isMeasuring && !isAutoMeasuring) { - CircularProgressIndicator(color = Color.White, modifier = Modifier.size(20.dp), strokeWidth = 2.dp) - } - Spacer(modifier = Modifier.width(8.dp)) - Text( - when { - isAutoMeasuring -> "Stop" - isMeasuring -> "Measuring..." - else -> "Spot" - }, - fontSize = 16.sp, - fontWeight = FontWeight.SemiBold, - color = Color.White ) + ) + .pointerInput(isAutoMeasuring, isMeasuring) { + detectTapGestures( + onTap = { + if (isAutoMeasuring) stopAutoMeasure() + else if (!isMeasuring) measure() + }, + onLongPress = { + if (!isAutoMeasuring && !isMeasuring) startAutoMeasure() + } + ) + }, + contentAlignment = Alignment.Center + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (isMeasuring && !isAutoMeasuring) { + CircularProgressIndicator(color = Color.White, modifier = Modifier.size(20.dp), strokeWidth = 2.dp) } + Spacer(modifier = Modifier.width(8.dp)) + Text( + when { + isAutoMeasuring -> "Stop" + isMeasuring -> "Measuring..." + else -> "Spot" + }, + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) } } }