diff --git a/android-app/app/src/main/java/de/harheimertc/ui/navigation/Destinations.kt b/android-app/app/src/main/java/de/harheimertc/ui/navigation/Destinations.kt index 832b3b9..d752e83 100644 --- a/android-app/app/src/main/java/de/harheimertc/ui/navigation/Destinations.kt +++ b/android-app/app/src/main/java/de/harheimertc/ui/navigation/Destinations.kt @@ -10,8 +10,12 @@ sealed class Destinations(val route: String) { object Links : Destinations("verein/links") object Impressum : Destinations("impressum") object Mannschaften : Destinations("mannschaften") - object MannschaftDetail : Destinations("mannschaften/{slug}") { - fun create(slug: String): String = "mannschaften/$slug" + object MannschaftDetail : Destinations("mannschaften/{slug}?season={season}") { + fun create(slug: String, season: String? = null): String { + val encodedSlug = android.net.Uri.encode(slug) + val selectedSeason = season?.takeIf { it.isNotBlank() } ?: return "mannschaften/$encodedSlug" + return "mannschaften/$encodedSlug?season=${android.net.Uri.encode(selectedSeason)}" + } } object MannschaftLegacyDetail : Destinations("mannschaft/{slug}") { fun create(slug: String): String = "mannschaft/$slug" diff --git a/android-app/app/src/main/java/de/harheimertc/ui/navigation/NavGraph.kt b/android-app/app/src/main/java/de/harheimertc/ui/navigation/NavGraph.kt index 70868be..58a66b9 100644 --- a/android-app/app/src/main/java/de/harheimertc/ui/navigation/NavGraph.kt +++ b/android-app/app/src/main/java/de/harheimertc/ui/navigation/NavGraph.kt @@ -17,6 +17,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.navArgument import androidx.hilt.navigation.compose.hiltViewModel import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -32,7 +33,9 @@ fun NavGraph( val backStackEntry = navController.currentBackStackEntryAsState().value val route = backStackEntry?.destination?.route val currentRoute = if (route == Destinations.MannschaftDetail.route) { - backStackEntry.arguments?.getString("slug")?.let(Destinations.MannschaftDetail::create) + backStackEntry.arguments?.getString("slug")?.let { slug -> + Destinations.MannschaftDetail.create(slug, backStackEntry.arguments?.getString("season")) + } } else route val navigationState by navigationViewModel.state.collectAsState() LaunchedEffect(currentRoute) { @@ -136,9 +139,13 @@ fun NavGraph( composable("mannschaften/jugend") { de.harheimertc.ui.screens.mannschaften.MannschaftenScreen(navController, !persistentNavigation) } - composable(Destinations.MannschaftDetail.route) { entry -> + composable( + route = Destinations.MannschaftDetail.route, + arguments = listOf(navArgument("season") { nullable = true; defaultValue = null }), + ) { entry -> de.harheimertc.ui.screens.mannschaften.MannschaftDetailScreen( slug = entry.arguments?.getString("slug").orEmpty(), + season = entry.arguments?.getString("season"), navController = navController, showBackNavigation = !persistentNavigation, ) @@ -146,6 +153,7 @@ fun NavGraph( composable(Destinations.MannschaftLegacyDetail.route) { entry -> de.harheimertc.ui.screens.mannschaften.MannschaftDetailScreen( slug = entry.arguments?.getString("slug").orEmpty(), + season = null, navController = navController, showBackNavigation = !persistentNavigation, ) diff --git a/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenScreen.kt b/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenScreen.kt index ec09e90..88e95f8 100644 --- a/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenScreen.kt +++ b/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenScreen.kt @@ -85,7 +85,7 @@ fun MannschaftenScreen( state.error != null -> item { ErrorPanel(state.error.orEmpty(), viewModel::load) } state.teams.isEmpty() -> item { Text("Keine Mannschaftsdaten geladen", color = Accent500) } else -> items(state.teams) { team -> - TeamCard(team) { navController.navigate(Destinations.MannschaftDetail.create(team.slug)) } + TeamCard(team) { navController.navigate(Destinations.MannschaftDetail.create(team.slug, state.selectedSeason)) } } } item { @@ -161,13 +161,14 @@ private fun TeamCard(team: Mannschaft, onOpen: () -> Unit) { @Composable fun MannschaftDetailScreen( slug: String, + season: String?, navController: NavController, showBackNavigation: Boolean, viewModel: MannschaftDetailViewModel = hiltViewModel(), ) { val state by viewModel.state.collectAsState() - var selectedTab by rememberSaveable(slug) { mutableStateOf(DetailTab.Matches) } - LaunchedEffect(slug) { viewModel.load(slug) } + var selectedTab by rememberSaveable(slug, season) { mutableStateOf(DetailTab.Matches) } + LaunchedEffect(slug, season) { viewModel.load(slug, season) } LazyColumn( modifier = Modifier.fillMaxSize().background(Color(0xFFFAFAFA)), contentPadding = PaddingValues(horizontal = 18.dp, vertical = 22.dp), @@ -229,7 +230,7 @@ fun MannschaftDetailScreen( } } } - } ?: item { ErrorPanel(state.matchesError ?: "Mannschaft nicht gefunden.") { viewModel.load(slug) } } + } ?: item { ErrorPanel(state.matchesError ?: "Mannschaft nicht gefunden.") { viewModel.load(slug, season) } } } } } diff --git a/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenViewModel.kt b/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenViewModel.kt index 59587d8..039bbd5 100644 --- a/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenViewModel.kt +++ b/android-app/app/src/main/java/de/harheimertc/ui/screens/mannschaften/MannschaftenViewModel.kt @@ -121,35 +121,38 @@ class MannschaftDetailViewModel @Inject constructor( ) : ViewModel() { private val _state = MutableStateFlow(MannschaftDetailUiState()) val state: StateFlow = _state - private var loadedSlug: String? = null + private var loadedKey: String? = null - fun load(slug: String) { - if (loadedSlug == slug) return - loadedSlug = slug + fun load(slug: String, season: String? = null) { + val selectedSeason = season?.takeIf { it.isNotBlank() } + val key = "$slug|${selectedSeason.orEmpty()}" + if (loadedKey == key) return + loadedKey = key viewModelScope.launch { - _state.value = MannschaftDetailUiState(loading = true) - val team = mannschaftenRepository.fetchMannschaften().getOrDefault(emptyList()).find { it.slug == slug } + _state.value = MannschaftDetailUiState(loading = true, season = selectedSeason) + val team = mannschaftenRepository.fetchMannschaften(selectedSeason).getOrDefault(emptyList()).find { it.slug == slug } if (team == null) { _state.value = MannschaftDetailUiState(loading = false, matchesError = "Mannschaft nicht gefunden.") return@launch } - spielplanRepository.fetchSpielplan() + spielplanRepository.fetchSpielplan(selectedSeason) .onSuccess { plan -> _state.value = MannschaftDetailUiState( loading = false, team = team, matches = plan.data.filter { matchesTeam(it, team.mannschaft) }, - season = plan.season, + season = plan.season ?: selectedSeason, ) if (team.informationenLink.isNotBlank()) { - loadTable(team, plan.season) + loadTable(team, plan.season ?: selectedSeason) } } .onFailure { _state.value = MannschaftDetailUiState( loading = false, team = team, - matchesError = "Der aktuelle Spielplan konnte nicht geladen werden.", + season = selectedSeason, + matchesError = "Der Spielplan konnte nicht geladen werden.", ) } } diff --git a/android-app/gradle.properties b/android-app/gradle.properties index 9f2cfc4..23c1fef 100644 --- a/android-app/gradle.properties +++ b/android-app/gradle.properties @@ -8,8 +8,8 @@ LOCAL_API_BASE_URL=https://harheimertc.tsschulz.de/ PRODUCTION_API_BASE_URL=https://harheimertc.de/ # Android app versioning for Play Store uploads -ANDROID_VERSION_CODE=24 -ANDROID_VERSION_NAME=0.9.19 +ANDROID_VERSION_CODE=25 +ANDROID_VERSION_NAME=0.9.20 # Temporary hotfix: disable R8 minification for release to avoid Retrofit generic signature stripping. RELEASE_MINIFY_ENABLED=false