From d5806d22ebcdea9dad86fe16053c55de45fed521 Mon Sep 17 00:00:00 2001 From: Ash Svitan Date: Fri, 17 Apr 2026 12:13:20 +0200 Subject: [PATCH] :hammer: Refactors API and saving prefs and adds data holders --- .../src/main/java/dev/svitan/antifed/API.kt | 61 ++++++++++- .../java/dev/svitan/antifed/AuthActivity.kt | 100 +++++++++++------- frontend/app/src/main/res/values/strings.xml | 2 +- 3 files changed, 122 insertions(+), 41 deletions(-) diff --git a/frontend/app/src/main/java/dev/svitan/antifed/API.kt b/frontend/app/src/main/java/dev/svitan/antifed/API.kt index 08f782c..1e4b47c 100644 --- a/frontend/app/src/main/java/dev/svitan/antifed/API.kt +++ b/frontend/app/src/main/java/dev/svitan/antifed/API.kt @@ -1,14 +1,55 @@ package dev.svitan.antifed import io.ktor.client.HttpClient +import io.ktor.client.call.body import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.engine.cio.CIO +import io.ktor.client.request.get +import io.ktor.client.request.headers +import io.ktor.http.HttpStatusCode import io.ktor.serialization.kotlinx.json.json import kotlinx.serialization.Serializable -val client = HttpClient(CIO) { - install(ContentNegotiation) { - json() +class API { + companion object { + val client = HttpClient(CIO) { + install(ContentNegotiation) { + json() + } + } + + suspend fun loadAuths() { + val apiDataHolder = APIDataHolder.getInstance() + val authDataHolder = AuthDataHolder.getInstance() + + val response = client.get("${apiDataHolder.serverUrl}/auth") { + headers { + append("Authorization", "Bearer ${apiDataHolder.token}") + } + } + + if (response.status == HttpStatusCode.OK) { + authDataHolder.auths = response.body>() + authDataHolder.authIndex = + authDataHolder.auths.indexOfFirst { it.id == authDataHolder.authId } + } else { + throw Exception("Error loading auths") + } + } + } +} + +class APIDataHolder { + var serverUrl: String = "" + var token: String = "" + var isOk: Boolean = false + + companion object { + private var holder: APIDataHolder = APIDataHolder() + + fun getInstance(): APIDataHolder { + return holder + } } } @@ -18,3 +59,17 @@ data class AuthDTO( val name: String, val createdAt: String ) + +class AuthDataHolder { + var auths: List = listOf() + var authId: String = "" + var authIndex: Int = -1 + + companion object { + private var holder: AuthDataHolder = AuthDataHolder() + + fun getInstance(): AuthDataHolder { + return holder + } + } +} diff --git a/frontend/app/src/main/java/dev/svitan/antifed/AuthActivity.kt b/frontend/app/src/main/java/dev/svitan/antifed/AuthActivity.kt index 83d183d..22dd282 100644 --- a/frontend/app/src/main/java/dev/svitan/antifed/AuthActivity.kt +++ b/frontend/app/src/main/java/dev/svitan/antifed/AuthActivity.kt @@ -23,10 +23,12 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -44,9 +46,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.content.edit import dev.svitan.antifed.ui.theme.AntiFedTheme -import io.ktor.client.call.body import io.ktor.client.request.get -import io.ktor.client.request.headers import io.ktor.http.HttpStatusCode import kotlinx.coroutines.delay @@ -61,10 +61,12 @@ class AuthActivity : ComponentActivity() { var serverUrl by remember { mutableStateOf("") } var token by remember { mutableStateOf("") } var showToken by remember { mutableStateOf(false) } + val apiDataHolder = APIDataHolder.getInstance() var authId by remember { mutableStateOf("") } var authIndex by remember { mutableIntStateOf(-1) } var auths by remember { mutableStateOf>(emptyList()) } + val authDataHolder = AuthDataHolder.getInstance() var needToCheckUrl by remember { mutableStateOf(false) } var checkingUrl by remember { mutableStateOf(false) } @@ -82,7 +84,7 @@ class AuthActivity : ComponentActivity() { LaunchedEffect(Unit) { serverUrl = prefs.getString(getString(R.string.server_url_key), "") ?: "" token = prefs.getString(getString(R.string.token_key), "") ?: "" - authId = prefs.getString(getString(R.string.auth_key), "") ?: "" + authId = prefs.getString(getString(R.string.auth_id_key), "") ?: "" isServerUrlOk = prefs.getBoolean(getString(R.string.server_url_okay_key), false) isTokenOk = prefs.getBoolean(getString(R.string.token_okay_key), false) } @@ -97,36 +99,25 @@ class AuthActivity : ComponentActivity() { needToCheckUrl = false isServerUrlOk = false - prefs.edit { - putBoolean(getString(R.string.server_url_okay_key), false) - } if (serverUrl.isBlank() || !serverUrlMatches()) return@LaunchedEffect delay(1000) checkingUrl = true isServerUrlOk = try { - val response = client.get(serverUrl) + val response = API.client.get(serverUrl) response.status == HttpStatusCode.OK } catch (_: Exception) { false } checkingUrl = false - prefs.edit { - putBoolean( - getString(R.string.server_url_okay_key), isServerUrlOk - ) - } } LaunchedEffect(token) { if (!needToCheckToken) return@LaunchedEffect needToCheckToken = false isTokenOk = false - prefs.edit { - putBoolean(getString(R.string.token_okay_key), false) - } if (!isServerUrlOk || token.isBlank()) return@LaunchedEffect @@ -134,32 +125,75 @@ class AuthActivity : ComponentActivity() { checkingToken = true try { - val response = client.get("$serverUrl/auth") { - headers { - append("Authorization", "Bearer $token") - } - } - - if (response.status == HttpStatusCode.OK) { - auths = response.body>() - authIndex = auths.indexOfFirst { it.id == authId } - isTokenOk = true - } + API.loadAuths() + auths = authDataHolder.auths + authIndex = authDataHolder.authIndex + isTokenOk = true } catch (e: Exception) { isTokenOk = false Log.e("AuthActivity", "Error checking token", e) } checkingToken = false + } + + // saves data to prefs and data holders + LaunchedEffect(serverUrl) { + apiDataHolder.serverUrl = serverUrl + prefs.edit { + putString( + getString(R.string.server_url_key), serverUrl + ) + } + } + + LaunchedEffect(token) { + apiDataHolder.token = token + prefs.edit { + putString( + getString(R.string.token_key), token + ) + } + } + + LaunchedEffect(isServerUrlOk) { + apiDataHolder.isOk = isServerUrlOk && isTokenOk + prefs.edit { + putBoolean( + getString(R.string.server_url_okay_key), + isServerUrlOk + ) + } + } + + LaunchedEffect(isTokenOk) { + apiDataHolder.isOk = isServerUrlOk && isTokenOk prefs.edit { putBoolean(getString(R.string.token_okay_key), isTokenOk) } } + LaunchedEffect(authId) { + authDataHolder.authId = authId + prefs.edit { + putString(getString(R.string.auth_id_key), authId) + } + } + + LaunchedEffect(auths, authIndex) { + authDataHolder.auths = auths + authDataHolder.authIndex = authIndex + } + Scaffold( topBar = { TopAppBar( - title = { Text(stringResource(R.string.auth)) }, + colors = TopAppBarDefaults.topAppBarColors( + titleContentColor = MaterialTheme.colorScheme.primary + ), + title = { + Text(stringResource(R.string.auth)) + }, navigationIcon = { IconButton(onClick = { finish() }) { Icon( @@ -172,6 +206,7 @@ class AuthActivity : ComponentActivity() { Column( modifier = Modifier .padding(padding) + .padding(bottom = 64.dp) .imePadding() .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, @@ -185,11 +220,7 @@ class AuthActivity : ComponentActivity() { onValueChange = { serverUrl = it needToCheckUrl = true - prefs.edit { - putString( - getString(R.string.server_url_key), it - ) - } + }, label = { Text(stringResource(R.string.server_url)) }, singleLine = true, @@ -209,11 +240,6 @@ class AuthActivity : ComponentActivity() { onValueChange = { token = it needToCheckToken = true - prefs.edit { - putString( - getString(R.string.token_key), it - ) - } }, label = { Text(stringResource(R.string.token)) }, singleLine = true, diff --git a/frontend/app/src/main/res/values/strings.xml b/frontend/app/src/main/res/values/strings.xml index a17cfea..8c3464c 100644 --- a/frontend/app/src/main/res/values/strings.xml +++ b/frontend/app/src/main/res/values/strings.xml @@ -10,7 +10,7 @@ server_url server_url_okay token - auth_id + auth_id Create new auth Biometrics Show token