diff --git a/shared/src/commonMain/composeResources/values/strings.xml b/shared/src/commonMain/composeResources/values/strings.xml index 5d46b590..f844b6e4 100644 --- a/shared/src/commonMain/composeResources/values/strings.xml +++ b/shared/src/commonMain/composeResources/values/strings.xml @@ -15,6 +15,11 @@ Sponsor Spectacled is an open-source software for journals, notes, and tasks - built on open standards (iCalendar + CalDAV), synced to your own server, with no accounts, no proprietary backend, and no tracking. \n\nIt's maintained across Android, iOS, Web, and Desktop as one codebase, which is a lot of ongoing work for a small project. If Spectacled is useful to you, chip in whatever it's worth to you - any amount helps keep development going. \n\nThank you for supporting open source! More donation options + Translations + Spectacled is translated by the community on Weblate, a libre translation platform. \n\nYou don't need a development environment or any Git knowledge - just sign in, pick your language and start translating right in your browser. Every translation is shared by all Spectacled apps on all platforms. + Translate on Weblate + Code + Spectacled is developed in the open on GitHub - one shared Kotlin Multiplatform codebase for Android, iOS, Web and Desktop. \n\nBug reports and feature ideas are just as welcome as pull requests. Have a look at the open issues to see what is currently being worked on, or where you could jump in. Thank you! PayPal More on GitHub.com diff --git a/shared/src/commonMain/kotlin/at/techbee/spectacled/screens/about/presentation/GitHubContributors.kt b/shared/src/commonMain/kotlin/at/techbee/spectacled/screens/about/presentation/GitHubContributors.kt index c4e3e878..dcbc4aec 100644 --- a/shared/src/commonMain/kotlin/at/techbee/spectacled/screens/about/presentation/GitHubContributors.kt +++ b/shared/src/commonMain/kotlin/at/techbee/spectacled/screens/about/presentation/GitHubContributors.kt @@ -2,18 +2,22 @@ package at.techbee.spectacled.screens.about.presentation import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.OpenInNew +import androidx.compose.material.icons.outlined.Code import androidx.compose.material.icons.outlined.Person +import androidx.compose.material.icons.outlined.Translate import androidx.compose.material3.Button +import androidx.compose.material3.ElevatedCard import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -30,19 +34,22 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import at.techbee.spectacled.SpectacledVariant import at.techbee.spectacled.screens.about.domain.GitHubContributor -import at.techbee.spectacled.screens.core.presentation.components.SpecialRoundedCard import at.techbee.spectacled.theme.AppTheme import coil3.compose.AsyncImage import io.github.aakira.napier.Napier import org.jetbrains.compose.resources.stringResource import spectacled.shared.generated.resources.Res +import spectacled.shared.generated.resources.about_code_contributions +import spectacled.shared.generated.resources.about_code_contributions_info import spectacled.shared.generated.resources.about_contributors +import spectacled.shared.generated.resources.about_translate_on_weblate +import spectacled.shared.generated.resources.about_translations +import spectacled.shared.generated.resources.about_translations_info import spectacled.shared.generated.resources.more_on_github -//TODO: Change for Release!!! -private const val GITHUB_CONTRIBUTORS_URL = "https://github.com/TechbeeAT/jtxBoard/graphs/contributors" - +private const val GITHUB_CONTRIBUTORS_URL = "https://github.com/TechbeeAT/spectacled/graphs/contributors" +private const val WEBLATE_URL = "https://hosted.weblate.org/engage/spectacled/" @Composable @@ -52,7 +59,7 @@ fun GitHubContributors( val uriHandler = LocalUriHandler.current Column( - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()) ) { Text( text = stringResource(Res.string.about_contributors), @@ -61,50 +68,116 @@ fun GitHubContributors( modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 8.dp, start = 8.dp, end = 8.dp) ) - LazyColumn( - verticalArrangement = Arrangement.spacedBy(4.dp), - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.fillMaxSize() + ElevatedCard( + modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp) ) { + Column( + modifier = Modifier.padding(16.dp).fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Outlined.Translate, + contentDescription = null, + modifier = Modifier.size(32.dp) + ) + Text( + text = stringResource(Res.string.about_translations), + style = MaterialTheme.typography.headlineSmall + ) + } - itemsIndexed(contributors) { index, contributor -> - SpecialRoundedCard( - isFirst = index == 0, - isLast = index == contributors.lastIndex, + Text( + text = stringResource(Res.string.about_translations_info), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center + ) + + Button( onClick = { try { - contributor.url?.let { uriHandler.openUri(it) } + uriHandler.openUri(WEBLATE_URL) } catch (e: Exception) { Napier.w(e.stackTraceToString()) } }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.padding(top = 8.dp) ) { - Column( - modifier = Modifier.padding(8.dp).fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), - horizontalAlignment = Alignment.CenterHorizontally + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically ) { + Text(stringResource(Res.string.about_translate_on_weblate)) + Icon(Icons.AutoMirrored.Outlined.OpenInNew, null) + } + } + } + } + + ElevatedCard { + + Column( + modifier = Modifier.padding(16.dp).fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Outlined.Code, + contentDescription = null, + modifier = Modifier.size(32.dp) + ) + Text( + text = stringResource(Res.string.about_code_contributions), + style = MaterialTheme.typography.headlineSmall + ) + } - AsyncImage( - model = contributor.avatarUrl, - contentDescription = null, - placeholder = rememberVectorPainter(Icons.Outlined.Person), - error = rememberVectorPainter(Icons.Outlined.Person), - fallback = rememberVectorPainter(Icons.Outlined.Person), - modifier = Modifier.size(80.dp).clip(CircleShape).shadow(2.dp) - ) + Text( + text = stringResource(Res.string.about_code_contributions_info), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center + ) - Text( - text = contributor.login, - style = MaterialTheme.typography.titleSmall - ) + FlowRow( + horizontalArrangement = Arrangement.Center + ) { + + contributors.forEach { contributor -> + + Column( + modifier = Modifier.padding(8.dp), + verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + AsyncImage( + model = contributor.avatarUrl, + contentDescription = null, + placeholder = rememberVectorPainter(Icons.Outlined.Person), + error = rememberVectorPainter(Icons.Outlined.Person), + fallback = rememberVectorPainter(Icons.Outlined.Person), + modifier = Modifier.size(80.dp).clip(CircleShape).shadow(2.dp) + ) + + Text( + text = contributor.login, + style = MaterialTheme.typography.titleSmall + ) + } } } - } - item { Button( onClick = { try { @@ -124,7 +197,9 @@ fun GitHubContributors( } } } + } + } }