Skip to content

Commit bbee4ba

Browse files
committed
Home screen: change layout to focus on "New scan"
1 parent 0b01a83 commit bbee4ba

File tree

7 files changed

+135
-71
lines changed

7 files changed

+135
-71
lines changed

app/src/main/java/org/fairscan/app/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class MainActivity : ComponentActivity() {
8080
cameraPermission = cameraPermission,
8181
currentDocument = document,
8282
navigation = navigation,
83-
onStartNewScan = navigation.toCameraScreen,
83+
onClearScan = { viewModel.startNewDocument() },
8484
recentDocuments = recentDocs,
8585
onOpenPdf = { file -> openPdf(file.toUri()) }
8686
)

app/src/main/java/org/fairscan/app/MainViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ class MainViewModel(
355355
current.toBuilder()
356356
.addDocuments(0, newDoc)
357357
.also { builder ->
358-
while (builder.documentsCount > 10) {
358+
while (builder.documentsCount > 3) {
359359
builder.removeDocuments(builder.documentsCount - 1)
360360
}
361361
}

app/src/main/java/org/fairscan/app/view/HomeScreen.kt

Lines changed: 117 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,34 @@ import androidx.compose.foundation.layout.fillMaxSize
2323
import androidx.compose.foundation.layout.fillMaxWidth
2424
import androidx.compose.foundation.layout.height
2525
import androidx.compose.foundation.layout.padding
26+
import androidx.compose.foundation.layout.size
2627
import androidx.compose.foundation.layout.width
2728
import androidx.compose.foundation.rememberScrollState
29+
import androidx.compose.foundation.shape.RoundedCornerShape
2830
import androidx.compose.foundation.verticalScroll
2931
import androidx.compose.material.icons.Icons
32+
import androidx.compose.material.icons.filled.DeleteOutline
3033
import androidx.compose.material.icons.filled.PhotoCamera
3134
import androidx.compose.material.icons.filled.PictureAsPdf
32-
import androidx.compose.material3.BottomAppBar
3335
import androidx.compose.material3.Button
36+
import androidx.compose.material3.ButtonDefaults
3437
import androidx.compose.material3.Card
3538
import androidx.compose.material3.ExperimentalMaterial3Api
3639
import androidx.compose.material3.HorizontalDivider
3740
import androidx.compose.material3.Icon
41+
import androidx.compose.material3.IconButton
3842
import androidx.compose.material3.ListItem
3943
import androidx.compose.material3.MaterialTheme
4044
import androidx.compose.material3.Scaffold
45+
import androidx.compose.material3.Surface
4146
import androidx.compose.material3.Text
4247
import androidx.compose.material3.TopAppBar
4348
import androidx.compose.runtime.Composable
44-
import androidx.compose.runtime.mutableStateOf
45-
import androidx.compose.runtime.saveable.rememberSaveable
4649
import androidx.compose.ui.Alignment
4750
import androidx.compose.ui.Modifier
51+
import androidx.compose.ui.draw.clip
4852
import androidx.compose.ui.graphics.asImageBitmap
53+
import androidx.compose.ui.layout.ContentScale
4954
import androidx.compose.ui.platform.LocalContext
5055
import androidx.compose.ui.res.stringResource
5156
import androidx.compose.ui.tooling.preview.Preview
@@ -65,11 +70,10 @@ fun HomeScreen(
6570
cameraPermission: CameraPermissionState,
6671
currentDocument: DocumentUiModel,
6772
navigation: Navigation,
68-
onStartNewScan: () -> Unit,
73+
onClearScan: () -> Unit,
6974
recentDocuments: List<RecentDocumentUiState>,
7075
onOpenPdf: (File) -> Unit,
7176
) {
72-
val showCloseDocDialog = rememberSaveable { mutableStateOf(false) }
7377
Scaffold (
7478
topBar = {
7579
TopAppBar(
@@ -79,52 +83,38 @@ fun HomeScreen(
7983
}
8084
)
8185
},
82-
bottomBar = {
83-
BottomAppBar {
84-
Spacer(Modifier.weight(1f))
85-
MainActionButton(
86-
onClick = {
87-
if (currentDocument.isEmpty()) {
88-
onStartNewScan()
89-
} else {
90-
showCloseDocDialog.value = true
91-
}
92-
},
93-
icon = Icons.Default.PhotoCamera,
94-
text = stringResource(R.string.start_a_new_scan),
95-
modifier = Modifier
96-
.padding(12.dp)
97-
.height(48.dp),
98-
)
99-
}
100-
}
10186
) { padding ->
10287
Column (
10388
modifier = Modifier
10489
.padding(padding)
10590
.fillMaxSize()
10691
.verticalScroll(rememberScrollState())
10792
) {
93+
Spacer(Modifier.weight(1f))
94+
10895
if (!cameraPermission.isGranted) {
10996
CameraPermissionRationale(cameraPermission)
97+
} else {
98+
ScanButton(
99+
onClick = {
100+
onClearScan()
101+
navigation.toCameraScreen()
102+
},
103+
Modifier.align(Alignment.CenterHorizontally)
104+
)
110105
}
111106

112-
if (!currentDocument.isEmpty()) {
113-
SectionTitle(stringResource(R.string.current_document))
114-
CurrentDocumentCard(currentDocument, navigation)
115-
}
107+
Spacer(Modifier.weight(1f))
116108

117-
if (recentDocuments.isNotEmpty()) {
118-
SectionTitle(stringResource(R.string.last_saved_documents))
109+
if (!currentDocument.isEmpty()) {
110+
OngoingScanBanner(
111+
currentDocument,
112+
onResumeScan = navigation.toDocumentScreen,
113+
onClearScan = onClearScan,
114+
)
115+
} else if (recentDocuments.isNotEmpty()) {
119116
RecentDocumentList(recentDocuments, onOpenPdf)
120117
}
121-
122-
if (showCloseDocDialog.value) {
123-
NewDocumentDialog(
124-
onConfirm = onStartNewScan,
125-
showCloseDocDialog,
126-
stringResource(R.string.new_document))
127-
}
128118
}
129119
}
130120
}
@@ -139,44 +129,95 @@ private fun CameraPermissionRationale(cameraPermission: CameraPermissionState) {
139129
Column(Modifier.padding(16.dp)) {
140130
Text(
141131
stringResource(R.string.camera_permission_rationale),
142-
style = MaterialTheme.typography.bodyMedium
143132
)
144133
Spacer(Modifier.height(8.dp))
145-
Button(onClick = { cameraPermission.request() }) {
134+
Button(
135+
onClick = { cameraPermission.request() },
136+
modifier = Modifier.align(Alignment.CenterHorizontally)
137+
) {
146138
Text(stringResource(R.string.grant_permission))
147139
}
148140
}
149141
}
150142
}
151143

152144
@Composable
153-
private fun CurrentDocumentCard(
145+
fun ScanButton(onClick: () -> Unit, modifier: Modifier) {
146+
Button(
147+
onClick = onClick,
148+
modifier = modifier.padding(32.dp),
149+
elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp)
150+
) {
151+
Icon(
152+
imageVector = Icons.Default.PhotoCamera,
153+
contentDescription = null,
154+
modifier = Modifier.size(48.dp)
155+
)
156+
Spacer(Modifier.width(8.dp))
157+
Text(
158+
text = stringResource(R.string.scan_button),
159+
style = MaterialTheme.typography.titleLarge
160+
)
161+
162+
}
163+
}
164+
165+
@Composable
166+
fun OngoingScanBanner(
154167
currentDocument: DocumentUiModel,
155-
navigation: Navigation,
168+
onResumeScan: () -> Unit,
169+
onClearScan: () -> Unit
156170
) {
157-
Card(
158-
modifier = Modifier
159-
.fillMaxWidth()
160-
.padding(horizontal = 12.dp, vertical = 6.dp)
171+
Surface(
172+
tonalElevation = 2.dp,
173+
shadowElevation = 4.dp,
161174
) {
162175
Row(
163-
verticalAlignment = Alignment.CenterVertically,
164-
modifier = Modifier.padding(12.dp)
176+
modifier = Modifier
177+
.fillMaxWidth()
178+
.padding(8.dp),
179+
verticalAlignment = Alignment.CenterVertically
165180
) {
166181
currentDocument.load(0)?.let {
167182
Image(
168183
bitmap = it.asImageBitmap(),
169184
contentDescription = null,
170185
modifier = Modifier
171-
.height(100.dp)
172-
.padding(4.dp)
186+
.size(60.dp)
187+
.clip(RoundedCornerShape(4.dp)),
188+
contentScale = ContentScale.Fit
189+
)
190+
}
191+
192+
Spacer(Modifier.width(12.dp))
193+
194+
Column(
195+
modifier = Modifier.weight(1f)
196+
) {
197+
Text(
198+
text = stringResource(R.string.scan_in_progress),
199+
style = MaterialTheme.typography.bodyLarge
200+
)
201+
Text(
202+
text = pageCountText(currentDocument.pageCount()),
203+
style = MaterialTheme.typography.bodyMedium,
204+
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f))
205+
}
206+
207+
IconButton(
208+
onClick = onClearScan,
209+
modifier = Modifier.size(24.dp)
210+
) {
211+
Icon(
212+
imageVector = Icons.Default.DeleteOutline,
213+
contentDescription = stringResource(R.string.discard_scan),
214+
tint = MaterialTheme.colorScheme.primary
173215
)
174216
}
175217
Spacer(Modifier.width(12.dp))
176-
Column(Modifier.weight(1f)) {
177-
Text(pageCountText(currentDocument.pageCount()))
218+
Button(onClick = onResumeScan) {
219+
Text(stringResource(R.string.resume))
178220
}
179-
MainActionButton(navigation.toDocumentScreen, stringResource(R.string.open))
180221
}
181222
}
182223
}
@@ -186,8 +227,13 @@ private fun RecentDocumentList(
186227
recentDocuments: List<RecentDocumentUiState>,
187228
onOpenPdf: (File) -> Unit
188229
) {
230+
HorizontalDivider()
231+
Text(
232+
stringResource(R.string.last_saved_documents),
233+
modifier = Modifier.padding(start = 12.dp, top = 16.dp, bottom = 8.dp)
234+
)
189235
Column {
190-
val maxListSize = 5
236+
val maxListSize = 3
191237
recentDocuments.subList(0, min(maxListSize, recentDocuments.size)).forEach { doc ->
192238
ListItem(
193239
headlineContent = { Text(doc.file.name) },
@@ -202,29 +248,19 @@ private fun RecentDocumentList(
202248
},
203249
modifier = Modifier.clickable { onOpenPdf(doc.file) }
204250
)
205-
HorizontalDivider()
206251
}
207252
}
208253
}
209254

210-
@Composable
211-
private fun SectionTitle(text: String) {
212-
Text(
213-
text,
214-
style = MaterialTheme.typography.titleLarge,
215-
modifier = Modifier.padding(start = 12.dp, top = 16.dp, bottom = 8.dp)
216-
)
217-
}
218-
219255
@Preview
220256
@Composable
221257
fun HomeScreenPreviewOnFirstLaunch() {
222258
MyScanTheme {
223259
HomeScreen(
224260
cameraPermission = rememberCameraPermissionState(),
225-
currentDocument = DocumentUiModel(listOf()) { _ -> null },
261+
currentDocument = fakeDocument(),
226262
navigation = dummyNavigation(),
227-
onStartNewScan = {},
263+
onClearScan = {},
228264
recentDocuments = listOf(),
229265
onOpenPdf = {},
230266
)
@@ -241,7 +277,22 @@ fun HomeScreenPreviewWithCurrentDocument() {
241277
listOf("gallica.bnf.fr-bpt6k5530456s-1.jpg"),
242278
LocalContext.current),
243279
navigation = dummyNavigation(),
244-
onStartNewScan = {},
280+
onClearScan = {},
281+
recentDocuments = listOf(),
282+
onOpenPdf = {},
283+
)
284+
}
285+
}
286+
287+
@Preview
288+
@Composable
289+
fun HomeScreenPreviewWithLastSavedFiles() {
290+
MyScanTheme {
291+
HomeScreen(
292+
cameraPermission = rememberCameraPermissionState(),
293+
currentDocument = fakeDocument(),
294+
navigation = dummyNavigation(),
295+
onClearScan = {},
245296
recentDocuments = listOf(
246297
RecentDocumentUiState(File("/path/my_file.pdf"), 1755971180000, 3),
247298
RecentDocumentUiState(File("/path/scan2.pdf"), 1755000500000, 1)

app/src/main/java/org/fairscan/app/view/PreviewUtils.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ fun dummyNavigation(): Navigation {
2222
return Navigation({}, {}, {}, {}, {}, {}, {})
2323
}
2424

25+
fun fakeDocument(): DocumentUiModel {
26+
return DocumentUiModel(listOf()) { _ -> null }
27+
}
28+
2529
fun fakeDocument(pageIds: List<String>, context: Context): DocumentUiModel {
2630
return DocumentUiModel(pageIds) { id ->
2731
context.assets.open(id).use { input ->

app/src/main/res/values-de/strings.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<string name="current_document">Aktuelles Dokument</string>
1414
<string name="delete_page">Seite löschen</string>
1515
<string name="delete_page_warning">Möchten Sie diese Seite löschen?</string>
16+
<string name="discard_scan">Löschen</string>
1617
<string name="document">Dokument</string>
1718
<string name="end_scan">Scan beenden</string>
1819
<string name="error">Fehler: %1$s</string>
@@ -34,10 +35,12 @@
3435
<string name="open">Öffnen</string>
3536
<string name="open_pdf">PDF öffnen</string>
3637
<string name="pdf_saved_to">PDF gespeichert unter %1$s</string>
38+
<string name="resume">Fortsetzen</string>
3739
<string name="save">Speichern</string>
40+
<string name="scan_button">Neuer Scan</string>
41+
<string name="scan_in_progress">Scan läuft</string>
3842
<string name="share">Teilen</string>
3943
<string name="share_pdf">PDF teilen</string>
40-
<string name="start_a_new_scan">Neuen Scan starten</string>
4144
<string name="unknown_size">Unbekannte Größe</string>
4245
<string name="version">Version</string>
4346
<string name="view_the_full_license">Vollständige Lizenz anzeigen</string>

app/src/main/res/values-fr/strings.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<string name="current_document">Document en cours</string>
1414
<string name="delete_page">Supprimer la page</string>
1515
<string name="delete_page_warning">Voulez-vous supprimer cette page ?</string>
16+
<string name="discard_scan">Supprimer le scan</string>
1617
<string name="document">Document</string>
1718
<string name="end_scan">Terminer le scan</string>
1819
<string name="error">Erreur : %1$s</string>
@@ -34,10 +35,12 @@
3435
<string name="open">Ouvrir</string>
3536
<string name="open_pdf">Ouvrir le PDF</string>
3637
<string name="pdf_saved_to">PDF enregistré dans %1$s</string>
38+
<string name="resume">Reprendre</string>
3739
<string name="save">Enregistrer</string>
40+
<string name="scan_button">Nouveau scan</string>
41+
<string name="scan_in_progress">Scan en cours</string>
3842
<string name="share">Partager</string>
3943
<string name="share_pdf">Partager le PDF</string>
40-
<string name="start_a_new_scan">Nouveau scan</string>
4144
<string name="unknown_size">Taille inconnue</string>
4245
<string name="version">Version</string>
4346
<string name="view_the_full_license">Voir la licence complète</string>

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<string name="current_document">Current document</string>
1515
<string name="delete_page">Delete page</string>
1616
<string name="delete_page_warning">Do you want to delete this page?</string>
17+
<string name="discard_scan">Discard scan</string>
1718
<string name="document">Document</string>
1819
<string name="end_scan">End scan</string>
1920
<string name="error">Error: %1$s</string>
@@ -35,10 +36,12 @@
3536
<string name="open">Open</string>
3637
<string name="open_pdf">Open PDF</string>
3738
<string name="pdf_saved_to">PDF saved to %1$s</string>
39+
<string name="resume">Resume</string>
3840
<string name="save">Save</string>
41+
<string name="scan_button">New Scan</string>
42+
<string name="scan_in_progress">Scan in progress</string>
3943
<string name="share">Share</string>
4044
<string name="share_pdf">Share PDF</string>
41-
<string name="start_a_new_scan">Start a new scan</string>
4245
<string name="unknown_size">Unknown size</string>
4346
<string name="version">Version</string>
4447
<string name="view_the_full_license">View the full license</string>

0 commit comments

Comments
 (0)