commit 1f1586659b6d418cd34b3a13f4401c960bfc9e0a
parent 178b003ba0e0edabeb73548c4cacd98e9c7715bf
Author: MTRNord <MTRNord@users.noreply.github.com>
Date: Mon, 28 Jul 2025 17:42:11 +0200
Refactor the sidebar
Diffstat:
4 files changed, 201 insertions(+), 168 deletions(-)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
@@ -21,10 +21,13 @@ android {
buildTypes {
release {
isMinifyEnabled = false
+ isShrinkResources = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
+
+ signingConfig = signingConfigs.getByName("debug")
}
}
compileOptions {
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/MainActivity.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/MainActivity.kt
@@ -31,6 +31,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -45,6 +46,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
+import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
@@ -103,143 +105,34 @@ class MainActivity : ComponentActivity() {
}
)
) { backStackEntry ->
- val calendarViewModel: CalendarViewModel = viewModel()
- val selectedTab by calendarViewModel.selectedTab.collectAsState()
- val calendars by calendarViewModel.calendars.collectAsState()
- val selectedCalendars by calendarViewModel.selectedCalendars.collectAsState()
- val events by calendarViewModel.events.collectAsState()
- val isRefreshing by calendarViewModel.isRefreshing.collectAsState()
- val tabArg = backStackEntry.arguments?.getInt("tab")
- // Tab nur beim initialen Aufruf setzen, nicht bei jedem Recomposition
- val didSetTab = remember { mutableStateOf(false) }
- if (!didSetTab.value && tabArg != null) {
- calendarViewModel.setTab(tabArg)
- didSetTab.value = true
- }
- AppScaffold(
- title = stringResource(R.string.app_name),
- calendars = calendars,
- selectedCalendars = selectedCalendars,
- selectedDestination = "calendar",
- onCalendarToggle = { cal -> calendarViewModel.toggleCalendar(cal) },
- onSettingsClick = { navController.navigate(Destinations.Settings.route) },
- onAboutClick = { navController.navigate(Destinations.About.route) },
- onCalendarClick = { navController.navigate(Destinations.Calendar.route + "&tab=$selectedTab") },
- floatingActionButton = {
- FloatingActionButton(onClick = { /* Event hinzufügen (später) */ }) {
- Icon(
- Icons.Default.Add,
- contentDescription = stringResource(R.string.event_add)
- )
- }
- }
- ) { innerPadding ->
- CalendarScreen(
- selectedTab = selectedTab,
- onTabSelected = { calendarViewModel.setTab(it) },
- events = events,
- modifier = innerPadding,
- isRefreshing = isRefreshing,
- onRefresh = { calendarViewModel.updateEvents() },
- navController = navController,
- viewModel = calendarViewModel,
- startMillis = calendarViewModel.run {
- javaClass.getDeclaredField("startMillis")
- .apply { isAccessible = true }.get(this) as Long
- },
- endMillis = calendarViewModel.run {
- javaClass.getDeclaredField("endMillis")
- .apply { isAccessible = true }.get(this) as Long
- }
- )
- }
+ CalendarView(
+ backStackEntry = backStackEntry,
+ navController = navController
+ )
}
composable(Destinations.EventDetails.route) { backStackEntry ->
- val eventId = backStackEntry.arguments?.getString("eventId")
- AppScaffold(
- title = stringResource(R.string.event_details_title),
- calendars = emptyList(),
- selectedCalendars = emptyList(),
- selectedDestination = "eventDetails",
- onCalendarToggle = {},
- onSettingsClick = { navController.navigate(Destinations.Settings.route) },
- onAboutClick = { navController.navigate(Destinations.About.route) },
- onCalendarClick = { navController.navigate(Destinations.Calendar.route + "&tab=2") },
- onBackClick = {
- navController.navigate(Destinations.Calendar.route + "&tab=2") {
- popUpTo(Destinations.EventDetails.route) { inclusive = true }
- }
- }
- ) { innerPadding ->
- Column(
- modifier = innerPadding
- .fillMaxSize()
- .padding(16.dp),
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
- ) {
- Text(stringResource(R.string.event_details, eventId ?: ""))
- Spacer(modifier = Modifier.height(24.dp))
- // Weitere Event-Details hier
- }
- }
+ EventDetailsView(
+ backStackEntry = backStackEntry,
+ navController = navController
+ )
}
- composable(Destinations.Settings.route) {
- val calendarViewModel: CalendarViewModel = viewModel()
- val calendars by calendarViewModel.calendars.collectAsState()
- val selectedCalendars by calendarViewModel.selectedCalendars.collectAsState()
- AppScaffold(
- title = stringResource(R.string.settings),
- calendars = calendars,
- selectedCalendars = selectedCalendars,
- selectedDestination = "settings",
- onCalendarToggle = { cal -> calendarViewModel.toggleCalendar(cal) },
- onSettingsClick = { navController.navigate(Destinations.Settings.route) },
- onAboutClick = { navController.navigate(Destinations.About.route) },
- onCalendarClick = { navController.navigate(Destinations.Calendar.route) }
- ) { innerPadding ->
- Column(
- modifier = innerPadding
- .fillMaxSize()
- ) {
- Text(
- stringResource(R.string.settings),
- modifier = Modifier.padding(16.dp)
- )
- // Weitere Einstellungen hier
- }
- }
+ composable(Destinations.Settings.route) { backStackEntry ->
+ SettingsView(
+ navController = navController,
+ backStackEntry = backStackEntry
+ )
}
- composable(Destinations.About.route) {
- val calendarViewModel: CalendarViewModel = viewModel()
- val calendars by calendarViewModel.calendars.collectAsState()
- val selectedCalendars by calendarViewModel.selectedCalendars.collectAsState()
- AppScaffold(
- title = stringResource(R.string.about) + " Nordic Calendar",
- calendars = calendars,
- selectedCalendars = selectedCalendars,
- selectedDestination = "about",
- onCalendarToggle = { cal -> calendarViewModel.toggleCalendar(cal) },
- onSettingsClick = { navController.navigate(Destinations.Settings.route) },
- onAboutClick = { navController.navigate(Destinations.About.route) },
- onCalendarClick = { navController.navigate(Destinations.Calendar.route) }
- ) { innerPadding ->
- Column(
- modifier = innerPadding
- .fillMaxSize()
- ) {
- Text(
- stringResource(R.string.about) + " Nordic Calendar",
- modifier = Modifier.padding(16.dp)
- )
- // Weitere Infos hier
- }
- }
+ composable(Destinations.About.route) { backStackEntry ->
+ AboutView(
+ navController = navController,
+ backStackEntry = backStackEntry
+ )
}
}
}
}
}
+
}
// Pass Navigation Actions: Create a function to handle navigation and pass it to screens.
@@ -334,3 +227,128 @@ fun IntroScreen(navController: NavHostController, onFinish: (() -> Unit)? = null
}
}
}
+
+@Composable
+fun CalendarView(backStackEntry: NavBackStackEntry, navController: NavHostController) {
+ val calendarViewModel: CalendarViewModel = viewModel()
+ val selectedTab by calendarViewModel.selectedTab.collectAsState()
+ val events by calendarViewModel.events.collectAsState()
+ val isRefreshing by calendarViewModel.isRefreshing.collectAsState()
+ val tabArg = backStackEntry.arguments?.getInt("tab")
+
+ LaunchedEffect(tabArg) {
+ if (tabArg != null) {
+ calendarViewModel.setTab(tabArg)
+ }
+ }
+
+ AppScaffold(
+ title = stringResource(R.string.app_name),
+ selectedDestination = "calendar",
+ navController = navController,
+ calendarViewModel = calendarViewModel,
+ floatingActionButton = {
+ FloatingActionButton(onClick = { /* Event hinzufügen (später) */ }) {
+ Icon(
+ Icons.Default.Add,
+ contentDescription = stringResource(R.string.event_add)
+ )
+ }
+ }
+ ) { innerPadding ->
+ CalendarScreen(
+ selectedTab = selectedTab,
+ onTabSelected = { calendarViewModel.setTab(it) },
+ events = events,
+ modifier = innerPadding,
+ isRefreshing = isRefreshing,
+ onRefresh = { calendarViewModel.updateEvents() },
+ navController = navController,
+ viewModel = calendarViewModel,
+ startMillis = calendarViewModel.run {
+ javaClass.getDeclaredField("startMillis")
+ .apply { isAccessible = true }.get(this) as Long
+ },
+ endMillis = calendarViewModel.run {
+ javaClass.getDeclaredField("endMillis")
+ .apply { isAccessible = true }.get(this) as Long
+ }
+ )
+ }
+}
+
+
+@Composable
+fun EventDetailsView(
+ backStackEntry: NavBackStackEntry,
+ navController: NavHostController
+) {
+ val eventId = backStackEntry.arguments?.getString("eventId")
+ AppScaffold(
+ title = stringResource(R.string.event_details_title),
+ selectedDestination = "eventDetails",
+ navController = navController,
+ ) { innerPadding ->
+ Column(
+ modifier = innerPadding
+ .fillMaxSize()
+ .padding(16.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(stringResource(R.string.event_details, eventId ?: ""))
+ Spacer(modifier = Modifier.height(24.dp))
+ // Weitere Event-Details hier
+ }
+ }
+}
+
+@Composable
+fun SettingsView(navController: NavHostController, backStackEntry: NavBackStackEntry) {
+ val parentEntry = remember(backStackEntry) {
+ navController.getBackStackEntry(Destinations.Calendar.route)
+ }
+ val calendarViewModel: CalendarViewModel = viewModel(parentEntry)
+ AppScaffold(
+ title = stringResource(R.string.settings),
+ selectedDestination = "settings",
+ navController = navController,
+ calendarViewModel
+ ) { innerPadding ->
+ Column(
+ modifier = innerPadding
+ .fillMaxSize()
+ ) {
+ Text(
+ stringResource(R.string.settings),
+ modifier = Modifier.padding(16.dp)
+ )
+ // Weitere Einstellungen hier
+ }
+ }
+}
+
+@Composable
+fun AboutView(navController: NavHostController, backStackEntry: NavBackStackEntry) {
+ val parentEntry = remember(backStackEntry) {
+ navController.getBackStackEntry(Destinations.Calendar.route)
+ }
+ val calendarViewModel: CalendarViewModel = viewModel(parentEntry)
+ AppScaffold(
+ title = stringResource(R.string.about) + " Nordic Calendar",
+ selectedDestination = "about",
+ navController = navController,
+ calendarViewModel
+ ) { innerPadding ->
+ Column(
+ modifier = innerPadding
+ .fillMaxSize()
+ ) {
+ Text(
+ stringResource(R.string.about) + " Nordic Calendar",
+ modifier = Modifier.padding(16.dp)
+ )
+ // Weitere Infos hier
+ }
+ }
+}
+\ No newline at end of file
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt
@@ -17,23 +17,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.navigation.NavController
import kotlinx.coroutines.launch
import space.midnightthoughts.nordiccalendar.R
-import space.midnightthoughts.nordiccalendar.util.Calendar
+import space.midnightthoughts.nordiccalendar.viewmodels.CalendarViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppScaffold(
title: String? = null,
- calendars: List<Calendar>,
- selectedCalendars: List<Calendar>,
selectedDestination: String,
- onCalendarToggle: (Calendar) -> Unit,
- onSettingsClick: () -> Unit,
- onAboutClick: () -> Unit,
- onCalendarClick: () -> Unit,
+ navController: NavController,
+ calendarViewModel: CalendarViewModel? = null,
floatingActionButton: (@Composable () -> Unit)? = null,
- onBackClick: (() -> Unit)? = null,
content: @Composable (Modifier) -> Unit
) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
@@ -42,22 +38,9 @@ fun AppScaffold(
drawerState = drawerState,
drawerContent = {
SidebarDrawer(
- calendars = calendars,
- selectedCalendars = selectedCalendars,
- onCalendarToggle = onCalendarToggle,
- onSettingsClick = {
- scope.launch { drawerState.close() }
- onSettingsClick()
- },
- onAboutClick = {
- scope.launch { drawerState.close() }
- onAboutClick()
- },
- onCalendarClick = {
- scope.launch { drawerState.close() }
- onCalendarClick()
- },
- selectedDestination = selectedDestination
+ selectedDestination = selectedDestination,
+ calendarViewModel = calendarViewModel,
+ navController = navController,
)
}
) {
@@ -66,8 +49,11 @@ fun AppScaffold(
TopAppBar(
title = { title ?: Text(stringResource(R.string.app_name)) },
navigationIcon = {
- if (onBackClick != null) {
- IconButton(onClick = onBackClick) {
+ if (navController.previousBackStackEntry != null) {
+ IconButton(onClick = {
+ scope.launch { drawerState.close() }
+ navController.navigateUp()
+ }) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back)
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt
@@ -1,5 +1,6 @@
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
@@ -16,22 +17,32 @@ import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
+import kotlinx.coroutines.launch
+import space.midnightthoughts.nordiccalendar.Destinations
import space.midnightthoughts.nordiccalendar.R
-import space.midnightthoughts.nordiccalendar.util.Calendar
+import space.midnightthoughts.nordiccalendar.viewmodels.CalendarViewModel
@Composable
fun SidebarDrawer(
- calendars: List<Calendar>,
- selectedCalendars: List<Calendar>,
- onCalendarToggle: (Calendar) -> Unit,
- onSettingsClick: () -> Unit,
- onAboutClick: () -> Unit,
- onCalendarClick: () -> Unit,
+ calendarViewModel: CalendarViewModel?,
+ navController: NavController,
selectedDestination: String
) {
+ val selectedCalendars = calendarViewModel?.selectedCalendars?.collectAsState()
+ val calendars = calendarViewModel?.calendars?.collectAsState()
+ Log.d(
+ "SidebarDrawer",
+ "Selected Calendars: ${selectedCalendars?.value}, Calendars: ${calendars?.value}"
+ )
+
+ val scope = rememberCoroutineScope()
+
ModalDrawerSheet {
Column(
modifier = Modifier
@@ -41,21 +52,27 @@ fun SidebarDrawer(
NavigationDrawerItem(
label = { Text(stringResource(R.string.calendar)) },
selected = selectedDestination == "calendar",
- onClick = onCalendarClick,
+ onClick = {
+ navController.navigate(Destinations.Calendar.route)
+ },
modifier = Modifier.fillMaxWidth(),
colors = NavigationDrawerItemDefaults.colors()
)
NavigationDrawerItem(
label = { Text(stringResource(R.string.settings)) },
selected = selectedDestination == "settings",
- onClick = onSettingsClick,
+ onClick = {
+ navController.navigate(Destinations.Settings.route)
+ },
modifier = Modifier.fillMaxWidth(),
colors = NavigationDrawerItemDefaults.colors()
)
NavigationDrawerItem(
label = { Text(stringResource(R.string.about)) },
selected = selectedDestination == "about",
- onClick = onAboutClick,
+ onClick = {
+ navController.navigate(Destinations.About.route)
+ },
modifier = Modifier.fillMaxWidth(),
colors = NavigationDrawerItemDefaults.colors()
)
@@ -64,18 +81,26 @@ fun SidebarDrawer(
Spacer(Modifier.height(8.dp))
Text(
stringResource(R.string.calendar_selection),
- style = MaterialTheme.typography.titleMedium
+ 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.forEach { calendar ->
+ calendars?.value?.forEach { calendar ->
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
Checkbox(
- checked = selectedCalendars.contains(calendar),
- onCheckedChange = { onCalendarToggle(calendar) }
+ checked = selectedCalendars?.value?.contains(calendar) == true,
+ onCheckedChange = {
+ scope.launch {
+ calendarViewModel.toggleCalendar(calendar)
+ }
+ }
)
Text(calendar.name, modifier = Modifier.padding(start = 8.dp))
}
}
+
+
}
}
}