// 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.viewmodel import ch.parano.myicek.auth.AuthSettings import ch.parano.myicek.auth.OAuthClient import ch.parano.myicek.network.ApiConfig import ch.parano.myicek.network.ApiService import ch.parano.myicek.network.AuthTokenHolder import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch sealed class AuthState { data object Loading : AuthState() data class Authenticated(val email: String) : AuthState() data object Unauthenticated : AuthState() } class AuthViewModel( private val apiService: ApiService, private val authSettings: AuthSettings, private val oauthClient: OAuthClient, ) : ViewModel() { private val _state = MutableStateFlow(AuthState.Loading) val state: StateFlow = _state.asStateFlow() fun init() { viewModelScope.launch { val token = authSettings.getStoredToken() if (token != null) { AuthTokenHolder.token = token try { val userInfo = apiService.getUserInfo() _state.value = AuthState.Authenticated(userInfo.email) } catch (e: Exception) { authSettings.clear() _state.value = AuthState.Unauthenticated } } else { _state.value = AuthState.Unauthenticated } } } fun login() { viewModelScope.launch { _state.value = AuthState.Loading try { val loginUrl = "${ApiConfig.baseUrl}/login?redirect_uri=" + oauthClient.redirectUri() val token = oauthClient.authenticate(loginUrl) if (token != null) { authSettings.setToken(token) val userInfo = apiService.getUserInfo() _state.value = AuthState.Authenticated(userInfo.email) } else { _state.value = AuthState.Unauthenticated } } catch (e: Exception) { _state.value = AuthState.Unauthenticated } } } fun logout() { authSettings.clear() _state.value = AuthState.Unauthenticated } }