549a2c722e
PlacementGuideView.kt: - 6-sensor Canvas layout (CH0-CH3 vertical + CH4/CH5 lateral wings) - Per-channel UrinAI detection (green/red color coding) - Direction guidance (up/down/left/right) - Check Position → maa → detect → display - Start Measurement when 4+ channels detected MeasurementLogService.kt: - JSON Lines format, daily rotation - Events: measurement, placement, ble_connected/disconnected, error - 90-day auto-purge - App internal storage: vesiscan_logs/YYYY-MM-DD.jsonl AppState.kt + MainActivity.kt: - PLACEMENT_GUIDE screen added to navigation - Flow: personalization → placementGuide → piezoMonitoring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
4.5 KiB
Kotlin
97 lines
4.5 KiB
Kotlin
package com.example.medilightv2android
|
|
|
|
import android.os.Bundle
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.compose.setContent
|
|
import androidx.activity.enableEdgeToEdge
|
|
import androidx.compose.animation.Crossfade
|
|
import androidx.compose.animation.core.tween
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.material3.Scaffold
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import app.rive.runtime.kotlin.core.Rive
|
|
import com.example.medilightv2android.services.KeychainService
|
|
import com.example.medilightv2android.services.NotificationService
|
|
import com.example.medilightv2android.ui.theme.Medilightv2androidTheme
|
|
import com.example.medilightv2android.ui.views.calibration.CalibrationView
|
|
import com.example.medilightv2android.ui.views.connection.DeviceScanView
|
|
import com.example.medilightv2android.ui.views.history.MeasurementHistoryView
|
|
import com.example.medilightv2android.ui.views.home.HomeView
|
|
import com.example.medilightv2android.ui.views.monitoring.PlacementGuideView
|
|
import com.example.medilightv2android.ui.views.monitoring.PiezoMonitoringView
|
|
import com.example.medilightv2android.ui.views.monitoring.VivamyoMonitoringView
|
|
import com.example.medilightv2android.ui.views.monitoring.UrineCameraScreen
|
|
import com.example.medilightv2android.ui.views.monitoring.VoidingDiaryView
|
|
import com.example.medilightv2android.ui.views.onboarding.OnboardingView
|
|
import com.example.medilightv2android.ui.views.personalization.PiezoPersonalizationView
|
|
import com.example.medilightv2android.ui.views.pin.PinMode
|
|
import com.example.medilightv2android.ui.views.pin.PinView
|
|
import com.example.medilightv2android.ui.views.registration.RegistrationView
|
|
import com.example.medilightv2android.ui.views.consent.ConsentView
|
|
import com.example.medilightv2android.ui.views.reminder.ReminderSettingsView
|
|
import com.example.medilightv2android.ui.views.sensorselect.SensorSelectView
|
|
|
|
class MainActivity : ComponentActivity() {
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
|
|
// Initialize services
|
|
Rive.init(this)
|
|
KeychainService.init(this)
|
|
NotificationService.getInstance(this)
|
|
|
|
enableEdgeToEdge()
|
|
setContent {
|
|
Medilightv2androidTheme {
|
|
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
|
MedilightApp(modifier = Modifier.padding(innerPadding))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
fun MedilightApp(modifier: Modifier = Modifier) {
|
|
val context = LocalContext.current
|
|
val appState = remember { AppState(context) }
|
|
|
|
Crossfade(
|
|
targetState = appState.currentScreen,
|
|
animationSpec = tween(300),
|
|
modifier = modifier,
|
|
label = "screen"
|
|
) { screen ->
|
|
when (screen) {
|
|
AppScreen.ONBOARDING -> OnboardingView(appState)
|
|
AppScreen.CONSENT -> ConsentView(appState)
|
|
AppScreen.REGISTRATION -> RegistrationView(appState)
|
|
AppScreen.HOME -> HomeView(appState)
|
|
AppScreen.SENSOR_SELECT -> SensorSelectView(appState)
|
|
AppScreen.DEVICE_SCAN -> DeviceScanView(appState)
|
|
AppScreen.NIRS_CALIBRATION -> CalibrationView(appState)
|
|
AppScreen.PIEZO_PERSONALIZATION -> PiezoPersonalizationView(appState)
|
|
AppScreen.PLACEMENT_GUIDE -> PlacementGuideView(appState)
|
|
AppScreen.PIN_SETUP -> PinView(appState, PinMode.SETUP, context)
|
|
AppScreen.PIN_ENTRY -> PinView(appState, PinMode.ENTER, context)
|
|
AppScreen.VIVAMYO_MONITORING -> VivamyoMonitoringView(appState)
|
|
AppScreen.PIEZO_MONITORING -> PiezoMonitoringView(appState)
|
|
AppScreen.MEASUREMENT_HISTORY -> MeasurementHistoryView(appState)
|
|
AppScreen.VOIDING_DIARY -> VoidingDiaryView(onBack = { appState.currentScreen = AppScreen.HOME })
|
|
AppScreen.URINE_CAMERA -> UrineCameraScreen(
|
|
onDone = { volume ->
|
|
if (volume != null && volume > 0) appState.resetLevel()
|
|
appState.currentScreen = AppScreen.PIEZO_MONITORING
|
|
},
|
|
onCancel = { appState.currentScreen = AppScreen.PIEZO_MONITORING }
|
|
)
|
|
AppScreen.REMINDER_SETTINGS -> ReminderSettingsView(
|
|
onBack = { appState.backToMonitoring() }
|
|
)
|
|
}
|
|
}
|
|
} |