feat(device-initialization, core): Plan-USB-Backup hinzugefügt, BackupService implementiert und UI-Export-Button ergänzt

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-04-29 15:08:11 +02:00
parent b94984043c
commit 62f9472695
8 changed files with 153 additions and 4 deletions
@@ -6,5 +6,5 @@ import at.mocode.frontend.features.device.initialization.presentation.DeviceInit
import org.koin.dsl.module
val deviceInitializationModule = module {
factory { DeviceInitializationViewModel(get()) }
factory { DeviceInitializationViewModel(get(), { deviceName -> get { org.koin.core.parameter.parametersOf(deviceName) } }) }
}
@@ -5,15 +5,18 @@ package at.mocode.frontend.features.device.initialization.presentation
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import at.mocode.frontend.core.network.backup.BackupService
import at.mocode.frontend.core.network.discovery.NetworkDiscoveryService
import at.mocode.frontend.features.device.initialization.domain.model.DeviceInitializationSettings
import at.mocode.frontend.features.device.initialization.domain.model.ExpectedClient
import at.mocode.frontend.features.device.initialization.domain.model.NetworkRole
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlin.time.Clock
class DeviceInitializationViewModel(
private val discoveryService: NetworkDiscoveryService
private val discoveryService: NetworkDiscoveryService,
private val backupServiceProvider: (String) -> BackupService
) : ViewModel() {
private val _uiState = MutableStateFlow(DeviceInitializationUiState())
val uiState: StateFlow<DeviceInitializationUiState> = _uiState.asStateFlow()
@@ -89,6 +92,26 @@ class DeviceInitializationViewModel(
}
}
fun testUsbBackup() {
val settings = uiState.value.settings
if (settings.backupPath.isBlank() || settings.sharedKey.isBlank()) {
println("[DeviceInit] Backup-Pfad oder Shared Key fehlt.")
return
}
viewModelScope.launch {
val service = backupServiceProvider(settings.deviceName)
val testData = "PoC Testdaten - ${settings.deviceName} - ${Clock.System.now()}"
val result = service.exportDelta(testData, settings.backupPath, settings.sharedKey)
if (result.isSuccess) {
println("[DeviceInit] USB-Backup Test erfolgreich.")
} else {
println("[DeviceInit] USB-Backup Test fehlgeschlagen: ${result.exceptionOrNull()?.message}")
}
}
}
fun completeInitialization() {
println("[DeviceInit] Konfiguration wird finalisiert...")
_uiState.update { it.copy(isLocked = true) }
@@ -7,6 +7,7 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Usb
import androidx.compose.material.icons.outlined.Visibility
import androidx.compose.material.icons.outlined.VisibilityOff
import androidx.compose.material3.*
@@ -141,6 +142,18 @@ actual fun DeviceInitializationConfig(
enabled = !uiState.isLocked
)
if (!uiState.isLocked && settings.backupPath.isNotBlank() && settings.sharedKey.isNotBlank()) {
OutlinedButton(
onClick = { viewModel.testUsbBackup() },
modifier = Modifier.padding(top = 4.dp).align(Alignment.End),
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp)
) {
Icon(Icons.Default.Usb, null, modifier = Modifier.size(18.dp))
Spacer(Modifier.width(8.dp))
Text("Plan-USB Test-Export", style = MaterialTheme.typography.labelLarge)
}
}
val printers = remember {
val systemPrinters = PrintServiceLookup.lookupPrintServices(null, null).map { it.name }.toMutableList()
if (!systemPrinters.contains("PDF-Export (Lokal)")) {