2 Commits

Author SHA1 Message Date
soraefir
757783534c Fix build, errors and spring cleaning 2026-05-23 11:35:02 +02:00
soraefir
3eba48ea7d WIP
# Conflicts:
#	build.gradle
#	gradle/wrapper/gradle-wrapper.properties
2026-05-23 10:53:36 +02:00
11 changed files with 76 additions and 86 deletions

View File

@@ -1,27 +1,25 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '2.3.21' id 'org.jetbrains.kotlin.plugin.serialization' version '2.3.21'
id 'org.jetbrains.kotlin.plugin.compose' version '2.3.21' id 'org.jetbrains.kotlin.plugin.compose' version '2.3.21'
id 'com.mikepenz.aboutlibraries.plugin' version '14.2.0' id 'com.mikepenz.aboutlibraries.plugin' version '14.2.0'
} }
android { android {
namespace 'net.helcel.beans' namespace 'net.helcel.beans'
compileSdk 36 compileSdk = 37
defaultConfig { defaultConfig {
buildConfigField("String", "APP_NAME", "\"Beans\"") buildConfigField("String", "APP_NAME", "\"Beans\"")
manifestPlaceholders["APP_NAME"] = "Beans" manifestPlaceholders["APP_NAME"] = "Beans"
applicationId 'net.helcel.beans' applicationId 'net.helcel.beans'
minSdk 28 minSdk = 28
targetSdk 36 targetSdk = 37
versionCode 4 versionCode 4
versionName "1.1a" versionName "1.1a"
} }
signingConfigs { signingConfigs {
create("release") { register("release") {
try { try {
def keystorePropertiesFile = rootProject.file("app/keystore.properties") def keystorePropertiesFile = rootProject.file("app/keystore.properties")
def keystoreProperties = new Properties() def keystoreProperties = new Properties()
@@ -36,20 +34,18 @@ android {
} }
} }
} }
buildTypes { buildTypes {
debug { debug {
debuggable true debuggable true
} }
release { release {
minifyEnabled true minifyEnabled true
shrinkResources false shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
signedRelease { signedRelease {
minifyEnabled true minifyEnabled true
shrinkResources false shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig = signingConfigs.getByName("release") signingConfig = signingConfigs.getByName("release")
} }
@@ -78,10 +74,6 @@ android {
kotlinCompilerExtensionVersion = "2.2.20" kotlinCompilerExtensionVersion = "2.2.20"
} }
kotlin {
jvmToolchain(21)
}
lint { lint {
disable 'UsingMaterialAndMaterial3Libraries' disable 'UsingMaterialAndMaterial3Libraries'
} }
@@ -91,7 +83,6 @@ aboutLibraries {
library { library {
exclusionPatterns = [~"androidx.*", ~"com.google.android.*", ~"org.jetbrains.*"] exclusionPatterns = [~"androidx.*", ~"com.google.android.*", ~"org.jetbrains.*"]
} }
excludeFields = ["generated"]
} }
dependencies { dependencies {

View File

@@ -16,7 +16,6 @@ import androidx.compose.material.Scaffold
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TopAppBar import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DateRange
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Percent import androidx.compose.material.icons.filled.Percent
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings

View File

@@ -152,11 +152,17 @@ fun SettingsMainScreen(onExit: ()->Unit = {}) {
fun SettingsScreen(navController: NavHostController = settingsNav()) { fun SettingsScreen(navController: NavHostController = settingsNav()) {
val context = LocalContext.current val context = LocalContext.current
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val keyTheme = stringResource(R.string.key_theme)
val defaultTheme = stringResource(R.string.system)
val keyProjection = stringResource(R.string.key_projection)
val keyGroup = stringResource(R.string.key_group)
val offString = stringResource(R.string.off)
var showEdit by remember { mutableStateOf(false) } var showEdit by remember { mutableStateOf(false) }
var theme by remember { mutableStateOf(prefs.getString(context.getString(R.string.key_theme), context.getString(R.string.system))!!) } var theme by remember { mutableStateOf(prefs.getString(keyTheme, defaultTheme)!!) }
var projection by remember { mutableStateOf(prefs.getString(context.getString(R.string.key_projection), "default")!!) } var projection by remember { mutableStateOf(prefs.getString(keyProjection, "default")!!) }
var groups by remember { mutableStateOf(prefs.getString(context.getString(R.string.key_group), context.getString(R.string.off))!!) } var groups by remember { mutableStateOf(prefs.getString(keyGroup,offString)!!) }
if(showEdit) if(showEdit)
EditPlaceDialog(true) { EditPlaceDialog(true) {
@@ -179,7 +185,7 @@ fun SettingsScreen(navController: NavHostController = settingsNav()) {
) )
MultiPreference(arrayOf(stringResource(R.string.system),stringResource(R.string.light),stringResource(R.string.dark)), theme) { newTheme -> MultiPreference(arrayOf(stringResource(R.string.system),stringResource(R.string.light),stringResource(R.string.dark)), theme) { newTheme ->
theme = newTheme theme = newTheme
prefs.edit { putString(context.getString(R.string.key_theme), newTheme) } prefs.edit { putString(keyTheme, newTheme) }
} }
HorizontalDivider() HorizontalDivider()
} }
@@ -192,7 +198,7 @@ fun SettingsScreen(navController: NavHostController = settingsNav()) {
) )
MultiPreference(arrayOf(stringResource(R.string.mercator), stringResource(R.string.azimuthalequidistant)), projection) { newProj -> MultiPreference(arrayOf(stringResource(R.string.mercator), stringResource(R.string.azimuthalequidistant)), projection) { newProj ->
projection = newProj projection = newProj
prefs.edit { putString(context.getString(R.string.key_projection), newProj) } prefs.edit { putString(keyProjection, newProj) }
Settings.refreshProjection() Settings.refreshProjection()
} }
HorizontalDivider() HorizontalDivider()
@@ -219,11 +225,11 @@ fun SettingsScreen(navController: NavHostController = settingsNav()) {
arrayOf(stringResource(R.string.on), stringResource(R.string.off)), arrayOf(stringResource(R.string.on), stringResource(R.string.off)),
groups groups
) { key -> ) { key ->
if (key == context.getString(R.string.off)) { if (key == offString) {
showDialog=true showDialog=true
} }
groups = key groups = key
prefs.edit { putString(context.getString(R.string.key_group), key) } prefs.edit { putString(keyGroup, key) }
} }
HorizontalDivider() HorizontalDivider()
} }
@@ -283,9 +289,13 @@ fun SettingsScreen(navController: NavHostController = settingsNav()) {
@Composable @Composable
fun RegionalScreen() { fun RegionalScreen() {
val context = LocalContext.current val context = LocalContext.current
val keyRegional = stringResource(R.string.key_regional)
val offString = stringResource(R.string.off)
val onString = stringResource(R.string.on)
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
var selected by remember { mutableStateOf(prefs.getString(context.getString(R.string.key_regional),context.getString(R.string.off))!!)} var selected by remember { mutableStateOf(prefs.getString(keyRegional, offString)!!)}
var regional by remember{ mutableStateOf(prefs.getString(context.getString(R.string.key_regional), context.getString(R.string.off))!!)} var regional by remember{ mutableStateOf(prefs.getString(keyRegional, offString)!!)}
var showDialog by remember{mutableStateOf(false)} var showDialog by remember{mutableStateOf(false)}
var showLoad by remember{mutableStateOf(false)} var showLoad by remember{mutableStateOf(false)}
@@ -305,7 +315,7 @@ fun RegionalScreen() {
regional= selected regional= selected
prefs.edit { prefs.edit {
putString( putString(
context.getString(R.string.key_regional), keyRegional,
regional regional
) )
} }
@@ -332,12 +342,12 @@ fun RegionalScreen() {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
MultiPreference(arrayOf(stringResource(R.string.on),stringResource(R.string.off)),regional) { key -> MultiPreference(arrayOf(stringResource(R.string.on),stringResource(R.string.off)),regional) { key ->
when (key) { when (key) {
context.getString(R.string.off) -> { showDialog=true offString -> { showDialog=true
selected=key selected=key
} }
context.getString(R.string.on) -> { onString -> {
regional = key regional = key
prefs.edit { putString(context.getString(R.string.key_regional), key) } prefs.edit { putString(keyRegional, key) }
showLoad=true showLoad=true
scope.launch { scope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@@ -354,7 +364,7 @@ fun RegionalScreen() {
@Composable @Composable
fun MultiPreference(list: Array<String>, selected: String, onSelected: (String) -> Unit) { fun MultiPreference(list: Array<String>, selected: String, onSelected: (String) -> Unit) {
Column(Modifier.padding(2.dp)) { Column(Modifier.padding(2.dp)) {
list.map { value -> list.forEach { value ->
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier

View File

@@ -115,7 +115,6 @@ fun StatsList(activeMode: LocType, countMode: Boolean) {
@Composable @Composable
fun StatsRow(group: Groups.Group, activeMode: LocType, countMode: Boolean) { fun StatsRow(group: Groups.Group, activeMode: LocType, countMode: Boolean) {
val context = LocalContext.current
val visited = remember(group, activeMode) { val visited = remember(group, activeMode) {
Data.visits.getVisitedByValue(group.key) Data.visits.getVisitedByValue(group.key)
@@ -124,18 +123,18 @@ fun StatsRow(group: Groups.Group, activeMode: LocType, countMode: Boolean) {
val count = when (activeMode) { val count = when (activeMode) {
LocType.WORLD -> World.WWW.children.filter { it.code in visited }.size LocType.WORLD -> World.WWW.children.filter { it.code in visited }.size
LocType.COUNTRY -> World.WWW.children.flatMap { it.children.filter { c -> c.code in visited } }.size LocType.COUNTRY -> World.WWW.children.flatMap { it.children.filter { c -> c.code in visited } }.size
LocType.STATE -> World.WWW.children.flatMap { itc->itc.children.flatMap { it.children.filter { it.code in visited } } }.size LocType.STATE -> World.WWW.children.flatMap { a->a.children.flatMap { b->b.children.filter { c->c.code in visited } } }.size
else -> 0 else -> 0
} }
val area = when (activeMode) { val area = when (activeMode) {
LocType.WORLD -> World.WWW.children.filter { it.code in visited }.sumOf { it.area } LocType.WORLD -> World.WWW.children.filter { it.code in visited }.sumOf { it.area }
LocType.COUNTRY -> World.WWW.children.flatMap { it.children.filter { c -> c.code in visited } }.sumOf { it.area } LocType.COUNTRY -> World.WWW.children.flatMap { it.children.filter { c -> c.code in visited } }.sumOf { it.area }
LocType.STATE -> World.WWW.children.flatMap { it.children.flatMap { it.children.filter { it.code in visited } } }.sumOf { it.area } LocType.STATE -> World.WWW.children.flatMap { a->a.children.flatMap { b->b.children.filter { c->c.code in visited } } }.sumOf { it.area }
else -> 0 else -> 0
} }
val displayValue = if (countMode) count.toString() else context.getString(R.string.number_with_unit, area, "km²") val displayValue = if (countMode) count.toString() else stringResource(R.string.number_with_unit, area, "km²")
val backgroundColor = group.color.color val backgroundColor = group.color.color
val textColor = getContrastColor(backgroundColor) val textColor = getContrastColor(backgroundColor)

View File

@@ -58,7 +58,7 @@ fun syncVisited(loc: GeoLoc?=World.WWW){
loc?.children?.forEach { tt -> loc?.children?.forEach { tt ->
tt.children.forEach {itc-> tt.children.forEach {itc->
if(Data.visits.getVisited(itc) in listOf(AUTO_GROUP,NO_GROUP)) { if(Data.visits.getVisited(itc) in listOf(AUTO_GROUP,NO_GROUP)) {
if(itc.children.any { itcc -> Data.visits.getVisited(itcc) != NO_GROUP }) if(itc.children.any { c -> Data.visits.getVisited(c) != NO_GROUP })
Data.visits.setVisited(itc, AUTO_GROUP) Data.visits.setVisited(itc, AUTO_GROUP)
else else
Data.visits.setVisited(itc, NO_GROUP) Data.visits.setVisited(itc, NO_GROUP)
@@ -126,7 +126,6 @@ fun EditPlaceScreen(loc: GeoLoc, onExit:()->Unit={}) {
} }
} }
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {

View File

@@ -7,7 +7,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.mikepenz.aboutlibraries.ui.compose.DefaultChipColors import com.mikepenz.aboutlibraries.ui.compose.DefaultChipColors
import com.mikepenz.aboutlibraries.ui.compose.DefaultLibraryColors import com.mikepenz.aboutlibraries.ui.compose.DefaultLibraryColors
import com.mikepenz.aboutlibraries.ui.compose.android.rememberLibraries import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
import net.helcel.beans.R import net.helcel.beans.R
import net.helcel.beans.activity.SysTheme import net.helcel.beans.activity.SysTheme
@@ -16,14 +16,14 @@ import net.helcel.beans.activity.SysTheme
@Preview @Preview
@Composable @Composable
fun LicenseScreen() { fun LicenseScreen() {
val libraries = rememberLibraries(R.raw.aboutlibraries) val libraries = produceLibraries(R.raw.aboutlibraries)
SysTheme { SysTheme {
LibrariesContainer( LibrariesContainer(
libraries = libraries.value, libraries = libraries.value,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
colors = DefaultLibraryColors( colors = DefaultLibraryColors(
backgroundColor = MaterialTheme.colors.background, libraryBackgroundColor = MaterialTheme.colors.background,
contentColor = MaterialTheme.colors.onBackground, libraryContentColor = MaterialTheme.colors.onBackground,
licenseChipColors = DefaultChipColors( licenseChipColors = DefaultChipColors(
containerColor = MaterialTheme.colors.primary, containerColor = MaterialTheme.colors.primary,
contentColor = MaterialTheme.colors.onPrimary, contentColor = MaterialTheme.colors.onPrimary,
@@ -37,6 +37,8 @@ fun LicenseScreen() {
contentColor = MaterialTheme.colors.onSecondary, contentColor = MaterialTheme.colors.onSecondary,
), ),
dialogConfirmButtonColor = MaterialTheme.colors.primary, dialogConfirmButtonColor = MaterialTheme.colors.primary,
dialogBackgroundColor = MaterialTheme.colors.onPrimary,
dialogContentColor = MaterialTheme.colors.primary,
) )
) )
} }

View File

@@ -2,6 +2,7 @@ package net.helcel.beans.countries
import net.helcel.beans.countries.Country.* import net.helcel.beans.countries.Country.*
@Suppress("RedundantSuppression", "SpellCheckingInspection", "unused")
enum class Group(override val fullName: String, override val children: Set<GeoLoc>) : GeoLoc { enum class Group(override val fullName: String, override val children: Set<GeoLoc>) : GeoLoc {
EEE( EEE(

View File

@@ -24,53 +24,53 @@ const val AUTO_GROUP = -1
@Serializable @Serializable
class Groups(val id: Int, private val grps: HashMap<Int, Group>) { class Groups(val id: Int, private val groups: HashMap<Int, Group>) {
@kotlinx.serialization.Transient @kotlinx.serialization.Transient
private val _groupsFlow = MutableStateFlow<List<Group>>(grps.values.toList()) private val _groupsFlow = MutableStateFlow<List<Group>>(groups.values.toList())
@kotlinx.serialization.Transient @kotlinx.serialization.Transient
val groupsFlow: StateFlow<List<Group>> = _groupsFlow.asStateFlow() val groupsFlow: StateFlow<List<Group>> = _groupsFlow.asStateFlow()
fun setGroup(key: Int, name: String, col: ColorDrawable) { fun setGroup(key: Int, name: String, col: ColorDrawable) {
grps[key] = Group(key, name, col) groups[key] = Group(key, name, col)
_groupsFlow.value = grps.values.toList() _groupsFlow.value = groups.values.toList()
} }
fun deleteGroup(key: Int) { fun deleteGroup(key: Int) {
grps.remove(key) groups.remove(key)
_groupsFlow.value = grps.values.toList() _groupsFlow.value = groups.values.toList()
} }
fun getGroupFromKey(key: Int): Group { fun getGroupFromKey(key: Int): Group {
return grps.getOrDefault(key, EmptyGroup()) return groups.getOrDefault(key, EmptyGroup())
} }
fun genKey(): Int { fun genKey(): Int {
val key = rnd.nextInt() val key = rnd.nextInt()
if (grps.containsKey(key) || key in listOf(NO_GROUP, DEFAULT_GROUP, AUTO_GROUP)) return genKey() if (groups.containsKey(key) || key in listOf(NO_GROUP, DEFAULT_GROUP, AUTO_GROUP)) return genKey()
return key return key
} }
fun size(): Int { fun size(): Int {
return grps.size return groups.size
} }
fun getUniqueEntry(): Group? { fun getUniqueEntry(): Group? {
assert(size() == 1) assert(size() == 1)
return if (grps.size == 1) { return if (groups.size == 1) {
grps[grps.keys.first()] groups[groups.keys.first()]
} else { } else {
null null
} }
} }
fun getGroupFromPos(pos: Int): Pair<Int, Group> { fun getGroupFromPos(pos: Int): Pair<Int, Group> {
if(grps.keys.isEmpty()) return Pair(NO_GROUP,Group(NO_GROUP,"-")) if(groups.keys.isEmpty()) return Pair(NO_GROUP,Group(NO_GROUP,"-"))
val key = grps.keys.toList()[pos] val key = groups.keys.toList()[pos]
return Pair(key, getGroupFromKey(key)) return Pair(key, getGroupFromKey(key))
} }
fun findGroupPos(key: Int): Int { fun findGroupPos(key: Int): Int {
return grps.keys.toList().indexOf(key) return groups.keys.toList().indexOf(key)
} }
class EmptyGroup : Group(0, "") class EmptyGroup : Group(0, "")

View File

@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/> <background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View File

@@ -1,24 +1,9 @@
# Project-wide Gradle settings. # Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=false android.enableJetifier=false
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.uniquePackageNames=false
android.dependency.useConstraints=false
android.r8.strictFullModeForKeepRules=false

View File

@@ -6,6 +6,9 @@ pluginManagement {
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
} }
} }
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
dependencyResolutionManagement { dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { repositories {