small changes

This commit is contained in:
2026-06-24 12:17:15 +02:00
parent 6bb1772608
commit 28e2309894
12 changed files with 79 additions and 82 deletions

View File

@ -23,7 +23,8 @@ android {
buildTypes {
release {
isMinifyEnabled = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
@ -36,6 +37,7 @@ android {
}
buildFeatures {
compose = true
buildConfig = true
}
}

View File

@ -1,21 +1,15 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Gson models used for API parsing.
-keep class com.tomhempel.coordinatorapp.data.** { *; }
-keep class com.tomhempel.coordinatorapp.network.** { *; }
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# AndroidX Security crypto (EncryptedSharedPreferences / MasterKey)
-keep class androidx.security.crypto.** { *; }
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# Gson reflective serialization
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn sun.misc.**
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# Keep line numbers for crash reports.
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile

View File

@ -5,7 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"

View File

@ -0,0 +1,11 @@
package com.tomhempel.coordinatorapp.network
import android.util.Log
import com.tomhempel.coordinatorapp.BuildConfig
internal object ApiLog {
fun response(label: String, httpCode: Int, body: String?) {
if (!BuildConfig.DEBUG) return
Log.d("NAT_AS_API", "$label HTTP $httpCode (${body?.length ?: 0} bytes)")
}
}

View File

@ -176,6 +176,7 @@ object NatAsApiClient {
private inline fun <T> execute(request: Request, parse: (JsonObject) -> T): T {
client.newCall(request).execute().use { response ->
val bodyText = response.body?.string()
ApiLog.response("${request.method} ${request.url.encodedPath}", response.code, bodyText)
val root = parseEnvelope(response.code, bodyText)
val data = root.get("data")
return when {

View File

@ -1,6 +1,7 @@
package com.tomhempel.coordinatorapp.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -15,7 +16,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontWeight
@ -44,25 +44,19 @@ fun CoordinatorBrandBadge(
iconSize: Dp = 40.dp,
) {
val scheme = MaterialTheme.colorScheme
val shape = RoundedCornerShape(22.dp)
Box(
modifier = modifier
.size(size)
.clip(RoundedCornerShape(22.dp))
.background(
Brush.linearGradient(
colors = listOf(
scheme.primary,
scheme.primary.copy(alpha = 0.82f),
scheme.primaryContainer,
),
),
),
.clip(shape)
.border(1.dp, scheme.outline, shape)
.background(scheme.surface),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_coordinator_mark),
contentDescription = null,
tint = scheme.onPrimary,
tint = scheme.primary,
modifier = Modifier.size(iconSize),
)
}

View File

@ -25,7 +25,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
@ -40,15 +39,7 @@ fun CoordinatorBackground(
Box(
modifier = modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
colors = listOf(
scheme.background,
scheme.surfaceVariant,
scheme.background,
),
),
),
.background(scheme.background),
) {
content()
}

View File

@ -3,7 +3,7 @@ package com.tomhempel.coordinatorapp.ui.theme
import androidx.compose.ui.graphics.Color
val BrandPurple = Color(0xFF6E56CF)
val BrandPurpleDark = Color(0xFF9B8AE8)
val BrandPurpleDark = Color(0xFF8F84B8)
val BrandWindowBg = Color(0xFFF4F8F7)
val BrandSurface = Color(0xFFFFFFFF)
@ -13,9 +13,9 @@ val BrandStroke = Color(0xFFD5E4E0)
val BrandDestructive = Color(0xFFC62828)
val BrandAccentContainer = Color(0xFFE6F4F0)
val BrandWindowBgDark = Color(0xFF121A19)
val BrandSurfaceDark = Color(0xFF1E2A28)
val BrandTextLight = Color(0xFFE8F2F0)
val BrandTextMutedDark = Color(0xFF8AA39E)
val BrandStrokeDark = Color(0xFF2D403C)
val BrandAccentContainerDark = Color(0xFF243532)
val BrandWindowBgDark = Color(0xFF0F1413)
val BrandSurfaceDark = Color(0xFF171D1C)
val BrandTextLight = Color(0xFFE4EDEB)
val BrandTextMutedDark = Color(0xFF7F9490)
val BrandStrokeDark = Color(0xFF2B3634)
val BrandAccentContainerDark = Color(0xFF222A28)

View File

@ -30,14 +30,14 @@ private val LightColorScheme = lightColorScheme(
private val DarkColorScheme = darkColorScheme(
primary = BrandPurpleDark,
onPrimary = Color(0xFF1F163D),
onPrimary = BrandWindowBgDark,
primaryContainer = BrandAccentContainerDark,
onPrimaryContainer = BrandTextLight,
background = BrandWindowBgDark,
onBackground = BrandTextLight,
surface = BrandSurfaceDark,
onSurface = BrandTextLight,
surfaceVariant = BrandAccentContainerDark,
surfaceVariant = BrandSurfaceDark,
onSurfaceVariant = BrandTextMutedDark,
outline = BrandStrokeDark,
error = BrandDestructive,

View File

@ -45,12 +45,29 @@ class CoordinatorViewModel(application: Application) : AndroidViewModel(applicat
counselors = counselors,
)
}
} catch (_: Exception) {
} catch (e: ApiException) {
if (e.isAuthError()) {
SessionStore.clear(context)
_uiState.update { CoordinatorUiState() }
} else {
_uiState.update {
CoordinatorUiState(
errorMessage = e.message ?: "Could not verify session",
)
}
}
} catch (e: Exception) {
_uiState.update {
CoordinatorUiState(
errorMessage = e.message ?: "Could not verify session",
)
}
}
}
}
private fun ApiException.isAuthError(): Boolean =
code == "UNAUTHORIZED" || code == "FORBIDDEN" || code == "PASSWORD_CHANGE_REQUIRED"
fun login(username: String, password: String) {
val trimmedUser = username.trim()

View File

@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older than API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
<exclude domain="sharedpref" path="." />
<exclude domain="database" path="." />
<exclude domain="file" path="." />
</full-backup-content>

View File

@ -1,19 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
<exclude domain="sharedpref" path="." />
<exclude domain="database" path="." />
<exclude domain="file" path="." />
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
<exclude domain="sharedpref" path="." />
<exclude domain="database" path="." />
<exclude domain="file" path="." />
</device-transfer>
-->
</data-extraction-rules>