feat: UI 일괄 수정 (5,6,7,8번)
5. Onboarding 간소화: 4단계→1단계 (Max Volume만) Step 1(자세)/2(위치)/4(최적화) 제거, Continue 바로 완료 6. 자동 reconnect: 앱 시작 시 마지막 기기에 자동 연결 SharedPreferences에 address+name 저장, HomeView에서 autoConnectLastDevice() 7. Demo 모드: DeviceScanView에서 Demo 버튼 제거 8. Android 뒤로가기: BackHandler로 화면별 네비게이션 매핑 Placement→Home, Monitoring→Placement, History/Diary→Monitoring 등 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package com.example.medilightv2android
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.animation.Crossfade
|
||||
@@ -60,6 +61,23 @@ fun MedilightApp(modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val appState = remember { AppState(context) }
|
||||
|
||||
// Android 뒤로가기 = 앱 내 뒤로가기
|
||||
BackHandler(enabled = appState.currentScreen != AppScreen.HOME) {
|
||||
when (appState.currentScreen) {
|
||||
AppScreen.SENSOR_SELECT -> appState.currentScreen = AppScreen.HOME
|
||||
AppScreen.DEVICE_SCAN -> appState.currentScreen = AppScreen.SENSOR_SELECT
|
||||
AppScreen.PIEZO_PERSONALIZATION -> appState.currentScreen = AppScreen.DEVICE_SCAN
|
||||
AppScreen.PLACEMENT_GUIDE -> appState.goHome()
|
||||
AppScreen.PIEZO_MONITORING -> appState.currentScreen = AppScreen.PLACEMENT_GUIDE
|
||||
AppScreen.VIVAMYO_MONITORING -> appState.goHome()
|
||||
AppScreen.MEASUREMENT_HISTORY -> appState.currentScreen = AppScreen.PIEZO_MONITORING
|
||||
AppScreen.VOIDING_DIARY -> appState.currentScreen = AppScreen.PIEZO_MONITORING
|
||||
AppScreen.REMINDER_SETTINGS -> appState.currentScreen = AppScreen.PIEZO_MONITORING
|
||||
AppScreen.URINE_CAMERA -> appState.currentScreen = AppScreen.PIEZO_MONITORING
|
||||
else -> appState.currentScreen = AppScreen.HOME
|
||||
}
|
||||
}
|
||||
|
||||
Crossfade(
|
||||
targetState = appState.currentScreen,
|
||||
animationSpec = tween(300),
|
||||
|
||||
@@ -221,6 +221,17 @@ class BleManager private constructor(private val context: Context) {
|
||||
handler.postDelayed(timeout, 10000)
|
||||
}
|
||||
|
||||
/** 저장된 마지막 기기에 자동 연결 시도 */
|
||||
fun autoConnectLastDevice() {
|
||||
if (isConnected.value) return
|
||||
val prefs = context.getSharedPreferences("medilight_prefs", Context.MODE_PRIVATE)
|
||||
val address = prefs.getString("last_device_address", null) ?: return
|
||||
val name = prefs.getString("last_device_name", null) ?: return
|
||||
debugLogger.info("AUTO_CONNECT attempting $name ($address)")
|
||||
lastConnectedAddress = address
|
||||
scheduleAutoReconnect()
|
||||
}
|
||||
|
||||
fun disconnect() {
|
||||
isUserDisconnect = true
|
||||
cancelAutoReconnect()
|
||||
@@ -614,7 +625,10 @@ class BleManager private constructor(private val context: Context) {
|
||||
|
||||
try {
|
||||
val prefs = context.getSharedPreferences("medilight_prefs", Context.MODE_PRIVATE)
|
||||
prefs.edit().putString("last_device_address", gatt.device.address).apply()
|
||||
prefs.edit()
|
||||
.putString("last_device_address", gatt.device.address)
|
||||
.putString("last_device_name", connectedDeviceName.value)
|
||||
.apply()
|
||||
} catch (_: Exception) {}
|
||||
|
||||
gatt.discoverServices()
|
||||
|
||||
-10
@@ -249,16 +249,6 @@ fun DeviceScanView(appState: AppState) {
|
||||
}
|
||||
}
|
||||
|
||||
// Demo mode button
|
||||
TextButton(
|
||||
onClick = { appState.enterDemoMode() },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 24.dp)
|
||||
) {
|
||||
Text("Demo Mode (No Device)", fontSize = 14.sp, color = MlSecondaryText)
|
||||
}
|
||||
|
||||
// Scan button
|
||||
Button(
|
||||
onClick = {
|
||||
|
||||
@@ -8,6 +8,9 @@ import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.example.medilightv2android.ble.BleManager
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@@ -22,6 +25,12 @@ import com.example.medilightv2android.ui.theme.*
|
||||
|
||||
@Composable
|
||||
fun HomeView(appState: AppState) {
|
||||
val context = LocalContext.current
|
||||
// 앱 시작 시 마지막 기기에 자동 연결 시도
|
||||
LaunchedEffect(Unit) {
|
||||
BleManager.getInstance(context).autoConnectLastDevice()
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
||||
+4
-32
@@ -37,7 +37,7 @@ fun PiezoPersonalizationView(appState: AppState) {
|
||||
val handler = remember { Handler(Looper.getMainLooper()) }
|
||||
var currentStep by remember { mutableIntStateOf(1) }
|
||||
var optimizationComplete by remember { mutableStateOf(false) }
|
||||
val totalSteps = 4
|
||||
val totalSteps = 1
|
||||
|
||||
fun startOptimization() {
|
||||
bleManager.onPiezoDataReceived = {
|
||||
@@ -88,43 +88,15 @@ fun PiezoPersonalizationView(appState: AppState) {
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// Step content
|
||||
// Max Volume만 표시
|
||||
when (currentStep) {
|
||||
1 -> PostureStep(appState)
|
||||
2 -> SensorPositionStep(appState)
|
||||
3 -> MaxVolumeStep(appState)
|
||||
4 -> {
|
||||
LaunchedEffect(Unit) { startOptimization() }
|
||||
OptimizationStep(optimizationComplete)
|
||||
}
|
||||
1 -> MaxVolumeStep(appState)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
// Navigation button
|
||||
if (currentStep < 4) {
|
||||
Button(
|
||||
onClick = { currentStep++ },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 32.dp)
|
||||
.padding(bottom = 32.dp)
|
||||
.height(56.dp),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
|
||||
contentPadding = PaddingValues()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().background(
|
||||
Brush.horizontalGradient(listOf(MlTeal, MlPrimary)),
|
||||
RoundedCornerShape(16.dp)
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("Next", fontSize = 18.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
|
||||
}
|
||||
}
|
||||
} else if (optimizationComplete) {
|
||||
if (currentStep <= totalSteps) {
|
||||
Button(
|
||||
onClick = { appState.personalizationComplete() },
|
||||
modifier = Modifier
|
||||
|
||||
Reference in New Issue
Block a user