mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 16:25:27 +02:00
Improved UX for cache clearing
This commit is contained in:
parent
d519af6ec8
commit
8be61f03f2
@ -23,7 +23,6 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
@ -82,7 +81,7 @@ fun Context.addShortcut(
|
||||
PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||
showToast(context, e.message ?: "Error")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,9 +35,17 @@ fun openLink(mContext: Context, url: String) {
|
||||
try {
|
||||
mContext.startActivity(Intent(Intent.ACTION_VIEW).setData(Uri.parse(url)))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Toast.makeText(mContext, R.string.error_label, Toast.LENGTH_SHORT).show()
|
||||
showToast(mContext, mContext.getString(R.string.error_label))
|
||||
}
|
||||
}
|
||||
|
||||
fun showToast(
|
||||
mContext: Context,
|
||||
text: String,
|
||||
duration: Int = Toast.LENGTH_SHORT
|
||||
) {
|
||||
Toast.makeText(mContext, text, duration).show()
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun isPortrait() = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT
|
||||
|
@ -22,6 +22,7 @@ import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CurrencyRatesDao {
|
||||
@ -32,6 +33,9 @@ interface CurrencyRatesDao {
|
||||
@Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId")
|
||||
suspend fun getLatestRates(baseId: String): List<CurrencyRatesEntity>
|
||||
|
||||
@Query("SELECT COUNT(*) from currency_rates")
|
||||
fun size(): Flow<Int>
|
||||
|
||||
@Query("DELETE FROM currency_rates")
|
||||
suspend fun clear()
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.CalendarContract
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
@ -73,6 +72,7 @@ import com.sadellie.unitto.core.base.R
|
||||
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
||||
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
|
||||
import com.sadellie.unitto.core.ui.isPortrait
|
||||
import com.sadellie.unitto.core.ui.showToast
|
||||
import com.sadellie.unitto.feature.datecalculator.components.AddSubtractKeyboard
|
||||
import com.sadellie.unitto.feature.datecalculator.components.DateTimeDialogs
|
||||
import com.sadellie.unitto.feature.datecalculator.components.DateTimeSelectorBlock
|
||||
@ -340,7 +340,7 @@ private fun Context.addEvent(start: ZonedDateTime, end: ZonedDateTime) {
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Toast.makeText(this, R.string.error_label, Toast.LENGTH_SHORT).show()
|
||||
showToast(this, this.getString(R.string.error_label))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,23 @@
|
||||
|
||||
package com.sadellie.unitto.feature.settings
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
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.Cached
|
||||
import androidx.compose.material.icons.filled.Calculate
|
||||
@ -29,12 +44,24 @@ import androidx.compose.material.icons.filled.Palette
|
||||
import androidx.compose.material.icons.filled.RateReview
|
||||
import androidx.compose.material.icons.filled.SwapHoriz
|
||||
import androidx.compose.material.icons.filled.Vibration
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material.icons.filled._123
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
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.graphics.compositeOver
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.sadellie.unitto.core.base.BuildConfig
|
||||
@ -44,6 +71,7 @@ import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
|
||||
import com.sadellie.unitto.core.ui.openLink
|
||||
import com.sadellie.unitto.core.ui.showToast
|
||||
import com.sadellie.unitto.data.userprefs.GeneralPreferences
|
||||
import com.sadellie.unitto.feature.settings.navigation.aboutRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.calculatorSettingsRoute
|
||||
@ -59,13 +87,15 @@ internal fun SettingsRoute(
|
||||
navControllerAction: (String) -> Unit,
|
||||
) {
|
||||
val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle()
|
||||
val cachePercentage = viewModel.cachePercentage.collectAsStateWithLifecycle()
|
||||
|
||||
SettingsScreen(
|
||||
userPrefs = userPrefs.value,
|
||||
navigateUp = navigateUp,
|
||||
navControllerAction = navControllerAction,
|
||||
updateVibrations = viewModel::updateVibrations,
|
||||
clearCache = viewModel::clearCache
|
||||
cachePercentage = cachePercentage.value,
|
||||
clearCache = viewModel::clearCache,
|
||||
)
|
||||
}
|
||||
|
||||
@ -75,6 +105,7 @@ private fun SettingsScreen(
|
||||
navigateUp: () -> Unit,
|
||||
navControllerAction: (String) -> Unit,
|
||||
updateVibrations: (Boolean) -> Unit,
|
||||
cachePercentage: Float,
|
||||
clearCache: () -> Unit,
|
||||
) {
|
||||
val mContext = LocalContext.current
|
||||
@ -83,101 +114,122 @@ private fun SettingsScreen(
|
||||
title = stringResource(R.string.settings_screen),
|
||||
navigationIcon = { NavigateUpButton(navigateUp) }
|
||||
) { padding ->
|
||||
LazyColumn(contentPadding = padding) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(padding)
|
||||
) {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Palette,
|
||||
iconDescription = stringResource(R.string.display_settings),
|
||||
headlineText = stringResource(R.string.display_settings),
|
||||
supportingText = stringResource(R.string.theme_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(displayRoute) }
|
||||
)
|
||||
|
||||
item("theme") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Palette,
|
||||
iconDescription = stringResource(R.string.display_settings),
|
||||
headlineText = stringResource(R.string.display_settings),
|
||||
supportingText = stringResource(R.string.theme_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(displayRoute) }
|
||||
)
|
||||
}
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Home,
|
||||
iconDescription = stringResource(R.string.starting_screen_setting),
|
||||
headlineText = stringResource(R.string.starting_screen_setting),
|
||||
supportingText = stringResource(R.string.starting_screen_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(startingScreenRoute) }
|
||||
)
|
||||
|
||||
item("starting screen") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Home,
|
||||
iconDescription = stringResource(R.string.starting_screen_setting),
|
||||
headlineText = stringResource(R.string.starting_screen_setting),
|
||||
supportingText = stringResource(R.string.starting_screen_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(startingScreenRoute) }
|
||||
)
|
||||
}
|
||||
UnittoListItem(
|
||||
icon = Icons.Default._123,
|
||||
iconDescription = stringResource(R.string.formatting_setting),
|
||||
headlineText = stringResource(R.string.formatting_setting),
|
||||
supportingText = stringResource(R.string.formatting_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(formattingRoute) }
|
||||
)
|
||||
|
||||
item("formatting") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default._123,
|
||||
iconDescription = stringResource(R.string.formatting_setting),
|
||||
headlineText = stringResource(R.string.formatting_setting),
|
||||
supportingText = stringResource(R.string.formatting_setting_support),
|
||||
modifier = Modifier.clickable { navControllerAction(formattingRoute) }
|
||||
)
|
||||
}
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Calculate,
|
||||
iconDescription = stringResource(R.string.calculator),
|
||||
headlineText = stringResource(R.string.calculator),
|
||||
supportingText = stringResource(R.string.calculator_settings_support),
|
||||
modifier = Modifier.clickable { navControllerAction(calculatorSettingsRoute) }
|
||||
)
|
||||
|
||||
item("calculator") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Calculate,
|
||||
iconDescription = stringResource(R.string.calculator),
|
||||
headlineText = stringResource(R.string.calculator),
|
||||
supportingText = stringResource(R.string.calculator_settings_support),
|
||||
modifier = Modifier.clickable { navControllerAction(calculatorSettingsRoute) }
|
||||
)
|
||||
}
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.SwapHoriz,
|
||||
iconDescription = stringResource(R.string.unit_converter),
|
||||
headlineText = stringResource(R.string.unit_converter),
|
||||
supportingText = stringResource(R.string.converter_settings_support),
|
||||
modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) }
|
||||
)
|
||||
|
||||
item("unit converter") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.SwapHoriz,
|
||||
iconDescription = stringResource(R.string.unit_converter),
|
||||
headlineText = stringResource(R.string.unit_converter),
|
||||
supportingText = stringResource(R.string.converter_settings_support),
|
||||
modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) }
|
||||
)
|
||||
}
|
||||
Header(stringResource(R.string.additional_settings_group))
|
||||
|
||||
item("additional") { Header(stringResource(R.string.additional_settings_group)) }
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Vibration,
|
||||
iconDescription = stringResource(R.string.enable_vibrations),
|
||||
headlineText = stringResource(R.string.enable_vibrations),
|
||||
supportingText = stringResource(R.string.enable_vibrations_support),
|
||||
modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) },
|
||||
switchState = userPrefs.enableVibrations,
|
||||
onSwitchChange = updateVibrations
|
||||
)
|
||||
|
||||
item("vibrations") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Vibration,
|
||||
iconDescription = stringResource(R.string.enable_vibrations),
|
||||
headlineText = stringResource(R.string.enable_vibrations),
|
||||
supportingText = stringResource(R.string.enable_vibrations_support),
|
||||
modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) },
|
||||
switchState = userPrefs.enableVibrations,
|
||||
onSwitchChange = updateVibrations
|
||||
)
|
||||
}
|
||||
|
||||
item("clear cache") {
|
||||
AnimatedVisibility(
|
||||
visible = cachePercentage > 0,
|
||||
enter = expandVertically() + fadeIn(),
|
||||
exit = shrinkVertically() + fadeOut(),
|
||||
) {
|
||||
UnittoListItem(
|
||||
headlineText = stringResource(R.string.clear_cache),
|
||||
icon = Icons.Default.Cached,
|
||||
iconDescription = stringResource(R.string.clear_cache),
|
||||
modifier = Modifier.clickable { clearCache() },
|
||||
modifier = Modifier.clickable { clearCache(); showToast(mContext, "👌") },
|
||||
trailing = {
|
||||
Box(
|
||||
Modifier
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.errorContainer)
|
||||
.size(52.dp, 24.dp),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.background(
|
||||
MaterialTheme.colorScheme.error.copy(alpha = cachePercentage)
|
||||
.compositeOver(Color.Green)
|
||||
)
|
||||
.height(24.dp)
|
||||
.fillMaxWidth(cachePercentage),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (cachePercentage == 1f) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Warning,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onError,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (BuildConfig.STORE_LINK.isNotEmpty()) {
|
||||
item("rate this app") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.RateReview,
|
||||
iconDescription = stringResource(R.string.rate_this_app),
|
||||
headlineText = stringResource(R.string.rate_this_app),
|
||||
modifier = Modifier.clickable { openLink(mContext, BuildConfig.STORE_LINK) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item("about") {
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Info,
|
||||
iconDescription = stringResource(R.string.about_unitto),
|
||||
headlineText = stringResource(R.string.about_unitto),
|
||||
supportingText = stringResource(R.string.about_unitto_support),
|
||||
modifier = Modifier.clickable { navControllerAction(aboutRoute) }
|
||||
icon = Icons.Default.RateReview,
|
||||
iconDescription = stringResource(R.string.rate_this_app),
|
||||
headlineText = stringResource(R.string.rate_this_app),
|
||||
modifier = Modifier.clickable { openLink(mContext, BuildConfig.STORE_LINK) }
|
||||
)
|
||||
}
|
||||
|
||||
UnittoListItem(
|
||||
icon = Icons.Default.Info,
|
||||
iconDescription = stringResource(R.string.about_unitto),
|
||||
headlineText = stringResource(R.string.about_unitto),
|
||||
supportingText = stringResource(R.string.about_unitto_support),
|
||||
modifier = Modifier.clickable { navControllerAction(aboutRoute) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,11 +237,14 @@ private fun SettingsScreen(
|
||||
@Preview
|
||||
@Composable
|
||||
private fun PreviewSettingsScreen() {
|
||||
var cacheSize by remember { mutableFloatStateOf(0.9f) }
|
||||
|
||||
SettingsScreen(
|
||||
userPrefs = GeneralPreferences(),
|
||||
navigateUp = {},
|
||||
navControllerAction = {},
|
||||
updateVibrations = {},
|
||||
clearCache = {}
|
||||
cachePercentage = cacheSize,
|
||||
clearCache = { cacheSize = 0f }
|
||||
)
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import com.sadellie.unitto.data.database.CurrencyRatesDao
|
||||
import com.sadellie.unitto.data.userprefs.GeneralPreferences
|
||||
import com.sadellie.unitto.data.userprefs.UserPreferencesRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -36,6 +38,12 @@ internal class SettingsViewModel @Inject constructor(
|
||||
val userPrefs = userPrefsRepository.generalPrefs
|
||||
.stateIn(viewModelScope, GeneralPreferences())
|
||||
|
||||
val cachePercentage = currencyRatesDao.size()
|
||||
.map {
|
||||
(it / 100_000f).coerceIn(0f, 1f)
|
||||
}
|
||||
.stateIn(viewModelScope, 0f)
|
||||
|
||||
/**
|
||||
* @see UserPreferencesRepository.updateVibrations
|
||||
*/
|
||||
@ -43,7 +51,7 @@ internal class SettingsViewModel @Inject constructor(
|
||||
userPrefsRepository.updateVibrations(enabled)
|
||||
}
|
||||
|
||||
fun clearCache() = viewModelScope.launch {
|
||||
fun clearCache() = viewModelScope.launch(Dispatchers.IO) {
|
||||
currencyRatesDao.clear()
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
|
||||
import com.sadellie.unitto.core.ui.openLink
|
||||
import com.sadellie.unitto.core.ui.showToast
|
||||
import com.sadellie.unitto.data.userprefs.AboutPreferences
|
||||
|
||||
@Composable
|
||||
@ -158,7 +159,7 @@ private fun AboutScreen(
|
||||
supportingText = "${BuildConfig.APP_NAME} (${BuildConfig.APP_CODE})",
|
||||
modifier = Modifier.combinedClickable {
|
||||
if (prefs.enableToolsExperiment) {
|
||||
Toast.makeText(mContext, "Experiments features are already enabled!", Toast.LENGTH_LONG).show()
|
||||
showToast(mContext, "Experiments features are already enabled!", Toast.LENGTH_LONG)
|
||||
return@combinedClickable
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ private fun AboutScreen(
|
||||
if (aboutItemClick < 7) return@combinedClickable
|
||||
|
||||
enableToolsExperiment()
|
||||
Toast.makeText(mContext, "Experimental features enabled!", Toast.LENGTH_LONG).show()
|
||||
showToast(mContext, "Experimental features enabled!", Toast.LENGTH_LONG)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user