diff --git a/app/build.gradle b/app/build.gradle index b7ff841..f0256b1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,6 +78,7 @@ android { } buildFeatures { compose true + buildConfig = true } composeOptions { kotlinCompilerExtensionVersion '1.5.1' diff --git a/app/src/main/java/app/myzel394/alibi/ui/Constants.kt b/app/src/main/java/app/myzel394/alibi/ui/Constants.kt index 903c212..bf3dce1 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/Constants.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/Constants.kt @@ -6,3 +6,46 @@ import androidx.compose.ui.unit.dp val BIG_PRIMARY_BUTTON_SIZE = 64.dp val MAX_AMPLITUDE = 20000 val SUPPORTS_DARK_MODE_NATIVELY = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + +// You are not allowed to change the constants below. +// If you do so, you will be blocked on GitHub. +const val REPO_URL = "https://github.com/Myzel394/Alibi" +const val TRANSLATION_HELP_URL = "https://crowdin.com/project/alibi" +const val GITHUB_SPONSORS_URL = "https://github.com/sponsors/Myzel394" +const val PUBLIC_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZTfvnhYJKwYBBAHaRw8BAQdAi2AiLsTaBoLhnQtY5vi3xBU/H428wbNfBSe+ +2dhz3r60Jk15emVsMzk0IDxnaXRodWIuN2Eyb3BAc2ltcGxlbG9naW4uY28+iJkE +ExYKAEEWIQR9BS8nNHwqrNgV0B3NE0dCwel5WQUCZTfvngIbAwUJEswDAAULCQgH +AgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRDNE0dCwel5WcS8AQCf9g6eEaut1suW +l6jCLIg3b1nWLckmLJaonM6PruUtigEAmVnFOxMpOZEIcILT8CD2Riy+IVN9gTNH +qOHnaFsu8AK4OARlN++eEgorBgEEAZdVAQUBAQdAe4ffDtRundKH9kam746i2TBu +P9sfb3QVi5QqfK+bek8DAQgHiH4EGBYKACYWIQR9BS8nNHwqrNgV0B3NE0dCwel5 +WQUCZTfvngIbDAUJEswDAAAKCRDNE0dCwel5WWwSAQDj4ZAl6bSqwbcptEMYQaPM +MMhMafm446MjkhQioeXw+wEAzA8mS6RBx7IZvu1dirmFHXOEYJclwjyQhNs4uEjq +/Ak= +=ICHe +-----END PGP PUBLIC KEY BLOCK-----""" +const val PUBLIC_KEY_FINGERPRINT = "7D05 2F27 347C 2AAC D815 D01D CD13 4742 C1E9 7959" +val CRYPTO_DONATIONS = mapOf( + "Bitcoin" to "bc1qw054829yj8e2u8glxnfcg3w22dkek577mjt5x6", + "Bitcoin Cash" to "qr9s64vfqedvurfef9ykf7szchmt0xyvnga452fc8l", + "Ethereum" to "0xbb5E631c03C65334d1d9EfBCD926DC1265CC20D7", + "Tether USD" to "0xbb5E631c03C65334d1d9EfBCD926DC1265CC20D7", + "Monero" to "83dm5wyuckG4aPbuMREHCEgLNwVn5i7963SKBhECaA7Ueb7DKBTy639R3QfMtb3DsFHMp8u6WGiCFgbdRDBBcz5sLduUtm8", + "Zcash" to "t1ZfvNpzfdaW6csT9Kc7iJA7LUU3hmNj2sx", + "Litecoin" to "LZayhTosZ9ToRvcbeR1gEDgb76Z7ZA2drN", + "Dash" to "XcTkni8CVAXBcuc5VwvHmsYftVK4CPLetU", + "Avalanche" to "0xbb5E631c03C65334d1d9EfBCD926DC1265CC20D7", + "XRP" to "rNpfDm8UwDTumCebchBadjVW2FEPteFgNg", + "Solana" to "2h6CB3hz5Vb2nYS1RQiXZ4aWTzc5frBPR7Sp1b4muFqb", + "ADA" to "addr1q8vy2vcp6lacaw8lkc29gufuzajaytc5qc0c2mxlmw5lndxcg5esr4lm36u0lds523cnc9m96gh3gpsls4kdlkaflx6qf6qpvc", + "Dogecoin" to "DUA4j7mVoc7Rvezu8YgeRKwxNuMzKeDoxD", + "Tron" to "THWVLGhne5wDsGjd1CNenHDKQGzvGzrzLb", + "Polkadot" to "1642iaR6AoKyM6qnnMHkfCRfRqRKJ2wC6Cm3UEWEFEz6EtZR", + "Cosmos" to "cosmos1vt5z6rfj5sgnkdlddkuu8srw3xupyqxscva9hz", + "Algorand" to "QBOQ6VSLMD77QEF33P5J3HKGOM5RZLNO6P5P3FTWCMQM3ORF6QY2W34KUI", + "Tezos" to "tz1QUWNYuFqDibGCrwmkdaHSpTx3d6ZdxLMi", + "Litecoin" to "LZayhTosZ9ToRvcbeR1gEDgb76Z7ZA2drN", + "Filecoin" to "f1j6pm3chzhgadpf6iwmtux33jb5gccj5arkg4dsq", +) diff --git a/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt b/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt index bd4bca3..efef5d4 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt @@ -27,6 +27,7 @@ import app.myzel394.alibi.dataStore import app.myzel394.alibi.db.LastRecording import app.myzel394.alibi.ui.enums.Screen import app.myzel394.alibi.ui.models.AudioRecorderModel +import app.myzel394.alibi.ui.screens.AboutScreen import app.myzel394.alibi.ui.screens.AudioRecorder import app.myzel394.alibi.ui.screens.CustomRecordingNotificationsScreen import app.myzel394.alibi.ui.screens.SettingsScreen @@ -111,5 +112,18 @@ fun Navigation( navController = navController, ) } + composable( + Screen.About.route, + enterTransition = { + scaleIn() + }, + exitTransition = { + scaleOut() + fadeOut(tween(150)) + } + ) { + AboutScreen( + navController = navController, + ) + } } } diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/DonationsTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/DonationsTile.kt new file mode 100644 index 0000000..1944e38 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/DonationsTile.kt @@ -0,0 +1,182 @@ +package app.myzel394.alibi.ui.components.AboutScreen.atoms + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.expandVertically +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +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.rememberScrollState +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.ContentCopy +import androidx.compose.material.icons.filled.CurrencyBitcoin +import androidx.compose.material.icons.filled.CurrencyFranc +import androidx.compose.material.icons.filled.CurrencyLira +import androidx.compose.material.icons.filled.CurrencyPound +import androidx.compose.material.icons.filled.CurrencyRuble +import androidx.compose.material.icons.filled.CurrencyRupee +import androidx.compose.material.icons.filled.CurrencyYen +import androidx.compose.material.icons.filled.CurrencyYuan +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import app.myzel394.alibi.R +import app.myzel394.alibi.ui.CRYPTO_DONATIONS +import app.myzel394.alibi.ui.GITHUB_SPONSORS_URL +import app.myzel394.alibi.ui.PUBLIC_KEY + +@Composable +fun DonationsTile() { + var donationsOpened by rememberSaveable { + mutableStateOf(false) + } + val label = stringResource(R.string.ui_about_contribute_donatation) + + Row( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .semantics { + contentDescription = label + } + .clickable { + donationsOpened = !donationsOpened + } + .background( + MaterialTheme.colorScheme.surfaceVariant + ) + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + listOf( + Icons.Default.CurrencyBitcoin, + Icons.Default.CurrencyFranc, + Icons.Default.CurrencyLira, + Icons.Default.CurrencyPound, + Icons.Default.CurrencyRuble, + Icons.Default.CurrencyRupee, + Icons.Default.CurrencyYen, + Icons.Default.CurrencyYuan, + ).asSequence().shuffled().first(), + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize.times(1.2f)) + ) + Text( + stringResource(R.string.ui_about_contribute_donatation), + fontWeight = FontWeight.Bold, + ) + } + + val rotation by animateFloatAsState( + if (donationsOpened) -180f else 0f, + label = "iconRotation" + ) + + Icon( + Icons.Default.ArrowDropDown, + contentDescription = null, + modifier = Modifier + .size(ButtonDefaults.IconSize.times(1.2f)) + .rotate(rotation) + ) + } + + val clipboardManager = + LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + + AnimatedVisibility( + visible = donationsOpened, + enter = expandVertically(), + ) { + Column { + val uriHandler = LocalUriHandler.current + + Button( + onClick = { + uriHandler.openUri(GITHUB_SPONSORS_URL) + }, + colors = ButtonDefaults.textButtonColors(), + modifier = Modifier.fillMaxWidth(), + ) { + Image( + painter = painterResource(R.drawable.ic_github), + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary), + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize.times(1.2f)) + ) + Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) + Text( + stringResource(R.string.ui_about_contribute_donation_githubSponsors) + ) + } + for (crypto in CRYPTO_DONATIONS) { + Row( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .clickable { + val clip = ClipData.newPlainText("text", crypto.value) + clipboardManager.setPrimaryClip(clip) + } + .padding(16.dp) + .horizontalScroll(rememberScrollState()), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + Icons.Default.ContentCopy, + contentDescription = null, + ) + Text( + crypto.key, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + ) + Text( + crypto.value, + fontSize = MaterialTheme.typography.bodyMedium.fontSize.times(0.5), + ) + } + } + } + } +} diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/GPGKeyOverview.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/GPGKeyOverview.kt new file mode 100644 index 0000000..572f888 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/AboutScreen/atoms/GPGKeyOverview.kt @@ -0,0 +1,77 @@ +package app.myzel394.alibi.ui.components.AboutScreen.atoms + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Key +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import app.myzel394.alibi.R +import app.myzel394.alibi.ui.PUBLIC_KEY_FINGERPRINT +import app.myzel394.alibi.ui.PUBLIC_KEY + +@Composable +fun GPGKeyOverview() { + Column( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .background( + MaterialTheme.colorScheme.primaryContainer + ) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Icon( + Icons.Default.Key, + contentDescription = null, + modifier = Modifier.size(48.dp) + ) + + Text( + stringResource(R.string.ui_about_gpg_key_hint), + style = MaterialTheme.typography.bodyMedium, + ) + + val clipboardManager = + LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + Text( + PUBLIC_KEY_FINGERPRINT, + modifier = Modifier + .clip(MaterialTheme.shapes.small) + .background( + MaterialTheme.colorScheme.surfaceVariant + ) + .padding(8.dp), + ) + Button( + onClick = { + val clip = ClipData.newPlainText("text", PUBLIC_KEY) + clipboardManager.setPrimaryClip(clip) + }, + colors = ButtonDefaults.textButtonColors(), + modifier = Modifier + .fillMaxWidth() + ) { + Text(stringResource(R.string.ui_about_gpg_key_copy)) + } + } +} diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/AboutTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/AboutTile.kt new file mode 100644 index 0000000..857584d --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/AboutTile.kt @@ -0,0 +1,69 @@ +package app.myzel394.alibi.ui.components.SettingsScreen.atoms + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.Notifications +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import app.myzel394.alibi.R +import app.myzel394.alibi.dataStore +import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.ui.components.atoms.SettingsTile +import app.myzel394.alibi.ui.enums.Screen + +@Composable +fun AboutTile( + navController: NavController, +) { + val label = stringResource(R.string.ui_about_title) + + Row( + modifier = Modifier + .padding(horizontal = 32.dp, vertical = 48.dp) + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .semantics { + contentDescription = label + } + .clickable { + navController.navigate(Screen.About.route) + } + .background(MaterialTheme.colorScheme.surfaceVariant) + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + Icons.Default.Info, + contentDescription = null, + ) + Text( + text = label, + ) + } + Icon( + Icons.Default.ChevronRight, + contentDescription = null, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/enums/Screen.kt b/app/src/main/java/app/myzel394/alibi/ui/enums/Screen.kt index 218bde3..d8ba5a8 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/enums/Screen.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/enums/Screen.kt @@ -5,6 +5,7 @@ sealed class Screen(val route: String) { data object Settings : Screen("settings") data object Welcome : Screen("welcome") data object CustomRecordingNotifications : Screen("custom-recording-notifications") + data object About : Screen("about") fun withArgs(vararg args: String): String { return buildString { diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/AboutScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/AboutScreen.kt new file mode 100644 index 0000000..8082fe5 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/screens/AboutScreen.kt @@ -0,0 +1,206 @@ +package app.myzel394.alibi.ui.screens + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +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 +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +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.filled.ArrowBack +import androidx.compose.material.icons.filled.OpenInNew +import androidx.compose.material3.ButtonDefaults +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.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import app.myzel394.alibi.R +import app.myzel394.alibi.BuildConfig +import app.myzel394.alibi.ui.TRANSLATION_HELP_URL +import app.myzel394.alibi.ui.REPO_URL +import app.myzel394.alibi.ui.components.AboutScreen.atoms.DonationsTile +import app.myzel394.alibi.ui.components.AboutScreen.atoms.GPGKeyOverview + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AboutScreen( + navController: NavController, +) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( + rememberTopAppBarState() + ) + val uriHandler = LocalUriHandler.current + + Scaffold( + topBar = { + TopAppBar( + title = { + Text(stringResource(R.string.ui_about_title)) + }, + navigationIcon = { + IconButton(onClick = navController::popBackStack) { + Icon( + Icons.Default.ArrowBack, + contentDescription = "Back" + ) + } + }, + scrollBehavior = scrollBehavior, + ) + }, + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) + ) { padding -> + Column( + modifier = Modifier + .padding(padding) + .padding(horizontal = 32.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(48.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Column( + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box( + modifier = Modifier + .clip(CircleShape) + .size(200.dp) + .background( + MaterialTheme.colorScheme.surfaceVariant + ), + ) { + Image( + painter = painterResource(R.drawable.launcher_foreground), + contentDescription = null, + ) + } + Text( + text = stringResource(R.string.app_name), + style = MaterialTheme.typography.headlineLarge, + ) + Text( + text = "Version %s (%s)".format( + BuildConfig.VERSION_NAME, + BuildConfig.VERSION_CODE.toString() + ), + style = MaterialTheme.typography.bodyMedium, + ) + } + Column( + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + Text( + stringResource(R.string.ui_about_contribute_title), + style = MaterialTheme.typography.titleMedium, + ) + Text( + stringResource(R.string.ui_about_contribute_message), + style = MaterialTheme.typography.titleMedium, + ) + + val githubLabel = stringResource(R.string.accessibility_open_in_browser, REPO_URL) + Row( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .semantics { + contentDescription = githubLabel + } + .clickable { + uriHandler.openUri(REPO_URL) + } + .background( + MaterialTheme.colorScheme.surfaceVariant + ) + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + painter = painterResource(R.drawable.ic_github), + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurfaceVariant), + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize.times(1.2f)) + ) + Text( + stringResource(R.string.ui_about_contribute_development), + fontWeight = FontWeight.Bold, + ) + Icon( + Icons.Default.OpenInNew, + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + } + + val crowdinLabel = + stringResource(R.string.accessibility_open_in_browser, TRANSLATION_HELP_URL) + Row( + modifier = Modifier + .fillMaxWidth() + .clip(MaterialTheme.shapes.medium) + .semantics { + contentDescription = crowdinLabel + } + .clickable { + uriHandler.openUri(TRANSLATION_HELP_URL) + } + .background( + MaterialTheme.colorScheme.surfaceVariant + ) + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + painter = painterResource(R.drawable.ic_crowdin), + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurfaceVariant), + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize.times(1.2f)) + ) + Text( + stringResource(R.string.ui_about_contribute_translation), + fontWeight = FontWeight.Bold, + ) + Icon( + Icons.Default.OpenInNew, + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + } + + DonationsTile() + + GPGKeyOverview() + } + } + } +} diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt index b64a964..0c2e972 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt @@ -39,6 +39,7 @@ import app.myzel394.alibi.R import app.myzel394.alibi.dataStore import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY +import app.myzel394.alibi.ui.components.SettingsScreen.atoms.AboutTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.CustomNotificationTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile @@ -147,6 +148,7 @@ fun SettingsScreen( ForceExactMaxDurationTile() InAppLanguagePicker() CustomNotificationTile(navController = navController) + AboutTile(navController = navController) AnimatedVisibility(visible = settings.showAdvancedSettings) { Column( horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app/src/main/res/drawable/ic_crowdin.xml b/app/src/main/res/drawable/ic_crowdin.xml new file mode 100644 index 0000000..8326732 --- /dev/null +++ b/app/src/main/res/drawable/ic_crowdin.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml new file mode 100644 index 0000000..34241ea --- /dev/null +++ b/app/src/main/res/drawable/ic_github.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 33e9c64..e3fd669 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,4 +88,14 @@ Show Duration Update notification This is a preview for your notification. You can edit the title and the message. At the bottom you can find some presets. + About Alibi + Support Alibi + In my free time I develop Alibi and other free open source software. It would mean the world to me if you could help me in any way :) + Developing features or fixing bugs + Open link in browser: %s + Translate Alibi into your language + Make a donation + You can copy my GPG key here. This key only exists once and I can use it to prove to you that I\'m really who I am. Please save it now so that you can verify my signature later. + Copy GPG Key + Become a GitHub Sponsor \ No newline at end of file