feat(desktop, device-initialization): Tools-Menü mit Backup-Option und Reset-Funktion ergänzt
Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
+25
@@ -8,6 +8,9 @@ import at.mocode.frontend.core.auth.di.authModule
|
||||
import at.mocode.frontend.core.localdb.AppDatabase
|
||||
import at.mocode.frontend.core.localdb.DatabaseProvider
|
||||
import at.mocode.frontend.core.localdb.localDbModule
|
||||
import at.mocode.frontend.core.network.NetworkConfig
|
||||
import at.mocode.frontend.core.network.chat.KtorWebSocketServerService
|
||||
import at.mocode.frontend.core.network.discovery.NetworkDiscoveryService
|
||||
import at.mocode.frontend.core.network.networkModule
|
||||
import at.mocode.frontend.core.sync.di.syncModule
|
||||
import at.mocode.frontend.features.billing.di.billingModule
|
||||
@@ -60,6 +63,28 @@ fun main() = application {
|
||||
)
|
||||
}
|
||||
println("[DesktopApp] KOIN initialisiert")
|
||||
// Base URL Log für schnelle Fehlerdiagnose
|
||||
println("[Network] baseUrl=${NetworkConfig.baseUrl}")
|
||||
|
||||
// Starte Netzwerk-Dienste für den POC
|
||||
val koin = GlobalContext.get()
|
||||
try {
|
||||
val wsServer = koin.get<KtorWebSocketServerService>()
|
||||
wsServer.start()
|
||||
val discovery = koin.get<NetworkDiscoveryService>()
|
||||
discovery.startDiscovery()
|
||||
// Im Host-Modus würden wir hier registerService aufrufen
|
||||
// Für den POC registrieren wir den lokalen Host-Dienst immer mit dem WS-Port
|
||||
try {
|
||||
discovery.registerService(wsServer.getPort())
|
||||
println("[DesktopApp] Discovery-Registrierung durchgeführt (Port ${wsServer.getPort()})")
|
||||
} catch (e: Exception) {
|
||||
println("[DesktopApp] Discovery-Registrierung fehlgeschlagen: ${'$'}{e.message}")
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
println("[DesktopApp] POC-Dienste konnten nicht gestartet werden: ${e.message}")
|
||||
}
|
||||
|
||||
// Testdaten für Prototyp laden
|
||||
at.mocode.frontend.shell.desktop.data.Store.seed()
|
||||
} catch (e: Exception) {
|
||||
|
||||
+68
-5
@@ -11,8 +11,7 @@ import androidx.compose.material.icons.filled.ChevronRight
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -20,6 +19,10 @@ import androidx.compose.ui.unit.dp
|
||||
import at.mocode.frontend.core.designsystem.theme.AppColors
|
||||
import at.mocode.frontend.core.designsystem.theme.Dimens
|
||||
import at.mocode.frontend.core.navigation.AppScreen
|
||||
import at.mocode.frontend.core.network.backup.BackupService
|
||||
import at.mocode.frontend.features.device.initialization.data.local.DeviceInitializationSettingsManager
|
||||
import org.koin.core.context.GlobalContext
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
@Composable
|
||||
fun DesktopTopHeader(
|
||||
@@ -84,9 +87,9 @@ fun DesktopTopHeader(
|
||||
}
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(Dimens.SpacingM)
|
||||
) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(Dimens.SpacingM)
|
||||
) {
|
||||
// Sync-Status Indikator
|
||||
val syncColor = if (connectedPeersCount > 0) AppColors.Success else MaterialTheme.colorScheme.outline
|
||||
val syncText = if (connectedPeersCount > 0) "$connectedPeersCount Peer(s)" else "Offline"
|
||||
@@ -126,6 +129,66 @@ fun DesktopTopHeader(
|
||||
color = MaterialTheme.colorScheme.outlineVariant
|
||||
)
|
||||
|
||||
// Diagnose/Tools: Backup jetzt erstellen + Reset-Aktionen
|
||||
var menuOpen by remember { mutableStateOf(false) }
|
||||
Box {
|
||||
Button(onClick = { menuOpen = true }, enabled = true) {
|
||||
Text("Tools")
|
||||
}
|
||||
DropdownMenu(expanded = menuOpen, onDismissRequest = { menuOpen = false }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Backup jetzt erstellen (PoC)") },
|
||||
onClick = {
|
||||
menuOpen = false
|
||||
val settings = DeviceInitializationSettingsManager.loadSettings()
|
||||
val backupPath = settings?.backupPath.orEmpty()
|
||||
val sharedKey = settings?.sharedKey.orEmpty()
|
||||
val deviceName = settings?.deviceName.orEmpty().ifBlank { "Meldestelle-Device" }
|
||||
if (backupPath.isBlank() || sharedKey.isBlank()) {
|
||||
println("[Backup] Abbruch: backupPath oder sharedKey nicht gesetzt. Öffne DeviceInitialization.")
|
||||
onNavigate(AppScreen.DeviceInitialization)
|
||||
} else {
|
||||
try {
|
||||
val backupService: BackupService = GlobalContext.get().get<BackupService> { parametersOf(deviceName) }
|
||||
val result = backupService.exportDelta("poc-backup", backupPath, sharedKey)
|
||||
result.onSuccess { path -> println("[Backup] Erfolgreich exportiert: ${'$'}path") }
|
||||
.onFailure { e -> println("[Backup] Fehler: ${'$'}{e.message}") }
|
||||
} catch (e: Exception) {
|
||||
println("[Backup] Fehler bei der Initialisierung: ${'$'}{e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
Divider()
|
||||
DropdownMenuItem(
|
||||
text = { Text("Einstellungen zurücksetzen") },
|
||||
onClick = {
|
||||
menuOpen = false
|
||||
val res = DeviceInitializationSettingsManager.resetToFactoryDefaults(deleteDatabase = false)
|
||||
if (res.isSuccess) {
|
||||
println("[Reset] settings.json gelöscht: ${'$'}{DeviceInitializationSettingsManager.getSettingsFilePath()}")
|
||||
} else {
|
||||
println("[Reset] Fehler: ${'$'}{res.exceptionOrNull()?.message}")
|
||||
}
|
||||
onNavigate(AppScreen.DeviceInitialization)
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Alles zurücksetzen (inkl. DB)") },
|
||||
onClick = {
|
||||
menuOpen = false
|
||||
val res = DeviceInitializationSettingsManager.resetToFactoryDefaults(deleteDatabase = true)
|
||||
if (res.isSuccess) {
|
||||
println("[Reset] settings + ~/.meldestelle gelöscht")
|
||||
} else {
|
||||
println("[Reset] Fehler: ${'$'}{res.exceptionOrNull()?.message}")
|
||||
}
|
||||
onNavigate(AppScreen.DeviceInitialization)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Profil / Logout Bereich
|
||||
if (isAuthenticated) {
|
||||
Text(
|
||||
|
||||
Reference in New Issue
Block a user