fixing clients

new frontend
This commit is contained in:
stefan
2025-09-26 13:14:00 +02:00
parent 94a76e4484
commit 97d0af1b07
11 changed files with 389 additions and 53 deletions
+56 -28
View File
@@ -16,6 +16,11 @@ group = "at.mocode.clients"
version = "1.0.0"
kotlin {
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
jvmToolchain(21)
jvm {
binaries {
executable {
@@ -27,9 +32,7 @@ kotlin {
outputModuleName = "web-app"
browser {
commonWebpackConfig {
cssSupport {
enabled.set(true)
}
cssSupport { enabled = true }
}
testTask {
enabled = false
@@ -38,38 +41,55 @@ kotlin {
binaries.executable()
}
jvmToolchain(21)
if (enableWasm) {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
binaries.executable()
}
}
applyDefaultHierarchyTemplate()
sourceSets {
val commonMain by getting {
dependencies {
// Feature modules
implementation(project(":clients:ping-feature"))
// Shared modules
implementation(project(":clients:shared:common-ui"))
implementation(project(":clients:shared:navigation"))
commonMain.dependencies {
// Feature modules
implementation(project(":clients:ping-feature"))
// Compose dependencies
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
// Shared modules
implementation(project(":clients:shared:common-ui"))
implementation(project(":clients:shared:navigation"))
// ViewModel lifecycle
implementation(libs.androidx.lifecycle.viewmodelCompose)
// Compose dependencies
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
// ViewModel lifecycle
implementation(libs.androidx.lifecycle.viewmodelCompose)
}
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
implementation(libs.kotlinx.coroutines.core)
}
jsMain.dependencies {
implementation(npm("html-webpack-plugin", "5.6.4"))
}
if (enableWasm) {
val wasmJsMain by getting {
dependencies {
implementation(npm("html-webpack-plugin", "5.6.4"))
}
}
}
val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
}
}
val commonTest by getting {
dependencies {
implementation(libs.kotlin.test)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
}
}
@@ -82,3 +102,11 @@ tasks.withType<Tar> {
tasks.withType<Zip> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
// Ensure copy/sync-based distribution tasks exclude duplicates (e.g., index.html from resources and HtmlWebpackPlugin)
tasks.withType<Copy> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
tasks.withType<Sync> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
+9 -3
View File
@@ -4,12 +4,18 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meldestelle</title>
<meta name="theme-color" content="#0f172a">
<link type="text/css" rel="stylesheet" href="styles.css">
<!-- <script src="web-app.js"></script>-->
<link rel="manifest" href="manifest.webmanifest">
</head>
<body>
<div id="ComposeTarget"></div>
<!--<script src="skiko.js"></script>-->
<!--<script src="Meldestelle-client.js"></script>-->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').catch(console.error);
});
}
</script>
</body>
</html>
@@ -0,0 +1,13 @@
{
"name": "Meldestelle",
"short_name": "Melde",
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0f172a",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
+49
View File
@@ -0,0 +1,49 @@
const CACHE_NAME = 'meldestelle-cache-v1';
const PRECACHE_URLS = [
'/',
'/index.html',
'/styles.css'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(PRECACHE_URLS))
.then(() => self.skipWaiting())
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => Promise.all(
keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k))
)).then(() => self.clients.claim())
);
});
self.addEventListener('fetch', (event) => {
const req = event.request;
if (req.mode === 'navigate') {
// Network-first for navigation
event.respondWith(
fetch(req).then((resp) => {
const copy = resp.clone();
caches.open(CACHE_NAME).then((cache) => cache.put('/', copy));
return resp;
}).catch(() => caches.match('/index.html'))
);
return;
}
// Cache-first for static assets
event.respondWith(
caches.match(req).then((cached) => {
if (cached) return cached;
return fetch(req).then((resp) => {
const copy = resp.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(req, copy));
return resp;
});
})
);
});
+5 -2
View File
@@ -1,10 +1,13 @@
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.CanvasBasedWindow
import androidx.compose.ui.window.ComposeViewport
import at.mocode.clients.app.App
import kotlinx.browser.document
import org.w3c.dom.HTMLElement
@OptIn(ExperimentalComposeUiApi::class)
fun main() {
CanvasBasedWindow("Meldestelle - WASM Application") {
val root = document.getElementById("ComposeTarget") as HTMLElement
ComposeViewport(root) {
App()
}
}
@@ -0,0 +1,10 @@
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const templatePath = path.resolve(__dirname, '../../../../clients/app/src/jsMain/resources/index.html');
config.plugins.push(new HtmlWebpackPlugin({
template: templatePath,
filename: 'index.html',
inject: 'body',
}));
+12 -4
View File
@@ -14,6 +14,7 @@ group = "at.mocode.clients"
version = "1.0.0"
kotlin {
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
jvm()
js {
browser {
@@ -23,10 +24,17 @@ kotlin {
}
}
if (enableWasm) {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
}
}
jvmToolchain(21)
sourceSets {
val commonMain by getting {
commonMain {
dependencies {
// Contract from backend
implementation(projects.services.ping.pingApi)
@@ -53,17 +61,17 @@ kotlin {
implementation(libs.androidx.lifecycle.viewmodelCompose)
}
}
val commonTest by getting {
commonTest {
dependencies {
implementation(libs.kotlin.test)
}
}
val jvmMain by getting {
jvmMain {
dependencies {
implementation(libs.ktor.client.cio)
}
}
val jsMain by getting {
jsMain {
dependencies {
implementation(libs.ktor.client.js)
}
+10 -2
View File
@@ -12,6 +12,7 @@ group = "at.mocode.clients.shared"
version = "1.0.0"
kotlin {
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
jvm()
js {
browser {
@@ -21,10 +22,17 @@ kotlin {
}
}
if (enableWasm) {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
}
}
jvmToolchain(21)
sourceSets {
val commonMain by getting {
commonMain {
dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
@@ -33,7 +41,7 @@ kotlin {
implementation(compose.components.resources)
}
}
val commonTest by getting {
commonTest {
dependencies {
implementation(libs.kotlin.test)
}
+8 -5
View File
@@ -10,24 +10,27 @@ group = "at.mocode.clients.shared"
version = "1.0.0"
kotlin {
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
jvm()
js {
browser()
}
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
if (enableWasm) {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
}
}
jvmToolchain(21)
sourceSets {
val commonMain by getting {
commonMain {
dependencies {
// No specific dependencies needed for navigation routes
}
}
val commonTest by getting {
commonTest {
dependencies {
implementation(libs.kotlin.test)
}