Home Page
The HomeScreen.kt file defines the main screen displayed after a successful login. It provides a quick overview of the patient's recent activity, including:
- the latest test (date and time),
- the total number of tests completed,
- recent questionnaire and configuration updates.
This screen also features:
- a custom top bar with the app logo, the
"Home"title, and a profile icon that links to the profile page, - action buttons to start a new test or fill out the latest questionnaire (conditionally enabled),
- a bottom navigation bar to switch between all main screens of the app.
1 - Data loading and state preparation
Upon composition, the screen loads the most recent files and metadata from internal storage and SharedPreferences, including:
- the most recent video file,
- the most recent questionnaire file,
- the latest configuration file,
- the stored dates of last modifications (config and survey),
- the
questionnaireFilledstate to determine if the survey can be retaken.
@Composable
fun HomePage(navController: NavHostController, patient: List<Patient>) {
val context = LocalContext.current
val videoDir = File(context.getExternalFilesDir(null), "EpilepsyTests/Videos")
val questionnaireDir = File(context.getExternalFilesDir(null), "EpilepsyTests/Questionnaires")
val configDir = context.filesDir
val latestVideo = videoDir.listFiles()?.maxByOrNull { it.lastModified() }
val totalTests = videoDir.listFiles { _, name ->
name.startsWith("Vidéo_") && name.endsWith(".mp4")
}?.size ?: 0
val lastQuestionnaire = questionnaireDir.listFiles()?.maxByOrNull { it.lastModified() }
val lastConfig = configDir.listFiles { _, name ->
name.startsWith("configuration_") && name.endsWith(".json")
}?.maxByOrNull { it.lastModified() }
val configDate = remember {
val prefs = context.getSharedPreferences("AppPrefsConfig", Context.MODE_PRIVATE)
val timestamp = prefs.getLong("lastConfigModification", -1L)
if (timestamp != -1L)
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(Date(timestamp))
else "N/A"
}
val lastSurveyModDate = remember {
val prefs = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
val timestamp = prefs.getLong("lastSurveyModification", -1L)
if (timestamp != -1L)
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(Date(timestamp))
else "N/A"
}
val videoDate = latestVideo?.let {
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(Date(it.lastModified()))
} ?: "N/A"
val videoTime = latestVideo?.let {
SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(it.lastModified()))
} ?: "N/A"
val questionnaireDate = lastQuestionnaire?.let {
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(Date(it.lastModified()))
} ?: "N/A"
val isQuestionnaireFilled = remember {
context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
.getBoolean("questionnaireFilled", true)
}
...
2 - UI Structure and Layout
The UI is built using Box, Column, and themed Text elements for consistency. Cards display key data, and buttons enable user actions.
Top App Bar
A colored bar displays:
- the logo,
- the
"Home"title, - a user icon leading to the profile screen.
Summary Cards
Three cards provide a snapshot of:
- Latest test (with date and time),
- Total number of tests recorded,
- Questionnaire and configuration details.
Actions
Two action buttons:
"Commencer un test"navigates to the test screen,"Remplir questionnaire"is enabled only if the survey hasn't been completed.
Code extract: UI composition
AppTheme {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.border(4.dp, Color(0xFF2B4765), RoundedCornerShape(1.dp))
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 70.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Top bar with logo, title and profile
...
// Summary cards
...
// Action buttons
...
}
// Bottom navigation bar
NavigationBar(
navController = navController,
modifier = Modifier.align(Alignment.BottomCenter)
)
}
}
3 - Navigation Bar
At the bottom of the screen, a persistent navigation bar allows quick access to:
HomeScreen.kt(current),DemoScreen.kt,FilesPage.kt,SettingsPage.kt.
@Composable
fun NavigationBar(navController: NavHostController, modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.height(70.dp)
.background(Color(0xFF2B4765)),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { navController.navigate("home") }) {
Image(
painter = painterResource(id = R.mipmap.ic_home_foreground),
contentDescription = "Home",
modifier = Modifier.fillMaxHeight().aspectRatio(1f)
)
}
IconButton(onClick = { navController.navigate("demo/0") }) {
Image(
painter = painterResource(id = R.mipmap.ic_demo_foreground),
contentDescription = "Demo",
modifier = Modifier.fillMaxHeight().aspectRatio(1f)
)
}
IconButton(onClick = { navController.navigate("files") }) {
Image(
painter = painterResource(id = R.mipmap.ic_files_foreground),
contentDescription = "Files",
modifier = Modifier.fillMaxHeight().aspectRatio(1f)
)
}
IconButton(onClick = { navController.navigate("settings") }) {
Image(
painter = painterResource(id = R.mipmap.ic_settings_foreground),
contentDescription = "Settings",
modifier = Modifier.fillMaxHeight().aspectRatio(1f)
)
}
}
}
Summary
The HomeScreen.kt centralizes essential patient information and gives quick access to all app functionalities. It balances a clean UI layout with dynamic content loaded from local files and preferences, ensuring that the app always displays the latest patient data.