commit af6e3d3c33e4000bc31fa353cb7e9c642f1b3295
parent 1f1586659b6d418cd34b3a13f4401c960bfc9e0a
Author: MTRNord <MTRNord@users.noreply.github.com>
Date: Mon, 28 Jul 2025 18:02:38 +0200
Refactor the calendar data slightly
Diffstat:
5 files changed, 70 insertions(+), 31 deletions(-)
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/MainActivity.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/MainActivity.kt
@@ -33,7 +33,6 @@ 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
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -231,9 +230,15 @@ 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 selectedTab = remember(calendarViewModel) {
+ calendarViewModel.selectedTab
+ }.collectAsState(initial = 0)
+ val events = remember(calendarViewModel) {
+ calendarViewModel.events
+ }.collectAsState(initial = emptyList())
+ val isRefreshing = remember(calendarViewModel) {
+ calendarViewModel.isRefreshing
+ }.collectAsState(initial = false)
val tabArg = backStackEntry.arguments?.getInt("tab")
LaunchedEffect(tabArg) {
@@ -257,11 +262,11 @@ fun CalendarView(backStackEntry: NavBackStackEntry, navController: NavHostContro
}
) { innerPadding ->
CalendarScreen(
- selectedTab = selectedTab,
+ selectedTab = selectedTab.value,
onTabSelected = { calendarViewModel.setTab(it) },
- events = events,
+ events = events.value,
modifier = innerPadding,
- isRefreshing = isRefreshing,
+ isRefreshing = isRefreshing.value,
onRefresh = { calendarViewModel.updateEvents() },
navController = navController,
viewModel = calendarViewModel,
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/AppScaffold.kt
@@ -14,6 +14,9 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@@ -34,6 +37,12 @@ fun AppScaffold(
) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
+ val isBackButtonVisible by remember {
+ derivedStateOf {
+ navController.previousBackStackEntry != null
+ }
+ }
+
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
@@ -41,6 +50,7 @@ fun AppScaffold(
selectedDestination = selectedDestination,
calendarViewModel = calendarViewModel,
navController = navController,
+ drawerState = drawerState,
)
}
) {
@@ -49,10 +59,10 @@ fun AppScaffold(
TopAppBar(
title = { title ?: Text(stringResource(R.string.app_name)) },
navigationIcon = {
- if (navController.previousBackStackEntry != null) {
+ if (isBackButtonVisible) {
IconButton(onClick = {
scope.launch { drawerState.close() }
- navController.navigateUp()
+ navController.popBackStack()
}) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/components/SidebarDrawer.kt
@@ -10,6 +10,7 @@ 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
import androidx.compose.material3.ModalDrawerSheet
@@ -18,6 +19,8 @@ import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@@ -32,13 +35,20 @@ import space.midnightthoughts.nordiccalendar.viewmodels.CalendarViewModel
fun SidebarDrawer(
calendarViewModel: CalendarViewModel?,
navController: NavController,
- selectedDestination: String
+ selectedDestination: String,
+ drawerState: DrawerState
) {
- val selectedCalendars = calendarViewModel?.selectedCalendars?.collectAsState()
- val calendars = calendarViewModel?.calendars?.collectAsState()
+ val calendars = remember(calendarViewModel) {
+ calendarViewModel?.calendars
+ }?.collectAsState(initial = emptyList())
+ val selectedCalendars = remember(calendars) {
+ derivedStateOf {
+ calendars?.value?.filter { it.selected }
+ }
+ }
Log.d(
"SidebarDrawer",
- "Selected Calendars: ${selectedCalendars?.value}, Calendars: ${calendars?.value}"
+ "Selected Calendars: ${selectedCalendars.value}, Calendars: ${calendars?.value}"
)
val scope = rememberCoroutineScope()
@@ -53,6 +63,9 @@ fun SidebarDrawer(
label = { Text(stringResource(R.string.calendar)) },
selected = selectedDestination == "calendar",
onClick = {
+ scope.launch {
+ drawerState.close()
+ }
navController.navigate(Destinations.Calendar.route)
},
modifier = Modifier.fillMaxWidth(),
@@ -62,6 +75,9 @@ fun SidebarDrawer(
label = { Text(stringResource(R.string.settings)) },
selected = selectedDestination == "settings",
onClick = {
+ scope.launch {
+ drawerState.close()
+ }
navController.navigate(Destinations.Settings.route)
},
modifier = Modifier.fillMaxWidth(),
@@ -71,6 +87,9 @@ fun SidebarDrawer(
label = { Text(stringResource(R.string.about)) },
selected = selectedDestination == "about",
onClick = {
+ scope.launch {
+ drawerState.close()
+ }
navController.navigate(Destinations.About.route)
},
modifier = Modifier.fillMaxWidth(),
@@ -89,10 +108,10 @@ fun SidebarDrawer(
calendars?.value?.forEach { calendar ->
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
Checkbox(
- checked = selectedCalendars?.value?.contains(calendar) == true,
+ checked = selectedCalendars.value?.contains(calendar) == true,
onCheckedChange = {
scope.launch {
- calendarViewModel.toggleCalendar(calendar)
+ calendarViewModel?.toggleCalendar(calendar)
}
}
)
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/util/CalendarData.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/util/CalendarData.kt
@@ -13,7 +13,9 @@ data class Calendar(
val accountName: String,
val accountType: String,
val syncEvents: Boolean,
- val visible: Boolean
+ val visible: Boolean,
+ // TODO: Store this somewhere so it is kept across app restarts
+ val selected: Boolean = true
)
data class Event(
diff --git a/app/src/main/java/space/midnightthoughts/nordiccalendar/viewmodels/CalendarViewModel.kt b/app/src/main/java/space/midnightthoughts/nordiccalendar/viewmodels/CalendarViewModel.kt
@@ -21,9 +21,6 @@ class CalendarViewModel(app: Application) : AndroidViewModel(app) {
private val _calendars = MutableStateFlow<List<Calendar>>(emptyList())
val calendars: StateFlow<List<Calendar>> = _calendars.asStateFlow()
- private val _selectedCalendars = MutableStateFlow<List<Calendar>>(emptyList())
- val selectedCalendars: StateFlow<List<Calendar>> = _selectedCalendars.asStateFlow()
-
private val _events = MutableStateFlow<List<Event>>(emptyList())
val events: StateFlow<List<Event>> = _events.asStateFlow()
@@ -42,20 +39,23 @@ class CalendarViewModel(app: Application) : AndroidViewModel(app) {
viewModelScope.launch {
val allCalendars = calendarData.getCalendars(contentResolver)
_calendars.value = allCalendars
- _selectedCalendars.value = allCalendars.filter { it.visible }
updateEvents()
isRefreshing.value = false
}
}
fun toggleCalendar(calendar: Calendar) {
- val current = _selectedCalendars.value.toMutableList()
- if (current.contains(calendar)) {
- current.remove(calendar)
- } else {
- current.add(calendar)
+ // TODO: Store this somewhere so it is kept across app restarts
+ Log.d("CalendarViewModel", "Toggling calendar: ${calendar.name}, ID: ${calendar.id}")
+
+ val updatedCalendars = _calendars.value.map {
+ if (it.id == calendar.id) {
+ it.copy(selected = !it.selected)
+ } else {
+ it
+ }
}
- _selectedCalendars.value = current
+ _calendars.value = updatedCalendars
updateEvents()
}
@@ -137,10 +137,12 @@ class CalendarViewModel(app: Application) : AndroidViewModel(app) {
endMillis = getDefaultEndMillis(tab)
Log.d(
"CalendarViewModel",
- "Updating events for selected calendars: ${_selectedCalendars.value.map { it.name }}"
+ "Updating events for selected calendars: ${
+ _calendars.value.filter { it.selected }.map { it.name }
+ }"
)
viewModelScope.launch {
- val selectedIds = _selectedCalendars.value.map { it.id }
+ val selectedIds = _calendars.value.filter { it.selected }.map { it.id }
Log.d("CalendarViewModel", "Selected calendar IDs: $selectedIds")
_events.value = calendarData.getEventsForCalendars(
contentResolver,
@@ -238,13 +240,14 @@ class CalendarViewModel(app: Application) : AndroidViewModel(app) {
private fun updateEventsCustom() {
isRefreshing.value = true
- val tab = _selectedTab.value
Log.d(
"CalendarViewModel",
- "Updating events for selected calendars: ${_selectedCalendars.value.map { it.name }}"
+ "Updating events for selected calendars: ${
+ _calendars.value.filter { it.selected }.map { it.name }
+ }"
)
viewModelScope.launch {
- val selectedIds = _selectedCalendars.value.map { it.id }
+ val selectedIds = _calendars.value.filter { it.selected }.map { it.id }
Log.d("CalendarViewModel", "Selected calendar IDs: $selectedIds")
_events.value = calendarData.getEventsForCalendars(
contentResolver,