docs(journal): POC-Status aktualisiert, Master-UX-Fixes dokumentiert und Follow-up geplant
Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
type: Roadmap
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
last_update: 2026-04-29
|
||||
last_update: 2026-04-30
|
||||
---
|
||||
|
||||
# MASTER ROADMAP: Meldestelle
|
||||
|
||||
🏗️ **[Lead Architect]** | 29. April 2026
|
||||
🏗️ **[Lead Architect]** | 30. April 2026
|
||||
|
||||
**Strategisches Ziel:**
|
||||
Entwicklung einer ÖTO-konformen, offline-fähigen Turnier-Meldestelle als Compose Desktop App (KMP).
|
||||
@@ -17,7 +17,7 @@ Vollständige Self-Hosted Infrastruktur (Gitea, Pangolin, Zora). Datensouveräni
|
||||
- Desktop-App ist der primäre Client (Compose Desktop, KMP) — „Desktop-First“ gilt für UX und Architektur.
|
||||
- Offline-First Betrieb mit lokaler Persistenz und opportunistischer Synchronisation.
|
||||
|
||||
**Aktueller technischer Stand (30.03.2026):**
|
||||
**Aktueller technischer Stand (30.04.2026):**
|
||||
* **Infrastruktur:** ✅ "Zora" (MS-R1, ARM64) ist live. Gitea & Registry laufen.
|
||||
* **Networking:** ✅ Pangolin Tunnel ersetzt Cloudflare.
|
||||
* **CI/CD:** ✅ Gitea Actions mit ARM64-Runner (VM 102) aktiv. Docker-Publish Pipeline grün.
|
||||
@@ -75,23 +75,19 @@ und über definierte Schnittstellen kommunizieren.
|
||||
|
||||
Fokus: Physische Implementierung der Turnier-Hierarchie und technisches Onboarding.
|
||||
|
||||
// Meilenstein 0 wird auf "In Arbeit" zurückgesetzt, da Web-Shell Korrekturen nötig sind
|
||||
// Meilenstein 0: Technische Geräte-Initialisierung (Prio 1) 🚧 IN ARBEIT (UI KORREKTUREN WEB)
|
||||
// [x] App-Icons (PNG/ICO): Implementiert (Fix für Build-Fehler).
|
||||
// [x] Docker-Fix: "services must be a mapping" behoben (dc-gui.yaml).
|
||||
// [x] Chat-Funktion (Desktop): MVP implementiert (Navigation & UI).
|
||||
// ... (Rest bleibt wie besprochen)
|
||||
### MEILENSTEIN 0: Technische Geräte-Initialisierung (Prio 1) 🚧 IN ARBEIT (STABILISIERUNG)
|
||||
|
||||
*Ziel: Ein stabiles, offline-fähiges technisches Fundament für die Desktop-App.*
|
||||
|
||||
* [x] **OS-Pfad-Auflösung:** Implementiert (Wartet auf Hardware-Test).
|
||||
* [x] **Netzwerk-Interface-Binding:** Fix: Explizite IP-Bindung für JmDNS implementiert.
|
||||
* [x] **Geführte Discovery ("Radar-Modus"):** Verbessert: UI mit Interface-Status-Indikatoren.
|
||||
* [x] **Plan-USB Integration (UI):** Implementiert (Wartet auf Hardware-Test).
|
||||
* [x] **Offline-Lizenzierung (Konzept):** Dokumentiert (ADR-0026).
|
||||
* [x] **UX-Optimierung:** Implementiert (Wartet auf Hardware-Test).
|
||||
* [x] **Plan-USB Implementierung:** Delta-Logik & AES-Export (Wartet auf Hardware-Test).
|
||||
* [ ] **PoC Verifikation:** 🔴 OFFEN (Hardware-Test durch User erforderlich).
|
||||
* [x] **App-Icons (PNG/ICO):** Implementiert (Fix für Build-Fehler).
|
||||
* [x] **Docker-Fix:** "services must be a mapping" behoben (dc-gui.yaml).
|
||||
* [x] **Chat-Funktion (Desktop):** MVP implementiert (Navigation & UI).
|
||||
* [x] **Geführte Discovery ("Zero-Config"):** Master-Namen statt IPs, "Wait-State" für Clients.
|
||||
* [x] **Native FileDialogs:** Stabile Pfad-Auswahl für Plan-USB auf allen Systemen.
|
||||
* [x] **Handshake-Feedback:** Visuelle Signalisierung des Verbindungsstatus (Grün/Rot).
|
||||
* [x] **Client-Konfiguration:** Master kann nun Clients in der UI hinzufügen und bearbeiten.
|
||||
* [x] **Master-UX:** Konfiguration beim Start nicht mehr zwangsgesperrt.
|
||||
* [ ] **PoC Verifikation:** 🔴 **FEHLGESCHLAGEN** (Hardware-Test durch User nicht erfolgreich - Analyse für Abend-Session erforderlich).
|
||||
|
||||
### MEILENSTEIN 1: Die Basis-Hierarchie (Prio 1) ⚪ GEPLANT
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
🏗️ **[Curator Journal]**
|
||||
Datum: 30. April 2026
|
||||
|
||||
# 🧹 Session-Abschluss: Master-UX & Client-Konfiguration
|
||||
|
||||
## 🚀 Highlights
|
||||
- **Master-Freiheit:** Die Konfiguration ist beim Start des Wizards nicht mehr zwangsgesperrt. Der Master kann nun alle Einstellungen (Name, Key, Interfaces) in Ruhe prüfen, bevor er finalisiert.
|
||||
- **Client-Management:** Der Master kann nun "erwartete Clients" direkt in der UI hinzufügen, umbenennen und deren Rollen (Richter, Zeitnehmer, etc.) anpassen.
|
||||
- **Dynamische Listen:** Fehler behoben, bei dem nach dem Löschen von Clients keine neuen mehr hinzugefügt werden konnten.
|
||||
|
||||
## 🛠️ Technische Details
|
||||
- **ViewModel-Fix:** `isLocked` im `DeviceInitializationViewModel` wird nun initial auf `false` gesetzt.
|
||||
- **UI-Implementierung:** `DeviceInitializationConfig.jvm.kt` nutzt nun `MsTextField` und `FilterChip` innerhalb der Client-Liste für direkte Bearbeitung.
|
||||
- **Rollen-Filter:** Der Master kann sich selbst nicht als "erwarteten Client" hinzufügen (Filter auf `NetworkRole.entries`).
|
||||
|
||||
## 📅 Ausblick
|
||||
- Abschluss von **Meilenstein 0** nach erfolgreichem Hardware-Test.
|
||||
- Start von **Meilenstein 1 (Basis-Hierarchie & Persistenz)**.
|
||||
@@ -0,0 +1,24 @@
|
||||
🏗️ **[Curator Journal]**
|
||||
Datum: 30. April 2026 (Abschluss-Update)
|
||||
|
||||
# 🧹 Session-Abschluss: POC-Status & Kritische Analyse
|
||||
|
||||
## 🚀 Implementierte Änderungen (Zusammenfassung)
|
||||
- **Zero-Config & UI-Fixes:** mDNS-Discovery mit sprechenden Namen, "Wait-State" für Clients und native Dateidialoge integriert.
|
||||
- **Master-UX Optimierung:** Die Konfiguration im Wizard ist nun beim Start entsperrt; Master können erwartete Clients hinzufügen/bearbeiten.
|
||||
- **Fehlerbehebung:** Kompilierfehler im `DeviceInitializationViewModel` (JVM/Common-Abstraktion) und Docker-Compose YAML-Struktur korrigiert.
|
||||
|
||||
## 🔴 Aktueller Status: POC FEHLGESCHLAGEN
|
||||
Trotz der technischen Umsetzungen meldet der User, dass der POC auf der Hardware weiterhin nicht funktioniert.
|
||||
- **Feedback:** "Es funktioniert noch immer nicht!"
|
||||
- **Konsequenz:** Die Session wird zur Dokumentation beendet. Eine tiefergehende Fehleranalyse (Netzwerk-Traces, Log-Inspektion) ist für die Abend-Session zwingend erforderlich.
|
||||
|
||||
## 📋 Checkliste für die Abend-Session (Analyse-Fokus)
|
||||
1. **mDNS Sichtbarkeit:** Warum finden sich Master und Client trotz "Zero-Config" nicht zuverlässig? (Mögliche Firewall-Themen oder Interface-Binding-Priorität).
|
||||
2. **Handshake-Logik:** Verbleibt der Client im "Wait-State" oder schlägt der Verbindungsversuch aktiv fehl?
|
||||
3. **UI-State Persistence:** Werden die Master-Einstellungen (Name, Key) korrekt für den mDNS-Broadcast übernommen?
|
||||
4. **Log-Analyse:** Prüfung der App-Logs auf dem Zielsystem (falls verfügbar).
|
||||
|
||||
## 📅 Nächste Schritte
|
||||
- Start der Abend-Session mit Fokus auf **Debugging der Netzwerk-Discovery**.
|
||||
- Verifikation der `init_device.aes` Erstellung bei manuellem Durchlauf des Masters.
|
||||
+5
-4
@@ -35,7 +35,7 @@ class DeviceInitializationViewModel(
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
settings = existingSettings,
|
||||
isLocked = existingSettings.isConfigured
|
||||
isLocked = false // Immer offen für Bearbeitung beim Start des Wizards
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -133,10 +133,11 @@ class DeviceInitializationViewModel(
|
||||
_uiState.update { it.copy(showRoleChangeWarning = false, pendingRole = null) }
|
||||
}
|
||||
|
||||
fun addExpectedClient(name: String, role: NetworkRole) {
|
||||
println("[DeviceInit] Erwarteter Client hinzugefügt: $name ($role)")
|
||||
fun addExpectedClient() {
|
||||
val name = "Neuer Client ${uiState.value.settings.expectedClients.size + 1}"
|
||||
println("[DeviceInit] Erwarteter Client hinzugefügt: $name")
|
||||
updateSettings {
|
||||
it.copy(expectedClients = it.expectedClients + ExpectedClient(name, role))
|
||||
it.copy(expectedClients = it.expectedClients + ExpectedClient(name, NetworkRole.RICHTER))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-4
@@ -236,7 +236,7 @@ actual fun DeviceInitializationConfig(
|
||||
HorizontalDivider(Modifier.padding(vertical = 8.dp))
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
|
||||
Text("👥 Erwartete Clients", style = MaterialTheme.typography.titleSmall)
|
||||
TextButton(onClick = { /* Add Client Dialog */ }) {
|
||||
TextButton(onClick = { viewModel.addExpectedClient() }) {
|
||||
Icon(Icons.Default.Add, null, Modifier.size(18.dp))
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Text("Hinzufügen")
|
||||
@@ -245,15 +245,46 @@ actual fun DeviceInitializationConfig(
|
||||
|
||||
settings.expectedClients.forEachIndexed { index, client ->
|
||||
ListItem(
|
||||
headlineContent = { Text(client.name, fontWeight = FontWeight.Medium) },
|
||||
supportingContent = { Text(client.role.name, style = MaterialTheme.typography.labelSmall) },
|
||||
headlineContent = {
|
||||
MsTextField(
|
||||
value = client.name,
|
||||
onValueChange = { newName ->
|
||||
viewModel.updateSettings { s ->
|
||||
val newList = s.expectedClients.toMutableList()
|
||||
newList[index] = newList[index].copy(name = newName)
|
||||
s.copy(expectedClients = newList)
|
||||
}
|
||||
},
|
||||
label = null,
|
||||
compact = true,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
NetworkRole.entries.filter { it != NetworkRole.MASTER }.forEach { role ->
|
||||
val isSelected = client.role == role
|
||||
FilterChip(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
viewModel.updateSettings { s ->
|
||||
val newList = s.expectedClients.toMutableList()
|
||||
newList[index] = newList[index].copy(role = role)
|
||||
s.copy(expectedClients = newList)
|
||||
}
|
||||
},
|
||||
label = { Text(role.name, style = MaterialTheme.typography.labelSmall) }
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
trailingContent = {
|
||||
IconButton(onClick = { viewModel.removeExpectedClient(index) }) {
|
||||
Icon(Icons.Default.Delete, null, tint = MaterialTheme.colorScheme.error, modifier = Modifier.size(20.dp))
|
||||
}
|
||||
},
|
||||
colors = ListItemDefaults.colors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)),
|
||||
modifier = Modifier.padding(vertical = 2.dp)
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user