nordiccalendar

A simple Material 3 native calendar app fitting my personal requirements
git clone git://archive.git.mtrnord.blog/MTRNord/nordiccalendar.git
Log | Files | Refs | README | LICENSE

commit 63e6fbad8de2b80cdbb7a029cad4f1dea050962e
parent 94ad0a56e7efd8cf013c8f184821364c77997476
Author: MTRNord <MTRNord@users.noreply.github.com>
Date:   Tue, 29 Jul 2025 21:52:42 +0200

Fix some oddness with the sidebar in the event details

Diffstat:
Mapp/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt | 133++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mapp/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt | 36+++++++++++++++++++-----------------
Mapp/src/main/java/space/midnightthoughts/nordiccalendar/screens/EventDetailsView.kt | 29+++++++++++++++++++----------
3 files changed, 122 insertions(+), 76 deletions(-)

diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt @@ -28,6 +28,60 @@ import space.midnightthoughts.nordiccalendar.R @OptIn(ExperimentalMaterial3Api::class) @Composable +private fun AppScaffoldContent( + title: String?, + isBackButtonVisible: Boolean, + navController: NavController, + onBackClick: (() -> Unit)? = null, + floatingActionButton: (@Composable () -> Unit)? = null, + content: @Composable (Modifier) -> Unit, + onMenuClick: (() -> Unit)? = null +) { + Scaffold( + topBar = { + TopAppBar( + title = { + if (title == null) { + Text(stringResource(R.string.app_name)) + } else { + Text(title) + } + }, + navigationIcon = { + if (isBackButtonVisible) { + IconButton( + onClick = { + onBackClick?.invoke() ?: navController.popBackStack() + }, + modifier = Modifier.size(48.dp) + ) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(R.string.back) + ) + } + } else if (onMenuClick != null) { + IconButton( + onClick = { onMenuClick() }, + modifier = Modifier.size(48.dp) + ) { + Icon( + Icons.Default.Menu, + contentDescription = stringResource(R.string.menu) + ) + } + } + } + ) + }, + floatingActionButton = floatingActionButton ?: { }, + ) { innerPadding -> + content(Modifier.padding(innerPadding)) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable fun AppScaffold( title: String? = null, selectedDestination: String, @@ -45,57 +99,38 @@ fun AppScaffold( } } - ModalNavigationDrawer( - drawerState = drawerState, - drawerContent = { - SidebarDrawer( - selectedDestination = selectedDestination, + if (isDrawerDestination) { + ModalNavigationDrawer( + drawerState = drawerState, + drawerContent = { + SidebarDrawer( + selectedDestination = selectedDestination, + navController = navController, + drawerState = drawerState, + ) + } + ) { + AppScaffoldContent( + title = title, + isBackButtonVisible = isBackButtonVisible, navController = navController, - drawerState = drawerState, + onBackClick = { + scope.launch { drawerState.close() } + onBackClick?.invoke() ?: navController.popBackStack() + }, + floatingActionButton = floatingActionButton, + content = content, + onMenuClick = { scope.launch { drawerState.open() } } ) } - ) { - Scaffold( - topBar = { - TopAppBar( - title = { - if (title == null) { - Text(stringResource(R.string.app_name)) - } else { - Text(title) - } - }, - navigationIcon = { - if (isBackButtonVisible) { - IconButton( - onClick = { - scope.launch { drawerState.close() } - onBackClick?.invoke() ?: navController.popBackStack() - }, - modifier = Modifier.size(48.dp) - ) { - Icon( - Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = stringResource(R.string.back) - ) - } - } else { - IconButton( - onClick = { scope.launch { drawerState.open() } }, - modifier = Modifier.size(48.dp) - ) { - Icon( - Icons.Default.Menu, - contentDescription = stringResource(R.string.menu) - ) - } - } - } - ) - }, - floatingActionButton = floatingActionButton ?: { }, - ) { innerPadding -> - content(Modifier.padding(innerPadding)) - } + } else { + AppScaffoldContent( + title = title, + isBackButtonVisible = true, + navController = navController, + onBackClick = onBackClick, + floatingActionButton = floatingActionButton, + content = content + ) } } diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt @@ -3,13 +3,10 @@ package space.midnightthoughts.nordiccalendar.components import android.util.Log import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Checkbox -import androidx.compose.material3.DividerDefaults import androidx.compose.material3.DrawerState import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme @@ -128,27 +125,32 @@ fun SidebarDrawer( modifier = Modifier.fillMaxWidth(), colors = NavigationDrawerItemDefaults.colors() ) - Spacer(Modifier.height(16.dp)) - HorizontalDivider(Modifier, DividerDefaults.Thickness, DividerDefaults.color) - Spacer(Modifier.height(8.dp)) + HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) Text( stringResource(R.string.calendar_selection), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(start = 8.dp, bottom = 8.dp, end = 8.dp, top = 8.dp) ) - Spacer(Modifier.height(8.dp)) - calendars.value.forEach { calendar -> - Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) { - Checkbox( - checked = selectedCalendars.value.contains(calendar), - onCheckedChange = { - scope.launch { - viewModel.toggleCalendar(calendar) + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 8.dp, vertical = 4.dp), + verticalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(4.dp) + ) { + + calendars.value.forEach { calendar -> + Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) { + Checkbox( + checked = selectedCalendars.value.contains(calendar), + onCheckedChange = { + scope.launch { + viewModel.toggleCalendar(calendar) + } } - } - ) - Text(calendar.name, modifier = Modifier.padding(start = 8.dp)) + ) + Text(calendar.name, modifier = Modifier.padding(start = 8.dp)) + } } } } diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/screens/EventDetailsView.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/screens/EventDetailsView.kt @@ -37,6 +37,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -147,11 +149,9 @@ fun EventDetailsView( BackHandler { handleBack() } AppScaffold( - title = event.value?.title - ?: stringResource( - R.string.event_details, - backStackEntry.arguments?.getString("eventId") ?: "" - ), + title = stringResource( + R.string.event_details_title, + ), selectedDestination = "eventDetails", navController = navController, onBackClick = handleBack // <-- Back-Logik an AppScaffold übergeben @@ -160,13 +160,22 @@ fun EventDetailsView( Column( modifier = Modifier .verticalScroll(scrollState) - .padding(16.dp) + .padding(bottom = 16.dp, start = 16.dp, end = 16.dp, top = 0.dp) .fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), ) { if (event.value != null) { + Text( + text = event.value?.title ?: "", + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onSurface, + fontWeight = FontWeight.Bold, + modifier = Modifier.semantics { + heading() + } + ) Column( - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(4.dp) ) { Text( // Check if the event is starting and ending on the same day or not @@ -189,7 +198,7 @@ fun EventDetailsView( .format(dateFormat) ) }, - style = MaterialTheme.typography.bodyLarge, + style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.primary, ) Text( @@ -201,7 +210,7 @@ fun EventDetailsView( endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalTime() .format(timeFormat) ), - style = MaterialTheme.typography.bodyMedium, + style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.primary, ) // Duration of the event @@ -210,7 +219,7 @@ fun EventDetailsView( R.string.event_duration, duration, ), - style = MaterialTheme.typography.bodyMedium, + style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.primary, ) }