diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 536aed0c..d7512aae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,8 +11,8 @@ android:supportsRtl="true" android:theme="@style/Theme.Unitto"> + android:name="firebase_analytics_collection_enabled" + android:value="false" /> diff --git a/app/src/main/java/com/sadellie/unitto/data/preferences/UserPreferences.kt b/app/src/main/java/com/sadellie/unitto/data/preferences/UserPreferences.kt index ad4145cf..f6c78067 100644 --- a/app/src/main/java/com/sadellie/unitto/data/preferences/UserPreferences.kt +++ b/app/src/main/java/com/sadellie/unitto/data/preferences/UserPreferences.kt @@ -1,10 +1,7 @@ package com.sadellie.unitto.data.preferences import android.content.Context -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.intPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.* import androidx.datastore.preferences.preferencesDataStore import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.Flow @@ -26,6 +23,7 @@ object UserPreferenceKeys { val OUTPUT_FORMAT = intPreferencesKey("OUTPUT_FORMAT_PREF_KEY") val LATEST_LEFT_SIDE = stringPreferencesKey("LATEST_LEFT_SIDE_PREF_KEY") val LATEST_RIGHT_SIDE = stringPreferencesKey("LATEST_RIGHT_SIDE_PREF_KEY") + val ENABLE_ANALYTICS = booleanPreferencesKey("ENABLE_ANALYTICS_PREF_KEY") } /** @@ -56,10 +54,21 @@ class UserPreferences @Inject constructor(@ApplicationContext private val contex } } + /** + * Gets boolean from datastore + * + * @param[default] Value to return if didn't find anything on fresh install + */ + fun getItem(key: Preferences.Key, default: Boolean): Flow { + return context.settingsDataStore.data.map { + it[key] ?: default + } + } + /** * Saves string value by key */ - suspend fun saveString(key: Preferences.Key, value: String) { + suspend fun saveItem(key: Preferences.Key, value: String) { context.settingsDataStore.edit { it[key] = value } @@ -68,7 +77,16 @@ class UserPreferences @Inject constructor(@ApplicationContext private val contex /** * Saves int value by key */ - suspend fun saveInt(key: Preferences.Key, value: Int) { + suspend fun saveItem(key: Preferences.Key, value: Int) { + context.settingsDataStore.edit { + it[key] = value + } + } + + /** + * Saves boolean value by key + */ + suspend fun saveItem(key: Preferences.Key, value: Boolean) { context.settingsDataStore.edit { it[key] = value } diff --git a/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt b/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt index 9b3e886a..07f0c935 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.crashlytics.FirebaseCrashlytics import com.sadellie.unitto.data.KEY_0 import com.sadellie.unitto.data.KEY_DOT @@ -45,7 +46,7 @@ class MainViewModel @Inject constructor( fun saveCurrentAppTheme(value: Int) { viewModelScope.launch { - mySettingsPrefs.saveInt(key = UserPreferenceKeys.CURRENT_APP_THEME, value) + mySettingsPrefs.saveItem(key = UserPreferenceKeys.CURRENT_APP_THEME, value) } } @@ -58,7 +59,7 @@ class MainViewModel @Inject constructor( fun setPrecisionPref(value: Int) { viewModelScope.launch { precision = value - mySettingsPrefs.saveInt(UserPreferenceKeys.DIGITS_PRECISION, value) + mySettingsPrefs.saveItem(UserPreferenceKeys.DIGITS_PRECISION, value) convertValue() } } @@ -73,7 +74,7 @@ class MainViewModel @Inject constructor( separator = value viewModelScope.launch { Formatter.setSeparator(value) - mySettingsPrefs.saveInt(UserPreferenceKeys.SEPARATOR, value) + mySettingsPrefs.saveItem(UserPreferenceKeys.SEPARATOR, value) convertValue() } } @@ -93,11 +94,24 @@ class MainViewModel @Inject constructor( outputFormat = value // Updating value on disk viewModelScope.launch { - mySettingsPrefs.saveInt(UserPreferenceKeys.OUTPUT_FORMAT, value) + mySettingsPrefs.saveItem(UserPreferenceKeys.OUTPUT_FORMAT, value) convertValue() } } + /** + * ANALYTICS + */ + var enableAnalytics: Boolean by mutableStateOf(false) + + fun setAnalyticsPref(value: Boolean) { + enableAnalytics = value + viewModelScope.launch { + mySettingsPrefs.saveItem(UserPreferenceKeys.ENABLE_ANALYTICS, value) + FirebaseAnalytics.getInstance(application).setAnalyticsCollectionEnabled(enableAnalytics) + } + } + /** * Unit we converting from (left side) */ @@ -400,8 +414,8 @@ class MainViewModel @Inject constructor( */ fun saveMe() { viewModelScope.launch { - mySettingsPrefs.saveString(UserPreferenceKeys.LATEST_LEFT_SIDE, unitFrom.unitId) - mySettingsPrefs.saveString(UserPreferenceKeys.LATEST_RIGHT_SIDE, unitTo.unitId) + mySettingsPrefs.saveItem(UserPreferenceKeys.LATEST_LEFT_SIDE, unitFrom.unitId) + mySettingsPrefs.saveItem(UserPreferenceKeys.LATEST_RIGHT_SIDE, unitTo.unitId) } } @@ -532,6 +546,9 @@ class MainViewModel @Inject constructor( * He can choose another unit group and doesn't need to wait for network to appear. * */ updateCurrenciesBasicUnits() + + enableAnalytics = mySettingsPrefs.getItem(UserPreferenceKeys.ENABLE_ANALYTICS, true).first() + FirebaseAnalytics.getInstance(application).setAnalyticsCollectionEnabled(enableAnalytics) } } } diff --git a/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsListItem.kt b/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsListItem.kt index 339e7f9f..3ed473b5 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsListItem.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsListItem.kt @@ -2,12 +2,10 @@ package com.sadellie.unitto.screens.setttings import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -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.* import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -17,22 +15,24 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp /** - * Represents one item in list on Settings screen + * Basic list item for settings screen. By default only has label and support text, clickable. + * This component can be easily modified if you provide additional component to it, + * for example a switch or a checkbox * - * @param modifier Modifier that is applied to a [Row] - * @param onClick Action to perform when clicking this item - * @param label Big text that is above support text - * @param supportText Smaller text that is below label + * @param label Main text + * @param supportText Text that is located below label + * @param onClick Action to perform when user clicks on this component (whole component is clickable) + * @param content Additional composable: buttons, switches, checkboxes or something else */ @Composable -fun SettingsListItem( - modifier: Modifier = Modifier, - onClick: () -> Unit, +private fun BasicSettingsListItem( label: String, supportText: String? = null, + onClick: () -> Unit = {}, + content: @Composable RowScope.() -> Unit = {} ) { Row( - modifier = modifier + modifier = Modifier .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, @@ -43,7 +43,9 @@ fun SettingsListItem( verticalAlignment = Alignment.CenterVertically, ) { Column( - Modifier.padding(horizontal = 0.dp) + Modifier + .padding(horizontal = 0.dp) + .weight(1f) // This makes additional composable to be seen ) { Text( modifier = Modifier @@ -62,5 +64,38 @@ fun SettingsListItem( ) } } + content() } } + +/** + * Represents one item in list on Settings screen + * + * @param label Main text + * @param supportText Text that is located below label + * @param onClick Action to perform when user clicks on this component (whole component is clickable) + */ +@Composable +fun SettingsListItem( + label: String, + supportText: String? = null, + onClick: () -> Unit, +) = BasicSettingsListItem(label, supportText, onClick) + +/** + * Represents one item in list on Settings screen + * + * @param label Main text + * @param supportText Text that is located below label + * @param switchState Current switch state + * @param onSwitchChange Action to perform when user clicks on this component or just switch + */ +@Composable +fun SettingsListItem( + label: String, + supportText: String? = null, + switchState: Boolean, + onSwitchChange: (Boolean) -> Unit +) = BasicSettingsListItem(label, supportText, { onSwitchChange(switchState) }) { + Switch(checked = switchState, onCheckedChange = { onSwitchChange(!it) }) +} diff --git a/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsScreen.kt b/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsScreen.kt index 6a5aa2ec..9dd14622 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsScreen.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/setttings/SettingsScreen.kt @@ -130,6 +130,11 @@ fun SettingsScreen( ) } ) + SettingsListItem( + label = stringResource(id = R.string.send_usage_statistics), + supportText = stringResource(id = R.string.send_usage_statistics_support), + switchState = mainViewModel.enableAnalytics, + onSwitchChange = { mainViewModel.setAnalyticsPref(!it) }) SettingsListItem( label = stringResource(R.string.third_party_licenses), onClick = { navControllerAction(ABOUT_SCREEN) } diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index 0ae5ac70..3221f378 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -718,5 +718,7 @@ Clear input Add or remove unit from favorites Empty search result + Send usage statistics + All data is anonymous and encrypted \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 796b556d..a473fcdb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -670,5 +670,7 @@ Солнце M Давление Ускорение + Отправлять статистику использования + Все данные анонимны и зашифрованы \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 899f646f..1167b838 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -930,6 +930,8 @@ Privacy Policy Third party licenses Rate this app + Send usage statistics + All data is anonymous and encrypted General Additional