From 7f34c395a3e45380a40b73b87476600169859653 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Nicolas <6371790+pynicolas@users.noreply.github.com> Date: Tue, 8 Jul 2025 20:57:15 +0200 Subject: [PATCH] AboutLibraries: display libraries --- app/build.gradle.kts | 1 + .../java/org/mydomain/myscan/MainActivity.kt | 7 +- .../java/org/mydomain/myscan/Navigation.kt | 2 + .../org/mydomain/myscan/view/AboutScreen.kt | 38 +++++++---- .../mydomain/myscan/view/DocumentScreen.kt | 3 +- .../mydomain/myscan/view/LibrariesScreen.kt | 67 +++++++++++++++++++ gradle/libs.versions.toml | 1 + 7 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/org/mydomain/myscan/view/LibrariesScreen.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a6003eb..c3a1e56 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -92,6 +92,7 @@ dependencies { implementation(libs.pdfbox) implementation(libs.icons.extended) implementation(libs.zoomable) + implementation(libs.aboutlibraries.compose.m3) testImplementation(libs.junit) testImplementation(libs.assertj) diff --git a/app/src/main/java/org/mydomain/myscan/MainActivity.kt b/app/src/main/java/org/mydomain/myscan/MainActivity.kt index 61bae12..446cb9f 100644 --- a/app/src/main/java/org/mydomain/myscan/MainActivity.kt +++ b/app/src/main/java/org/mydomain/myscan/MainActivity.kt @@ -41,6 +41,7 @@ import org.mydomain.myscan.ui.theme.MyScanTheme import org.mydomain.myscan.view.AboutScreen import org.mydomain.myscan.view.CameraScreen import org.mydomain.myscan.view.DocumentScreen +import org.mydomain.myscan.view.LibrariesScreen import org.opencv.android.OpenCVLoader import java.io.File @@ -62,6 +63,7 @@ class MainActivity : ComponentActivity() { toCameraScreen = { viewModel.navigateTo(Screen.Camera) }, toDocumentScreen = { viewModel.navigateTo(Screen.Document()) }, toAboutScreen = { viewModel.navigateTo(Screen.About) }, + toLibrariesScreen = { viewModel.navigateTo(Screen.Libraries) }, back = { viewModel.navigateBack() } ) when (val screen = currentScreen) { @@ -95,7 +97,10 @@ class MainActivity : ComponentActivity() { ) } is Screen.About -> { - AboutScreen(onBack = navigation.back) + AboutScreen(onBack = navigation.back, onViewLibraries = navigation.toLibrariesScreen) + } + is Screen.Libraries -> { + LibrariesScreen(onBack = navigation.back) } } } diff --git a/app/src/main/java/org/mydomain/myscan/Navigation.kt b/app/src/main/java/org/mydomain/myscan/Navigation.kt index e7a76e4..afdb36f 100644 --- a/app/src/main/java/org/mydomain/myscan/Navigation.kt +++ b/app/src/main/java/org/mydomain/myscan/Navigation.kt @@ -18,11 +18,13 @@ sealed class Screen { object Camera : Screen() data class Document(val initialPage: Int = 0) : Screen() object About : Screen() + object Libraries : Screen() } data class Navigation( val toCameraScreen: () -> Unit, val toDocumentScreen: () -> Unit, val toAboutScreen: () -> Unit, + val toLibrariesScreen: () -> Unit, val back: () -> Unit, ) diff --git a/app/src/main/java/org/mydomain/myscan/view/AboutScreen.kt b/app/src/main/java/org/mydomain/myscan/view/AboutScreen.kt index 28cf86e..f4f1791 100644 --- a/app/src/main/java/org/mydomain/myscan/view/AboutScreen.kt +++ b/app/src/main/java/org/mydomain/myscan/view/AboutScreen.kt @@ -57,8 +57,8 @@ import org.mydomain.myscan.ui.theme.MyScanTheme @OptIn(ExperimentalMaterial3Api::class) @Composable -fun AboutScreen(onBack: () -> Unit) { - val showLicenceDialog = rememberSaveable { mutableStateOf(false) } +fun AboutScreen(onBack: () -> Unit, onViewLibraries: () -> Unit) { + val showLicenseDialog = rememberSaveable { mutableStateOf(false) } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) Scaffold( topBar = { @@ -72,15 +72,19 @@ fun AboutScreen(onBack: () -> Unit) { ) } ) { paddingValues -> - AboutContent(Modifier.padding(paddingValues), showLicenceDialog) + AboutContent(modifier = Modifier.padding(paddingValues), showLicenseDialog, onViewLibraries) } - if (showLicenceDialog.value) { - LicenseBottomSheet(sheetState, onDismiss = { showLicenceDialog.value = false }) + if (showLicenseDialog.value) { + LicenseBottomSheet(sheetState, onDismiss = { showLicenseDialog.value = false }) } } @Composable -fun AboutContent(modifier: Modifier = Modifier, showLicenceDialog: MutableState) { +fun AboutContent( + modifier: Modifier = Modifier, + showLicenseDialog: MutableState, + onViewLibraries: () -> Unit, + ) { Column( modifier = modifier .fillMaxSize() @@ -104,7 +108,7 @@ fun AboutContent(modifier: Modifier = Modifier, showLicenceDialog: MutableState< Text( "Version", - style = MaterialTheme.typography.titleSmall + style = MaterialTheme.typography.titleMedium ) Text(BuildConfig.VERSION_NAME) @@ -112,7 +116,7 @@ fun AboutContent(modifier: Modifier = Modifier, showLicenceDialog: MutableState< Text( "License", - style = MaterialTheme.typography.titleSmall + style = MaterialTheme.typography.titleMedium ) Text( "This application is licensed under the GNU General Public License v3.0.", @@ -121,19 +125,26 @@ fun AboutContent(modifier: Modifier = Modifier, showLicenceDialog: MutableState< Text( text = "View the full license", style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.clickable() { showLicenceDialog.value = true }, + modifier = Modifier.clickable { showLicenseDialog.value = true }, color = MaterialTheme.colorScheme.primary ) Spacer(Modifier.height(16.dp)) Text( - "This application is based on the following open-source libraries", - style = MaterialTheme.typography.titleSmall + "Libraries", + style = MaterialTheme.typography.titleMedium ) Text( - "• CameraX\n• Jetpack Compose\n• LiteRT\n• OpenCV\n• PDFBox", + "This application uses several open-source libraries, including:\n" + + "• CameraX\n• Jetpack Compose\n• LiteRT\n• OpenCV\n• PDFBox", style = MaterialTheme.typography.bodyMedium) + Text( + text = "View full list", + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.clickable(onClick = onViewLibraries), + color = MaterialTheme.colorScheme.primary + ) Spacer(Modifier.height(32.dp)) } @@ -194,11 +205,10 @@ fun LicenseBottomSheet( } } - @Preview @Composable fun AboutScreenPreview() { MyScanTheme { - AboutScreen(onBack = {}) + AboutScreen(onBack = {}, onViewLibraries = {}) } } \ No newline at end of file diff --git a/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt b/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt index f71bb24..886ef20 100644 --- a/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt +++ b/app/src/main/java/org/mydomain/myscan/view/DocumentScreen.kt @@ -284,7 +284,8 @@ fun DocumentScreenPreview() { BitmapFactory.decodeStream(input) } }, - navigation = Navigation({}, {}, {}, {}), + navigation = Navigation( + {}, {}, {}, {}, {}), pdfActions = PdfGenerationActions( {}, {}, {}, MutableStateFlow(PdfGenerationUiState()), diff --git a/app/src/main/java/org/mydomain/myscan/view/LibrariesScreen.kt b/app/src/main/java/org/mydomain/myscan/view/LibrariesScreen.kt new file mode 100644 index 0000000..b6add86 --- /dev/null +++ b/app/src/main/java/org/mydomain/myscan/view/LibrariesScreen.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2025 Pierre-Yves Nicolas + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +package org.mydomain.myscan.view + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults +import com.mikepenz.aboutlibraries.ui.compose.android.rememberLibraries +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer +import org.mydomain.myscan.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LibrariesScreen(onBack: () -> Unit) { + Scaffold( + topBar = { + TopAppBar( + title = { Text("Open-source libraries") }, + navigationIcon = { + IconButton(onClick = onBack) { + Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back") + } + } + ) + } + ) { padding -> + Surface(modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + val librariesState by rememberLibraries(R.raw.aboutlibraries) + LibrariesContainer( + libraries = librariesState, + textStyles = LibraryDefaults.libraryTextStyles( + nameTextStyle = MaterialTheme.typography.titleMedium, + licensesTextStyle = MaterialTheme.typography.labelSmall + ), + ) + } + } +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2dca2f7..352cce3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -46,6 +46,7 @@ litert-metadata = { group = "com.google.ai.edge.litert", name = "litert-metadata opencv = { group="org.opencv", name="opencv", version.ref = "opencv" } pdfbox = { group = "com.tom-roush", name = "pdfbox-android", version.ref = "pdfbox" } zoomable = { group = "net.engawapg.lib", name = "zoomable", version.ref = "zoomable" } +aboutlibraries-compose-m3 = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "aboutLibraries" } assertj = { group="org.assertj", name="assertj-core", version.ref = "assertj" }