add checkbox and golemio api

This commit is contained in:
2026-01-22 11:55:46 +01:00
parent fdde5c086a
commit 077c26eec7
6 changed files with 191 additions and 228 deletions
@@ -4,11 +4,28 @@ import android.app.Activity
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import androidx.compose.ui.semantics.getOrNull
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.OkHttpClient
import ovh.plrapps.mapcompose.api.moveMarker
import java.net.URL
@Serializable
data class HaukResponse(
val type: Int,
val expire: Long,
val serverTime: Double,
val interval: Int,
val points: List<List<Double?>>,
val encrypted: Boolean,
val salt: String? = null
)
private val json = Json {
coerceInputValues = true // Coerce nulls to default values if applicable
ignoreUnknownKeys = true // Ignore fields in JSON not present in the data class
}
// OkHttpClient for making HTTP requests
val httpClient = OkHttpClient.Builder()
.build()
@@ -35,17 +52,21 @@ private fun fetchHaukPosition(haukUrl: String, callee: Activity) {
}
message = "{" + message.substringAfter("{");
val hauk_response = Json.decodeFromString<HaukResponse>(message)
val hauk_response = json.decodeFromString<HaukResponse>(message)
val lat = hauk_response.points.last()?.getOrNull(0)
val lon = hauk_response.points.last()?.getOrNull(1)
if (lat != null && lon != null) {
HaukMainHandler.post {
mapState.moveMarker("target_position", x = longitudeToXNormalized(hauk_response.points.last()[1]), y = latitudeToYNormalized(hauk_response.points.last()[0]))
mapState.moveMarker("target_position", x = longitudeToXNormalized(lon), y = latitudeToYNormalized(lat))
}
}
} else {
Toast.makeText(callee, "TARGET LOCATION NOT AVAILABLE", Toast.LENGTH_SHORT).show()
}}
} catch (e: Exception) {
// Post UI update to main thread
HaukMainHandler.post {
Toast.makeText(callee, e.message ?: "Unknown error", Toast.LENGTH_LONG).show()
Toast.makeText(callee, e.message ?: "Unknown error", Toast.LENGTH_SHORT).show()
}
}
}
@@ -1,17 +1,22 @@
package org.pupes.mhdrunpathfinder
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -33,7 +38,7 @@ import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.serialization.Serializable
import androidx.core.content.edit
import ovh.plrapps.mapcompose.api.addLayer
import ovh.plrapps.mapcompose.api.addMarker
import ovh.plrapps.mapcompose.api.scrollTo
@@ -42,21 +47,11 @@ import ovh.plrapps.mapcompose.ui.MapUI
import ovh.plrapps.mapcompose.ui.state.MapState
import java.net.URL
@Serializable
data class HaukResponse(
val type: Int,
val expire: Long,
val serverTime: Double,
val interval: Int,
val points: List<List<Double>>,
val encrypted: Boolean,
val salt: String? = null
)
// MapState configuration for OpenStreetMap
// Max zoom level is 18, tile size is 256x256
// At zoom level 18, there are 2^18 = 262144 tiles in each dimension
// So fullWidth/Height = 256 * 262144
// So fullWidth/Height = 256 * 2^18
val mapState = MapState(
levelCount = 19, // zoom levels 0-18
fullWidth = 67108864, // 256 * 2^18
@@ -78,11 +73,10 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MainScreen()
MainScreen(this)
}
}
}
startHaukTracking("https://hauk.limit6.eu/?M4SJ-SH7I",this)
startLocationTracking(this)
}
@@ -95,8 +89,18 @@ class MainActivity : ComponentActivity() {
}
@Composable
fun MainScreen() {
fun MainScreen(callee: Activity) {
val sharedPreferences = remember { callee.getSharedPreferences("PREFERENCES", Context.MODE_PRIVATE) }
var showSettings by remember { mutableStateOf(false) }
var haukUrl by remember { mutableStateOf("") }
var golemioAPIkey by remember { mutableStateOf(sharedPreferences.getString("golemioAPIkey", "")?: "" ) }
var haukState by remember { mutableStateOf(false) }
var golemioState by remember { mutableStateOf(false)}
if (golemioAPIkey.isNotEmpty()) {
golemioState = true
/*TODO: START MHD TRACKING*/
}
Box(modifier = Modifier.fillMaxSize()) {
OpenStreetMapScreen()
@@ -107,7 +111,55 @@ fun MainScreen() {
.padding(end = 5.dp, bottom = 5.dp)
)
if (showSettings) {
ShowSettingsMenu(onDismiss = { showSettings = false })
ShowSettingsMenu(
onDismiss = { showSettings = false },
haukUrl = haukUrl,
onHaukUrlChange = { haukUrl = it },
onHaukApply = {
if (haukUrl.isNotEmpty()) {
haukState = true
stopHaukTracking()
startHaukTracking(haukUrl, callee)
}
},
haukState = haukState,
onHaukStateChange = {
haukState = it
if (it) {
if (haukUrl.isNotEmpty()) {
stopHaukTracking()
startHaukTracking(haukUrl, callee)
}
} else {
stopHaukTracking()
}
},
golemioAPIkey = golemioAPIkey,
onGolemioAPIChange = { golemioAPIkey = it },
onGolemioApply = {
if (golemioAPIkey.isNotEmpty()) {
golemioState = true
sharedPreferences.edit {
putString("golemioAPIkey", golemioAPIkey)
}
/*TODO: START MHD TRACKING*/
}
},
golemioState = golemioState,
onGolemioStateChange = {
golemioState = it
if (it) {
if (golemioAPIkey.isNotEmpty()) {
sharedPreferences.edit {
putString("golemioAPIkey", golemioAPIkey)
}
/*TODO: START MHD TRACKING*/
}
} else {
/*TODO: STOP MHD TRACKING*/
}
}
)
}
}
}
@@ -134,22 +186,52 @@ fun SettingsButton(modifier: Modifier = Modifier, onClick: () -> Unit = {}) {
@Preview
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun ShowSettingsMenu(modifier: Modifier = Modifier, onDismiss: () -> Unit = {}) {
fun ShowSettingsMenu(
modifier: Modifier = Modifier,
onDismiss: () -> Unit = {},
haukUrl: String = "",
onHaukUrlChange: (String) -> Unit = {},
onHaukApply: () -> Unit = {},
haukState: Boolean = false,
onHaukStateChange: (Boolean) -> Unit = {},
golemioAPIkey: String = "",
onGolemioAPIChange: (String) -> Unit = {},
onGolemioApply: () -> Unit = {},
golemioState: Boolean = false,
onGolemioStateChange: (Boolean) -> Unit = {}
) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Column() {
Column( verticalArrangement = Arrangement.spacedBy(10.dp)) {
Row() {
TextField(
state = rememberTextFieldState(),
label = { Text("Target Hauk URL") },
Checkbox(
checked = haukState,
onCheckedChange = { onHaukStateChange(it) }
)
ElevatedButton(onClick = { },modifier = Modifier.padding(start = 5.dp), shape = RectangleShape) {
TextField(
value = haukUrl,
onValueChange = onHaukUrlChange,
label = { Text("Target Hauk URL") },
modifier = Modifier
.width(250.dp)
)
ElevatedButton(onClick = onHaukApply, modifier = Modifier.padding(start = 5.dp), shape = RectangleShape) {
Text("Apply")
}
}
Row() {
Checkbox(
checked = golemioState,
onCheckedChange = { onGolemioStateChange(it) }
)
TextField(value = golemioAPIkey, onValueChange = onGolemioAPIChange, label = { Text("Golemio API Key") },
modifier = Modifier
.width(250.dp));
ElevatedButton(onClick = onGolemioApply, modifier = Modifier.padding(start = 5.dp), shape = RectangleShape) {
Text("Apply")
}
}
}
}
}}
@Preview
@Composable
@@ -0,0 +1,2 @@
package org.pupes.mhdrunpathfinder