PDF-005
This commit is contained in:
+26
-7
@@ -40,6 +40,7 @@ import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
@@ -56,6 +57,7 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.Lifecycle
|
||||
@@ -67,7 +69,9 @@ import de.medapp.wunddoku.R
|
||||
import de.medapp.wunddoku.domain.model.CheckItem
|
||||
import de.medapp.wunddoku.domain.model.DocumentationBlock
|
||||
import de.medapp.wunddoku.domain.model.Photo
|
||||
import kotlinx.coroutines.launch
|
||||
import de.medapp.wunddoku.pdf.AndroidPdfOpener
|
||||
import de.medapp.wunddoku.pdf.PdfOpenResult
|
||||
import de.medapp.wunddoku.pdf.toUserMessage
|
||||
|
||||
/**
|
||||
* Bearbeitungsansicht für eine Wunddokumentation. Zeigt einen Block nach dem anderen mit
|
||||
@@ -113,15 +117,30 @@ fun DocumentationEditScreen(
|
||||
contract = ActivityResultContracts.PickMultipleVisualMedia(),
|
||||
) { uris: List<Uri> -> viewModel.onPhotosPicked(uris) }
|
||||
|
||||
// Für die kurze Erfolgs-/Fehlermeldung nach einem PDF-Exportversuch (rein zum manuellen
|
||||
// Testen von PDF-001/002 - Öffnen/Teilen der Datei folgt erst in PDF-005/006).
|
||||
// Für die Erfolgs-/Fehlermeldung nach einem PDF-Exportversuch (PDF-001/002) inkl. optionaler
|
||||
// "ANZEIGEN"-Aktion (PDF-005). PdfOpener wird bewusst hier in der Compose-Schicht instanziiert
|
||||
// (mit dem Activity-Context aus LocalContext, analog zum Photo-Picker-Launcher oben) - das
|
||||
// Starten einer externen Activity ist eine UI-/Plattform-Aktion, keine Repository-Aufgabe.
|
||||
val context = LocalContext.current
|
||||
val pdfOpener = remember(context) { AndroidPdfOpener(context) }
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
LaunchedEffect(uiState.pdfExportMessage) {
|
||||
val message = uiState.pdfExportMessage
|
||||
if (message != null) {
|
||||
snackbarHostState.showSnackbar(message)
|
||||
viewModel.dismissPdfExportMessage()
|
||||
val message = uiState.pdfExportMessage ?: return@LaunchedEffect
|
||||
val exportedFile = uiState.lastExportedPdfFile
|
||||
// "ANZEIGEN" wird ausschließlich angeboten, wenn tatsächlich eine erfolgreich erzeugte
|
||||
// Datei vorliegt - bei einem fehlgeschlagenen Export ist exportedFile null und die
|
||||
// Snackbar zeigt keine Aktion an.
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = message,
|
||||
actionLabel = if (exportedFile != null) "ANZEIGEN" else null,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed && exportedFile != null) {
|
||||
when (val openResult = pdfOpener.open(exportedFile)) {
|
||||
PdfOpenResult.Success -> Unit
|
||||
is PdfOpenResult.Failure -> snackbarHostState.showSnackbar(openResult.toUserMessage())
|
||||
}
|
||||
}
|
||||
viewModel.dismissPdfExportMessage()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
|
||||
+25
-8
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
data class DocumentationEditUiState(
|
||||
val documentation: Documentation? = null,
|
||||
@@ -39,6 +40,14 @@ data class DocumentationEditUiState(
|
||||
/** Kurze, fachlich übersetzte Erfolgs-/Fehlermeldung nach einem Exportversuch - einmalig als
|
||||
* Snackbar angezeigt (s. Screen), danach über [DocumentationEditViewModel.dismissPdfExportMessage] geleert. */
|
||||
val pdfExportMessage: String? = null,
|
||||
/**
|
||||
* Die zuletzt erfolgreich erzeugte PDF-Datei dieser Dokumentation (PDF-005: "ANZEIGEN" in
|
||||
* der Snackbar). `null` sowohl vor dem ersten Export als auch nach einem fehlgeschlagenen
|
||||
* Export - "ANZEIGEN" wird nur angeboten, wenn hier tatsächlich eine Datei vorliegt. Wird
|
||||
* bei jedem neuen Exportversuch zunächst zurückgesetzt, damit niemals eine veraltete Datei
|
||||
* referenziert werden kann, während ein neuer Export läuft.
|
||||
*/
|
||||
val lastExportedPdfFile: File? = null,
|
||||
) {
|
||||
val blockCount: Int get() = documentation?.blocks?.size ?: 0
|
||||
}
|
||||
@@ -237,16 +246,24 @@ class DocumentationEditViewModel(
|
||||
*/
|
||||
fun exportPdf() {
|
||||
viewModelScope.launch {
|
||||
_uiState.update { it.copy(pdfExportInProgress = true, pdfExportMessage = null) }
|
||||
_uiState.update {
|
||||
it.copy(pdfExportInProgress = true, pdfExportMessage = null, lastExportedPdfFile = null)
|
||||
}
|
||||
val result = repository.exportPdf(documentationId)
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
pdfExportInProgress = false,
|
||||
pdfExportMessage = when (result) {
|
||||
is PdfExportResult.Success -> "PDF erzeugt: ${result.file.name}"
|
||||
is PdfExportResult.Failure -> "PDF-Erzeugung fehlgeschlagen: ${result.error.toUserMessage()}"
|
||||
},
|
||||
)
|
||||
when (result) {
|
||||
is PdfExportResult.Success -> it.copy(
|
||||
pdfExportInProgress = false,
|
||||
pdfExportMessage = "PDF erfolgreich erstellt",
|
||||
lastExportedPdfFile = result.file,
|
||||
)
|
||||
|
||||
is PdfExportResult.Failure -> it.copy(
|
||||
pdfExportInProgress = false,
|
||||
pdfExportMessage = "PDF-Erzeugung fehlgeschlagen: ${result.error.toUserMessage()}",
|
||||
lastExportedPdfFile = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user