Export: avoid silencing issues in applyRenaming
This commit is contained in:
@@ -187,7 +187,7 @@ class MainActivity : ComponentActivity() {
|
||||
pdfActions = ExportActions(
|
||||
prepareExportIfNeeded = exportViewModel::prepareExportIfNeeded,
|
||||
setFilename = exportViewModel::setFilename,
|
||||
share = { share(exportViewModel.applyRenaming(), exportViewModel) },
|
||||
share = { exportViewModel.onShareClicked() },
|
||||
save = { exportViewModel.onSaveClicked() },
|
||||
open = { item -> openUri(item.uri, item.format.mimeType) },
|
||||
),
|
||||
@@ -324,6 +324,9 @@ class MainActivity : ComponentActivity() {
|
||||
exportViewModel.onRequestSave(context)
|
||||
}
|
||||
}
|
||||
is ExportEvent.Share -> {
|
||||
share(event.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,10 +346,8 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun share(result: ExportResult?, viewModel: ExportViewModel) {
|
||||
if (result == null || result.files.isEmpty()) return
|
||||
|
||||
viewModel.setAsShared()
|
||||
private fun share(result: ExportResult) {
|
||||
if (result.files.isEmpty()) return
|
||||
|
||||
val uris = result.files.map(::uriForFile)
|
||||
val intent = Intent().apply {
|
||||
|
||||
@@ -584,7 +584,7 @@ private fun ErrorBar(error: ExportError) {
|
||||
@Composable
|
||||
private fun ExportError.toDisplayText(): Pair<String, String?> {
|
||||
return when (this) {
|
||||
is ExportError.OnPrepare -> {
|
||||
is ExportError.OnPrepareOrShare -> {
|
||||
val summary = message
|
||||
val details = throwable.message
|
||||
summary to details
|
||||
@@ -684,7 +684,7 @@ fun PreviewExportScreenAfterSave() {
|
||||
fun ExportScreenPreviewWithError() {
|
||||
ExportPreviewToCustomize(
|
||||
ExportUiState(error =
|
||||
ExportError.OnPrepare("PDF generation failed", IOException("Boom")))
|
||||
ExportError.OnPrepareOrShare("PDF generation failed", IOException("Boom")))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ data class SaveDir(
|
||||
|
||||
sealed class ExportError {
|
||||
|
||||
data class OnPrepare(
|
||||
data class OnPrepareOrShare(
|
||||
val message: String,
|
||||
val throwable: Throwable,
|
||||
) : ExportError()
|
||||
|
||||
@@ -61,6 +61,7 @@ import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
sealed interface ExportEvent {
|
||||
data object RequestSave : ExportEvent
|
||||
data class Share(val result: ExportResult) : ExportEvent
|
||||
}
|
||||
|
||||
class ExportViewModel(container: AppContainer, val imageRepository: ImageRepository): ViewModel() {
|
||||
@@ -160,7 +161,7 @@ class ExportViewModel(container: AppContainer, val imageRepository: ImageReposit
|
||||
val message = "Failed to prepare $exportFormat export"
|
||||
logger.e("FairScan", message, e)
|
||||
_uiState.update {
|
||||
it.copy(error = ExportError.OnPrepare(message, e))
|
||||
it.copy(error = ExportError.OnPrepareOrShare(message, e))
|
||||
}
|
||||
} finally {
|
||||
_uiState.update { it.copy(isGenerating = false) }
|
||||
@@ -184,29 +185,27 @@ class ExportViewModel(container: AppContainer, val imageRepository: ImageReposit
|
||||
ExportResult.Jpeg(files, sizeInBytes)
|
||||
}
|
||||
|
||||
fun setAsShared() {
|
||||
_uiState.update { it.copy(hasShared = true) }
|
||||
private fun renameFile(source: File, target: File) {
|
||||
if (source.absolutePath == target.absolutePath) return
|
||||
if (target.exists() && !target.delete()) {
|
||||
throw IOException("Cannot delete existing file ${target.absolutePath}")
|
||||
}
|
||||
if (!source.renameTo(target)) {
|
||||
throw IOException("Failed to rename ${source.name} to ${target.name}")
|
||||
}
|
||||
}
|
||||
|
||||
fun applyRenaming(): ExportResult? {
|
||||
val result = _uiState.value.result ?: return null
|
||||
private fun applyRenaming(): ExportResult {
|
||||
val result = _uiState.value.result
|
||||
?: throw IllegalStateException("Export result missing")
|
||||
ensureValidFilename()
|
||||
val filename = _uiState.value.filename
|
||||
when (result) {
|
||||
val updated = when (result) {
|
||||
is ExportResult.Pdf -> {
|
||||
val fileName = FileManager.addPdfExtensionIfMissing(filename)
|
||||
val newFile = File(result.file.parentFile, fileName)
|
||||
val tempFile = result.file
|
||||
if (tempFile.absolutePath != newFile.absolutePath) {
|
||||
if (newFile.exists()) newFile.delete()
|
||||
val success = tempFile.renameTo(newFile)
|
||||
if (!success) return null
|
||||
_uiState.update {
|
||||
it.copy(result = ExportResult.Pdf(
|
||||
newFile, result.sizeInBytes, result.pageCount)
|
||||
)
|
||||
}
|
||||
}
|
||||
renameFile(result.file, newFile)
|
||||
ExportResult.Pdf(newFile, result.sizeInBytes, result.pageCount)
|
||||
}
|
||||
is ExportResult.Jpeg -> {
|
||||
val base = filename.removeSuffix(".jpg")
|
||||
@@ -214,17 +213,28 @@ class ExportViewModel(container: AppContainer, val imageRepository: ImageReposit
|
||||
val renamedFiles = files.mapIndexed { index, file ->
|
||||
val indexSuffix = if (files.size == 1) "" else "_${index + 1}"
|
||||
val newFile = File(file.parentFile, "${base}${indexSuffix}.jpg")
|
||||
if (file.absolutePath != newFile.absolutePath) {
|
||||
if (newFile.exists()) newFile.delete()
|
||||
file.renameTo(newFile)
|
||||
}
|
||||
renameFile(file, newFile)
|
||||
newFile
|
||||
}
|
||||
val updated = result.copy(jpegFiles = renamedFiles)
|
||||
_uiState.update { it.copy(result = updated) }
|
||||
result.copy(jpegFiles = renamedFiles)
|
||||
}
|
||||
}
|
||||
_uiState.update { it.copy(result = updated) }
|
||||
return updated
|
||||
}
|
||||
|
||||
fun onShareClicked() {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = applyRenaming()
|
||||
_events.emit(ExportEvent.Share(result))
|
||||
_uiState.update { it.copy(hasShared = true) }
|
||||
} catch (e: Exception) {
|
||||
val message = "Failed to prepare share"
|
||||
logger.e("FairScan", message, e)
|
||||
_uiState.update { it.copy(error = ExportError.OnPrepareOrShare(message, e)) }
|
||||
}
|
||||
}
|
||||
return _uiState.value.result
|
||||
}
|
||||
|
||||
fun onSaveClicked() {
|
||||
|
||||
Reference in New Issue
Block a user