diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b5f9c1d..4c3c663 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -35,6 +35,9 @@ + + { return availLocaleDateFormats.map { (DateFormat.getDateInstance( @@ -113,6 +120,28 @@ class PreferencesRepository { .edit().putInt(keyThemeMode, themeMode.ordinal).apply() } + fun getTopBarFont( + context: Context, + sharedPrefs: String = sharedPrefsName, + ): Int{ + try { + return context.getSharedPreferences(sharedPrefs, ComponentActivity.MODE_PRIVATE) + .getInt(keyTopBarFont,TopBarFont.NORMAL.ordinal) + } catch (e: Exception){ + e.printStackTrace() + } + return TopBarFont.NORMAL.ordinal + } + + fun setTopBarFont( + context: Context, + sharedPrefs: String = sharedPrefsName, + topBarFont: TopBarFont + ) { + return context.getSharedPreferences(sharedPrefs, ComponentActivity.MODE_PRIVATE) + .edit().putInt(keyTopBarFont, topBarFont.ordinal).apply() + } + fun getDynamicColors( context: Context, sharedPrefs: String = sharedPrefsName, diff --git a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/activity/UISettingsActivity.kt b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/activity/UISettingsActivity.kt new file mode 100644 index 0000000..0606fe0 --- /dev/null +++ b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/activity/UISettingsActivity.kt @@ -0,0 +1,21 @@ +package com.lorenzovainigli.foodexpirationdates.view.activity + +import android.os.Build +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.annotation.RequiresApi +import com.lorenzovainigli.foodexpirationdates.view.composable.activity.UISettingsActivityLayout +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class UISettingsActivity : ComponentActivity() { + + @RequiresApi(Build.VERSION_CODES.O) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + UISettingsActivityLayout() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/MyTopAppBar.kt b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/MyTopAppBar.kt index b294ccb..09b7174 100644 --- a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/MyTopAppBar.kt +++ b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/MyTopAppBar.kt @@ -6,11 +6,17 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.padding import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.lorenzovainigli.foodexpirationdates.model.repository.PreferencesRepository import com.lorenzovainigli.foodexpirationdates.ui.theme.FoodExpirationDatesTheme +import com.lorenzovainigli.foodexpirationdates.viewmodel.PreferencesViewModel @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -18,8 +24,13 @@ fun MyTopAppBar( title: String, actions: @Composable RowScope.() -> Unit = {}, navigationIcon: @Composable () -> Unit = {}, - scrollBehavior: TopAppBarScrollBehavior? = null + scrollBehavior: TopAppBarScrollBehavior? = null, + prefsViewModel: PreferencesViewModel? = viewModel() ) { + val context = LocalContext.current + val topBarFontState = prefsViewModel?.getTopBarFont(context)?.collectAsState()?.value + ?: PreferencesRepository.Companion.TopBarFont.NORMAL.ordinal + LargeTopAppBar( modifier = Modifier .padding(bottom = 4.dp) @@ -30,7 +41,13 @@ fun MyTopAppBar( title = { Text( text = title, - color = MaterialTheme.colorScheme.primary + color = MaterialTheme.colorScheme.primary, + fontWeight = when(topBarFontState){ + PreferencesRepository.Companion.TopBarFont.NORMAL.ordinal -> FontWeight.Normal + PreferencesRepository.Companion.TopBarFont.BOLD.ordinal -> FontWeight.Medium + PreferencesRepository.Companion.TopBarFont.EXTRA_BOLD.ordinal-> FontWeight.Bold + else -> null + } ) }, actions = actions, diff --git a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/SettingsActivityLayout.kt b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/SettingsActivityLayout.kt index db3b1e7..6c447cc 100644 --- a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/SettingsActivityLayout.kt +++ b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/SettingsActivityLayout.kt @@ -2,6 +2,7 @@ package com.lorenzovainigli.foodexpirationdates.view.composable.activity import android.app.Activity import android.content.Context +import android.content.Intent import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.foundation.isSystemInDarkTheme @@ -45,6 +46,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.lorenzovainigli.foodexpirationdates.R import com.lorenzovainigli.foodexpirationdates.model.repository.PreferencesRepository import com.lorenzovainigli.foodexpirationdates.ui.theme.FoodExpirationDatesTheme +import com.lorenzovainigli.foodexpirationdates.view.activity.UISettingsActivity import com.lorenzovainigli.foodexpirationdates.view.composable.DateFormatDialog import com.lorenzovainigli.foodexpirationdates.view.composable.MyTopAppBar import com.lorenzovainigli.foodexpirationdates.view.composable.NotificationTimeBottomSheet @@ -233,6 +235,19 @@ fun SettingsActivityLayout( } ) } + SettingsItem( + label = stringResource(R.string.ui_settings) + ){ + OutlinedButton( + onClick = { + val intent = Intent(context, UISettingsActivity::class.java) + context.startActivity(intent) + } + ) { + Text(text = stringResource(R.string.custom_ui)) + } + } + } } } diff --git a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/UISettingsActivityLayout.kt b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/UISettingsActivityLayout.kt new file mode 100644 index 0000000..146e3cc --- /dev/null +++ b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/view/composable/activity/UISettingsActivityLayout.kt @@ -0,0 +1,134 @@ +package com.lorenzovainigli.foodexpirationdates.view.composable.activity + +import android.app.Activity +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.lorenzovainigli.foodexpirationdates.R +import com.lorenzovainigli.foodexpirationdates.model.repository.PreferencesRepository +import com.lorenzovainigli.foodexpirationdates.ui.theme.FoodExpirationDatesTheme +import com.lorenzovainigli.foodexpirationdates.view.composable.MyTopAppBar +import com.lorenzovainigli.foodexpirationdates.view.composable.SettingsItem +import com.lorenzovainigli.foodexpirationdates.view.preview.DefaultPreviews +import com.lorenzovainigli.foodexpirationdates.view.preview.LanguagePreviews +import com.lorenzovainigli.foodexpirationdates.viewmodel.PreferencesViewModel + +@OptIn(ExperimentalMaterial3Api::class) +@RequiresApi(Build.VERSION_CODES.O) +@Composable +fun UISettingsActivityLayout( + context: Context = LocalContext.current, + prefsViewModel: PreferencesViewModel? = viewModel() +) { + val activity = (context as? Activity) + val topBarFontState = prefsViewModel?.getTopBarFont(context)?.collectAsState()?.value + ?: PreferencesRepository.Companion.TopBarFont.NORMAL.ordinal + val darkThemeState = prefsViewModel?.getThemeMode(context)?.collectAsState()?.value + ?: PreferencesRepository.Companion.ThemeMode.SYSTEM + val dynamicColorsState = prefsViewModel?.getDynamicColors(context)?.collectAsState()?.value + ?: false + + val isInDarkTheme = when (darkThemeState) { + PreferencesRepository.Companion.ThemeMode.LIGHT.ordinal -> false + PreferencesRepository.Companion.ThemeMode.DARK.ordinal -> true + else -> isSystemInDarkTheme() + } + + FoodExpirationDatesTheme( + darkTheme = isInDarkTheme, + dynamicColor = dynamicColorsState + ){ + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + MyTopAppBar( + title = stringResource(id = R.string.ui_settings), + navigationIcon = { + IconButton(onClick = { activity?.finish() }) { + Icon( + imageVector = Icons.Outlined.ArrowBack, + contentDescription = stringResource(id = R.string.back), + tint = MaterialTheme.colorScheme.primary + ) + } + }, + scrollBehavior = scrollBehavior + ) + } + ) { padding -> + Column( + modifier = Modifier + .padding(padding) + .padding(10.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + SettingsItem( + label = stringResource(R.string.top_bar_font_weight) + ) { + PreferencesRepository.Companion.TopBarFont.values().forEach { topBarFont-> + Spacer( + modifier = Modifier + .fillMaxHeight() + .weight(0.1f) + ) + if (topBarFont.ordinal == topBarFontState) { + Button(onClick = {}) { + Text( + text = context.getString(topBarFont.label) + ) + } + } + if (topBarFont.ordinal != topBarFontState) { + OutlinedButton( + onClick = { + prefsViewModel?.setTopBarFont(context, topBarFont) + }, + ) { + Text( + text = context.getString(topBarFont.label) + ) + } + } + } + } + } + } + } +} + +@RequiresApi(Build.VERSION_CODES.O) +@DefaultPreviews +@LanguagePreviews +@Composable +fun UISettingsActivityLayoutPreview() { + UISettingsActivityLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/viewmodel/PreferencesViewModel.kt b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/viewmodel/PreferencesViewModel.kt index 0aaa0c7..813122c 100644 --- a/app/src/main/java/com/lorenzovainigli/foodexpirationdates/viewmodel/PreferencesViewModel.kt +++ b/app/src/main/java/com/lorenzovainigli/foodexpirationdates/viewmodel/PreferencesViewModel.kt @@ -25,10 +25,12 @@ class PreferencesViewModel @Inject constructor(): ViewModel() { private var _themeMode = MutableStateFlow(0) private var themeMode = _themeMode.asStateFlow() - private var _dynamicColors = MutableStateFlow(false) private var dynamicColors = _dynamicColors.asStateFlow() + private var _topBarFont = MutableStateFlow(0) + private var topbarFont = _topBarFont.asStateFlow() + fun getDateFormat(context: Context): StateFlow { viewModelScope.launch { _dateFormat.value = PreferencesRepository.getUserDateFormat(context) @@ -88,6 +90,23 @@ class PreferencesViewModel @Inject constructor(): ViewModel() { _themeMode.value = theme.ordinal } + fun getTopBarFont(context: Context):StateFlow { + viewModelScope.launch { + _topBarFont.value = PreferencesRepository.getTopBarFont(context) + } + return topbarFont + } + + fun setTopBarFont(context: Context, topBarFont: PreferencesRepository.Companion.TopBarFont) { + viewModelScope.launch { + PreferencesRepository.setTopBarFont( + context = context, + topBarFont = topBarFont + ) + } + _topBarFont.value = topBarFont.ordinal + } + fun getDynamicColors(context: Context): StateFlow { viewModelScope.launch { _dynamicColors.value = PreferencesRepository.getDynamicColors(context) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a31e081..9436807 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,13 @@ Dark %1$s deleted Undo + Normal + Bold + Extra Bold + UI Settings + Custom UI + Top Bar Font Weight + Display a list with food expiration dates in ascending time order.