diff --git a/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt b/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt index 0cdb156e..27d5c44c 100644 --- a/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt +++ b/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt @@ -21,7 +21,7 @@ package com.sadellie.unitto.data import kotlinx.coroutines.flow.Flow @Suppress("UNCHECKED_CAST") -fun combine( +fun combine( flow: Flow, flow2: Flow, flow3: Flow, @@ -30,9 +30,10 @@ fun combine( flow6: Flow, flow7: Flow, flow8: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R + flow9: Flow, + transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R ): Flow = - kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8) { args: Array<*> -> + kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9) { args: Array<*> -> transform( args[0] as T1, args[1] as T2, @@ -42,5 +43,6 @@ fun combine( args[5] as T6, args[6] as T7, args[7] as T8, + args[8] as T9, ) } diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt index 5f2e3a93..afb5b24d 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt +++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt @@ -52,6 +52,7 @@ import javax.inject.Inject * @property latestRightSideUnit Latest [AbstractUnit] that was on the right side * @property shownUnitGroups [UnitGroup]s that user wants to see. Excludes other [UnitGroup]s, * @property enableVibrations When true will use haptic feedback in app. + * @property enableToolsExperiment When true will enable experimental Tools screen. */ data class UserPreferences( val themingMode: ThemingMode? = null, @@ -63,7 +64,8 @@ data class UserPreferences( val latestLeftSideUnit: String = MyUnitIDS.kilometer, val latestRightSideUnit: String = MyUnitIDS.mile, val shownUnitGroups: List = ALL_UNIT_GROUPS, - val enableVibrations: Boolean = true + val enableVibrations: Boolean = true, + val enableToolsExperiment: Boolean = false ) /** @@ -84,6 +86,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS val LATEST_RIGHT_SIDE = stringPreferencesKey("LATEST_RIGHT_SIDE_PREF_KEY") val SHOWN_UNIT_GROUPS = stringPreferencesKey("SHOWN_UNIT_GROUPS_PREF_KEY") val ENABLE_VIBRATIONS = booleanPreferencesKey("ENABLE_VIBRATIONS_PREF_KEY") + val ENABLE_TOOLS_EXPERIMENT = booleanPreferencesKey("ENABLE_TOOLS_EXPERIMENT_PREF_KEY") } val userPreferencesFlow: Flow = dataStore.data @@ -126,6 +129,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS } ?: ALL_UNIT_GROUPS val enableVibrations: Boolean = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true + val enableToolsExperiment: Boolean = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false UserPreferences( themingMode = themingMode, @@ -137,7 +141,8 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS latestLeftSideUnit = latestLeftSideUnit, latestRightSideUnit = latestRightSideUnit, shownUnitGroups = shownUnitGroups, - enableVibrations = enableVibrations + enableVibrations = enableVibrations, + enableToolsExperiment = enableToolsExperiment ) } @@ -237,4 +242,15 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS preferences[PrefsKeys.ENABLE_VIBRATIONS] = enabled } } + + /** + * Update preference on whether or not show tools screen. + * + * @param enabled True if user wants to enable this feature. + */ + suspend fun updateToolsExperiment(enabled: Boolean) { + dataStore.edit { preferences -> + preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] = enabled + } + } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt index fd4a01dc..cd908a03 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt @@ -73,25 +73,27 @@ internal fun ConverterScreen( modifier = Modifier, title = { AnimatedTopBarText(launched) }, navigationIcon = { - BadgedBox( - modifier = Modifier - .padding(horizontal = 16.dp) - .clickable( - onClick = navigateToTools, - interactionSource = remember { MutableInteractionSource() }, - indication = rememberRipple(false), - role = Role.Button - ), - badge = { - Badge { Text("1") } - }, - content = { - Icon( - Icons.Outlined.Science, - contentDescription = stringResource(R.string.tools_screen) - ) - } - ) + if (uiState.value.showTools) { + BadgedBox( + modifier = Modifier + .padding(horizontal = 16.dp) + .clickable( + onClick = navigateToTools, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(false), + role = Role.Button + ), + badge = { + Badge { Text("1") } + }, + content = { + Icon( + Icons.Outlined.Science, + contentDescription = stringResource(R.string.tools_screen) + ) + } + ) + } }, actions = { IconButton(onClick = navigateToSettings) { diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt index 24ab64ac..1752375c 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt @@ -34,6 +34,7 @@ import com.sadellie.unitto.data.units.AbstractUnit * @property unitTo Unit on the right. * @property mode * @property formatTime If true will format output when converting time. + * @property showTools If true will show tools button in TopBar. */ data class ConverterUIState( val inputValue: String = KEY_0, @@ -44,7 +45,8 @@ data class ConverterUIState( val unitFrom: AbstractUnit? = null, val unitTo: AbstractUnit? = null, val mode: ConverterMode = ConverterMode.DEFAULT, - val formatTime: Boolean = true + val formatTime: Boolean = true, + val showTools: Boolean = false ) enum class ConverterMode { diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt index 3bb0b873..17ae3e57 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt @@ -141,8 +141,9 @@ class ConverterViewModel @Inject constructor( _result, _showLoading, _showError, - _formatTime - ) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, formatTime -> + _formatTime, + userPrefs + ) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, formatTime, prefs -> return@combine ConverterUIState( inputValue = inputValue, calculatedValue = calculatedValue, @@ -156,7 +157,8 @@ class ConverterViewModel @Inject constructor( * changing units. */ mode = if (_unitFrom.value is NumberBaseUnit) ConverterMode.BASE else ConverterMode.DEFAULT, - formatTime = formatTime + formatTime = formatTime, + showTools = prefs.enableToolsExperiment ) } .stateIn( diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt index 582cd6a3..218dd5d8 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt @@ -18,7 +18,9 @@ package com.sadellie.unitto.feature.settings +import android.widget.Toast import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Code @@ -39,22 +41,23 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sadellie.unitto.core.base.BuildConfig +import com.sadellie.unitto.core.ui.R import com.sadellie.unitto.core.ui.common.UnittoLargeTopAppBar import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.core.ui.R import com.sadellie.unitto.feature.settings.components.AlertDialogWithList @Composable internal fun AboutScreen( navigateUpAction: () -> Unit, - navigateToThirdParty: () -> Unit + navigateToThirdParty: () -> Unit, + viewModel: SettingsViewModel ) { val mContext = LocalContext.current - - var showDialog: Boolean by rememberSaveable { - mutableStateOf(false) - } + val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle() + var aboutItemClick: Int by rememberSaveable { mutableStateOf(0) } + var showDialog: Boolean by rememberSaveable { mutableStateOf(false) } UnittoLargeTopAppBar( title = stringResource(R.string.about_unitto), @@ -177,7 +180,18 @@ internal fun AboutScreen( }, headlineText = { Text(stringResource(R.string.app_version_name_setting)) }, supportingText = { Text("${BuildConfig.APP_NAME} (${BuildConfig.APP_CODE})") }, - modifier = Modifier.clickable {} + modifier = Modifier.combinedClickable { + if (userPrefs.value.enableToolsExperiment) { + Toast.makeText(mContext, "Tools already enabled!", Toast.LENGTH_LONG).show() + return@combinedClickable + } + + aboutItemClick++ + if (aboutItemClick < 7) return@combinedClickable + + viewModel.enableToolsExperiment() + Toast.makeText(mContext, "Tools enabled!", Toast.LENGTH_LONG).show() + } ) } } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt index 7454d637..83dd3f9f 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt @@ -48,7 +48,7 @@ class SettingsViewModel @Inject constructor( val hiddenUnitGroups = unitGroupsRepository.hiddenUnitGroups /** - * @see [UserPreferencesRepository.updateThemingMode] + * @see UserPreferencesRepository.updateThemingMode */ fun updateThemingMode(themingMode: ThemingMode) { viewModelScope.launch { @@ -57,7 +57,7 @@ class SettingsViewModel @Inject constructor( } /** - * @see [UserPreferencesRepository.updateDynamicTheme] + * @see UserPreferencesRepository.updateDynamicTheme */ fun updateDynamicTheme(enabled: Boolean) { viewModelScope.launch { @@ -66,7 +66,7 @@ class SettingsViewModel @Inject constructor( } /** - * @see [UserPreferencesRepository.updateAmoledTheme] + * @see UserPreferencesRepository.updateAmoledTheme */ fun updateAmoledTheme(enabled: Boolean) { viewModelScope.launch { @@ -75,7 +75,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UserPreferencesRepository.updateDigitsPrecision] + * @see UserPreferencesRepository.updateDigitsPrecision */ fun updatePrecision(precision: Int) { viewModelScope.launch { @@ -84,7 +84,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UserPreferencesRepository.updateSeparator] + * @see UserPreferencesRepository.updateSeparator */ fun updateSeparator(separator: Int) { viewModelScope.launch { @@ -93,7 +93,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UserPreferencesRepository.updateOutputFormat] + * @see UserPreferencesRepository.updateOutputFormat */ fun updateOutputFormat(outputFormat: Int) { viewModelScope.launch { @@ -102,7 +102,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UserPreferencesRepository.updateVibrations] + * @see UserPreferencesRepository.updateVibrations */ fun updateVibrations(enabled: Boolean) { viewModelScope.launch { @@ -111,8 +111,8 @@ class SettingsViewModel @Inject constructor( } /** - * See [UnitGroupsRepository.markUnitGroupAsHidden] and - * [UserPreferencesRepository.updateShownUnitGroups] + * @see UnitGroupsRepository.markUnitGroupAsHidden + * @see UserPreferencesRepository.updateShownUnitGroups */ fun hideUnitGroup(unitGroup: UnitGroup) { viewModelScope.launch { @@ -122,8 +122,8 @@ class SettingsViewModel @Inject constructor( } /** - * See [UnitGroupsRepository.markUnitGroupAsShown] and - * [UserPreferencesRepository.updateShownUnitGroups] + * @see UnitGroupsRepository.markUnitGroupAsShown + * @see UserPreferencesRepository.updateShownUnitGroups */ fun returnUnitGroup(unitGroup: UnitGroup) { viewModelScope.launch { @@ -133,7 +133,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UnitGroupsRepository.moveShownUnitGroups] + * @see UnitGroupsRepository.moveShownUnitGroups */ fun onMove(from: ItemPosition, to: ItemPosition) { viewModelScope.launch { @@ -142,7 +142,7 @@ class SettingsViewModel @Inject constructor( } /** - * See [UserPreferencesRepository.updateShownUnitGroups] + * @see UserPreferencesRepository.updateShownUnitGroups */ fun onDragEnd() { viewModelScope.launch { @@ -150,6 +150,15 @@ class SettingsViewModel @Inject constructor( } } + /** + * @see UserPreferencesRepository.updateToolsExperiment + */ + fun enableToolsExperiment() { + viewModelScope.launch { + userPrefsRepository.updateToolsExperiment(true) + } + } + /** * Prevent from dragging over non-draggable items (headers and hidden) * diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt index 08d99546..6289314a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt @@ -76,7 +76,8 @@ fun NavGraphBuilder.settingGraph( composable(aboutRoute) { AboutScreen( navigateUpAction = { navController.navigateUp() }, - navigateToThirdParty = { navController.navigate(thirdPartyRoute) } + navigateToThirdParty = { navController.navigate(thirdPartyRoute) }, + viewModel = settingsViewModel ) }