Export screen: style improvements

This commit is contained in:
Pierre-Yves Nicolas
2026-02-01 20:56:02 +01:00
parent 0c8974af9a
commit 974666f071

View File

@@ -22,11 +22,11 @@ import androidx.activity.compose.BackHandler
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@@ -42,6 +42,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Clear import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.ContentCopy import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Done
@@ -58,6 +59,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -192,11 +194,11 @@ fun ExportScreen(
) { innerPadding -> ) { innerPadding ->
val containerModifier = Modifier val containerModifier = Modifier
.padding(innerPadding) .padding(innerPadding)
.padding(16.dp) .padding(horizontal = 16.dp)
val onThumbnailClick = navigation.toDocumentScreen val onThumbnailClick = navigation.toDocumentScreen
if (!isLandscape(LocalConfiguration.current)) { if (!isLandscape(LocalConfiguration.current)) {
Column( Column(
modifier = containerModifier.fillMaxSize(), modifier = containerModifier.fillMaxSize().padding(vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
PdfInfosAndResultBar(uiState, currentDocument, onOpen, onThumbnailClick) PdfInfosAndResultBar(uiState, currentDocument, onOpen, onThumbnailClick)
@@ -231,16 +233,55 @@ private fun PdfInfosAndResultBar(
onOpen: (SavedItem) -> Unit, onOpen: (SavedItem) -> Unit,
onThumbnailClick: () -> Unit, onThumbnailClick: () -> Unit,
) { ) {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
PdfInfoCard {
PdfInfos(uiState, currentDocument, onThumbnailClick)
SaveStatusBar(uiState, onOpen)
}
uiState.error?.let {
ErrorBar(it)
}
}
}
@Composable
private fun PdfInfoCard(
content: @Composable ColumnScope.() -> Unit
) {
Surface(
shape = RoundedCornerShape(12.dp),
color = MaterialTheme.colorScheme.surface,
tonalElevation = 1.dp,
modifier = Modifier.fillMaxWidth()
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(12.dp)
) {
content()
}
}
}
@Composable
private fun PdfInfos(
uiState: ExportUiState,
currentDocument: DocumentUiModel,
onThumbnailClick: () -> Unit,
) {
val result = uiState.result val result = uiState.result
Row (horizontalArrangement = Arrangement.spacedBy(16.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
val thumbnail = currentDocument.loadThumbnail(0) val thumbnail = currentDocument.loadThumbnail(0)
thumbnail?.let { thumbnail?.let {
Card( Card(
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
shape = RoundedCornerShape(6.dp), shape = RoundedCornerShape(6.dp),
modifier = Modifier.padding(4.dp) modifier = Modifier
.padding(4.dp)
.heightIn(max = THUMBNAIL_SIZE_DP.dp) .heightIn(max = THUMBNAIL_SIZE_DP.dp)
.widthIn(max = THUMBNAIL_SIZE_DP.dp) .widthIn(max = THUMBNAIL_SIZE_DP.dp)
) { ) {
@@ -283,10 +324,6 @@ private fun PdfInfosAndResultBar(
} }
} }
} }
SaveStatusBar(uiState, onOpen)
if (uiState.error != null) {
ErrorBar(uiState.error)
}
} }
@Composable @Composable
@@ -348,28 +385,31 @@ private fun MainActions(
Column( Column(
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
FilenameTextField(filename, onFilenameChange) ActionSurface {
FilenameTextField(filename, onFilenameChange)
Row( Row(
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
ExportButton( ExportButton(
onClick = onShare, onClick = onShare,
enabled = uiState.result != null, enabled = uiState.result != null,
isPrimary = !uiState.hasSavedOrShared, isPrimary = !uiState.hasSavedOrShared,
icon = Icons.Default.Share, icon = Icons.Default.Share,
text = stringResource(R.string.share), text = stringResource(R.string.share),
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
ExportButton( ExportButton(
onClick = onSave, onClick = onSave,
enabled = uiState.result != null, enabled = uiState.result != null,
isPrimary = !uiState.hasSavedOrShared, isPrimary = !uiState.hasSavedOrShared,
icon = Icons.Default.Download, icon = Icons.Default.Download,
text = stringResource(R.string.save), text = stringResource(R.string.save),
modifier = Modifier.weight(1f).alpha(if (uiState.isSaving) 0.6f else 1f) modifier = Modifier.weight(1f)
) .alpha(if (uiState.isSaving) 0.6f else 1f)
)
}
} }
ExportButton( ExportButton(
icon = Icons.Default.Done, icon = Icons.Default.Done,
@@ -381,6 +421,27 @@ private fun MainActions(
} }
} }
@Composable
private fun ActionSurface(
modifier: Modifier = Modifier,
content: @Composable ColumnScope.() -> Unit
) {
Surface(
shape = RoundedCornerShape(12.dp),
color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f),
tonalElevation = 1.dp,
modifier = modifier.fillMaxWidth()
) {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.padding(12.dp)
) {
content()
}
}
}
@Composable @Composable
fun ExportButton( fun ExportButton(
icon: ImageVector, icon: ImageVector,
@@ -414,41 +475,62 @@ fun ExportButton(
modifier = modifier modifier = modifier
) { ) {
Icon(icon, contentDescription = null) Icon(icon, contentDescription = null)
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(4.dp))
Text(text) Text(text)
} }
} }
@Composable @Composable
private fun SaveInfoBar(savedBundle: SavedBundle, onOpen: (SavedItem) -> Unit) { private fun SaveInfoBar(
val dirName = savedBundle.saveDir?.name?:stringResource(R.string.download_dirname) savedBundle: SavedBundle,
Row( onOpen: (SavedItem) -> Unit,
verticalAlignment = Alignment.CenterVertically, ) {
horizontalArrangement = Arrangement.Absolute.SpaceBetween, val dirName = savedBundle.saveDir?.name ?: stringResource(R.string.download_dirname)
modifier = Modifier val items = savedBundle.items
.fillMaxWidth() val nbFiles = items.size
.background(MaterialTheme.colorScheme.surfaceVariant) val firstFileName = items[0].fileName
.padding(vertical = 8.dp, horizontal = 16.dp),
Surface(
shape = RoundedCornerShape(10.dp),
color = MaterialTheme.colorScheme.surfaceVariant,
tonalElevation = 0.dp,
modifier = Modifier.fillMaxWidth()
) { ) {
val items = savedBundle.items Column(
val nbFiles = items.size verticalArrangement = Arrangement.spacedBy(8.dp),
val firstFileName = items[0].fileName modifier = Modifier.padding(12.dp)
Text( ) {
text = LocalResources.current.getQuantityString(
R.plurals.files_saved_to, Row(verticalAlignment = Alignment.CenterVertically) {
nbFiles, Icon(
nbFiles, firstFileName, dirName imageVector = Icons.Default.CheckCircle,
), contentDescription = null,
style = MaterialTheme.typography.bodyMedium, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.weight(1f), )
) Spacer(Modifier.width(8.dp))
if (nbFiles == 1) { Text(
Spacer(Modifier.width(8.dp)) text = LocalResources.current.getQuantityString(
MainActionButton( R.plurals.files_saved_to,
onClick = { onOpen(items[0]) }, nbFiles,
text = stringResource(R.string.open), nbFiles, firstFileName, dirName
icon = Icons.AutoMirrored.Filled.OpenInNew, ),
) style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(1f)
)
}
if (nbFiles == 1) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
MainActionButton(
onClick = { onOpen(items[0]) },
text = stringResource(R.string.open),
icon = Icons.AutoMirrored.Filled.OpenInNew,
)
}
}
} }
} }
} }