🛠️ MainState rework

* Non-null variables
* Better, scalable structure
This commit is contained in:
Acclorite 2024-09-01 21:14:06 +03:00
parent 9561357f65
commit 3b287ff1a0
28 changed files with 206 additions and 197 deletions

View file

@ -109,13 +109,13 @@ class Activity : AppCompatActivity() {
if (isLoaded.value) { if (isLoaded.value) {
BookStoryTheme( BookStoryTheme(
theme = state.value.theme!!, theme = state.value.theme,
isDark = state.value.darkTheme!!.isDark(), isDark = state.value.darkTheme.isDark(),
isPureDark = state.value.pureDark!!.isPureDark(this), isPureDark = state.value.pureDark.isPureDark(this),
themeContrast = state.value.themeContrast!! themeContrast = state.value.themeContrast
) { ) {
NavigationHost( NavigationHost(
startScreen = if (state.value.showStartScreen!!) Screen.Start startScreen = if (state.value.showStartScreen) Screen.Start
else Screen.Library else Screen.Library
) { ) {
navigation( navigation(

View file

@ -6,6 +6,7 @@ import android.os.Build
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.Keep import androidx.annotation.Keep
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.datastore.preferences.core.Preferences
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.Constants
import ua.acclorite.book_story.domain.util.DataStoreConstants import ua.acclorite.book_story.domain.util.DataStoreConstants
@ -37,169 +38,179 @@ import java.util.Locale
@Parcelize @Parcelize
data class MainState( data class MainState(
// General Settings // General Settings
val language: String? = null, val language: String = provideDefaultValue {
val theme: Theme? = null, val locale = Locale.getDefault().language.take(2)
val darkTheme: DarkTheme? = null, Constants.LANGUAGES.any { locale == it.first }.run {
val pureDark: PureDark? = null, if (this) locale
val themeContrast: ThemeContrast? = null, else "en"// Default language.
val showStartScreen: Boolean? = null, }
val checkForUpdates: Boolean? = null, },
val doublePressExit: Boolean? = null, val theme: Theme = provideDefaultValue {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Theme.DYNAMIC
else Theme.BLUE
},
val darkTheme: DarkTheme = provideDefaultValue { DarkTheme.FOLLOW_SYSTEM },
val pureDark: PureDark = provideDefaultValue { PureDark.OFF },
val themeContrast: ThemeContrast = provideDefaultValue { ThemeContrast.STANDARD },
val showStartScreen: Boolean = provideDefaultValue { true },
val checkForUpdates: Boolean = provideDefaultValue { false },
val doublePressExit: Boolean = provideDefaultValue { false },
// Reader Settings // Reader Settings
val fontFamily: String? = null, val fontFamily: String = provideDefaultValue { Constants.FONTS[0].id },
val isItalic: Boolean? = null, val isItalic: Boolean = provideDefaultValue { false },
val fontSize: Int? = null, val fontSize: Int = provideDefaultValue { 16 },
val lineHeight: Int? = null, val lineHeight: Int = provideDefaultValue { 4 },
val paragraphHeight: Int? = null, val paragraphHeight: Int = provideDefaultValue { 8 },
val paragraphIndentation: Boolean? = null, val paragraphIndentation: Boolean = provideDefaultValue { false },
val sidePadding: Int? = null, val sidePadding: Int = provideDefaultValue { 6 },
val doubleClickTranslation: Boolean? = null, val doubleClickTranslation: Boolean = provideDefaultValue { false },
val fastColorPresetChange: Boolean? = null, val fastColorPresetChange: Boolean = provideDefaultValue { true },
val textAlignment: ReaderTextAlignment? = null, val textAlignment: ReaderTextAlignment = provideDefaultValue { ReaderTextAlignment.START },
val letterSpacing: Int? = null, val letterSpacing: Int = provideDefaultValue { 0 },
// Browse Settings // Browse Settings
val browseFilesStructure: BrowseFilesStructure? = null, val browseFilesStructure: BrowseFilesStructure = provideDefaultValue {
val browseLayout: BrowseLayout? = null, BrowseFilesStructure.DIRECTORIES
val browseAutoGridSize: Boolean? = null, },
val browseGridSize: Int? = null, val browseLayout: BrowseLayout = provideDefaultValue { BrowseLayout.LIST },
val browsePinFavoriteDirectories: Boolean? = null, val browseAutoGridSize: Boolean = provideDefaultValue { true },
val browseSortOrder: BrowseSortOrder? = null, val browseGridSize: Int = provideDefaultValue { 0 },
val browseSortOrderDescending: Boolean? = null, val browsePinFavoriteDirectories: Boolean = provideDefaultValue { true },
val browseIncludedFilterItems: List<String>? = null, val browseSortOrder: BrowseSortOrder = provideDefaultValue { BrowseSortOrder.LAST_MODIFIED },
val browseSortOrderDescending: Boolean = provideDefaultValue { true },
val browseIncludedFilterItems: List<String> = provideDefaultValue { emptyList() },
) : Parcelable { ) : Parcelable {
companion object { companion object {
/** /**
* Initializes [MainState] by given [Map]. * Initializes [MainState] by given [Map].
* If no value provided in [data], assigns default value.
*/ */
fun initialize(data: Map<String, Any>): MainState { fun initialize(data: Map<String, Any>): MainState {
DataStoreConstants.apply { val defaultState = MainState()
val language: String = data[LANGUAGE.name] as? String ?: if ( fun <V, T> provideValue(
Constants.LANGUAGES.any { Locale.getDefault().language.take(2) == it.first } key: Preferences.Key<T>,
) { convert: T.() -> V = { this as V },
Locale.getDefault().language.take(2) default: MainState.() -> V
} else { ): V {
"en" return (data[key.name] as? T)?.convert() ?: defaultState.default()
} }
val theme: String = data[THEME.name] as? String ?: if ( return DataStoreConstants.run {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S MainState(
) Theme.DYNAMIC.name else Theme.BLUE.name language = provideValue(
LANGUAGE
) { language },
val darkTheme: String = data[DARK_THEME.name] as? String theme = provideValue(
?: DarkTheme.FOLLOW_SYSTEM.name THEME, convert = { toTheme() }
) { theme },
val pureDark: String = data[PURE_DARK.name] as? String darkTheme = provideValue(
?: PureDark.OFF.name DARK_THEME, convert = { toDarkTheme() }
) { darkTheme },
val themeContrast: String = data[THEME_CONTRAST.name] as? String pureDark = provideValue(
?: ThemeContrast.STANDARD.name PURE_DARK, convert = { toPureDark() }
) { pureDark },
val showStartScreen: Boolean = data[SHOW_START_SCREEN.name] as? Boolean themeContrast = provideValue(
?: true THEME_CONTRAST, convert = { toThemeContrast() }
) { themeContrast },
val fontFamily: String = data[FONT.name] as? String showStartScreen = provideValue(
?: Constants.FONTS[0].id SHOW_START_SCREEN
) { showStartScreen },
val isItalic: Boolean = data[IS_ITALIC.name] as? Boolean fontFamily = provideValue(
?: false FONT
) { fontFamily },
val fontSize: Int = data[FONT_SIZE.name] as? Int isItalic = provideValue(
?: 16 IS_ITALIC
) { isItalic },
val lineHeight: Int = data[LINE_HEIGHT.name] as? Int fontSize = provideValue(
?: 4 FONT_SIZE
) { fontSize },
val paragraphHeight: Int = data[PARAGRAPH_HEIGHT.name] as? Int lineHeight = provideValue(
?: 8 LINE_HEIGHT
) { lineHeight },
val paragraphIndentation: Boolean = data[PARAGRAPH_INDENTATION.name] as? Boolean paragraphHeight = provideValue(
?: false PARAGRAPH_HEIGHT
) { paragraphHeight },
val checkForUpdates: Boolean = data[CHECK_FOR_UPDATES.name] as? Boolean paragraphIndentation = provideValue(
?: false PARAGRAPH_INDENTATION
) { paragraphIndentation },
val sidePadding: Int = data[SIDE_PADDING.name] as? Int checkForUpdates = provideValue(
?: 6 CHECK_FOR_UPDATES
) { checkForUpdates },
val doubleClickTranslation: Boolean = sidePadding = provideValue(
data[DOUBLE_CLICK_TRANSLATION.name] as? Boolean SIDE_PADDING
?: false ) { sidePadding },
val fastColorPresetChange: Boolean = doubleClickTranslation = provideValue(
data[FAST_COLOR_PRESET_CHANGE.name] as? Boolean DOUBLE_CLICK_TRANSLATION
?: true ) { doubleClickTranslation },
val browseFilesStructure: String = data[BROWSE_FILES_STRUCTURE.name] as? String fastColorPresetChange = provideValue(
?: BrowseFilesStructure.DIRECTORIES.name FAST_COLOR_PRESET_CHANGE
) { fastColorPresetChange },
val browseLayout: String = data[BROWSE_LAYOUT.name] as? String browseFilesStructure = provideValue(
?: BrowseLayout.LIST.name BROWSE_FILES_STRUCTURE, convert = { toFilesStructure() }
) { browseFilesStructure },
val browseAutoGridSize: Boolean = browseLayout = provideValue(
data[BROWSE_AUTO_GRID_SIZE.name] as? Boolean BROWSE_LAYOUT, convert = { toBrowseLayout() }
?: true ) { browseLayout },
val browseGridSize: Int = browseAutoGridSize = provideValue(
data[BROWSE_GRID_SIZE.name] as? Int BROWSE_AUTO_GRID_SIZE
?: 0 ) { browseAutoGridSize },
val browsePinFavoriteDirectories: Boolean = browseGridSize = provideValue(
data[BROWSE_PIN_FAVORITE_DIRECTORIES.name] as? Boolean BROWSE_GRID_SIZE
?: true ) { browseGridSize },
val browseSortOrder: String = browsePinFavoriteDirectories = provideValue(
data[BROWSE_SORT_ORDER.name] as? String BROWSE_PIN_FAVORITE_DIRECTORIES
?: BrowseSortOrder.LAST_MODIFIED.name ) { browsePinFavoriteDirectories },
val browseSortOrderDescending: Boolean = browseSortOrder = provideValue(
data[BROWSE_SORT_ORDER_DESCENDING.name] as? Boolean BROWSE_SORT_ORDER, convert = { toBrowseSortOrder() }
?: true ) { browseSortOrder },
val browseIncludedFilterItems = browseSortOrderDescending = provideValue(
(data[BROWSE_INCLUDED_FILTER_ITEMS.name] as? Set<String>)?.toList() BROWSE_SORT_ORDER_DESCENDING
?: emptyList() ) { browseSortOrderDescending },
val textAlignment = data[TEXT_ALIGNMENT.name] as? String browseIncludedFilterItems = provideValue(
?: ReaderTextAlignment.START.name BROWSE_INCLUDED_FILTER_ITEMS, convert = { toList() }
) { browseIncludedFilterItems },
val doublePressExit = data[DOUBLE_PRESS_EXIT.name] as? Boolean textAlignment = provideValue(
?: false TEXT_ALIGNMENT, convert = { toTextAlignment() }
) { textAlignment },
val letterSpacing = data[LETTER_SPACING.name] as? Int doublePressExit = provideValue(
?: 0 DOUBLE_PRESS_EXIT
) { doublePressExit },
return MainState( letterSpacing = provideValue(
language = language, LETTER_SPACING
theme = theme.toTheme(), ) { letterSpacing },
darkTheme = darkTheme.toDarkTheme(),
pureDark = pureDark.toPureDark(),
themeContrast = themeContrast.toThemeContrast(),
showStartScreen = showStartScreen,
fontFamily = fontFamily,
isItalic = isItalic,
fontSize = fontSize,
lineHeight = lineHeight,
paragraphHeight = paragraphHeight,
paragraphIndentation = paragraphIndentation,
checkForUpdates = checkForUpdates,
sidePadding = sidePadding,
doubleClickTranslation = doubleClickTranslation,
fastColorPresetChange = fastColorPresetChange,
browseFilesStructure = browseFilesStructure.toFilesStructure(),
browseLayout = browseLayout.toBrowseLayout(),
browseAutoGridSize = browseAutoGridSize,
browseGridSize = browseGridSize,
browsePinFavoriteDirectories = browsePinFavoriteDirectories,
browseSortOrder = browseSortOrder.toBrowseSortOrder(),
browseSortOrderDescending = browseSortOrderDescending,
browseIncludedFilterItems = browseIncludedFilterItems,
textAlignment = textAlignment.toTextAlignment(),
doublePressExit = doublePressExit,
letterSpacing = letterSpacing,
) )
} }
} }
} }
}
private fun <D> provideDefaultValue(calculation: () -> D): D {
return calculation()
} }

View file

@ -318,7 +318,7 @@ class MainViewModel @Inject constructor(
is MainEvent.OnChangeBrowseIncludedFilterItem -> { is MainEvent.OnChangeBrowseIncludedFilterItem -> {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val set = _state.value.browseIncludedFilterItems!!.toMutableSet() val set = _state.value.browseIncludedFilterItems.toMutableSet()
if (!set.add(event.item)) { if (!set.add(event.item)) {
set.remove(event.item) set.remove(event.item)
} }
@ -384,9 +384,9 @@ class MainViewModel @Inject constructor(
val settings = getAllSettings.execute(viewModelScope) val settings = getAllSettings.execute(viewModelScope)
// All additional execution // All additional execution
changeLanguage.execute(settings.language!!) changeLanguage.execute(settings.language)
if (settings.checkForUpdates == true) { if (settings.checkForUpdates) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
checkForUpdates.execute( checkForUpdates.execute(
postNotification = true postNotification = true
@ -394,9 +394,7 @@ class MainViewModel @Inject constructor(
} }
} }
updateStateWithSavedHandle { updateStateWithSavedHandle { settings }
settings
}
isSettingsReady.update { true } isSettingsReady.update { true }
} }

View file

@ -175,7 +175,7 @@ private fun BrowseScreen(
true -> { true -> {
onEvent( onEvent(
BrowseEvent.OnSelectFile( BrowseEvent.OnSelectFile(
includedFileFormats = mainState.value.browseIncludedFilterItems!!, includedFileFormats = mainState.value.browseIncludedFilterItems,
file = selectableFile file = selectableFile
) )
) )
@ -194,7 +194,7 @@ private fun BrowseScreen(
false -> { false -> {
onEvent( onEvent(
BrowseEvent.OnSelectFile( BrowseEvent.OnSelectFile(
includedFileFormats = mainState.value.browseIncludedFilterItems!!, includedFileFormats = mainState.value.browseIncludedFilterItems,
file = selectableFile file = selectableFile
) )
) )
@ -211,7 +211,7 @@ private fun BrowseScreen(
} else { } else {
onEvent( onEvent(
BrowseEvent.OnSelectFile( BrowseEvent.OnSelectFile(
includedFileFormats = mainState.value.browseIncludedFilterItems!!, includedFileFormats = mainState.value.browseIncludedFilterItems,
file = selectableFile file = selectableFile
) )
) )

View file

@ -29,7 +29,7 @@ fun BrowseLayout(
onFavoriteItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit onItemClick: (SelectableFile) -> Unit
) { ) {
when (mainState.value.browseLayout!!) { when (mainState.value.browseLayout) {
BrowseLayout.LIST -> { BrowseLayout.LIST -> {
BrowseListLayout( BrowseListLayout(
state = state, state = state,
@ -43,8 +43,8 @@ fun BrowseLayout(
BrowseLayout.GRID -> { BrowseLayout.GRID -> {
BrowseGridLayout( BrowseGridLayout(
state = state, state = state,
gridSize = mainState.value.browseGridSize!!, gridSize = mainState.value.browseGridSize,
autoGridSize = mainState.value.browseAutoGridSize!!, autoGridSize = mainState.value.browseAutoGridSize,
filteredFiles = filteredFiles, filteredFiles = filteredFiles,
onLongItemClick = onLongItemClick, onLongItemClick = onLongItemClick,
onFavoriteItemClick = onFavoriteItemClick, onFavoriteItemClick = onFavoriteItemClick,

View file

@ -75,7 +75,7 @@ fun BrowseTopBar(
} }
val isScrolled = remember { val isScrolled = remember {
derivedStateOf { derivedStateOf {
when (mainState.value.browseLayout!!) { when (mainState.value.browseLayout) {
BrowseLayout.LIST -> state.value.listState.canScrollBackward BrowseLayout.LIST -> state.value.listState.canScrollBackward
BrowseLayout.GRID -> state.value.gridState.canScrollBackward BrowseLayout.GRID -> state.value.gridState.canScrollBackward
} }
@ -155,7 +155,7 @@ fun BrowseTopBar(
contentDescription = R.string.filter_content_desc, contentDescription = R.string.filter_content_desc,
disableOnClick = false, disableOnClick = false,
color = animateColorAsState( color = animateColorAsState(
if (mainState.value.browseIncludedFilterItems!!.isNotEmpty()) { if (mainState.value.browseIncludedFilterItems.isNotEmpty()) {
MaterialTheme.colorScheme.primary MaterialTheme.colorScheme.primary
} else LocalContentColor.current, } else LocalContentColor.current,
label = "" label = ""
@ -195,7 +195,7 @@ fun BrowseTopBar(
) { ) {
onEvent( onEvent(
BrowseEvent.OnSelectFiles( BrowseEvent.OnSelectFiles(
includedFileFormats = mainState.value.browseIncludedFilterItems!!, includedFileFormats = mainState.value.browseIncludedFilterItems,
files = filteredFiles files = filteredFiles
) )
) )

View file

@ -601,7 +601,7 @@ class BrowseViewModel @Inject constructor(
fun <T> thenCompareBy( fun <T> thenCompareBy(
selector: (T) -> Comparable<*>? selector: (T) -> Comparable<*>?
): Comparator<T> { ): Comparator<T> {
return if (mainState.browseSortOrderDescending!!) { return if (mainState.browseSortOrderDescending) {
compareByDescending(selector) compareByDescending(selector)
} else { } else {
compareBy(selector) compareBy(selector)
@ -609,7 +609,7 @@ class BrowseViewModel @Inject constructor(
} }
fun List<SelectableFile>.filterFiles(): List<SelectableFile> { fun List<SelectableFile>.filterFiles(): List<SelectableFile> {
if (mainState.browseIncludedFilterItems!!.isEmpty()) { if (mainState.browseIncludedFilterItems.isEmpty()) {
return this return this
} }
@ -649,7 +649,7 @@ class BrowseViewModel @Inject constructor(
if ( if (
Environment.getExternalStorageDirectory() == _state.value.selectedDirectory Environment.getExternalStorageDirectory() == _state.value.selectedDirectory
&& it.isFavorite && it.isFavorite
&& mainState.browsePinFavoriteDirectories!! && mainState.browsePinFavoriteDirectories
) { ) {
return@filter true return@filter true
} }
@ -658,20 +658,20 @@ class BrowseViewModel @Inject constructor(
} }
.sortedWith( .sortedWith(
compareByDescending<SelectableFile> { compareByDescending<SelectableFile> {
when (mainState.browsePinFavoriteDirectories!!) { when (mainState.browsePinFavoriteDirectories) {
true -> it.isFavorite true -> it.isFavorite
false -> true false -> true
} }
}.then( }.then(
compareByDescending { compareByDescending {
when (mainState.browseSortOrder!! != BrowseSortOrder.FILE_TYPE) { when (mainState.browseSortOrder != BrowseSortOrder.FILE_TYPE) {
true -> it.isDirectory true -> it.isDirectory
false -> true false -> true
} }
} }
).then( ).then(
thenCompareBy { thenCompareBy {
when (mainState.browseSortOrder!!) { when (mainState.browseSortOrder) {
BrowseSortOrder.NAME -> { BrowseSortOrder.NAME -> {
it.fileOrDirectory.name.lowercase().trim() it.fileOrDirectory.name.lowercase().trim()
} }

View file

@ -288,7 +288,7 @@ private fun LibraryScreen(
return@BackHandler return@BackHandler
} }
if (shouldExit || !mainState.value.doublePressExit!!) { if (shouldExit || !mainState.value.doublePressExit) {
activity.finish() activity.finish()
return@BackHandler return@BackHandler
} }

View file

@ -211,19 +211,19 @@ private fun ReaderScreen(
mainState.value.fontSize, mainState.value.fontSize,
mainState.value.lineHeight mainState.value.lineHeight
) { ) {
(mainState.value.fontSize!! + mainState.value.lineHeight!!).sp (mainState.value.fontSize + mainState.value.lineHeight).sp
} }
val letterSpacing = remember(mainState.value.letterSpacing) { val letterSpacing = remember(mainState.value.letterSpacing) {
(mainState.value.letterSpacing!! / 100f).em (mainState.value.letterSpacing / 100f).em
} }
val sidePadding = remember(mainState.value.sidePadding) { val sidePadding = remember(mainState.value.sidePadding) {
(mainState.value.sidePadding!! * 3).dp (mainState.value.sidePadding * 3).dp
} }
val paragraphHeight = remember(mainState.value.paragraphHeight) { val paragraphHeight = remember(mainState.value.paragraphHeight) {
(mainState.value.paragraphHeight!! * 3).dp (mainState.value.paragraphHeight * 3).dp
} }
val fontStyle = remember(mainState.value.isItalic) { val fontStyle = remember(mainState.value.isItalic) {
when (mainState.value.isItalic!!) { when (mainState.value.isItalic) {
true -> FontStyle.Italic true -> FontStyle.Italic
false -> FontStyle.Normal false -> FontStyle.Normal
} }
@ -354,7 +354,7 @@ private fun ReaderScreen(
} }
) )
.readerFastColorPresetChange( .readerFastColorPresetChange(
fastColorPresetChangeEnabled = mainState.value.fastColorPresetChange!!, fastColorPresetChangeEnabled = mainState.value.fastColorPresetChange,
isLoading = state.value.loading, isLoading = state.value.loading,
toolbarHidden = toolbarHidden, toolbarHidden = toolbarHidden,
onSettingsEvent = onSettingsEvent, onSettingsEvent = onSettingsEvent,
@ -389,12 +389,12 @@ private fun ReaderScreen(
fontColor = fontColor.value, fontColor = fontColor.value,
lineHeight = lineHeight, lineHeight = lineHeight,
fontStyle = fontStyle, fontStyle = fontStyle,
textAlignment = mainState.value.textAlignment!!, textAlignment = mainState.value.textAlignment,
fontSize = mainState.value.fontSize!!.sp, fontSize = mainState.value.fontSize.sp,
letterSpacing = letterSpacing, letterSpacing = letterSpacing,
sidePadding = sidePadding, sidePadding = sidePadding,
paragraphIndentation = mainState.value.paragraphIndentation!!, paragraphIndentation = mainState.value.paragraphIndentation,
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation!!, doubleClickTranslationEnabled = mainState.value.doubleClickTranslation,
toolbarHidden = toolbarHidden, toolbarHidden = toolbarHidden,
onEvent = onEvent onEvent = onEvent
) )

View file

@ -18,13 +18,13 @@ fun FastColorPresetChangeSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SwitchWithTitle( SwitchWithTitle(
selected = state.value.fastColorPresetChange!!, selected = state.value.fastColorPresetChange,
title = stringResource(id = R.string.fast_color_preset_change_option), title = stringResource(id = R.string.fast_color_preset_change_option),
description = stringResource(id = R.string.fast_color_preset_change_option_desc), description = stringResource(id = R.string.fast_color_preset_change_option_desc),
onClick = { onClick = {
onMainEvent( onMainEvent(
MainEvent.OnChangeFastColorPresetChange( MainEvent.OnChangeFastColorPresetChange(
!state.value.fastColorPresetChange!! !state.value.fastColorPresetChange
) )
) )
} }

View file

@ -22,7 +22,7 @@ fun PureDarkSetting(
state: State<MainState>, state: State<MainState>,
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
ExpandingTransition(visible = state.value.darkTheme!!.isDark()) { ExpandingTransition(visible = state.value.darkTheme.isDark()) {
SegmentedButtonWithTitle( SegmentedButtonWithTitle(
title = stringResource(id = R.string.pure_dark_option), title = stringResource(id = R.string.pure_dark_option),
buttons = PureDark.entries.map { buttons = PureDark.entries.map {

View file

@ -29,19 +29,19 @@ fun ThemeContrastSetting(
state: State<MainState>, state: State<MainState>,
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
val themeContrastTheme = remember { mutableStateOf(state.value.theme!!) } val themeContrastTheme = remember { mutableStateOf(state.value.theme) }
LaunchedEffect(state.value.theme) { LaunchedEffect(state.value.theme) {
if (themeContrastTheme.value != state.value.theme && state.value.theme != Theme.DYNAMIC) { if (themeContrastTheme.value != state.value.theme && state.value.theme != Theme.DYNAMIC) {
themeContrastTheme.value = state.value.theme!! themeContrastTheme.value = state.value.theme
} }
} }
BookStoryTheme( BookStoryTheme(
theme = themeContrastTheme.value, theme = themeContrastTheme.value,
isDark = state.value.darkTheme!!.isDark(), isDark = state.value.darkTheme.isDark(),
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current), isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
themeContrast = state.value.themeContrast!! themeContrast = state.value.themeContrast
) { ) {
ExpandingTransition(visible = state.value.theme != Theme.DYNAMIC) { ExpandingTransition(visible = state.value.theme != Theme.DYNAMIC) {
SegmentedButtonWithTitle( SegmentedButtonWithTitle(

View file

@ -91,9 +91,9 @@ fun ThemeSetting(
ThemeSettingItem( ThemeSettingItem(
theme = themeEntry, theme = themeEntry,
darkTheme = state.value.darkTheme!!.isDark(), darkTheme = state.value.darkTheme.isDark(),
themeContrast = state.value.themeContrast!!, themeContrast = state.value.themeContrast,
isPureDark = state.value.pureDark!!.isPureDark(context = LocalContext.current), isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
selected = state.value.theme == themeEntry.first selected = state.value.theme == themeEntry.first
) { ) {
onMainEvent(MainEvent.OnChangeTheme(themeEntry.first.toString())) onMainEvent(MainEvent.OnChangeTheme(themeEntry.first.toString()))

View file

@ -34,7 +34,7 @@ fun LazyListScope.BrowseFilterSetting(
customItems(Constants.EXTENSIONS, key = { it }) { customItems(Constants.EXTENSIONS, key = { it }) {
FilterItem( FilterItem(
item = it, item = it,
isSelected = state.value.browseIncludedFilterItems!!.any { item -> isSelected = state.value.browseIncludedFilterItems.any { item ->
item == it item == it
} }
) { ) {

View file

@ -21,10 +21,10 @@ fun BrowseGridSizeSetting(
) { ) {
ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) { ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) {
SliderWithTitle( SliderWithTitle(
value = state.value.browseGridSize!! value = state.value.browseGridSize
to " ${stringResource(R.string.browse_grid_size_per_row)}", to " ${stringResource(R.string.browse_grid_size_per_row)}",
valuePlaceholder = stringResource(id = R.string.browse_grid_size_auto), valuePlaceholder = stringResource(id = R.string.browse_grid_size_auto),
showPlaceholder = state.value.browseAutoGridSize!!, showPlaceholder = state.value.browseAutoGridSize,
fromValue = 0, fromValue = 0,
toValue = 10, toValue = 10,
title = stringResource(id = R.string.browse_grid_size_option), title = stringResource(id = R.string.browse_grid_size_option),

View file

@ -21,13 +21,13 @@ fun BrowsePinFavoriteDirectoriesSetting(
) { ) {
ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) { ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) {
SwitchWithTitle( SwitchWithTitle(
selected = state.value.browsePinFavoriteDirectories!!, selected = state.value.browsePinFavoriteDirectories,
title = stringResource(id = R.string.browse_pin_favorite_directories_option), title = stringResource(id = R.string.browse_pin_favorite_directories_option),
description = stringResource(id = R.string.browse_pin_favorite_directories_option_desc) description = stringResource(id = R.string.browse_pin_favorite_directories_option_desc)
) { ) {
onMainEvent( onMainEvent(
MainEvent.OnChangeBrowsePinFavoriteDirectories( MainEvent.OnChangeBrowsePinFavoriteDirectories(
!state.value.browsePinFavoriteDirectories!! !state.value.browsePinFavoriteDirectories
) )
) )
} }

View file

@ -41,13 +41,13 @@ fun LazyListScope.BrowseSortOrderSetting(
customItems(BrowseSortOrder.entries, key = { it.name }) { customItems(BrowseSortOrder.entries, key = { it.name }) {
SortItem( SortItem(
item = it, item = it,
isSelected = state.value.browseSortOrder!! == it, isSelected = state.value.browseSortOrder == it,
isDescending = state.value.browseSortOrderDescending!! isDescending = state.value.browseSortOrderDescending
) { ) {
if (state.value.browseSortOrder!! == it) { if (state.value.browseSortOrder == it) {
onMainEvent( onMainEvent(
MainEvent.OnChangeBrowseSortOrderDescending( MainEvent.OnChangeBrowseSortOrderDescending(
!state.value.browseSortOrderDescending!! !state.value.browseSortOrderDescending
) )
) )
} else { } else {

View file

@ -59,13 +59,13 @@ fun CheckForUpdatesSetting(
} }
SwitchWithTitle( SwitchWithTitle(
selected = state.value.checkForUpdates!!, selected = state.value.checkForUpdates,
title = stringResource(id = R.string.check_for_updates_option), title = stringResource(id = R.string.check_for_updates_option),
description = stringResource(id = R.string.check_for_updates_option_desc) description = stringResource(id = R.string.check_for_updates_option_desc)
) { ) {
onSettingsEvent( onSettingsEvent(
SettingsEvent.OnGeneralChangeCheckForUpdates( SettingsEvent.OnGeneralChangeCheckForUpdates(
enable = !state.value.checkForUpdates!!, enable = !state.value.checkForUpdates,
activity = activity, activity = activity,
notificationsPermissionState = notificationsPermissionState, notificationsPermissionState = notificationsPermissionState,
onChangeCheckForUpdates = { onChangeCheckForUpdates = {

View file

@ -20,12 +20,12 @@ fun DoublePressExitSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SwitchWithTitle( SwitchWithTitle(
selected = state.value.doublePressExit!!, selected = state.value.doublePressExit,
title = stringResource(id = R.string.double_press_exit_option), title = stringResource(id = R.string.double_press_exit_option),
description = stringResource(id = R.string.double_press_exit_option_desc) description = stringResource(id = R.string.double_press_exit_option_desc)
) { ) {
onMainEvent( onMainEvent(
MainEvent.OnChangeDoublePressExit(!state.value.doublePressExit!!) MainEvent.OnChangeDoublePressExit(!state.value.doublePressExit)
) )
} }
} }

View file

@ -18,13 +18,13 @@ fun DoubleClickTranslationSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SwitchWithTitle( SwitchWithTitle(
selected = state.value.doubleClickTranslation!!, selected = state.value.doubleClickTranslation,
title = stringResource(id = R.string.double_click_translation_option), title = stringResource(id = R.string.double_click_translation_option),
description = stringResource(id = R.string.double_click_translation_option_desc), description = stringResource(id = R.string.double_click_translation_option_desc),
onClick = { onClick = {
onMainEvent( onMainEvent(
MainEvent.OnChangeDoubleClickTranslation( MainEvent.OnChangeDoubleClickTranslation(
!state.value.doubleClickTranslation!! !state.value.doubleClickTranslation
) )
) )
} }

View file

@ -18,7 +18,7 @@ fun FontSizeSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SliderWithTitle( SliderWithTitle(
value = state.value.fontSize!! to "pt", value = state.value.fontSize to "pt",
fromValue = 10, fromValue = 10,
toValue = 35, toValue = 35,
title = stringResource(id = R.string.font_size_option), title = stringResource(id = R.string.font_size_option),

View file

@ -38,7 +38,7 @@ fun FontStyleSetting(
fontFamily = fontFamily.font, fontFamily = fontFamily.font,
fontStyle = FontStyle.Normal fontStyle = FontStyle.Normal
), ),
selected = !state.value.isItalic!! selected = !state.value.isItalic
), ),
ButtonItem( ButtonItem(
id = "italic", id = "italic",
@ -47,7 +47,7 @@ fun FontStyleSetting(
fontFamily = fontFamily.font, fontFamily = fontFamily.font,
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic
), ),
selected = state.value.isItalic!! selected = state.value.isItalic
), ),
), ),
onClick = { onClick = {

View file

@ -18,7 +18,7 @@ fun LetterSpacingSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SliderWithTitle( SliderWithTitle(
value = state.value.letterSpacing!! to "pt", value = state.value.letterSpacing to "pt",
fromValue = -8, fromValue = -8,
toValue = 16, toValue = 16,
title = stringResource(id = R.string.letter_spacing_option), title = stringResource(id = R.string.letter_spacing_option),

View file

@ -18,7 +18,7 @@ fun LineHeightSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SliderWithTitle( SliderWithTitle(
value = state.value.lineHeight!! to "pt", value = state.value.lineHeight to "pt",
fromValue = 1, fromValue = 1,
toValue = 24, toValue = 24,
title = stringResource(id = R.string.line_height_option), title = stringResource(id = R.string.line_height_option),

View file

@ -18,7 +18,7 @@ fun ParagraphHeightSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SliderWithTitle( SliderWithTitle(
value = state.value.paragraphHeight!! to "pt", value = state.value.paragraphHeight to "pt",
fromValue = 0, fromValue = 0,
toValue = 36, toValue = 36,
title = stringResource(id = R.string.paragraph_height_option), title = stringResource(id = R.string.paragraph_height_option),

View file

@ -18,11 +18,11 @@ fun ParagraphIndentationSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SwitchWithTitle( SwitchWithTitle(
selected = state.value.paragraphIndentation!!, selected = state.value.paragraphIndentation,
title = stringResource(id = R.string.paragraph_indentation_option) title = stringResource(id = R.string.paragraph_indentation_option)
) { ) {
onMainEvent( onMainEvent(
MainEvent.OnChangeParagraphIndentation(!state.value.paragraphIndentation!!) MainEvent.OnChangeParagraphIndentation(!state.value.paragraphIndentation)
) )
} }
} }

View file

@ -18,7 +18,7 @@ fun SidePaddingSetting(
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
SliderWithTitle( SliderWithTitle(
value = state.value.sidePadding!! to "pt", value = state.value.sidePadding to "pt",
fromValue = 1, fromValue = 1,
toValue = 20, toValue = 20,
title = stringResource(id = R.string.side_padding_option), title = stringResource(id = R.string.side_padding_option),

View file

@ -32,7 +32,7 @@ fun TextAlignmentSetting(
ReaderTextAlignment.END -> stringResource(id = R.string.text_alignment_end) ReaderTextAlignment.END -> stringResource(id = R.string.text_alignment_end)
}, },
textStyle = MaterialTheme.typography.labelLarge, textStyle = MaterialTheme.typography.labelLarge,
selected = it == state.value.textAlignment!! selected = it == state.value.textAlignment
) )
}, },
onClick = { onClick = {