Export screen: add a spinner during the save operation

This commit is contained in:
Pierre-Yves Nicolas
2026-01-29 21:07:18 +01:00
parent 85c966a7aa
commit f32b4f8799
3 changed files with 41 additions and 13 deletions

View File

@@ -56,6 +56,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
@@ -117,19 +118,25 @@ fun ExportScreenWrapper(
uiState = uiState,
navigation = navigation,
onShare = {
if (!uiState.isSaving) {
ensureCorrectFileName()
pdfActions.share()
}
},
onSave = {
if (!uiState.isSaving) {
ensureCorrectFileName()
pdfActions.save()
}
},
onOpen = pdfActions.open,
onCloseScan = {
if (!uiState.isSaving) {
if (uiState.hasSavedOrShared)
onCloseScan()
else
showConfirmationDialog.value = true
}
},
)
@@ -235,15 +242,32 @@ private fun TextFieldAndPdfInfos(
)
}
}
if (uiState.savedBundle != null) {
SaveInfoBar(uiState.savedBundle, onOpen)
}
SaveStatusBar(uiState, onOpen)
if (uiState.errorMessage != null) {
ErrorBar(uiState.errorMessage)
}
}
@Composable
private fun SaveStatusBar(
uiState: ExportUiState,
onOpen: (SavedItem) -> Unit,
) {
when {
uiState.isSaving -> {
Row(verticalAlignment = Alignment.CenterVertically) {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp
)
}
}
uiState.savedBundle != null -> {
SaveInfoBar(uiState.savedBundle, onOpen)
}
}
}
@Composable
private fun FilenameTextField(
filename: MutableState<String>,
@@ -299,7 +323,7 @@ private fun MainActions(
isPrimary = !uiState.hasSavedOrShared,
icon = Icons.Default.Download,
text = stringResource(R.string.save),
modifier = Modifier.weight(1f)
modifier = Modifier.weight(1f).alpha(if (uiState.isSaving) 0.6f else 1f)
)
}
ExportButton(

View File

@@ -20,6 +20,7 @@ import org.fairscan.app.ui.screens.settings.ExportFormat
data class ExportUiState(
val format: ExportFormat = ExportFormat.PDF,
val isGenerating: Boolean = false,
val isSaving: Boolean = false,
val result: ExportResult? = null,
val savedBundle: SavedBundle? = null,
val hasShared: Boolean = false,

View File

@@ -193,6 +193,7 @@ class ExportViewModel(container: AppContainer, val imageRepository: ImageReposit
fun onRequestSave(context: Context) {
viewModelScope.launch {
_uiState.update {it.copy(isSaving = true, errorMessage = null, savedBundle = null) }
try {
// Must not run on the main thread: some SAF providers (e.g. Nextcloud)
// may perform network I/O
@@ -208,6 +209,8 @@ class ExportViewModel(container: AppContainer, val imageRepository: ImageReposit
} catch (e: Exception) {
logger.e("FairScan", "Failed to save PDF", e)
_events.emit(ExportEvent.SaveError)
} finally {
_uiState.update { it.copy(isSaving = false) }
}
}
}