refactor(device-initialization): Code-Bereinigung, ungenutzte Parameter entfernt und WasmJS-Unterstützung vervollständigt
Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
parent
e91b10daa3
commit
fb77a5065b
|
|
@ -276,7 +276,7 @@ und über definierte Schnittstellen kommunizieren.
|
|||
|
||||
## 4. Geplante Phasen
|
||||
|
||||
### PHASE 13: Export & ZNS-Rückmeldung ✅ ABGESCHLOSSEN
|
||||
### PHASE 13: Export & ZNS-Rückmeldung ✅ ABGESCHLOSSEN (18. April 2026)
|
||||
*Ziel: Finalisierung der Turnier-Daten und Rückübermittlung an den OEPS.*
|
||||
|
||||
* [x] **Mail-Service Integration:** Online-Nennungen via REST/Mail empfangen und persistieren. ✓ (April 2026)
|
||||
|
|
@ -284,6 +284,10 @@ und über definierte Schnittstellen kommunizieren.
|
|||
18. April 2026)
|
||||
* [x] **Plug-and-Play Architektur:** Umstellung der Frontend-Komponenten auf fachlich autarke Organismen (ADR-0024).
|
||||
✓ (18. April 2026)
|
||||
* [x] **WASM-Transition:** Projektweite Umstellung auf JVM (Desktop) und wasmJs (Web). Eliminierung von `js(IR)`. ✓ (
|
||||
18. April 2026)
|
||||
* [x] **Geräte-Initialisierung:** Refactoring des Onboarding-Prozesses in das Plug-and-Play Modul
|
||||
`device-initialization`. ✓ (18. April 2026)
|
||||
* [ ] **XML-Export:** Vollständiger B-Satz Export (inkl. Ergebnisse und Platzierungen).
|
||||
* [ ] **ZNS-Portal:** Upload-Integration in das OEPS-ZNS.
|
||||
* [ ] **Archivierung:** Langzeit-Archivierung abgeschlossener Turniere.
|
||||
|
|
|
|||
|
|
@ -50,7 +50,11 @@ Prinzip und ist fachlich präzise benannt.
|
|||
* **ViewModel-Fix:** `DeviceInitializationViewModel` erbt nun von `androidx.lifecycle.ViewModel`, was die Integration in
|
||||
`koinViewModel` ermöglicht.
|
||||
* **DesktopMainLayout:** Syntaxfehler beim `koinViewModel`-Aufruf behoben und Typos (`geraetName` -> `deviceName`)
|
||||
korrigiert.
|
||||
korrigiert. Unbenutzter `settings`-Parameter entfernt.
|
||||
* **Multiplatform-Härtung:** `DeviceInitializationSettingsManager` und `DeviceInitializationConfig` auf `expect/actual`
|
||||
umgestellt, um JVM-Lecks im Common-Code zu vermeiden und JS/WasmJS Kompatibilität (via Stubs) sicherzustellen.
|
||||
umgestellt.
|
||||
* **Beta-Warnungen:** `@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")` hinzugefügt, um
|
||||
Compiler-Warnungen in den Domain-Klassen zu unterdrücken.
|
||||
* **WASM-Komplettierung:** `DeviceInitializationSettingsManager` nutzt nun `localStorage` im Web.
|
||||
`DeviceInitializationConfig` wurde für WasmJS funktional implementiert (Basis-Konfiguration).
|
||||
* **UI-Cleanup:** Code-Duplikate in der Desktop-Konfiguration durch `MsSettingsField` reduziert.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
|
||||
package at.mocode.frontend.features.deviceinitialization.domain
|
||||
|
||||
expect object DeviceInitializationSettingsManager {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,35 @@
|
|||
@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
|
||||
package at.mocode.frontend.features.deviceinitialization.domain
|
||||
|
||||
import kotlinx.browser.localStorage
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
actual object DeviceInitializationSettingsManager {
|
||||
private const val SETTINGS_KEY = "device_initialization_settings"
|
||||
private val json = Json { prettyPrint = true; ignoreUnknownKeys = true }
|
||||
|
||||
actual fun saveSettings(settings: DeviceInitializationSettings) {
|
||||
// Nicht implementiert für WasmJS
|
||||
try {
|
||||
val content = json.encodeToString(DeviceInitializationSettings.serializer(), settings)
|
||||
localStorage.setItem(SETTINGS_KEY, content)
|
||||
} catch (e: Exception) {
|
||||
println("Fehler beim Speichern der Einstellungen (WasmJS): ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
actual fun loadSettings(): DeviceInitializationSettings? = null
|
||||
actual fun loadSettings(): DeviceInitializationSettings? {
|
||||
val content = localStorage.getItem(SETTINGS_KEY) ?: return null
|
||||
return try {
|
||||
json.decodeFromString<DeviceInitializationSettings>(DeviceInitializationSettings.serializer(), content)
|
||||
} catch (e: Exception) {
|
||||
println("Fehler beim Laden der Einstellungen (WasmJS): ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
actual fun isConfigured(): Boolean = false
|
||||
actual fun isConfigured(): Boolean {
|
||||
val settings = loadSettings() ?: return false
|
||||
return DeviceInitializationValidator.canContinue(settings)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,92 @@
|
|||
package at.mocode.frontend.features.deviceinitialization.presentation
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Visibility
|
||||
import androidx.compose.material.icons.outlined.VisibilityOff
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import at.mocode.frontend.features.deviceinitialization.domain.DeviceInitializationValidator
|
||||
|
||||
@Composable
|
||||
actual fun DeviceInitializationConfig(
|
||||
uiState: DeviceInitializationUiState,
|
||||
viewModel: DeviceInitializationViewModel
|
||||
) {
|
||||
Text("Konfiguration für Web (WasmJS) ist nicht implementiert.")
|
||||
val settings = uiState.settings
|
||||
|
||||
Card(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
Text("⚙️ Geräte-Konfiguration", style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
MsSettingsField(
|
||||
value = settings.deviceName,
|
||||
onValueChange = { viewModel.updateSettings { s -> s.copy(deviceName = it) } },
|
||||
label = "Gerätename",
|
||||
placeholder = "z.B. Web-Client",
|
||||
isError = settings.deviceName.isNotEmpty() && !DeviceInitializationValidator.isNameValid(settings.deviceName),
|
||||
errorText = "Mindestens ${DeviceInitializationValidator.MIN_NAME_LENGTH} Zeichen erforderlich."
|
||||
)
|
||||
|
||||
var passwordVisible by remember { mutableStateOf(false) }
|
||||
MsSettingsField(
|
||||
value = settings.sharedKey,
|
||||
onValueChange = { viewModel.updateSettings { s -> s.copy(sharedKey = it) } },
|
||||
label = "Sicherheitsschlüssel (Sync-Key)",
|
||||
placeholder = "Mindestens 8 Zeichen",
|
||||
isError = settings.sharedKey.isNotEmpty() && !DeviceInitializationValidator.isKeyValid(settings.sharedKey),
|
||||
errorText = "Mindestens ${DeviceInitializationValidator.MIN_KEY_LENGTH} Zeichen erforderlich.",
|
||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||
Icon(
|
||||
imageVector = if (passwordVisible) Icons.Outlined.VisibilityOff else Icons.Outlined.Visibility,
|
||||
contentDescription = if (passwordVisible) "Verbergen" else "Anzeigen"
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Text(
|
||||
"Hinweis: In der Web-Version sind erweiterte Master-Funktionen (wie lokales Backup) derzeit deaktiviert.",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MsSettingsField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
label: String,
|
||||
placeholder: String,
|
||||
isError: Boolean,
|
||||
errorText: String,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
trailingIcon: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
label = { Text(label) },
|
||||
placeholder = { Text(placeholder) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
isError = isError,
|
||||
visualTransformation = visualTransformation,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = {
|
||||
if (isError) {
|
||||
Text(errorText)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,4 @@
|
|||
{
|
||||
"geraetName": "Meldestelle",
|
||||
"sharedKey": "Meldestelle",
|
||||
"backupPath": "/home/stefan/WsMeldestelle/Meldestelle/meldestelle/docs/temp",
|
||||
"networkRole": "MASTER",
|
||||
"expectedClients": [
|
||||
{
|
||||
"name": "Richter-Turm",
|
||||
"role": "RICHTER"
|
||||
}
|
||||
]
|
||||
"deviceName": "Richter-Turm",
|
||||
"sharedKey": "Meldestelle"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ fun DesktopMainLayout(
|
|||
onboardingSettings = it
|
||||
DeviceInitializationSettingsManager.saveSettings(it)
|
||||
},
|
||||
settings = onboardingSettings,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -523,7 +522,6 @@ private fun DesktopContentArea(
|
|||
currentScreen: AppScreen,
|
||||
onNavigate: (AppScreen) -> Unit,
|
||||
onBack: () -> Unit,
|
||||
settings: DeviceInitializationSettings,
|
||||
onSettingsChange: (DeviceInitializationSettings) -> Unit,
|
||||
) {
|
||||
when (currentScreen) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user