Ping Frontend Desktop und WasmJs funktionieren

This commit is contained in:
2025-09-10 21:24:59 +02:00
parent f236ed0de6
commit a0063d7ea3
4 changed files with 194 additions and 38 deletions
+12
View File
@@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.compose.compiler)
}
@@ -28,6 +29,13 @@ kotlin {
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
// HTTP client dependencies for ping-service
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.contentNegotiation)
implementation(libs.ktor.client.serialization.kotlinx.json)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
@@ -35,6 +43,10 @@ kotlin {
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
implementation(libs.ktor.client.cio)
}
wasmJsMain.dependencies {
implementation(libs.ktor.client.js)
}
}
}
@@ -4,41 +4,51 @@
android:width="450dp"
android:height="450dp"
android:viewportWidth="64"
android:viewportHeight="64">
<path
android:pathData="M56.25,18V46L32,60 7.75,46V18L32,4Z"
android:fillColor="#6075f2"/>
<path
android:pathData="m41.5,26.5v11L32,43V60L56.25,46V18Z"
android:fillColor="#6b57ff"/>
<path
android:pathData="m32,43 l-9.5,-5.5v-11L7.75,18V46L32,60Z">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="23.131"
android:centerY="18.441"
android:gradientRadius="42.132"
android:type="radial">
<item android:offset="0" android:color="#FF5383EC"/>
<item android:offset="0.867" android:color="#FF7F52FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M22.5,26.5 L32,21 41.5,26.5 56.25,18 32,4 7.75,18Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="44.172"
android:startY="4.377"
android:endX="17.973"
android:endY="34.035"
android:type="linear">
<item android:offset="0" android:color="#FF33C3FF"/>
<item android:offset="0.878" android:color="#FF5383EC"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m32,21 l9.526,5.5v11L32,43 22.474,37.5v-11z"
android:fillColor="#000000"/>
</vector>
android:viewportHeight="64"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.android.com/aapt ">
<path
android:pathData="M56.25,18V46L32,60 7.75,46V18L32,4Z"
android:fillColor="#6075f2"/>
<path
android:pathData="m41.5,26.5v11L32,43V60L56.25,46V18Z"
android:fillColor="#6b57ff"/>
<path
android:pathData="m32,43 l-9.5,-5.5v-11L7.75,18V46L32,60Z">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="23.131"
android:centerY="18.441"
android:gradientRadius="42.132"
android:type="radial">
<item
android:offset="0"
android:color="#FF5383EC"/>
<item
android:offset="0.867"
android:color="#FF7F52FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M22.5,26.5 L32,21 41.5,26.5 56.25,18 32,4 7.75,18Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="44.172"
android:startY="4.377"
android:endX="17.973"
android:endY="34.035"
android:type="linear">
<item
android:offset="0"
android:color="#FF33C3FF"/>
<item
android:offset="0.878"
android:color="#FF5383EC"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m32,21 l9.526,5.5v11L32,43 22.474,37.5v-11z"
android:fillColor="#000000"/>
</vector>
@@ -7,20 +7,66 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeContentPadding
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.ui.tooling.preview.Preview
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
@Serializable
data class PingResponse(
val status: String,
val timestamp: String? = null,
val message: String? = null
)
sealed class PingState {
object Idle : PingState()
object Loading : PingState()
data class Success(val response: PingResponse) : PingState()
data class Error(val message: String) : PingState()
}
@Composable
@Preview
fun App() {
MaterialTheme {
var showContent by remember { mutableStateOf(false) }
var pingState by remember { mutableStateOf<PingState>(PingState.Idle) }
val coroutineScope = rememberCoroutineScope()
// Create HTTP client
val httpClient = remember {
HttpClient {
install(ContentNegotiation) {
json()
}
}
}
// Cleanup client on disposal
DisposableEffect(Unit) {
onDispose {
httpClient.close()
}
}
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
@@ -35,6 +81,7 @@ fun App() {
modifier = Modifier.padding(top = 32.dp, bottom = 16.dp)
)
// Platform Info Button
Button(
onClick = { showContent = !showContent },
modifier = Modifier.padding(16.dp)
@@ -42,6 +89,91 @@ fun App() {
Text(if (showContent) "Platform-Info ausblenden" else "Platform-Info anzeigen")
}
// Ping Backend Button
Button(
onClick = {
coroutineScope.launch {
pingState = PingState.Loading
try {
val response: PingResponse = httpClient.get("http://localhost:8082/ping").body()
pingState = PingState.Success(response)
} catch (e: Exception) {
pingState = PingState.Error(e.message ?: "Unknown error occurred")
}
}
},
enabled = pingState !is PingState.Loading,
modifier = Modifier.padding(8.dp)
) {
if (pingState is PingState.Loading) {
CircularProgressIndicator(
modifier = Modifier.height(16.dp),
color = MaterialTheme.colorScheme.onPrimary
)
Spacer(modifier = Modifier.height(8.dp))
}
Text("Ping Backend")
}
// Ping Status Display
when (val state = pingState) {
is PingState.Success -> {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = "✅ Ping erfolgreich!",
style = MaterialTheme.typography.titleMedium,
color = Color(0xFF4CAF50)
)
Text(
text = "Status: ${state.response.status}",
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 4.dp)
)
state.response.timestamp?.let {
Text(
text = "Zeit: $it",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 2.dp)
)
}
}
}
}
is PingState.Error -> {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = "❌ Ping fehlgeschlagen",
style = MaterialTheme.typography.titleMedium,
color = Color(0xFFF44336)
)
Text(
text = "Fehler: ${state.message}",
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
else -> {
// Idle or Loading state - no additional display needed
}
}
AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
Column(