// SPDX-License-Identifier: GPL-3.0-or-later // MyIce Kotlin Multiplatform — schedule/convocation viewer // Copyright (C) 2026 parano.ch // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package ch.parano.myicek 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.setValue import ch.parano.myicek.auth.AuthSettings import ch.parano.myicek.auth.OAuthClient import ch.parano.myicek.cache.ScheduleCache import ch.parano.myicek.network.ApiService import ch.parano.myicek.network.createHttpClient import ch.parano.myicek.ui.screens.EventDetailScreen import ch.parano.myicek.ui.screens.LoginScreen import ch.parano.myicek.ui.screens.ScheduleScreen import ch.parano.myicek.ui.theme.MyIceTheme import ch.parano.myicek.viewmodel.AuthState import ch.parano.myicek.viewmodel.AuthViewModel import ch.parano.myicek.viewmodel.EventDetailViewModel import ch.parano.myicek.viewmodel.ScheduleViewModel import com.russhwolf.settings.Settings sealed class Screen { data object Login : Screen() data object Schedule : Screen() data class EventDetail( val gameId: String, val account: String, val eventTitle: String, val eventStart: String, val eventEnd: String, ) : Screen() } @Composable fun App( oauthClient: OAuthClient, ) { val apiService = remember { ApiService(createHttpClient()) } val authSettings = remember { AuthSettings(Settings()) } val cache = remember { ScheduleCache(Settings()) } val authViewModel = remember { AuthViewModel(apiService, authSettings, oauthClient) } val scheduleViewModel = remember { ScheduleViewModel(apiService, cache, authSettings) } val eventDetailViewModel = remember { EventDetailViewModel(apiService) } var currentScreen by remember { mutableStateOf(Screen.Login) } LaunchedEffect(Unit) { authViewModel.init() } val authState by authViewModel.state.collectAsState() LaunchedEffect(authState) { currentScreen = when (authState) { is AuthState.Authenticated -> Screen.Schedule is AuthState.Unauthenticated -> Screen.Login AuthState.Loading -> currentScreen } if (authState is AuthState.Authenticated) { scheduleViewModel.loadAccounts() } } MyIceTheme { when (val screen = currentScreen) { Screen.Login -> LoginScreen(viewModel = authViewModel) Screen.Schedule -> ScheduleScreen( scheduleViewModel = scheduleViewModel, authViewModel = authViewModel, onEventClick = { gameId, account, eventTitle, eventStart, eventEnd -> currentScreen = Screen.EventDetail(gameId, account, eventTitle, eventStart, eventEnd) }, ) is Screen.EventDetail -> EventDetailScreen( gameId = screen.gameId, account = screen.account, eventTitle = screen.eventTitle, eventStart = screen.eventStart, eventEnd = screen.eventEnd, viewModel = eventDetailViewModel, onBack = { currentScreen = Screen.Schedule }, ) } } }