From 7d71e8d4edf5fcbb83da94c0cb330716cfc50a19 Mon Sep 17 00:00:00 2001 From: mdrlzy Date: Mon, 25 Dec 2023 02:11:07 +0600 Subject: [PATCH 1/4] Privacy policy, hide crash report setting & disable ACRA for Google Play --- app/build.gradle | 1 + .../dev/arkbuilders/rate/presentation/App.kt | 4 +- .../presentation/settings/SettingsScreen.kt | 55 ++++++++++++++----- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 20e8e791b..2b52e7979 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,6 +22,7 @@ android { buildConfigField "String", "ACRA_LOGIN", "\"$login\"" buildConfigField "String", "ACRA_PASS", "\"$password\"" buildConfigField "String", "ACRA_URI", "\"$uri\"" + buildConfigField "boolean", "GOOGLE_PLAY_BUILD", "true" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/dev/arkbuilders/rate/presentation/App.kt b/app/src/main/java/dev/arkbuilders/rate/presentation/App.kt index 5c06fe33d..b659e20eb 100644 --- a/app/src/main/java/dev/arkbuilders/rate/presentation/App.kt +++ b/app/src/main/java/dev/arkbuilders/rate/presentation/App.kt @@ -29,7 +29,9 @@ class App : Application() { super.onCreate() Timber.plant(Timber.DebugTree()) DIManager.init(this) - initAcra() + + if (!BuildConfig.GOOGLE_PLAY_BUILD) + initAcra() initWorker() } diff --git a/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt b/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt index 3d4ce44f3..3c859aed4 100644 --- a/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt +++ b/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt @@ -2,8 +2,11 @@ package dev.arkbuilders.rate.presentation.settings +import android.content.Intent +import android.net.Uri import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -41,18 +44,24 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog +import androidx.core.content.ContextCompat import androidx.lifecycle.viewmodel.compose.viewModel import com.ramcosta.composedestinations.annotation.Destination +import dev.arkbuilders.rate.BuildConfig import dev.arkbuilders.rate.R import dev.arkbuilders.rate.data.preferences.PreferenceKey import dev.arkbuilders.rate.di.DIManager +private val PRIVACY_POLICY_URL = "https://app-privacy-policy-generator.firebaseapp.com/" + @Destination @Composable fun SettingsScreen() { @@ -60,7 +69,10 @@ fun SettingsScreen() { viewModel(factory = DIManager.component.settingsVMFactory()) if (vm.initialized) { - Settings(vm) + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Settings(Modifier.weight(1f), vm) + PrivacyPolicy() + } } else { Box(modifier = Modifier.fillMaxSize()) { CircularProgressIndicator() @@ -69,11 +81,26 @@ fun SettingsScreen() { } @Composable -private fun Settings(vm: SettingsViewModel) { +private fun PrivacyPolicy() { + val ctx = LocalContext.current + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { + Text( + modifier = Modifier.clickable { + val intent = Intent(Intent.ACTION_VIEW) + intent.data = Uri.parse(PRIVACY_POLICY_URL) + ctx.startActivity(intent) + }, + text = "Privacy policy", + textDecoration = TextDecoration.Underline + ) + } +} + +@Composable +private fun Settings(modifier: Modifier = Modifier, vm: SettingsViewModel) { Column( - modifier = Modifier + modifier = modifier .verticalScroll(rememberScrollState()) - .padding(16.dp) ) { SettingsGroup(name = R.string.currencies) { SettingsNumberComp( @@ -116,15 +143,17 @@ private fun Settings(vm: SettingsViewModel) { onCheck = { true } ) } - SettingsGroup(name = R.string.privacy) { - SettingsSwitchComp( - name = R.string.crash_reports, - state = vm.boolPrefs[PreferenceKey.CrashReport]!! - ) { state -> - vm.onToggle( - PreferenceKey.CrashReport, - state - ) + if (!BuildConfig.GOOGLE_PLAY_BUILD) { + SettingsGroup(name = R.string.privacy) { + SettingsSwitchComp( + name = R.string.crash_reports, + state = vm.boolPrefs[PreferenceKey.CrashReport]!! + ) { state -> + vm.onToggle( + PreferenceKey.CrashReport, + state + ) + } } } } From 59225e75757c3a72aa93a3d0a431162ea387914f Mon Sep 17 00:00:00 2001 From: mdrlzy Date: Mon, 25 Dec 2023 11:24:16 +0600 Subject: [PATCH 2/4] Explanation of pair alerts --- .../pairalert/PairAlertConditionScreen.kt | 60 +++++++++++++++++++ .../main/res/drawable/ic_question_mark.xml | 5 ++ app/src/main/res/values/strings.xml | 2 + 3 files changed, 67 insertions(+) create mode 100644 app/src/main/res/drawable/ic_question_mark.xml diff --git a/app/src/main/java/dev/arkbuilders/rate/presentation/pairalert/PairAlertConditionScreen.kt b/app/src/main/java/dev/arkbuilders/rate/presentation/pairalert/PairAlertConditionScreen.kt index 5e47a3e08..40638eae6 100644 --- a/app/src/main/java/dev/arkbuilders/rate/presentation/pairalert/PairAlertConditionScreen.kt +++ b/app/src/main/java/dev/arkbuilders/rate/presentation/pairalert/PairAlertConditionScreen.kt @@ -14,12 +14,14 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.Button import androidx.compose.material.Card import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -31,16 +33,23 @@ import androidx.compose.runtime.remember 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.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import dev.arkbuilders.rate.R import dev.arkbuilders.rate.data.model.PairAlertCondition import dev.arkbuilders.rate.presentation.destinations.AddCurrencyScreenDestination import dev.arkbuilders.rate.presentation.destinations.PairAlertConditionScreenDestination import dev.arkbuilders.rate.presentation.shared.SharedViewModel +import dev.arkbuilders.rate.presentation.theme.Purple500 import dev.arkbuilders.rate.presentation.utils.activityViewModel import dev.arkbuilders.rate.utils.removeFractionalPartIfEmpty @@ -50,8 +59,27 @@ fun PairAlertConditionScreen( navigator: DestinationsNavigator, viewModel: SharedViewModel = activityViewModel() ) { + var descDialog by remember { mutableStateOf(false) } + Box(modifier = Modifier.fillMaxSize()) { LazyColumn(modifier = Modifier.fillMaxSize()) { + item { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.CenterEnd + ) { + IconButton( + modifier = Modifier.padding(top = 16.dp, end = 8.dp), + onClick = { descDialog = true } + ) { + Icon( + painter = painterResource(R.drawable.ic_question_mark), + contentDescription = "", + tint = Purple500 + ) + } + } + } items( viewModel.pairAlertConditions, key = { it.id } @@ -63,6 +91,11 @@ fun PairAlertConditionScreen( } } } + + if (descDialog) + DescDialog { + descDialog = false + } } @Composable @@ -205,4 +238,31 @@ private fun AddOrDeleteBtn( Icon(Icons.Filled.Delete, "Delete") } } +} + +@Composable +private fun DescDialog(onDismiss: () -> Unit) { + Dialog(onDismissRequest = { onDismiss() }) { + Surface( + shape = RoundedCornerShape(20.dp), + color = Color.White + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(R.string.pair_alerts_desc), + textAlign = TextAlign.Center + ) + Button( + modifier = Modifier.padding(top = 10.dp), + onClick = { onDismiss() }) { + Text(text = stringResource(R.string.ok)) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_question_mark.xml b/app/src/main/res/drawable/ic_question_mark.xml new file mode 100644 index 000000000..1d4bf0826 --- /dev/null +++ b/app/src/main/res/drawable/ic_question_mark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a1b46d3c..9128542da 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,4 +19,6 @@ List Used count Used time + App in the background checks the specified exchange rates once a day and if the condition matches, then displays a notification. + OK From 473f0628121fcbf67d72b55a98ea23093f3f887d Mon Sep 17 00:00:00 2001 From: mdrlzy Date: Mon, 25 Dec 2023 14:59:32 +0600 Subject: [PATCH 3/4] minor --- app/build.gradle | 2 +- .../presentation/settings/SettingsScreen.kt | 50 +++++++++++-------- app/src/main/res/values/strings.xml | 2 + 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2b52e7979..51949eb77 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,7 +22,7 @@ android { buildConfigField "String", "ACRA_LOGIN", "\"$login\"" buildConfigField "String", "ACRA_PASS", "\"$password\"" buildConfigField "String", "ACRA_URI", "\"$uri\"" - buildConfigField "boolean", "GOOGLE_PLAY_BUILD", "true" + buildConfigField "boolean", "GOOGLE_PLAY_BUILD", "false" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt b/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt index 3c859aed4..56d322f99 100644 --- a/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt +++ b/app/src/main/java/dev/arkbuilders/rate/presentation/settings/SettingsScreen.kt @@ -60,8 +60,6 @@ import dev.arkbuilders.rate.R import dev.arkbuilders.rate.data.preferences.PreferenceKey import dev.arkbuilders.rate.di.DIManager -private val PRIVACY_POLICY_URL = "https://app-privacy-policy-generator.firebaseapp.com/" - @Destination @Composable fun SettingsScreen() { @@ -69,10 +67,7 @@ fun SettingsScreen() { viewModel(factory = DIManager.component.settingsVMFactory()) if (vm.initialized) { - Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { - Settings(Modifier.weight(1f), vm) - PrivacyPolicy() - } + Settings(vm) } else { Box(modifier = Modifier.fillMaxSize()) { CircularProgressIndicator() @@ -83,23 +78,35 @@ fun SettingsScreen() { @Composable private fun PrivacyPolicy() { val ctx = LocalContext.current - Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { - Text( - modifier = Modifier.clickable { - val intent = Intent(Intent.ACTION_VIEW) - intent.data = Uri.parse(PRIVACY_POLICY_URL) - ctx.startActivity(intent) - }, - text = "Privacy policy", - textDecoration = TextDecoration.Underline - ) + val url = stringResource(id = R.string.privacy_policy_url) + Surface( + color = Color.Transparent, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + onClick = { + val intent = Intent(Intent.ACTION_VIEW) + intent.data = Uri.parse(url) + ctx.startActivity(intent) + }, + ) { + Column { + Text( + modifier = Modifier.padding(16.dp), + text = stringResource(id = R.string.privacy_policy), + style = MaterialTheme.typography.body1, + ) + Divider() + } + } } @Composable -private fun Settings(modifier: Modifier = Modifier, vm: SettingsViewModel) { +private fun Settings(vm: SettingsViewModel) { Column( - modifier = modifier + modifier = Modifier + .padding(16.dp) .verticalScroll(rememberScrollState()) ) { SettingsGroup(name = R.string.currencies) { @@ -143,8 +150,9 @@ private fun Settings(modifier: Modifier = Modifier, vm: SettingsViewModel) { onCheck = { true } ) } - if (!BuildConfig.GOOGLE_PLAY_BUILD) { - SettingsGroup(name = R.string.privacy) { + SettingsGroup(name = R.string.privacy) { + PrivacyPolicy() + if (!BuildConfig.GOOGLE_PLAY_BUILD) { SettingsSwitchComp( name = R.string.crash_reports, state = vm.boolPrefs[PreferenceKey.CrashReport]!! @@ -274,7 +282,7 @@ fun SettingsNumberComp( modifier = Modifier.size(24.dp) ) } - Spacer(modifier = Modifier.width(16.dp)) + Spacer(modifier = Modifier.width(8.dp)) Column(modifier = Modifier.padding(8.dp)) { Text( text = stringResource(id = name), diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9128542da..98bf69efc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,4 +21,6 @@ Used time App in the background checks the specified exchange rates once a day and if the condition matches, then displays a notification. OK + https://app-privacy-policy-generator.firebaseapp.com/ + Privacy policy From 344e6bb55b4addc3480b919997c23833cce8e514 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Wed, 17 Jan 2024 11:17:11 +0300 Subject: [PATCH 4/4] Link to the actual privacy policy --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 98bf69efc..d58d30d23 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,6 +21,6 @@ Used time App in the background checks the specified exchange rates once a day and if the condition matches, then displays a notification. OK - https://app-privacy-policy-generator.firebaseapp.com/ + https://www.ark-builders.dev/apps/rate/privacy-policy Privacy policy