Add contact information to the About screen
This commit is contained in:
@@ -14,8 +14,10 @@
|
||||
*/
|
||||
package org.fairscan.app.view
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -25,10 +27,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Email
|
||||
import androidx.compose.material.icons.filled.Language
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -48,10 +53,15 @@ 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.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import org.fairscan.app.BuildConfig
|
||||
import org.fairscan.app.R
|
||||
import org.fairscan.app.ui.theme.MyScanTheme
|
||||
@@ -83,71 +93,116 @@ fun AboutContent(
|
||||
showLicenseDialog: MutableState<Boolean>,
|
||||
onViewLibraries: () -> Unit,
|
||||
) {
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.app_name),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
|
||||
Text(stringResource(R.string.app_name), style = MaterialTheme.typography.headlineMedium)
|
||||
Text(
|
||||
stringResource(R.string.app_tagline),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
HorizontalDivider()
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
stringResource(R.string.version),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
Text(BuildConfig.VERSION_NAME)
|
||||
Section(title = stringResource(R.string.version)) {
|
||||
Text(BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Section(title = stringResource(R.string.developer)) {
|
||||
Text("Pierre-Yves Nicolas")
|
||||
}
|
||||
|
||||
Text(
|
||||
stringResource(R.string.license),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
Text(
|
||||
stringResource(R.string.licensed_under),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.view_the_full_license),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.clickable { showLicenseDialog.value = true },
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Section(title = stringResource(R.string.contact)) {
|
||||
val emailAddress = "contact@fairscan.org"
|
||||
ContactLink(
|
||||
icon = Icons.Default.Email,
|
||||
text = emailAddress,
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_SENDTO).apply {
|
||||
data = "mailto:$emailAddress".toUri()
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
)
|
||||
val websiteUrl = "https://fairscan.org"
|
||||
ContactLink(
|
||||
icon = Icons.Default.Language,
|
||||
text = websiteUrl,
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_VIEW, websiteUrl.toUri())
|
||||
context.startActivity(intent)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Section(title = stringResource(R.string.license)) {
|
||||
Text(
|
||||
stringResource(R.string.licensed_under),
|
||||
|
||||
Text(
|
||||
stringResource(R.string.libraries),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
Text(
|
||||
stringResource(R.string.libraries_intro) +
|
||||
"\n• CameraX\n• Jetpack Compose\n• LiteRT\n• OpenCV\n• PDFBox",
|
||||
style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
text = stringResource(R.string.view_full_list),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.clickable(onClick = onViewLibraries),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.view_the_full_license),
|
||||
modifier = Modifier.clickable { showLicenseDialog.value = true },
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Section(title = stringResource(R.string.libraries)) {
|
||||
Text(
|
||||
stringResource(R.string.libraries_intro) +
|
||||
"\n• CameraX\n• Jetpack Compose\n• LiteRT\n• OpenCV\n• PDFBox",
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.view_full_list),
|
||||
modifier = Modifier.clickable(onClick = onViewLibraries),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(32.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Section(title: String, content: @Composable () -> Unit) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(title, style = MaterialTheme.typography.titleMedium)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContactLink(icon: ImageVector, text: String, onClick: () -> Unit) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onClick() }
|
||||
.padding(vertical = 4.dp)
|
||||
) {
|
||||
Icon(icon, contentDescription = null, tint = MaterialTheme.colorScheme.primary)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(
|
||||
text,
|
||||
style = MaterialTheme.typography.bodyLarge.copy(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
textDecoration = TextDecoration.Underline
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LicenseBottomSheet(
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
<string name="camera_permission_rationale">Die App benötigt Zugriff auf die Kamera, um Dokumente zu scannen. Aufgenommene Bilder werden nur auf diesem Gerät gespeichert und beim Schließen des aktuellen Dokuments gelöscht.</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="clear_text">Text löschen</string>
|
||||
<string name="contact">Kontakt</string>
|
||||
<string name="creating_pdf">PDF wird erstellt…</string>
|
||||
<string name="delete_page">Seite löschen</string>
|
||||
<string name="delete_page_warning">Möchten Sie diese Seite löschen?</string>
|
||||
<string name="developer">Entwickler</string>
|
||||
<string name="discard_scan">Löschen</string>
|
||||
<string name="end_scan">Scan beenden</string>
|
||||
<string name="error">Fehler: %1$s</string>
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
<string name="camera_permission_denied">L\'autorisation d\'accès à la caméra a été refusée</string>
|
||||
<string name="camera_permission_rationale">L’application a besoin d’accéder à l’appareil photo pour scanner des documents. Les images capturées sont enregistrées uniquement sur cet appareil et seront supprimées lorsque vous fermerez le document en cours.</string>
|
||||
<string name="cancel">Annuler</string>
|
||||
<string name="contact">Contact</string>
|
||||
<string name="clear_text">Effacer le text</string>
|
||||
<string name="creating_pdf">Création du PDF…</string>
|
||||
<string name="delete_page">Supprimer la page</string>
|
||||
<string name="delete_page_warning">Voulez-vous supprimer cette page ?</string>
|
||||
<string name="developer">Développeur</string>
|
||||
<string name="discard_scan">Supprimer le scan</string>
|
||||
<string name="end_scan">Terminer le scan</string>
|
||||
<string name="error">Erreur : %1$s</string>
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
<string name="camera_permission_rationale">The app requires camera access to scan documents. Captured images are stored only on this device and will be deleted when you close the current document.</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="clear_text">Clear text</string>
|
||||
<string name="contact">Contact</string>
|
||||
<string name="creating_pdf">Creating PDF…</string>
|
||||
<string name="delete_page">Delete page</string>
|
||||
<string name="delete_page_warning">Do you want to delete this page?</string>
|
||||
<string name="developer">Developer</string>
|
||||
<string name="discard_scan">Discard scan</string>
|
||||
<string name="end_scan">End scan</string>
|
||||
<string name="error">Error: %1$s</string>
|
||||
|
||||
Reference in New Issue
Block a user