diff --git a/app/src/main/java/ua/acclorite/book_story/core/helpers/CollectionHelpers.kt b/app/src/main/java/ua/acclorite/book_story/core/helpers/CollectionHelpers.kt index 248c1720..f2c83df7 100644 --- a/app/src/main/java/ua/acclorite/book_story/core/helpers/CollectionHelpers.kt +++ b/app/src/main/java/ua/acclorite/book_story/core/helpers/CollectionHelpers.kt @@ -8,4 +8,13 @@ package ua.acclorite.book_story.core.helpers fun MutableList.addAll(calculation: () -> List) { addAll(calculation()) +} + +fun List.toggle(item: T): List { + return toMutableList().apply { toggle(item) } +} + +fun MutableList.toggle(item: T) { + if (contains(item)) remove(item) + else add(item) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt b/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt index f1ec15ae..0046edda 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt @@ -31,14 +31,12 @@ import ua.acclorite.book_story.data.parser.TextParserImpl import ua.acclorite.book_story.data.repository.BookRepositoryImpl import ua.acclorite.book_story.data.repository.CategoryRepositoryImpl import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl -import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl import ua.acclorite.book_story.data.repository.PermissionRepositoryImpl import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.CategoryRepository import ua.acclorite.book_story.domain.repository.ColorPresetRepository -import ua.acclorite.book_story.domain.repository.DataStoreRepository import ua.acclorite.book_story.domain.repository.FileSystemRepository import ua.acclorite.book_story.domain.repository.HistoryRepository import ua.acclorite.book_story.domain.repository.PermissionRepository @@ -71,12 +69,6 @@ abstract class RepositoryModule { colorPresetRepositoryImpl: ColorPresetRepositoryImpl ): ColorPresetRepository - @Binds - @Singleton - abstract fun bindDataStoreRepository( - dataStoreRepositoryImpl: DataStoreRepositoryImpl - ): DataStoreRepository - @Binds @Singleton abstract fun bindFileSystemRepository( diff --git a/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStore.kt b/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStore.kt index 75e4ef26..565db64a 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStore.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStore.kt @@ -10,6 +10,5 @@ import androidx.datastore.preferences.core.Preferences interface DataStore { suspend fun getNullableData(key: Preferences.Key): T? - suspend fun getAllData(): Set>? suspend fun putData(key: Preferences.Key, value: T) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStoreImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStoreImpl.kt index 19d4a5cc..5b84e781 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStoreImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/local/data_store/DataStoreImpl.kt @@ -10,12 +10,8 @@ import android.app.Application import android.content.Context import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.preferencesDataStore -import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.flow.map -import java.io.IOException import javax.inject.Inject private val Context.dataStore by preferencesDataStore("data_store") @@ -23,30 +19,14 @@ private val Context.dataStore by preferencesDataStore("data_store") class DataStoreImpl @Inject constructor(context: Application) : DataStore { private val dataStore = context.dataStore - /** - * Gets data from DataStore by given [key]. If no such [key] exists, returns null. - */ - override suspend fun getNullableData(key: Preferences.Key): T? = - dataStore.data.catch { exception -> - if (exception is IOException) emit(emptyPreferences()) - else throw exception - }.map { preferences -> - preferences[key] - }.firstOrNull() - - /** - * Gets all keys from DataStore. - */ - override suspend fun getAllData(): Set>? { - return dataStore.data - .map { - it.asMap().keys - }.firstOrNull() + override suspend fun getNullableData(key: Preferences.Key): T? { + return try { + dataStore.data.firstOrNull()?.get(key) + } catch (_: Exception) { + null + } } - /** - * Puts data in DataStore by given [key]. - */ override suspend fun putData(key: Preferences.Key, value: T) { dataStore.edit { preferences -> preferences[key] = value diff --git a/app/src/main/java/ua/acclorite/book_story/data/model/common/NullableBook.kt b/app/src/main/java/ua/acclorite/book_story/data/model/common/NullableBook.kt index e0aca6ac..157781e6 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/model/common/NullableBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/model/common/NullableBook.kt @@ -8,7 +8,6 @@ package ua.acclorite.book_story.data.model.common import androidx.compose.runtime.Immutable import ua.acclorite.book_story.core.ui.UIText -import ua.acclorite.book_story.data.model.library.BookWithCover @Immutable sealed class NullableBook( diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/FileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/FileParser.kt index 90822926..fb9bd1b9 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/FileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/FileParser.kt @@ -6,9 +6,8 @@ package ua.acclorite.book_story.data.parser +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover - interface FileParser { suspend fun parse(cachedFile: CachedFile): BookWithCover? diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/FileParserImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/FileParserImpl.kt index a91ebbef..36173cea 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/FileParserImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/FileParserImpl.kt @@ -7,8 +7,8 @@ package ua.acclorite.book_story.data.parser import android.util.Log +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.epub.EpubFileParser import ua.acclorite.book_story.data.parser.fb2.Fb2FileParser import ua.acclorite.book_story.data.parser.html.HtmlFileParser diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt index 6408d061..1d741b76 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt @@ -14,8 +14,8 @@ import org.jsoup.Jsoup import org.jsoup.parser.Parser import ua.acclorite.book_story.R import ua.acclorite.book_story.core.ui.UIText +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.library.Book import java.io.File diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/fb2/Fb2FileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/fb2/Fb2FileParser.kt index ce50fd5f..984d4594 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/fb2/Fb2FileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/fb2/Fb2FileParser.kt @@ -10,8 +10,8 @@ import org.jsoup.Jsoup import org.jsoup.parser.Parser import ua.acclorite.book_story.R import ua.acclorite.book_story.core.ui.UIText +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.library.Book import javax.inject.Inject diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/html/HtmlFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/html/HtmlFileParser.kt index b51bbaba..95d43a71 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/html/HtmlFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/html/HtmlFileParser.kt @@ -10,8 +10,8 @@ import org.jsoup.Jsoup import org.jsoup.parser.Parser import ua.acclorite.book_story.R import ua.acclorite.book_story.core.ui.UIText +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.library.Book import javax.inject.Inject diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt index bd13dd39..954dad66 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt @@ -11,8 +11,8 @@ import com.tom_roush.pdfbox.android.PDFBoxResourceLoader import com.tom_roush.pdfbox.pdmodel.PDDocument import ua.acclorite.book_story.R import ua.acclorite.book_story.core.ui.UIText +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.library.Book import javax.inject.Inject diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt index 17fc2883..c304c515 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt @@ -8,8 +8,8 @@ package ua.acclorite.book_story.data.parser.txt import ua.acclorite.book_story.R import ua.acclorite.book_story.core.ui.UIText +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.library.Book import javax.inject.Inject diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt index b8230bce..96c59f8f 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt @@ -13,10 +13,6 @@ import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject import javax.inject.Singleton -/** - * Color Preset repository. - * Manages all [ColorPreset] related work. - */ @Singleton class ColorPresetRepositoryImpl @Inject constructor( private val database: BookDao, diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt deleted file mode 100644 index 501a38a8..00000000 --- a/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.data.repository - -import androidx.datastore.preferences.core.Preferences -import ua.acclorite.book_story.data.local.data_store.DataStore -import ua.acclorite.book_story.domain.repository.DataStoreRepository -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Data Store repository. - * Manages all [DataStore] related work. - */ -@Singleton -class DataStoreRepositoryImpl @Inject constructor( - private val dataStore: DataStore -) : DataStoreRepository { - - override suspend fun putPreference( - key: Preferences.Key, - value: T - ): Result = runCatching { - dataStore.putData(key, value) - } - - override suspend fun getPreference( - key: Preferences.Key - ): Result = runCatching { - dataStore.getNullableData(key) ?: throw NoSuchElementException("Could not get preference.") - } - - override suspend fun getAllPreferences(): Result>> = runCatching { - dataStore.getAllData() ?: throw NoSuchElementException("Could not get all preferences.") - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt index ab17b50f..a81e3112 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt @@ -9,8 +9,8 @@ package ua.acclorite.book_story.data.repository import ua.acclorite.book_story.core.data.ExtensionsData import ua.acclorite.book_story.data.local.room.BookDao import ua.acclorite.book_story.data.mapper.file.FileMapper +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.data.model.file.CachedFile -import ua.acclorite.book_story.data.model.library.BookWithCover import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.domain.model.file.File import ua.acclorite.book_story.domain.repository.FileSystemRepository diff --git a/app/src/main/java/ua/acclorite/book_story/data/settings/SettingsManager.kt b/app/src/main/java/ua/acclorite/book_story/data/settings/SettingsManager.kt new file mode 100644 index 00000000..53180202 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/settings/SettingsManager.kt @@ -0,0 +1,352 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.data.settings + +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.doublePreferencesKey +import androidx.datastore.preferences.core.intPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.stringSetPreferencesKey +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import ua.acclorite.book_story.core.data.CoreData +import ua.acclorite.book_story.core.log.logI +import ua.acclorite.book_story.data.local.data_store.DataStore +import ua.acclorite.book_story.data.settings.model.Setting +import ua.acclorite.book_story.presentation.browse.model.BrowseLayout +import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder +import ua.acclorite.book_story.presentation.library.model.LibraryLayout +import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder +import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition +import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects +import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness +import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture +import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount +import ua.acclorite.book_story.presentation.reader.model.ReaderScreenOrientation +import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment +import ua.acclorite.book_story.ui.reader.data.ReaderData +import ua.acclorite.book_story.ui.reader.model.FontWithName +import ua.acclorite.book_story.ui.theme.model.DarkTheme +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment +import ua.acclorite.book_story.ui.theme.model.PureDark +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast +import java.util.Locale +import java.util.concurrent.atomic.AtomicInteger +import javax.inject.Inject +import javax.inject.Singleton + +@Suppress("UNCHECKED_CAST") +@Singleton +class SettingsManager @Inject constructor( + private val dataStore: DataStore +) { + private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + + private val settingsCount = AtomicInteger(0) + private val initializedSettingsCount = AtomicInteger(0) + + private val _initialized = MutableStateFlow(false) + val initialized = _initialized.asStateFlow() + + + /* ------ Settings --------------------------- */ + /* ------ General ---------------------------- */ + val language = setting( + key = stringPreferencesKey("language"), + default = Locale.getDefault().language.take(2).let { locale -> + CoreData.languages.any { locale == it.first }.run { + if (this) locale + else "en"// Default language (English) + } + } + ) + val theme = setting( + key = stringPreferencesKey("theme"), default = Theme.Companion.entries().first(), + serialize = { it.name }, deserialize = { Theme.valueOf(it) } + ) + val darkTheme = setting( + key = stringPreferencesKey("dark_theme"), default = DarkTheme.FOLLOW_SYSTEM, + serialize = { it.name }, deserialize = { DarkTheme.valueOf(it) } + ) + val pureDark = setting( + key = stringPreferencesKey("pure_dark"), default = PureDark.OFF, + serialize = { it.name }, deserialize = { PureDark.valueOf(it) } + ) + val absoluteDark = setting( + key = booleanPreferencesKey("absolute_dark"), default = false + ) + val themeContrast = setting( + key = stringPreferencesKey("theme_contrast"), default = ThemeContrast.STANDARD, + serialize = { it.name }, deserialize = { ThemeContrast.valueOf(it) } + ) + val showStartScreen = setting( + key = booleanPreferencesKey("guide"), default = true + ) + val doublePressExit = setting( + key = booleanPreferencesKey("double_press_exit"), default = false + ) + + /* ------ Reader ----------------------------- */ + val fontFamily = setting( + key = stringPreferencesKey("font"), default = ReaderData.fonts[0], + serialize = { it.id }, deserialize = { id -> + ReaderData.fonts.find { it.id == id } ?: ReaderData.fonts[0] + } + ) + val fontThickness = setting( + key = stringPreferencesKey("font_thickness"), default = ReaderFontThickness.NORMAL, + serialize = { it.name }, deserialize = { ReaderFontThickness.valueOf(it) } + ) + val italic = setting( + key = booleanPreferencesKey("font_style"), default = false + ) + val fontSize = setting( + key = intPreferencesKey("font_size"), default = 16 + ) + val lineHeight = setting( + key = intPreferencesKey("line_height"), default = 4 + ) + val paragraphHeight = setting( + key = intPreferencesKey("paragraph_height"), default = 8 + ) + val paragraphIndentation = setting( + key = intPreferencesKey("paragraph_indentation_int"), default = 0 + ) + val sidePadding = setting( + key = intPreferencesKey("side_padding"), default = 6 + ) + val verticalPadding = setting( + key = intPreferencesKey("vertical_padding"), default = 0 + ) + val doubleClickTranslation = setting( + key = booleanPreferencesKey("double_click_translation"), default = false + ) + val fastColorPresetChange = setting( + key = booleanPreferencesKey("fast_color_preset_change"), default = true + ) + val textAlignment = setting( + key = stringPreferencesKey("text_alignment"), default = ReaderTextAlignment.JUSTIFY, + serialize = { it.name }, deserialize = { ReaderTextAlignment.valueOf(it) } + ) + val letterSpacing = setting( + key = intPreferencesKey("letter_spacing"), default = 0 + ) + val cutoutPadding = setting( + key = booleanPreferencesKey("cutout_padding"), default = false + ) + val fullscreen = setting( + key = booleanPreferencesKey("fullscreen"), default = true + ) + val keepScreenOn = setting( + key = booleanPreferencesKey("keep_screen_on"), default = true + ) + val hideBarsOnFastScroll = setting( + key = booleanPreferencesKey("hide_bars_on_fast_scroll"), default = false + ) + val perceptionExpander = setting( + key = booleanPreferencesKey("perception_expander"), default = false + ) + val perceptionExpanderPadding = setting( + key = intPreferencesKey("perception_expander_padding"), default = 5 + ) + val perceptionExpanderThickness = setting( + key = intPreferencesKey("perception_expander_thickness"), default = 4 + ) + val screenOrientation = setting( + key = stringPreferencesKey("screen_orientation"), default = ReaderScreenOrientation.DEFAULT, + serialize = { it.name }, deserialize = { ReaderScreenOrientation.valueOf(it) } + ) + val customScreenBrightness = setting( + key = booleanPreferencesKey("custom_screen_brightness"), default = false + ) + val screenBrightness = setting( + key = doublePreferencesKey("screen_brightness"), default = 0.5f, + serialize = { it.toDouble() }, deserialize = { it.toFloat() } + ) + val horizontalGesture = setting( + key = stringPreferencesKey("horizontal_gesture"), default = ReaderHorizontalGesture.OFF, + serialize = { it.name }, deserialize = { ReaderHorizontalGesture.valueOf(it) } + ) + val horizontalGestureScroll = setting( + key = doublePreferencesKey("horizontal_gesture_scroll"), default = 0.7f, + serialize = { it.toDouble() }, deserialize = { it.toFloat() } + ) + val horizontalGestureSensitivity = setting( + key = doublePreferencesKey("horizontal_gesture_sensitivity"), default = 0.6f, + serialize = { it.toDouble() }, deserialize = { it.toFloat() } + ) + val horizontalGestureAlphaAnim = setting( + key = booleanPreferencesKey("horizontal_gesture_alpha_anim_bool"), default = true + ) + val horizontalGesturePullAnim = setting( + key = booleanPreferencesKey("horizontal_gesture_pull_anim"), default = true + ) + val bottomBarPadding = setting( + key = intPreferencesKey("bottom_bar_padding"), default = 0 + ) + val highlightedReading = setting( + key = booleanPreferencesKey("highlighted_reading"), default = false + ) + val highlightedReadingThickness = setting( + key = intPreferencesKey("highlighted_reading_thickness"), default = 2 + ) + val chapterTitleAlignment = setting( + key = stringPreferencesKey("chapter_title_alignment"), + default = ReaderTextAlignment.JUSTIFY, + serialize = { it.name }, deserialize = { ReaderTextAlignment.valueOf(it) } + ) + val images = setting( + key = booleanPreferencesKey("images"), default = true + ) + val imagesCaptions = setting( + key = booleanPreferencesKey("images_captions"), default = true + ) + val imagesCornersRoundness = setting( + key = intPreferencesKey("images_corners_roundness"), default = 8 + ) + val imagesAlignment = setting( + key = stringPreferencesKey("images_alignment"), default = HorizontalAlignment.START, + serialize = { it.name }, deserialize = { HorizontalAlignment.valueOf(it) } + ) + val imagesWidth = setting( + key = doublePreferencesKey("images_width"), default = 0.8f, + serialize = { it.toDouble() }, deserialize = { it.toFloat() } + ) + val imagesColorEffects = setting( + key = stringPreferencesKey("images_color_effects"), default = ReaderColorEffects.OFF, + serialize = { it.name }, deserialize = { ReaderColorEffects.valueOf(it) } + ) + val progressBar = setting( + key = booleanPreferencesKey("progress_bar"), default = false + ) + val progressBarPadding = setting( + key = intPreferencesKey("progress_bar_padding"), default = 4 + ) + val progressBarAlignment = setting( + key = stringPreferencesKey("progress_bar_alignment"), default = HorizontalAlignment.CENTER, + serialize = { it.name }, deserialize = { HorizontalAlignment.valueOf(it) } + ) + val progressBarFontSize = setting( + key = intPreferencesKey("progress_bar_font_size"), default = 8 + ) + val progressCount = setting( + key = stringPreferencesKey("progress_count"), default = ReaderProgressCount.PERCENTAGE, + serialize = { it.name }, deserialize = { ReaderProgressCount.valueOf(it) } + ) + + /* ------ Library ---------------------------- */ + val libraryLayout = setting( + key = stringPreferencesKey("library_layout"), default = LibraryLayout.GRID, + serialize = { it.name }, deserialize = { LibraryLayout.valueOf(it) } + ) + val libraryAutoGridSize = setting( + key = booleanPreferencesKey("library_auto_grid_size"), default = true + ) + val libraryGridSize = setting( + key = intPreferencesKey("library_grid_size"), default = 0 + ) + val libraryTitlePosition = setting( + key = stringPreferencesKey("library_title_position"), default = LibraryTitlePosition.BELOW, + serialize = { it.name }, deserialize = { LibraryTitlePosition.valueOf(it) } + ) + val libraryShowReadButton = setting( + key = booleanPreferencesKey("library_show_read_button"), default = true + ) + val libraryShowProgress = setting( + key = booleanPreferencesKey("library_show_progress"), default = true + ) + val libraryShowBookCount = setting( + key = booleanPreferencesKey("library_show_book_count"), default = true + ) + val libraryShowCategoryTabs = setting( + key = booleanPreferencesKey("library_show_category_tabs"), default = true + ) + val libraryShowDefaultTab = setting( + key = booleanPreferencesKey("library_show_default_tab"), default = false + ) + val librarySortOrder = setting( + key = stringPreferencesKey("library_sort_order"), default = LibrarySortOrder.LAST_READ, + serialize = { it.name }, deserialize = { LibrarySortOrder.valueOf(it) } + ) + val librarySortOrderDescending = setting( + key = booleanPreferencesKey("library_sort_order_descending"), default = true + ) + val libraryPerCategorySort = setting( + key = booleanPreferencesKey("library_per_category_sort"), default = false + ) + + /* ------ Browse ----------------------------- */ + val browseLayout = setting( + key = stringPreferencesKey("browse_layout"), default = BrowseLayout.LIST, + serialize = { it.name }, deserialize = { BrowseLayout.valueOf(it) } + ) + val browseAutoGridSize = setting( + key = booleanPreferencesKey("browse_auto_grid_size"), default = true + ) + val browseGridSize = setting( + key = intPreferencesKey("browse_grid_size"), default = 0 + ) + val browseSortOrder = setting( + key = stringPreferencesKey("browse_sort_order"), default = BrowseSortOrder.LAST_MODIFIED, + serialize = { it.name }, deserialize = { BrowseSortOrder.valueOf(it) } + ) + val browseSortOrderDescending = setting( + key = booleanPreferencesKey("browse_sort_order_descending"), default = true + ) + val browseIncludedFilterItems = setting, Set>( + key = stringSetPreferencesKey("browse_included_filter_items"), default = emptyList(), + serialize = { it.toSet() }, deserialize = { it.toList() } + ) + val browsePinnedPaths = setting, Set>( + key = stringSetPreferencesKey("browse_pinned_paths"), default = emptyList(), + serialize = { it.toSet() }, deserialize = { it.toList() } + ) + /* - - - - - - - - - - - - - - - - - - - - - - */ + + + private fun setting( + key: Preferences.Key

, + default: T, + serialize: (T) -> P = { it as P }, + deserialize: (P) -> T = { it as T } + ): Setting { + settingsCount.incrementAndGet() + + return Setting( + key = key, + default = default, + setSetting = { + scope.launch { + logI("Updating setting: [${key.name}].") + dataStore.putData(key, it) + } + }, + serialize = serialize, + deserialize = deserialize + ).also { setting -> + scope.launch { + setting.init(dataStore.getNullableData

(key)) + logI("Successfully initialized setting: [${key.name}].") + initializeSetting() + } + } + } + + private fun initializeSetting() { + if (initializedSettingsCount.incrementAndGet() == settingsCount.get()) { + logI("Successfully initialized all $settingsCount settings.") + _initialized.update { true } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/settings/model/Setting.kt b/app/src/main/java/ua/acclorite/book_story/data/settings/model/Setting.kt new file mode 100644 index 00000000..e5c8a9fb --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/settings/model/Setting.kt @@ -0,0 +1,39 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.data.settings.model + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.datastore.preferences.core.Preferences +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.update + +@Stable +class Setting( + val key: Preferences.Key

, + default: T, + private val setSetting: (P) -> Unit, + private val serialize: (T) -> P, + private val deserialize: (P) -> T +) { + private val _value = MutableStateFlow(default) + val value: T + @Composable get() = _value.collectAsStateWithLifecycle().value + val lastValue: T + get() = _value.value + + fun update(value: T) { + _value.update { value } + setSetting(serialize(value)) + } + + fun init(value: P?) { + if (value == null) return + _value.update { deserialize(value) } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt deleted file mode 100644 index 17111b8b..00000000 --- a/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.domain.repository - -import androidx.datastore.preferences.core.Preferences - -interface DataStoreRepository { - suspend fun putPreference( - key: Preferences.Key, - value: T - ): Result - - suspend fun getPreference( - key: Preferences.Key, - ): Result - - suspend fun getAllPreferences(): Result>> -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt index b55ae026..48be7e21 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt @@ -6,7 +6,7 @@ package ua.acclorite.book_story.domain.repository -import ua.acclorite.book_story.data.model.library.BookWithCover +import ua.acclorite.book_story.data.model.common.BookWithCover import ua.acclorite.book_story.domain.model.file.File interface FileSystemRepository { diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguagePreferenceUseCase.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguagePreferenceUseCase.kt deleted file mode 100644 index 2b39c8b9..00000000 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguagePreferenceUseCase.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.domain.use_case.data_store - -import androidx.appcompat.app.AppCompatDelegate -import androidx.core.os.LocaleListCompat -import ua.acclorite.book_story.core.log.logE -import ua.acclorite.book_story.core.log.logI -import ua.acclorite.book_story.domain.repository.DataStoreRepository -import ua.acclorite.book_story.presentation.main.data.DataStoreData -import javax.inject.Inject - -class ChangeLanguagePreferenceUseCase @Inject constructor( - private val dataStoreRepository: DataStoreRepository -) { - - suspend operator fun invoke(language: String) { - logI("Changing language preference.") - - dataStoreRepository.putPreference( - DataStoreData.LANGUAGE, - language - ).fold( - onSuccess = { - logI("Successfully changed language preference.") - - val appLocale = LocaleListCompat.forLanguageTags(language) - AppCompatDelegate.setApplicationLocales(appLocale) - }, - onFailure = { - logE("Could not change language preference with error: ${it.message}") - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetPreferencesUseCase.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetPreferencesUseCase.kt deleted file mode 100644 index aea20ed2..00000000 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetPreferencesUseCase.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.domain.use_case.data_store - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.withContext -import ua.acclorite.book_story.core.log.logE -import ua.acclorite.book_story.core.log.logI -import ua.acclorite.book_story.core.log.logW -import ua.acclorite.book_story.domain.repository.DataStoreRepository -import ua.acclorite.book_story.presentation.main.MainState -import java.util.concurrent.ConcurrentHashMap -import javax.inject.Inject - -class GetPreferencesUseCase @Inject constructor( - private val dataStoreRepository: DataStoreRepository -) { - - suspend operator fun invoke(): MainState { - logI("Getting all preferences (MainState).") - - return withContext(Dispatchers.Default) { - dataStoreRepository.getAllPreferences().mapCatching { keys -> - logI("Got [${keys.size}] preference keys.") - - val preferences = ConcurrentHashMap() - keys.map { key -> - async { - dataStoreRepository.getPreference(key).fold( - onSuccess = { - it?.let { preference -> - preferences[key.name] = preference - } - }, - onFailure = { - logW("Could not get [${key.name}] preference.") - preferences.remove(key.name) - } - ) - } - }.awaitAll() - - MainState.initialize(preferences) - }.fold( - onSuccess = { - logI("Successfully got all preferences (MainState).") - it - }, - onFailure = { - logE("Could not get all preferences (MainState) with error: ${it.message}") - MainState() - } - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/PutPreferenceUseCase.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/PutPreferenceUseCase.kt deleted file mode 100644 index 60083212..00000000 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/PutPreferenceUseCase.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.domain.use_case.data_store - -import androidx.datastore.preferences.core.Preferences -import ua.acclorite.book_story.core.log.logE -import ua.acclorite.book_story.core.log.logI -import ua.acclorite.book_story.domain.repository.DataStoreRepository -import javax.inject.Inject - -class PutPreferenceUseCase @Inject constructor( - private val dataStoreRepository: DataStoreRepository -) { - - suspend operator fun invoke(key: Preferences.Key, value: T) { - logI("Putting preference [${key.name}].") - - dataStoreRepository.putPreference(key, value).fold( - onSuccess = { - logI("Successfully put preference [${key.name}].") - }, - onFailure = { - logE("Could not put preference [${key.name}] with error: ${it.message}") - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/settings/UpdateLanguageUseCase.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/settings/UpdateLanguageUseCase.kt new file mode 100644 index 00000000..d41d5677 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/settings/UpdateLanguageUseCase.kt @@ -0,0 +1,23 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.domain.use_case.settings + +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat +import ua.acclorite.book_story.data.settings.SettingsManager +import javax.inject.Inject + +class UpdateLanguageUseCase @Inject constructor( + private val settings: SettingsManager +) { + + operator fun invoke(language: String) { + val appLocale = LocaleListCompat.forLanguageTags(language) + AppCompatDelegate.setApplicationLocales(appLocale) + settings.language.update(language) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseScreen.kt index 8486ecda..e5fb5062 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.ui.focus.FocusRequester import androidx.hilt.navigation.compose.hiltViewModel @@ -24,12 +23,13 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize +import ua.acclorite.book_story.core.helpers.toggle import ua.acclorite.book_story.presentation.browse.model.BrowseLayout import ua.acclorite.book_story.presentation.library.LibraryScreen -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.navigator.Screen import ua.acclorite.book_story.presentation.settings.BrowseSettingsScreen import ua.acclorite.book_story.ui.browse.BrowseContent +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.navigator.LocalNavigator @Parcelize @@ -64,10 +64,9 @@ object BrowseScreen : Screen, Parcelable { override fun Content() { val navigator = LocalNavigator.current val screenModel = hiltViewModel() - val mainModel = hiltViewModel() + val settings = LocalSettings.current val state = screenModel.state.collectAsStateWithLifecycle() - val mainState = mainModel.state.collectAsStateWithLifecycle() val listState = rememberLazyListState(initialListIndex, initialListOffset) val gridState = rememberLazyGridState(initialGridIndex, initialGridOffset) @@ -85,15 +84,18 @@ object BrowseScreen : Screen, Parcelable { } ) - val files = remember { - derivedStateOf { - screenModel.filterList( - files = state.value.files, - sortOrderDescending = mainState.value.browseSortOrderDescending, - includedFilterItems = mainState.value.browseIncludedFilterItems, - sortOrder = mainState.value.browseSortOrder - ) - } + val files = remember( + state.value.files, + settings.browseIncludedFilterItems.value, + settings.browseSortOrderDescending.value, + settings.browseSortOrder.value + ) { + screenModel.filterList( + files = state.value.files, + sortOrderDescending = settings.browseSortOrderDescending.lastValue, + includedFilterItems = settings.browseIncludedFilterItems.lastValue, + sortOrder = settings.browseSortOrder.lastValue + ) } LaunchedEffect(Unit) { @@ -112,7 +114,7 @@ object BrowseScreen : Screen, Parcelable { initialGridIndex = 0 initialGridOffset = 0 - when (mainState.value.browseLayout) { + when (settings.browseLayout.lastValue) { BrowseLayout.LIST -> { initialListIndex = listState.firstVisibleItemIndex initialListOffset = listState.firstVisibleItemScrollOffset @@ -127,7 +129,7 @@ object BrowseScreen : Screen, Parcelable { } BrowseContent( - files = files.value, + files = files, selectedBooksAddDialog = state.value.selectedBooksAddDialog, refreshState = refreshState, loadingAddDialog = state.value.loadingAddDialog, @@ -135,11 +137,11 @@ object BrowseScreen : Screen, Parcelable { bottomSheet = state.value.bottomSheet, listState = listState, gridState = gridState, - layout = mainState.value.browseLayout, - gridSize = mainState.value.browseGridSize, - autoGridSize = mainState.value.browseAutoGridSize, - includedFilterItems = mainState.value.browseIncludedFilterItems, - pinnedPaths = mainState.value.browsePinnedPaths, + layout = settings.browseLayout.value, + gridSize = settings.browseGridSize.value, + autoGridSize = settings.browseAutoGridSize.value, + includedFilterItems = settings.browseIncludedFilterItems.value, + pinnedPaths = settings.browsePinnedPaths.value, canScrollBackList = listState.canScrollBackward, canScrollBackGrid = gridState.canScrollBackward, hasSelectedItems = state.value.hasSelectedItems, @@ -147,7 +149,7 @@ object BrowseScreen : Screen, Parcelable { isRefreshing = state.value.isRefreshing, isLoading = state.value.isLoading, dialogHidden = state.value.dialog == null, - filesEmpty = files.value.isEmpty(), + filesEmpty = files.isEmpty(), showSearch = state.value.showSearch, searchQuery = state.value.searchQuery, focusRequester = focusRequester, @@ -164,7 +166,11 @@ object BrowseScreen : Screen, Parcelable { dismissAddDialog = screenModel::onEvent, selectAddDialog = screenModel::onEvent, actionAddDialog = screenModel::onEvent, - changePinnedPaths = mainModel::onEvent, + updatePinnedPaths = { + settings.browsePinnedPaths.update( + settings.browsePinnedPaths.lastValue.toggle(it) + ) + }, navigateToLibrary = { navigator.push(LibraryScreen, saveInBackStack = false) }, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/crash/CrashActivity.kt b/app/src/main/java/ua/acclorite/book_story/presentation/crash/CrashActivity.kt index e9ebadd3..6d20213f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/crash/CrashActivity.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/crash/CrashActivity.kt @@ -12,9 +12,9 @@ import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.isSystemInDarkTheme import androidx.core.view.WindowCompat -import ua.acclorite.book_story.presentation.main.model.ThemeContrast import ua.acclorite.book_story.ui.theme.BookStoryTheme -import ua.acclorite.book_story.ui.theme.Theme +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast class CrashActivity : AppCompatActivity() { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/help/HelpScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/help/HelpScreen.kt index 3764d640..3606365d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/help/HelpScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/help/HelpScreen.kt @@ -10,14 +10,12 @@ import android.os.Parcelable import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.hilt.navigation.compose.hiltViewModel import kotlinx.parcelize.Parcelize import ua.acclorite.book_story.presentation.browse.BrowseScreen -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.navigator.Screen import ua.acclorite.book_story.presentation.start.StartScreen import ua.acclorite.book_story.ui.common.components.top_bar.collapsibleTopAppBarScrollBehavior +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.help.HelpContent import ua.acclorite.book_story.ui.navigator.LocalNavigator @@ -28,7 +26,7 @@ data class HelpScreen(val fromStart: Boolean) : Screen, Parcelable { @Composable override fun Content() { val navigator = LocalNavigator.current - val mainModel = hiltViewModel() + val settings = LocalSettings.current val (scrollBehavior, listState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior() @@ -36,12 +34,12 @@ data class HelpScreen(val fromStart: Boolean) : Screen, Parcelable { fromStart = fromStart, scrollBehavior = scrollBehavior, listState = listState, - changeShowStartScreen = mainModel::onEvent, + changeShowStartScreen = { settings.showStartScreen.update(it) }, navigateToBrowse = { navigator.push(BrowseScreen, saveInBackStack = false) }, navigateToStart = { - mainModel.onEvent(MainEvent.OnChangeShowStartScreen(true)) + settings.showStartScreen.update(true) navigator.push(StartScreen, saveInBackStack = false) }, navigateBack = { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt index 53d55c0b..4bbda1bd 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt @@ -26,11 +26,11 @@ import kotlinx.parcelize.Parcelize import ua.acclorite.book_story.presentation.book_info.BookInfoScreen import ua.acclorite.book_story.presentation.browse.BrowseScreen import ua.acclorite.book_story.presentation.history.HistoryScreen -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.navigator.Screen import ua.acclorite.book_story.presentation.reader.ReaderScreen import ua.acclorite.book_story.presentation.settings.LibrarySettingsScreen import ua.acclorite.book_story.presentation.settings.SettingsModel +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.library.LibraryContent import ua.acclorite.book_story.ui.navigator.LocalNavigator @@ -59,22 +59,23 @@ object LibraryScreen : Screen, Parcelable { @Composable override fun Content() { val navigator = LocalNavigator.current - val screenModel = hiltViewModel() - val mainModel = hiltViewModel() val settingsModel = hiltViewModel() + val settings = LocalSettings.current val state = screenModel.state.collectAsStateWithLifecycle() - val mainState = mainModel.state.collectAsStateWithLifecycle() val settingsState = settingsModel.state.collectAsStateWithLifecycle() - val showDefaultCategory = remember(state.value.books, settingsState.value.categories) { + val showDefaultCategory = remember( + state.value.books, + settingsState.value.categories, + settings.libraryShowDefaultTab.value + ) { derivedStateOf { val categoryIds = settingsState.value.categories.map { it.id }.toSet() state.value.books.any { book -> book.data.categories.none { category -> category in categoryIds } - } || settingsState.value.categories.isEmpty() - || mainState.value.libraryAlwaysShowDefaultTab + } || settingsState.value.categories.isEmpty() || settings.libraryShowDefaultTab.lastValue } } @@ -108,11 +109,11 @@ object LibraryScreen : Screen, Parcelable { books = state.value.books, selectedItemsCount = state.value.selectedItemsCount, hasSelectedItems = state.value.hasSelectedItems, - titlePosition = mainState.value.libraryTitlePosition, - readButton = mainState.value.libraryReadButton, - showProgress = mainState.value.libraryShowProgress, - showCategoryTabs = mainState.value.libraryShowCategoryTabs, - showBookCount = mainState.value.libraryShowBookCount, + titlePosition = settings.libraryTitlePosition.value, + readButton = settings.libraryShowReadButton.value, + showProgress = settings.libraryShowProgress.value, + showCategoryTabs = settings.libraryShowCategoryTabs.value, + showBookCount = settings.libraryShowBookCount.value, showSearch = state.value.showSearch, searchQuery = state.value.searchQuery, bookCount = state.value.books.count(), @@ -120,22 +121,22 @@ object LibraryScreen : Screen, Parcelable { pagerState = pagerState, isLoading = state.value.isLoading, isRefreshing = state.value.isRefreshing, - doublePressExit = mainState.value.doublePressExit, - layout = mainState.value.libraryLayout, - gridSize = mainState.value.libraryGridSize, - autoGridSize = mainState.value.libraryAutoGridSize, + doublePressExit = settings.doublePressExit.value, + layout = settings.libraryLayout.value, + gridSize = settings.libraryGridSize.value, + autoGridSize = settings.libraryAutoGridSize.value, categories = settingsState.value.categories, showDefaultCategory = showDefaultCategory.value, categoriesSort = settingsState.value.categoriesSort, - sortOrder = mainState.value.librarySortOrder, - sortOrderDescending = mainState.value.librarySortOrderDescending, - perCategorySort = mainState.value.libraryPerCategorySort, + sortOrder = settings.librarySortOrder.value, + sortOrderDescending = settings.librarySortOrderDescending.value, + perCategorySort = settings.libraryPerCategorySort.value, refreshState = refreshState, dialog = state.value.dialog, bottomSheet = state.value.bottomSheet, updateCategorySort = settingsModel::onEvent, - changeLibrarySortOrder = mainModel::onEvent, - changeLibrarySortOrderDescending = mainModel::onEvent, + changeSortOrder = { settings.librarySortOrder.update(it) }, + changeSortOrderDescending = { settings.librarySortOrderDescending.update(it) }, selectBook = screenModel::onEvent, searchVisibility = screenModel::onEvent, requestFocus = screenModel::onEvent, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainActivity.kt b/app/src/main/java/ua/acclorite/book_story/presentation/main/MainActivity.kt index 6a08d1dd..9ac31ef9 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainActivity.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/main/MainActivity.kt @@ -23,44 +23,42 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import dagger.hilt.android.AndroidEntryPoint import kotlinx.collections.immutable.persistentListOf import ua.acclorite.book_story.R +import ua.acclorite.book_story.data.settings.SettingsManager import ua.acclorite.book_story.presentation.browse.BrowseModel import ua.acclorite.book_story.presentation.browse.BrowseScreen import ua.acclorite.book_story.presentation.history.HistoryModel import ua.acclorite.book_story.presentation.history.HistoryScreen import ua.acclorite.book_story.presentation.library.LibraryModel import ua.acclorite.book_story.presentation.library.LibraryScreen -import ua.acclorite.book_story.presentation.main.model.isDark -import ua.acclorite.book_story.presentation.main.model.isPureDark import ua.acclorite.book_story.presentation.navigator.NavigatorItem import ua.acclorite.book_story.presentation.navigator.StackEvent import ua.acclorite.book_story.presentation.settings.SettingsModel import ua.acclorite.book_story.presentation.start.StartScreen import ua.acclorite.book_story.ui.common.components.navigation_bar.NavigationBar import ua.acclorite.book_story.ui.common.components.navigation_rail.NavigationRail +import ua.acclorite.book_story.ui.common.helpers.ProvideSettings import ua.acclorite.book_story.ui.main.MainActivityKeyboardManager import ua.acclorite.book_story.ui.navigator.Navigator import ua.acclorite.book_story.ui.navigator.NavigatorTabs import ua.acclorite.book_story.ui.theme.BookStoryTheme import ua.acclorite.book_story.ui.theme.Transitions import java.lang.reflect.Field +import javax.inject.Inject @SuppressLint("DiscouragedPrivateApi") @AndroidEntryPoint class MainActivity : AppCompatActivity() { - // Creating an instance of Models - private val mainModel: MainModel by viewModels() + + @Inject + lateinit var settings: SettingsManager private val settingsModel: SettingsModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { - // Splash screen - installSplashScreen().apply { - setKeepOnScreenCondition { - !mainModel.isReady.value - } + installSplashScreen().setKeepOnScreenCondition { + !settings.initialized.value || !settingsModel.isReady.value } - // Default super super.onCreate(savedInstanceState) // Bigger Cursor size for Room @@ -72,9 +70,6 @@ class MainActivity : AppCompatActivity() { e.printStackTrace() } - // Initializing the MainModel - mainModel.init(settingsModel.isReady) - // Edge to edge enableEdgeToEdge() WindowCompat.setDecorFitsSystemWindows(window, false) @@ -85,84 +80,83 @@ class MainActivity : AppCompatActivity() { val historyModel = hiltViewModel() val browseModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() - val isLoaded = mainModel.isReady.collectAsStateWithLifecycle() - - val tabs = persistentListOf( - NavigatorItem( - screen = LibraryScreen, - title = R.string.library_screen, - tooltip = R.string.library_content_desc, - selectedIcon = R.drawable.library_screen_filled, - unselectedIcon = R.drawable.library_screen_outlined - ), - NavigatorItem( - screen = HistoryScreen, - title = R.string.history_screen, - tooltip = R.string.history_content_desc, - selectedIcon = R.drawable.history_screen_filled, - unselectedIcon = R.drawable.history_screen_outlined - ), - NavigatorItem( - screen = BrowseScreen, - title = R.string.browse_screen, - tooltip = R.string.browse_content_desc, - selectedIcon = R.drawable.browse_screen_filled, - unselectedIcon = R.drawable.browse_screen_outlined + ProvideSettings(settings) { + val tabs = persistentListOf( + NavigatorItem( + screen = LibraryScreen, + title = R.string.library_screen, + tooltip = R.string.library_content_desc, + selectedIcon = R.drawable.library_screen_filled, + unselectedIcon = R.drawable.library_screen_outlined + ), + NavigatorItem( + screen = HistoryScreen, + title = R.string.history_screen, + tooltip = R.string.history_content_desc, + selectedIcon = R.drawable.history_screen_filled, + unselectedIcon = R.drawable.history_screen_outlined + ), + NavigatorItem( + screen = BrowseScreen, + title = R.string.browse_screen, + tooltip = R.string.browse_content_desc, + selectedIcon = R.drawable.browse_screen_filled, + unselectedIcon = R.drawable.browse_screen_outlined + ) ) - ) - MainActivityKeyboardManager() + MainActivityKeyboardManager() - if (isLoaded.value) { - BookStoryTheme( - theme = state.value.theme, - isDark = state.value.darkTheme.isDark(), - isPureDark = state.value.pureDark.isPureDark(this), - themeContrast = state.value.themeContrast - ) { - Navigator( - initialScreen = if (state.value.showStartScreen) StartScreen - else LibraryScreen, - transitionSpec = { lastEvent -> - when (lastEvent) { - StackEvent.Default -> { - Transitions.SlidingTransitionIn - .togetherWith(Transitions.SlidingTransitionOut) + if (settings.initialized.collectAsStateWithLifecycle().value) { + BookStoryTheme( + theme = settings.theme.value, + isDark = settings.darkTheme.value.isDark(), + isPureDark = settings.pureDark.value.isPureDark(this), + themeContrast = settings.themeContrast.value + ) { + Navigator( + initialScreen = if (settings.showStartScreen.value) StartScreen + else LibraryScreen, + transitionSpec = { lastEvent -> + when (lastEvent) { + StackEvent.Default -> { + Transitions.SlidingTransitionIn + .togetherWith(Transitions.SlidingTransitionOut) + } + + StackEvent.Pop -> { + Transitions.BackSlidingTransitionIn + .togetherWith(Transitions.BackSlidingTransitionOut) + } + } + }, + contentKey = { + when (it) { + LibraryScreen, HistoryScreen, BrowseScreen -> "tabs" + else -> it + } + }, + backHandlerEnabled = { it != StartScreen } + ) { screen -> + when (screen) { + LibraryScreen, HistoryScreen, BrowseScreen -> { + NavigatorTabs( + currentTab = screen, + transitionSpec = { + Transitions.FadeTransitionIn + .togetherWith(Transitions.FadeTransitionOut) + }, + navigationBar = { NavigationBar(tabs = tabs) }, + navigationRail = { NavigationRail(tabs = tabs) } + ) { tab -> + tab.Content() + } } - StackEvent.Pop -> { - Transitions.BackSlidingTransitionIn - .togetherWith(Transitions.BackSlidingTransitionOut) + else -> { + screen.Content() } } - }, - contentKey = { - when (it) { - LibraryScreen, HistoryScreen, BrowseScreen -> "tabs" - else -> it - } - }, - backHandlerEnabled = { it != StartScreen } - ) { screen -> - when (screen) { - LibraryScreen, HistoryScreen, BrowseScreen -> { - NavigatorTabs( - currentTab = screen, - transitionSpec = { - Transitions.FadeTransitionIn - .togetherWith(Transitions.FadeTransitionOut) - }, - navigationBar = { NavigationBar(tabs = tabs) }, - navigationRail = { NavigationRail(tabs = tabs) } - ) { tab -> - tab.Content() - } - } - - else -> { - screen.Content() - } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/main/MainEvent.kt deleted file mode 100644 index 4a27a637..00000000 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainEvent.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.presentation.main - -import androidx.compose.runtime.Immutable - -@Immutable -sealed class MainEvent { - data class OnChangeLanguage(val value: String) : MainEvent() - data class OnChangeTheme(val value: String) : MainEvent() - data class OnChangeDarkTheme(val value: String) : MainEvent() - data class OnChangePureDark(val value: String) : MainEvent() - data class OnChangeThemeContrast(val value: String) : MainEvent() - data class OnChangeFontFamily(val value: String) : MainEvent() - data class OnChangeFontStyle(val value: Boolean) : MainEvent() - data class OnChangeFontSize(val value: Int) : MainEvent() - data class OnChangeLineHeight(val value: Int) : MainEvent() - data class OnChangeParagraphHeight(val value: Int) : MainEvent() - data class OnChangeParagraphIndentation(val value: Int) : MainEvent() - data class OnChangeShowStartScreen(val value: Boolean) : MainEvent() - data class OnChangeSidePadding(val value: Int) : MainEvent() - data class OnChangeDoubleClickTranslation(val value: Boolean) : MainEvent() - data class OnChangeFastColorPresetChange(val value: Boolean) : MainEvent() - data class OnChangeBrowseLayout(val value: String) : MainEvent() - data class OnChangeBrowseAutoGridSize(val value: Boolean) : MainEvent() - data class OnChangeBrowseGridSize(val value: Int) : MainEvent() - data class OnChangeBrowseSortOrder(val value: String) : MainEvent() - data class OnChangeBrowseSortOrderDescending(val value: Boolean) : MainEvent() - data class OnChangeBrowseIncludedFilterItem(val value: String) : MainEvent() - data class OnChangeTextAlignment(val value: String) : MainEvent() - data class OnChangeDoublePressExit(val value: Boolean) : MainEvent() - data class OnChangeLetterSpacing(val value: Int) : MainEvent() - data class OnChangeAbsoluteDark(val value: Boolean) : MainEvent() - data class OnChangeCutoutPadding(val value: Boolean) : MainEvent() - data class OnChangeFullscreen(val value: Boolean) : MainEvent() - data class OnChangeKeepScreenOn(val value: Boolean) : MainEvent() - data class OnChangeVerticalPadding(val value: Int) : MainEvent() - data class OnChangeHideBarsOnFastScroll(val value: Boolean) : MainEvent() - data class OnChangePerceptionExpander(val value: Boolean) : MainEvent() - data class OnChangePerceptionExpanderPadding(val value: Int) : MainEvent() - data class OnChangePerceptionExpanderThickness(val value: Int) : MainEvent() - data class OnChangeScreenOrientation(val value: String) : MainEvent() - data class OnChangeCustomScreenBrightness(val value: Boolean) : MainEvent() - data class OnChangeScreenBrightness(val value: Float) : MainEvent() - data class OnChangeHorizontalGesture(val value: String) : MainEvent() - data class OnChangeHorizontalGestureScroll(val value: Float) : MainEvent() - data class OnChangeHorizontalGestureSensitivity(val value: Float) : MainEvent() - data class OnChangeBottomBarPadding(val value: Int) : MainEvent() - data class OnChangeHighlightedReading(val value: Boolean) : MainEvent() - data class OnChangeHighlightedReadingThickness(val value: Int) : MainEvent() - data class OnChangeChapterTitleAlignment(val value: String) : MainEvent() - data class OnChangeImages(val value: Boolean) : MainEvent() - data class OnChangeImagesCaptions(val value: Boolean) : MainEvent() - data class OnChangeImagesCornersRoundness(val value: Int) : MainEvent() - data class OnChangeImagesAlignment(val value: String) : MainEvent() - data class OnChangeImagesWidth(val value: Float) : MainEvent() - data class OnChangeImagesColorEffects(val value: String) : MainEvent() - data class OnChangeProgressBar(val value: Boolean) : MainEvent() - data class OnChangeProgressBarPadding(val value: Int) : MainEvent() - data class OnChangeProgressBarAlignment(val value: String) : MainEvent() - data class OnChangeProgressBarFontSize(val value: Int) : MainEvent() - data class OnChangeBrowsePinnedPaths(val value: String) : MainEvent() - data class OnChangeFontThickness(val value: String) : MainEvent() - data class OnChangeProgressCount(val value: String) : MainEvent() - data class OnChangeHorizontalGestureAlphaAnim(val value: Boolean) : MainEvent() - data class OnChangeHorizontalGesturePullAnim(val value: Boolean) : MainEvent() - data class OnChangeLibraryLayout(val value: String) : MainEvent() - data class OnChangeLibraryAutoGridSize(val value: Boolean) : MainEvent() - data class OnChangeLibraryGridSize(val value: Int) : MainEvent() - data class OnChangeLibraryReadButton(val value: Boolean) : MainEvent() - data class OnChangeLibraryShowProgress(val value: Boolean) : MainEvent() - data class OnChangeLibraryTitlePosition(val value: String) : MainEvent() - data class OnChangeLibraryShowBookCount(val value: Boolean) : MainEvent() - data class OnChangeLibraryShowCategoryTabs(val value: Boolean) : MainEvent() - data class OnChangeLibraryAlwaysShowDefaultTab(val value: Boolean) : MainEvent() - data class OnChangeLibrarySortOrder(val value: String) : MainEvent() - data class OnChangeLibrarySortOrderDescending(val value: Boolean) : MainEvent() - data class OnChangeLibraryPerCategorySort(val value: Boolean) : MainEvent() -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/main/MainModel.kt deleted file mode 100644 index 35af6acf..00000000 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainModel.kt +++ /dev/null @@ -1,732 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.presentation.main - -import androidx.datastore.preferences.core.Preferences -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import kotlinx.coroutines.yield -import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguagePreferenceUseCase -import ua.acclorite.book_story.domain.use_case.data_store.GetPreferencesUseCase -import ua.acclorite.book_story.domain.use_case.data_store.PutPreferenceUseCase -import ua.acclorite.book_story.presentation.browse.model.BrowseLayout -import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder -import ua.acclorite.book_story.presentation.library.model.LibraryLayout -import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder -import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition -import ua.acclorite.book_story.presentation.main.data.DataStoreData -import ua.acclorite.book_story.presentation.main.model.DarkTheme -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment -import ua.acclorite.book_story.presentation.main.model.PureDark -import ua.acclorite.book_story.presentation.main.model.ThemeContrast -import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects -import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness -import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture -import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount -import ua.acclorite.book_story.presentation.reader.model.ReaderScreenOrientation -import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment -import ua.acclorite.book_story.ui.reader.data.ReaderData -import ua.acclorite.book_story.ui.theme.Theme -import javax.inject.Inject - - -@HiltViewModel -class MainModel @Inject constructor( - private val stateHandle: SavedStateHandle, - private val putPreferenceUseCase: PutPreferenceUseCase, - private val changeLanguagePreferenceUseCase: ChangeLanguagePreferenceUseCase, - private val getPreferencesUseCase: GetPreferencesUseCase -) : ViewModel() { - - private val mutex = Mutex() - - private val _isReady = MutableStateFlow(false) - val isReady = _isReady.asStateFlow() - - private val mainModelReady = MutableStateFlow(false) - - private val _state: MutableStateFlow = MutableStateFlow( - stateHandle["main_state"] ?: MainState() - ) - val state = _state.asStateFlow() - - fun onEvent(event: MainEvent) { - when (event) { - is MainEvent.OnChangeLanguage -> handleLanguageUpdate(event) - - is MainEvent.OnChangeDarkTheme -> handleDatastoreUpdate( - key = DataStoreData.DARK_THEME, - value = event.value, - updateState = { - it.copy(darkTheme = DarkTheme.valueOf(this)) - } - ) - - is MainEvent.OnChangePureDark -> handleDatastoreUpdate( - key = DataStoreData.PURE_DARK, - value = event.value, - updateState = { - it.copy(pureDark = PureDark.valueOf(this)) - } - ) - - is MainEvent.OnChangeThemeContrast -> handleDatastoreUpdate( - key = DataStoreData.THEME_CONTRAST, - value = event.value, - updateState = { - it.copy(themeContrast = ThemeContrast.valueOf(this)) - } - ) - - is MainEvent.OnChangeTheme -> handleDatastoreUpdate( - key = DataStoreData.THEME, - value = event.value, - updateState = { - it.copy(theme = Theme.valueOf(this)) - } - ) - - is MainEvent.OnChangeFontFamily -> handleDatastoreUpdate( - key = DataStoreData.FONT, - value = event.value, - updateState = { - it.copy( - fontFamily = ReaderData.fonts.run { - find { font -> - font.id == event.value - }?.id ?: get(0).id - } - ) - } - ) - - is MainEvent.OnChangeFontStyle -> handleDatastoreUpdate( - key = DataStoreData.IS_ITALIC, - value = event.value, - updateState = { - it.copy(isItalic = this) - } - ) - - is MainEvent.OnChangeFontSize -> handleDatastoreUpdate( - key = DataStoreData.FONT_SIZE, - value = event.value, - updateState = { - it.copy(fontSize = this) - } - ) - - is MainEvent.OnChangeLineHeight -> handleDatastoreUpdate( - key = DataStoreData.LINE_HEIGHT, - value = event.value, - updateState = { - it.copy(lineHeight = this) - } - ) - - is MainEvent.OnChangeParagraphHeight -> handleDatastoreUpdate( - key = DataStoreData.PARAGRAPH_HEIGHT, - value = event.value, - updateState = { - it.copy(paragraphHeight = this) - } - ) - - is MainEvent.OnChangeParagraphIndentation -> handleDatastoreUpdate( - key = DataStoreData.PARAGRAPH_INDENTATION, - value = event.value, - updateState = { - it.copy(paragraphIndentation = this) - } - ) - - is MainEvent.OnChangeShowStartScreen -> handleDatastoreUpdate( - key = DataStoreData.SHOW_START_SCREEN, - value = event.value, - updateState = { - it.copy(showStartScreen = this) - } - ) - - is MainEvent.OnChangeSidePadding -> handleDatastoreUpdate( - key = DataStoreData.SIDE_PADDING, - value = event.value, - updateState = { - it.copy(sidePadding = this) - } - ) - - is MainEvent.OnChangeDoubleClickTranslation -> handleDatastoreUpdate( - key = DataStoreData.DOUBLE_CLICK_TRANSLATION, - value = event.value, - updateState = { - it.copy(doubleClickTranslation = this) - } - ) - - is MainEvent.OnChangeFastColorPresetChange -> handleDatastoreUpdate( - key = DataStoreData.FAST_COLOR_PRESET_CHANGE, - value = event.value, - updateState = { - it.copy(fastColorPresetChange = this) - } - ) - - is MainEvent.OnChangeBrowseLayout -> handleDatastoreUpdate( - key = DataStoreData.BROWSE_LAYOUT, - value = event.value, - updateState = { - it.copy(browseLayout = BrowseLayout.valueOf(this)) - } - ) - - is MainEvent.OnChangeBrowseAutoGridSize -> handleDatastoreUpdate( - key = DataStoreData.BROWSE_AUTO_GRID_SIZE, - value = event.value, - updateState = { - it.copy(browseAutoGridSize = this) - } - ) - - is MainEvent.OnChangeBrowseGridSize -> handleDatastoreUpdate( - key = DataStoreData.BROWSE_GRID_SIZE, - value = event.value, - updateState = { - it.copy(browseGridSize = this) - } - ) - - is MainEvent.OnChangeBrowseSortOrder -> handleDatastoreUpdate( - key = DataStoreData.BROWSE_SORT_ORDER, - value = event.value, - updateState = { - it.copy(browseSortOrder = BrowseSortOrder.valueOf(this)) - } - ) - - is MainEvent.OnChangeBrowseSortOrderDescending -> handleDatastoreUpdate( - key = DataStoreData.BROWSE_SORT_ORDER_DESCENDING, - value = event.value, - updateState = { - it.copy(browseSortOrderDescending = this) - } - ) - - is MainEvent.OnChangeBrowseIncludedFilterItem -> handleBrowseIncludedFilterItemUpdate( - event = event - ) - - is MainEvent.OnChangeTextAlignment -> handleDatastoreUpdate( - key = DataStoreData.TEXT_ALIGNMENT, - value = event.value, - updateState = { - it.copy(textAlignment = ReaderTextAlignment.valueOf(this)) - } - ) - - is MainEvent.OnChangeDoublePressExit -> handleDatastoreUpdate( - key = DataStoreData.DOUBLE_PRESS_EXIT, - value = event.value, - updateState = { - it.copy(doublePressExit = this) - } - ) - - is MainEvent.OnChangeLetterSpacing -> handleDatastoreUpdate( - key = DataStoreData.LETTER_SPACING, - value = event.value, - updateState = { - it.copy(letterSpacing = this) - } - ) - - is MainEvent.OnChangeAbsoluteDark -> handleDatastoreUpdate( - key = DataStoreData.ABSOLUTE_DARK, - value = event.value, - updateState = { - it.copy(absoluteDark = this) - } - ) - - is MainEvent.OnChangeCutoutPadding -> handleDatastoreUpdate( - key = DataStoreData.CUTOUT_PADDING, - value = event.value, - updateState = { - it.copy(cutoutPadding = this) - } - ) - - is MainEvent.OnChangeFullscreen -> handleDatastoreUpdate( - key = DataStoreData.FULLSCREEN, - value = event.value, - updateState = { - it.copy(fullscreen = this) - } - ) - - is MainEvent.OnChangeKeepScreenOn -> handleDatastoreUpdate( - key = DataStoreData.KEEP_SCREEN_ON, - value = event.value, - updateState = { - it.copy(keepScreenOn = this) - } - ) - - is MainEvent.OnChangeVerticalPadding -> handleDatastoreUpdate( - key = DataStoreData.VERTICAL_PADDING, - value = event.value, - updateState = { - it.copy(verticalPadding = this) - } - ) - - is MainEvent.OnChangeHideBarsOnFastScroll -> handleDatastoreUpdate( - key = DataStoreData.HIDE_BARS_ON_FAST_SCROLL, - value = event.value, - updateState = { - it.copy(hideBarsOnFastScroll = this) - } - ) - - is MainEvent.OnChangePerceptionExpander -> handleDatastoreUpdate( - key = DataStoreData.PERCEPTION_EXPANDER, - value = event.value, - updateState = { - it.copy(perceptionExpander = this) - } - ) - - is MainEvent.OnChangePerceptionExpanderPadding -> handleDatastoreUpdate( - key = DataStoreData.PERCEPTION_EXPANDER_PADDING, - value = event.value, - updateState = { - it.copy(perceptionExpanderPadding = this) - } - ) - - is MainEvent.OnChangePerceptionExpanderThickness -> handleDatastoreUpdate( - key = DataStoreData.PERCEPTION_EXPANDER_THICKNESS, - value = event.value, - updateState = { - it.copy(perceptionExpanderThickness = this) - } - ) - - is MainEvent.OnChangeScreenOrientation -> handleDatastoreUpdate( - key = DataStoreData.SCREEN_ORIENTATION, - value = event.value, - updateState = { - it.copy(screenOrientation = ReaderScreenOrientation.valueOf(this)) - } - ) - - is MainEvent.OnChangeCustomScreenBrightness -> handleDatastoreUpdate( - key = DataStoreData.CUSTOM_SCREEN_BRIGHTNESS, - value = event.value, - updateState = { - it.copy(customScreenBrightness = this) - } - ) - - is MainEvent.OnChangeScreenBrightness -> handleDatastoreUpdate( - key = DataStoreData.SCREEN_BRIGHTNESS, - value = event.value.toDouble(), - updateState = { - it.copy(screenBrightness = this.toFloat()) - } - ) - - is MainEvent.OnChangeHorizontalGesture -> handleDatastoreUpdate( - key = DataStoreData.HORIZONTAL_GESTURE, - value = event.value, - updateState = { - it.copy(horizontalGesture = ReaderHorizontalGesture.valueOf(this)) - } - ) - - is MainEvent.OnChangeHorizontalGestureScroll -> handleDatastoreUpdate( - key = DataStoreData.HORIZONTAL_GESTURE_SCROLL, - value = event.value.toDouble(), - updateState = { - it.copy(horizontalGestureScroll = this.toFloat()) - } - ) - - is MainEvent.OnChangeHorizontalGestureSensitivity -> handleDatastoreUpdate( - key = DataStoreData.HORIZONTAL_GESTURE_SENSITIVITY, - value = event.value.toDouble(), - updateState = { - it.copy(horizontalGestureSensitivity = this.toFloat()) - } - ) - - is MainEvent.OnChangeBottomBarPadding -> handleDatastoreUpdate( - key = DataStoreData.BOTTOM_BAR_PADDING, - value = event.value, - updateState = { - it.copy(bottomBarPadding = this) - } - ) - - is MainEvent.OnChangeHighlightedReading -> handleDatastoreUpdate( - key = DataStoreData.HIGHLIGHTED_READING, - value = event.value, - updateState = { - it.copy(highlightedReading = this) - } - ) - - is MainEvent.OnChangeHighlightedReadingThickness -> handleDatastoreUpdate( - key = DataStoreData.HIGHLIGHTED_READING_THICKNESS, - value = event.value, - updateState = { - it.copy(highlightedReadingThickness = this) - } - ) - - is MainEvent.OnChangeChapterTitleAlignment -> handleDatastoreUpdate( - key = DataStoreData.CHAPTER_TITLE_ALIGNMENT, - value = event.value, - updateState = { - it.copy(chapterTitleAlignment = ReaderTextAlignment.valueOf(this)) - } - ) - - is MainEvent.OnChangeImages -> handleDatastoreUpdate( - key = DataStoreData.IMAGES, - value = event.value, - updateState = { - it.copy(images = this) - } - ) - - is MainEvent.OnChangeImagesCaptions -> handleDatastoreUpdate( - key = DataStoreData.IMAGES_CAPTIONS, - value = event.value, - updateState = { - it.copy(imagesCaptions = this) - } - ) - - is MainEvent.OnChangeImagesCornersRoundness -> handleDatastoreUpdate( - key = DataStoreData.IMAGES_CORNERS_ROUNDNESS, - value = event.value, - updateState = { - it.copy(imagesCornersRoundness = this) - } - ) - - is MainEvent.OnChangeImagesAlignment -> handleDatastoreUpdate( - key = DataStoreData.IMAGES_ALIGNMENT, - value = event.value, - updateState = { - it.copy(imagesAlignment = HorizontalAlignment.valueOf(this)) - } - ) - - is MainEvent.OnChangeImagesWidth -> handleDatastoreUpdate( - key = DataStoreData.IMAGES_WIDTH, - value = event.value.toDouble(), - updateState = { - it.copy(imagesWidth = this.toFloat()) - } - ) - - is MainEvent.OnChangeImagesColorEffects -> handleDatastoreUpdate( - key = DataStoreData.IMAGES_COLOR_EFFECTS, - value = event.value, - updateState = { - it.copy(imagesColorEffects = ReaderColorEffects.valueOf(this)) - } - ) - - is MainEvent.OnChangeProgressBar -> handleDatastoreUpdate( - key = DataStoreData.PROGRESS_BAR, - value = event.value, - updateState = { - it.copy(progressBar = this) - } - ) - - is MainEvent.OnChangeProgressBarPadding -> handleDatastoreUpdate( - key = DataStoreData.PROGRESS_BAR_PADDING, - value = event.value, - updateState = { - it.copy(progressBarPadding = this) - } - ) - - is MainEvent.OnChangeProgressBarAlignment -> handleDatastoreUpdate( - key = DataStoreData.PROGRESS_BAR_ALIGNMENT, - value = event.value, - updateState = { - it.copy(progressBarAlignment = HorizontalAlignment.valueOf(this)) - } - ) - - is MainEvent.OnChangeProgressBarFontSize -> handleDatastoreUpdate( - key = DataStoreData.PROGRESS_BAR_FONT_SIZE, - value = event.value, - updateState = { - it.copy(progressBarFontSize = this) - } - ) - - is MainEvent.OnChangeBrowsePinnedPaths -> handleBrowsePinnedPathsUpdate( - event = event - ) - - is MainEvent.OnChangeFontThickness -> handleDatastoreUpdate( - key = DataStoreData.FONT_THICKNESS, - value = event.value, - updateState = { - it.copy(fontThickness = ReaderFontThickness.valueOf(this)) - } - ) - - is MainEvent.OnChangeProgressCount -> handleDatastoreUpdate( - key = DataStoreData.PROGRESS_COUNT, - value = event.value, - updateState = { - it.copy(progressCount = ReaderProgressCount.valueOf(this)) - } - ) - - is MainEvent.OnChangeHorizontalGestureAlphaAnim -> handleDatastoreUpdate( - key = DataStoreData.HORIZONTAL_GESTURE_ALPHA_ANIM, - value = event.value, - updateState = { - it.copy(horizontalGestureAlphaAnim = this) - } - ) - - is MainEvent.OnChangeHorizontalGesturePullAnim -> handleDatastoreUpdate( - key = DataStoreData.HORIZONTAL_GESTURE_PULL_ANIM, - value = event.value, - updateState = { - it.copy(horizontalGesturePullAnim = this) - } - ) - - is MainEvent.OnChangeLibraryLayout -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_LAYOUT, - value = event.value, - updateState = { - it.copy(libraryLayout = LibraryLayout.valueOf(this)) - } - ) - - is MainEvent.OnChangeLibraryAutoGridSize -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_AUTO_GRID_SIZE, - value = event.value, - updateState = { - it.copy(libraryAutoGridSize = this) - } - ) - - is MainEvent.OnChangeLibraryGridSize -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_GRID_SIZE, - value = event.value, - updateState = { - it.copy(libraryGridSize = this) - } - ) - - is MainEvent.OnChangeLibraryReadButton -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_READ_BUTTON, - value = event.value, - updateState = { - it.copy(libraryReadButton = this) - } - ) - - is MainEvent.OnChangeLibraryShowProgress -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_SHOW_PROGRESS, - value = event.value, - updateState = { - it.copy(libraryShowProgress = this) - } - ) - - is MainEvent.OnChangeLibraryTitlePosition -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_TITLE_POSITION, - value = event.value, - updateState = { - it.copy(libraryTitlePosition = LibraryTitlePosition.valueOf(this)) - } - ) - - is MainEvent.OnChangeLibraryShowBookCount -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_SHOW_BOOK_COUNT, - value = event.value, - updateState = { - it.copy(libraryShowBookCount = this) - } - ) - - is MainEvent.OnChangeLibraryShowCategoryTabs -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_SHOW_CATEGORY_TABS, - value = event.value, - updateState = { - it.copy(libraryShowCategoryTabs = this) - } - ) - - is MainEvent.OnChangeLibraryAlwaysShowDefaultTab -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_ALWAYS_SHOW_DEFAULT_TAB, - value = event.value, - updateState = { - it.copy(libraryAlwaysShowDefaultTab = this) - } - ) - - is MainEvent.OnChangeLibrarySortOrder -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_SORT_ORDER, - value = event.value, - updateState = { - it.copy(librarySortOrder = LibrarySortOrder.valueOf(this)) - } - ) - - is MainEvent.OnChangeLibrarySortOrderDescending -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_SORT_ORDER_DESCENDING, - value = event.value, - updateState = { - it.copy(librarySortOrderDescending = this) - } - ) - - is MainEvent.OnChangeLibraryPerCategorySort -> handleDatastoreUpdate( - key = DataStoreData.LIBRARY_PER_CATEGORY_SORT, - value = event.value, - updateState = { - it.copy(libraryPerCategorySort = this) - } - ) - } - } - - fun init(settingsModelReady: StateFlow) { - viewModelScope.launch(Dispatchers.Main) { - val settings = getPreferencesUseCase() - - /* All additional execution */ - changeLanguagePreferenceUseCase(settings.language) - - updateStateWithSavedHandle { settings } - mainModelReady.update { true } - } - - val isReady = combine( - mainModelReady.asStateFlow(), - settingsModelReady - ) { values -> - values.all { it } - } - - viewModelScope.launch(Dispatchers.Main) { - isReady.first { bool -> - if (bool) { - _isReady.update { - true - } - } - bool - } - } - } - - private fun handleLanguageUpdate(event: MainEvent.OnChangeLanguage) { - viewModelScope.launch(Dispatchers.Main.immediate) { - changeLanguagePreferenceUseCase(event.value) - updateStateWithSavedHandle { - it.copy(language = event.value) - } - } - } - - private fun handleBrowseIncludedFilterItemUpdate( - event: MainEvent.OnChangeBrowseIncludedFilterItem - ) { - val set = _state.value.browseIncludedFilterItems.toMutableSet() - if (!set.add(event.value)) { - set.remove(event.value) - } - handleDatastoreUpdate( - key = DataStoreData.BROWSE_INCLUDED_FILTER_ITEMS, - value = set, - updateState = { - it.copy(browseIncludedFilterItems = toList()) - } - ) - } - - private fun handleBrowsePinnedPathsUpdate( - event: MainEvent.OnChangeBrowsePinnedPaths - ) { - val set = _state.value.browsePinnedPaths.toMutableSet() - if (!set.add(event.value)) { - set.remove(event.value) - } - handleDatastoreUpdate( - key = DataStoreData.BROWSE_PINNED_PATHS, - value = set, - updateState = { - it.copy(browsePinnedPaths = toList()) - } - ) - } - - /** - * Handles and updates Datastore. - */ - private fun handleDatastoreUpdate( - key: Preferences.Key, - value: V, - updateState: V.(MainState) -> MainState - ) { - viewModelScope.launch(Dispatchers.Main.immediate) { - putPreferenceUseCase(key = key, value = value) - updateStateWithSavedHandle { - value.updateState(it) - } - } - } - - /** - * Updates [MainState] along with [SavedStateHandle]. - */ - private suspend fun updateStateWithSavedHandle( - function: (MainState) -> MainState - ) { - withContext(Dispatchers.Main.immediate) { - _state.update { - stateHandle["main_state"] = function(it) - function(it) - } - } - } - - private suspend inline fun MutableStateFlow.update(function: (T) -> T) { - mutex.withLock { - yield() - this.value = function(this.value) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/main/MainState.kt deleted file mode 100644 index 5bcab089..00000000 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/MainState.kt +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -@file:Suppress("UNCHECKED_CAST") - -package ua.acclorite.book_story.presentation.main - -import android.os.Parcelable -import androidx.annotation.Keep -import androidx.compose.runtime.Immutable -import androidx.datastore.preferences.core.Preferences -import kotlinx.parcelize.Parcelize -import ua.acclorite.book_story.core.data.CoreData -import ua.acclorite.book_story.presentation.browse.model.BrowseLayout -import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder -import ua.acclorite.book_story.presentation.library.model.LibraryLayout -import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder -import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition -import ua.acclorite.book_story.presentation.main.data.DataStoreData -import ua.acclorite.book_story.presentation.main.model.DarkTheme -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment -import ua.acclorite.book_story.presentation.main.model.PureDark -import ua.acclorite.book_story.presentation.main.model.ThemeContrast -import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects -import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness -import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture -import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount -import ua.acclorite.book_story.presentation.reader.model.ReaderScreenOrientation -import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment -import ua.acclorite.book_story.ui.reader.data.ReaderData -import ua.acclorite.book_story.ui.theme.Theme -import java.util.Locale - -/** - * Main State. - * All app's settings/preferences/permanent-variables are here. - * Wrapped in SavedStateHandle, so it won't reset. - */ -@Immutable -@Keep -@Parcelize -data class MainState( - // General Settings - val language: String = provideDefaultValue { - val locale = Locale.getDefault().language.take(2) - CoreData.languages.any { locale == it.first }.run { - if (this) locale - else "en"// Default language. - } - }, - val theme: Theme = provideDefaultValue { Theme.entries().first() }, - val darkTheme: DarkTheme = provideDefaultValue { DarkTheme.FOLLOW_SYSTEM }, - val pureDark: PureDark = provideDefaultValue { PureDark.OFF }, - val absoluteDark: Boolean = provideDefaultValue { false }, - val themeContrast: ThemeContrast = provideDefaultValue { ThemeContrast.STANDARD }, - val showStartScreen: Boolean = provideDefaultValue { true }, - val doublePressExit: Boolean = provideDefaultValue { false }, - - // Reader Settings - val fontFamily: String = provideDefaultValue { ReaderData.fonts[0].id }, - val fontThickness: ReaderFontThickness = provideDefaultValue { ReaderFontThickness.NORMAL }, - val isItalic: Boolean = provideDefaultValue { false }, - val fontSize: Int = provideDefaultValue { 16 }, - val lineHeight: Int = provideDefaultValue { 4 }, - val paragraphHeight: Int = provideDefaultValue { 8 }, - val paragraphIndentation: Int = provideDefaultValue { 0 }, - val sidePadding: Int = provideDefaultValue { 6 }, - val verticalPadding: Int = provideDefaultValue { 0 }, - val doubleClickTranslation: Boolean = provideDefaultValue { false }, - val fastColorPresetChange: Boolean = provideDefaultValue { true }, - val textAlignment: ReaderTextAlignment = provideDefaultValue { ReaderTextAlignment.JUSTIFY }, - val letterSpacing: Int = provideDefaultValue { 0 }, - val cutoutPadding: Boolean = provideDefaultValue { false }, - val fullscreen: Boolean = provideDefaultValue { true }, - val keepScreenOn: Boolean = provideDefaultValue { true }, - val hideBarsOnFastScroll: Boolean = provideDefaultValue { false }, - val perceptionExpander: Boolean = provideDefaultValue { false }, - val perceptionExpanderPadding: Int = provideDefaultValue { 5 }, - val perceptionExpanderThickness: Int = provideDefaultValue { 4 }, - val screenOrientation: ReaderScreenOrientation = provideDefaultValue { - ReaderScreenOrientation.DEFAULT - }, - val customScreenBrightness: Boolean = provideDefaultValue { false }, - val screenBrightness: Float = provideDefaultValue { 0.5f }, - val horizontalGesture: ReaderHorizontalGesture = provideDefaultValue { - ReaderHorizontalGesture.OFF - }, - val horizontalGestureScroll: Float = provideDefaultValue { 0.7f }, - val horizontalGestureSensitivity: Float = provideDefaultValue { 0.6f }, - val horizontalGestureAlphaAnim: Boolean = provideDefaultValue { true }, - val horizontalGesturePullAnim: Boolean = provideDefaultValue { true }, - val bottomBarPadding: Int = provideDefaultValue { 0 }, - val highlightedReading: Boolean = provideDefaultValue { false }, - val highlightedReadingThickness: Int = provideDefaultValue { 2 }, - val chapterTitleAlignment: ReaderTextAlignment = provideDefaultValue { ReaderTextAlignment.JUSTIFY }, - val images: Boolean = provideDefaultValue { true }, - val imagesCaptions: Boolean = provideDefaultValue { true }, - val imagesCornersRoundness: Int = provideDefaultValue { 8 }, - val imagesAlignment: HorizontalAlignment = provideDefaultValue { HorizontalAlignment.START }, - val imagesWidth: Float = provideDefaultValue { 0.8f }, - val imagesColorEffects: ReaderColorEffects = provideDefaultValue { ReaderColorEffects.OFF }, - val progressBar: Boolean = provideDefaultValue { false }, - val progressBarPadding: Int = provideDefaultValue { 4 }, - val progressBarAlignment: HorizontalAlignment = provideDefaultValue { HorizontalAlignment.CENTER }, - val progressBarFontSize: Int = provideDefaultValue { 8 }, - val progressCount: ReaderProgressCount = provideDefaultValue { ReaderProgressCount.PERCENTAGE }, - - // Library settings - val libraryLayout: LibraryLayout = provideDefaultValue { LibraryLayout.GRID }, - val libraryAutoGridSize: Boolean = provideDefaultValue { true }, - val libraryGridSize: Int = provideDefaultValue { 0 }, - val libraryTitlePosition: LibraryTitlePosition = provideDefaultValue { LibraryTitlePosition.BELOW }, - val libraryReadButton: Boolean = provideDefaultValue { true }, - val libraryShowProgress: Boolean = provideDefaultValue { true }, - val libraryShowBookCount: Boolean = provideDefaultValue { true }, - val libraryShowCategoryTabs: Boolean = provideDefaultValue { true }, - val libraryAlwaysShowDefaultTab: Boolean = provideDefaultValue { false }, - val librarySortOrder: LibrarySortOrder = provideDefaultValue { LibrarySortOrder.LAST_READ }, - val librarySortOrderDescending: Boolean = provideDefaultValue { true }, - val libraryPerCategorySort: Boolean = provideDefaultValue { false }, - - // Browse Settings - val browseLayout: BrowseLayout = provideDefaultValue { BrowseLayout.LIST }, - val browseAutoGridSize: Boolean = provideDefaultValue { true }, - val browseGridSize: Int = provideDefaultValue { 0 }, - val browseSortOrder: BrowseSortOrder = provideDefaultValue { BrowseSortOrder.LAST_MODIFIED }, - val browseSortOrderDescending: Boolean = provideDefaultValue { true }, - val browseIncludedFilterItems: List = provideDefaultValue { emptyList() }, - val browsePinnedPaths: List = provideDefaultValue { emptyList() }, -) : Parcelable { - companion object { - private fun provideDefaultValue(calculation: () -> D): D { - return calculation() - } - - /** - * Initializes [MainState] by given [Map]. - * If no value provided in [data], assigns default value. - */ - fun initialize(data: Map): MainState { - val defaultState = MainState() - fun provideValue( - key: Preferences.Key, - convert: T.() -> V = { this as V }, - default: MainState.() -> V - ): V { - return (data[key.name] as? T)?.convert() ?: defaultState.default() - } - - return DataStoreData.run { - MainState( - language = provideValue( - LANGUAGE - ) { language }, - - theme = provideValue( - THEME, convert = { Theme.valueOf(this) } - ) { theme }, - - darkTheme = provideValue( - DARK_THEME, convert = { DarkTheme.valueOf(this) } - ) { darkTheme }, - - pureDark = provideValue( - PURE_DARK, convert = { PureDark.valueOf(this) } - ) { pureDark }, - - absoluteDark = provideValue( - ABSOLUTE_DARK - ) { absoluteDark }, - - themeContrast = provideValue( - THEME_CONTRAST, convert = { ThemeContrast.valueOf(this) } - ) { themeContrast }, - - showStartScreen = provideValue( - SHOW_START_SCREEN - ) { showStartScreen }, - - fontFamily = provideValue( - FONT - ) { fontFamily }, - - isItalic = provideValue( - IS_ITALIC - ) { isItalic }, - - fontSize = provideValue( - FONT_SIZE - ) { fontSize }, - - lineHeight = provideValue( - LINE_HEIGHT - ) { lineHeight }, - - paragraphHeight = provideValue( - PARAGRAPH_HEIGHT - ) { paragraphHeight }, - - paragraphIndentation = provideValue( - PARAGRAPH_INDENTATION - ) { paragraphIndentation }, - - sidePadding = provideValue( - SIDE_PADDING - ) { sidePadding }, - - doubleClickTranslation = provideValue( - DOUBLE_CLICK_TRANSLATION - ) { doubleClickTranslation }, - - fastColorPresetChange = provideValue( - FAST_COLOR_PRESET_CHANGE - ) { fastColorPresetChange }, - - browseLayout = provideValue( - BROWSE_LAYOUT, convert = { BrowseLayout.valueOf(this) } - ) { browseLayout }, - - browseAutoGridSize = provideValue( - BROWSE_AUTO_GRID_SIZE - ) { browseAutoGridSize }, - - browseGridSize = provideValue( - BROWSE_GRID_SIZE - ) { browseGridSize }, - - browseSortOrder = provideValue( - BROWSE_SORT_ORDER, convert = { BrowseSortOrder.valueOf(this) } - ) { browseSortOrder }, - - browseSortOrderDescending = provideValue( - BROWSE_SORT_ORDER_DESCENDING - ) { browseSortOrderDescending }, - - browseIncludedFilterItems = provideValue( - BROWSE_INCLUDED_FILTER_ITEMS, convert = { toList() } - ) { browseIncludedFilterItems }, - - textAlignment = provideValue( - TEXT_ALIGNMENT, convert = { ReaderTextAlignment.valueOf(this) } - ) { textAlignment }, - - doublePressExit = provideValue( - DOUBLE_PRESS_EXIT - ) { doublePressExit }, - - letterSpacing = provideValue( - LETTER_SPACING - ) { letterSpacing }, - - cutoutPadding = provideValue( - CUTOUT_PADDING - ) { cutoutPadding }, - - fullscreen = provideValue( - FULLSCREEN - ) { fullscreen }, - - keepScreenOn = provideValue( - KEEP_SCREEN_ON - ) { keepScreenOn }, - - verticalPadding = provideValue( - VERTICAL_PADDING - ) { verticalPadding }, - - hideBarsOnFastScroll = provideValue( - HIDE_BARS_ON_FAST_SCROLL - ) { hideBarsOnFastScroll }, - - perceptionExpander = provideValue( - PERCEPTION_EXPANDER - ) { perceptionExpander }, - - perceptionExpanderPadding = provideValue( - PERCEPTION_EXPANDER_PADDING - ) { perceptionExpanderPadding }, - - perceptionExpanderThickness = provideValue( - PERCEPTION_EXPANDER_THICKNESS - ) { perceptionExpanderThickness }, - - screenOrientation = provideValue( - SCREEN_ORIENTATION, convert = { ReaderScreenOrientation.valueOf(this) } - ) { screenOrientation }, - - customScreenBrightness = provideValue( - CUSTOM_SCREEN_BRIGHTNESS - ) { customScreenBrightness }, - - screenBrightness = provideValue( - SCREEN_BRIGHTNESS, convert = { this.toFloat() } - ) { screenBrightness }, - - horizontalGesture = provideValue( - HORIZONTAL_GESTURE, convert = { ReaderHorizontalGesture.valueOf(this) } - ) { horizontalGesture }, - - horizontalGestureScroll = provideValue( - HORIZONTAL_GESTURE_SCROLL, convert = { toFloat() } - ) { horizontalGestureScroll }, - - horizontalGestureSensitivity = provideValue( - HORIZONTAL_GESTURE_SENSITIVITY, convert = { toFloat() } - ) { horizontalGestureSensitivity }, - - bottomBarPadding = provideValue( - BOTTOM_BAR_PADDING - ) { bottomBarPadding }, - - highlightedReading = provideValue( - HIGHLIGHTED_READING - ) { highlightedReading }, - - highlightedReadingThickness = provideValue( - HIGHLIGHTED_READING_THICKNESS - ) { highlightedReadingThickness }, - - chapterTitleAlignment = provideValue( - CHAPTER_TITLE_ALIGNMENT, convert = { ReaderTextAlignment.valueOf(this) } - ) { chapterTitleAlignment }, - - images = provideValue( - IMAGES - ) { images }, - - imagesCaptions = provideValue( - IMAGES_CAPTIONS - ) { imagesCaptions }, - - imagesCornersRoundness = provideValue( - IMAGES_CORNERS_ROUNDNESS - ) { imagesCornersRoundness }, - - imagesAlignment = provideValue( - IMAGES_ALIGNMENT, convert = { HorizontalAlignment.valueOf(this) } - ) { imagesAlignment }, - - imagesWidth = provideValue( - IMAGES_WIDTH, convert = { toFloat() } - ) { imagesWidth }, - - imagesColorEffects = provideValue( - IMAGES_COLOR_EFFECTS, convert = { ReaderColorEffects.valueOf(this) } - ) { imagesColorEffects }, - - progressBar = provideValue( - PROGRESS_BAR - ) { progressBar }, - - progressBarPadding = provideValue( - PROGRESS_BAR_PADDING - ) { progressBarPadding }, - - progressBarAlignment = provideValue( - PROGRESS_BAR_ALIGNMENT, convert = { HorizontalAlignment.valueOf(this) } - ) { progressBarAlignment }, - - progressBarFontSize = provideValue( - PROGRESS_BAR_FONT_SIZE - ) { progressBarFontSize }, - - browsePinnedPaths = provideValue( - BROWSE_PINNED_PATHS, convert = { toList() } - ) { browsePinnedPaths }, - - fontThickness = provideValue( - FONT_THICKNESS, convert = { ReaderFontThickness.valueOf(this) } - ) { fontThickness }, - - progressCount = provideValue( - PROGRESS_COUNT, convert = { ReaderProgressCount.valueOf(this) } - ) { progressCount }, - - horizontalGestureAlphaAnim = provideValue( - HORIZONTAL_GESTURE_ALPHA_ANIM - ) { horizontalGestureAlphaAnim }, - - horizontalGesturePullAnim = provideValue( - HORIZONTAL_GESTURE_PULL_ANIM - ) { horizontalGesturePullAnim }, - - libraryLayout = provideValue( - LIBRARY_LAYOUT, convert = { LibraryLayout.valueOf(this) } - ) { libraryLayout }, - - libraryAutoGridSize = provideValue( - LIBRARY_AUTO_GRID_SIZE - ) { libraryAutoGridSize }, - - libraryGridSize = provideValue( - LIBRARY_GRID_SIZE - ) { libraryGridSize }, - - libraryReadButton = provideValue( - LIBRARY_READ_BUTTON - ) { libraryReadButton }, - - libraryShowProgress = provideValue( - LIBRARY_SHOW_PROGRESS - ) { libraryShowProgress }, - - libraryTitlePosition = provideValue( - LIBRARY_TITLE_POSITION, convert = { LibraryTitlePosition.valueOf(this) } - ) { libraryTitlePosition }, - - libraryShowBookCount = provideValue( - LIBRARY_SHOW_BOOK_COUNT - ) { libraryShowBookCount }, - - libraryShowCategoryTabs = provideValue( - LIBRARY_SHOW_CATEGORY_TABS - ) { libraryShowCategoryTabs }, - - libraryAlwaysShowDefaultTab = provideValue( - LIBRARY_ALWAYS_SHOW_DEFAULT_TAB - ) { libraryAlwaysShowDefaultTab }, - - librarySortOrder = provideValue( - LIBRARY_SORT_ORDER, convert = { LibrarySortOrder.valueOf(this) } - ) { librarySortOrder }, - - librarySortOrderDescending = provideValue( - LIBRARY_SORT_ORDER_DESCENDING - ) { librarySortOrderDescending }, - - libraryPerCategorySort = provideValue( - LIBRARY_PER_CATEGORY_SORT - ) { libraryPerCategorySort }, - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/data/DataStoreData.kt b/app/src/main/java/ua/acclorite/book_story/presentation/main/data/DataStoreData.kt deleted file mode 100644 index 7ba2d70b..00000000 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/data/DataStoreData.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Book's Story — free and open-source Material You eBook reader. - * Copyright (C) 2024-2025 Acclorite - * SPDX-License-Identifier: GPL-3.0-only - */ - -package ua.acclorite.book_story.presentation.main.data - -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.doublePreferencesKey -import androidx.datastore.preferences.core.intPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.core.stringSetPreferencesKey - -object DataStoreData { - // General settings - val LANGUAGE = stringPreferencesKey("language") - val THEME = stringPreferencesKey("theme") - val DARK_THEME = stringPreferencesKey("dark_theme") - val PURE_DARK = stringPreferencesKey("pure_dark") - val ABSOLUTE_DARK = booleanPreferencesKey("absolute_dark") - val THEME_CONTRAST = stringPreferencesKey("theme_contrast") - val SHOW_START_SCREEN = booleanPreferencesKey("guide") - val DOUBLE_PRESS_EXIT = booleanPreferencesKey("double_press_exit") - - // Reader settings - val DOUBLE_CLICK_TRANSLATION = booleanPreferencesKey("double_click_translation") - val FAST_COLOR_PRESET_CHANGE = booleanPreferencesKey("fast_color_preset_change") - val SIDE_PADDING = intPreferencesKey("side_padding") - val VERTICAL_PADDING = intPreferencesKey("vertical_padding") - val FONT = stringPreferencesKey("font") - val FONT_THICKNESS = stringPreferencesKey("font_thickness") - val IS_ITALIC = booleanPreferencesKey("font_style") - val FONT_SIZE = intPreferencesKey("font_size") - val LINE_HEIGHT = intPreferencesKey("line_height") - val PARAGRAPH_HEIGHT = intPreferencesKey("paragraph_height") - val PARAGRAPH_INDENTATION = intPreferencesKey("paragraph_indentation_int") - val TEXT_ALIGNMENT = stringPreferencesKey("text_alignment") - val LETTER_SPACING = intPreferencesKey("letter_spacing") - val CUTOUT_PADDING = booleanPreferencesKey("cutout_padding") - val FULLSCREEN = booleanPreferencesKey("fullscreen") - val KEEP_SCREEN_ON = booleanPreferencesKey("keep_screen_on") - val HIDE_BARS_ON_FAST_SCROLL = booleanPreferencesKey("hide_bars_on_fast_scroll") - val PERCEPTION_EXPANDER = booleanPreferencesKey("perception_expander") - val PERCEPTION_EXPANDER_PADDING = intPreferencesKey("perception_expander_padding") - val PERCEPTION_EXPANDER_THICKNESS = intPreferencesKey("perception_expander_thickness") - val SCREEN_ORIENTATION = stringPreferencesKey("screen_orientation") - val CUSTOM_SCREEN_BRIGHTNESS = booleanPreferencesKey("custom_screen_brightness") - val SCREEN_BRIGHTNESS = doublePreferencesKey("screen_brightness") - val HORIZONTAL_GESTURE = stringPreferencesKey("horizontal_gesture") - val HORIZONTAL_GESTURE_SCROLL = doublePreferencesKey("horizontal_gesture_scroll") - val HORIZONTAL_GESTURE_SENSITIVITY = doublePreferencesKey("horizontal_gesture_sensitivity") - val HORIZONTAL_GESTURE_ALPHA_ANIM = booleanPreferencesKey("horizontal_gesture_alpha_anim_bool") - val HORIZONTAL_GESTURE_PULL_ANIM = booleanPreferencesKey("horizontal_gesture_pull_anim") - val BOTTOM_BAR_PADDING = intPreferencesKey("bottom_bar_padding") - val HIGHLIGHTED_READING = booleanPreferencesKey("highlighted_reading") - val HIGHLIGHTED_READING_THICKNESS = intPreferencesKey("highlighted_reading_thickness") - val CHAPTER_TITLE_ALIGNMENT = stringPreferencesKey("chapter_title_alignment") - val IMAGES = booleanPreferencesKey("images") - val IMAGES_CAPTIONS = booleanPreferencesKey("images_captions") - val IMAGES_CORNERS_ROUNDNESS = intPreferencesKey("images_corners_roundness") - val IMAGES_ALIGNMENT = stringPreferencesKey("images_alignment") - val IMAGES_WIDTH = doublePreferencesKey("images_width") - val IMAGES_COLOR_EFFECTS = stringPreferencesKey("images_color_effects") - val PROGRESS_BAR = booleanPreferencesKey("progress_bar") - val PROGRESS_BAR_PADDING = intPreferencesKey("progress_bar_padding") - val PROGRESS_BAR_ALIGNMENT = stringPreferencesKey("progress_bar_alignment") - val PROGRESS_BAR_FONT_SIZE = intPreferencesKey("progress_bar_font_size") - val PROGRESS_COUNT = stringPreferencesKey("progress_count") - - // Library settings - val LIBRARY_LAYOUT = stringPreferencesKey("library_layout") - val LIBRARY_AUTO_GRID_SIZE = booleanPreferencesKey("library_auto_grid_size") - val LIBRARY_GRID_SIZE = intPreferencesKey("library_grid_size") - val LIBRARY_READ_BUTTON = booleanPreferencesKey("library_read_button") - val LIBRARY_SHOW_PROGRESS = booleanPreferencesKey("library_show_progress") - val LIBRARY_TITLE_POSITION = stringPreferencesKey("library_title_position") - val LIBRARY_SHOW_BOOK_COUNT = booleanPreferencesKey("library_show_book_count") - val LIBRARY_SHOW_CATEGORY_TABS = booleanPreferencesKey("library_show_category_tabs") - val LIBRARY_ALWAYS_SHOW_DEFAULT_TAB = booleanPreferencesKey("library_always_show_default_tab") - val LIBRARY_SORT_ORDER = stringPreferencesKey("library_sort_order") - val LIBRARY_SORT_ORDER_DESCENDING = booleanPreferencesKey("library_sort_order_descending") - val LIBRARY_PER_CATEGORY_SORT = booleanPreferencesKey("library_per_category_sort") - - // Browse settings - val BROWSE_LAYOUT = stringPreferencesKey("browse_layout") - val BROWSE_AUTO_GRID_SIZE = booleanPreferencesKey("browse_auto_grid_size") - val BROWSE_GRID_SIZE = intPreferencesKey("browse_grid_size") - val BROWSE_SORT_ORDER = stringPreferencesKey("browse_sort_order") - val BROWSE_SORT_ORDER_DESCENDING = booleanPreferencesKey("browse_sort_order_descending") - val BROWSE_INCLUDED_FILTER_ITEMS = stringSetPreferencesKey("browse_included_filter_items") - val BROWSE_PINNED_PATHS = stringSetPreferencesKey("browse_pinned_paths") -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/reader/ReaderScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/reader/ReaderScreen.kt index 4ebfb372..9c0575cc 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/reader/ReaderScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/reader/ReaderScreen.kt @@ -46,17 +46,16 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.parcelize.Parcelize import ua.acclorite.book_story.core.helpers.calculateProgress import ua.acclorite.book_story.presentation.book_info.BookInfoScreen -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.navigator.Screen import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.presentation.settings.SettingsModel import ua.acclorite.book_story.ui.common.helpers.LocalActivity +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.helpers.setBrightness import ua.acclorite.book_story.ui.navigator.LocalNavigator import ua.acclorite.book_story.ui.reader.ReaderContent -import ua.acclorite.book_story.ui.reader.data.ReaderData import kotlin.math.roundToInt @Parcelize @@ -72,11 +71,10 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { override fun Content() { val navigator = LocalNavigator.current val screenModel = hiltViewModel() - val mainModel = hiltViewModel() val settingsModel = hiltViewModel() + val settings = LocalSettings.current val state = screenModel.state.collectAsStateWithLifecycle() - val mainState = mainModel.state.collectAsStateWithLifecycle() val settingsState = settingsModel.state.collectAsStateWithLifecycle() val activity = LocalActivity.current @@ -99,12 +97,12 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { if (velocity in -70f..70f) return@let if (!state.value.showMenu) return@let if (state.value.lockMenu) return@let - if (!mainState.value.hideBarsOnFastScroll) return@let + if (!settings.hideBarsOnFastScroll.lastValue) return@let screenModel.onEvent( ReaderEvent.OnMenuVisibility( show = false, - fullscreenMode = mainState.value.fullscreen, + fullscreenMode = settings.fullscreen.lastValue, saveCheckpoint = false, activity = activity ) @@ -116,13 +114,6 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { } } - val fontFamily = remember(mainState.value.fontFamily) { - ReaderData.fonts.run { - find { - it.id == mainState.value.fontFamily - } ?: get(0) - } - } val backgroundColor = animateColorAsState( targetValue = settingsState.value.selectedColorPreset.backgroundColor ) @@ -130,89 +121,87 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { targetValue = settingsState.value.selectedColorPreset.fontColor ) val lineHeight = remember( - mainState.value.fontSize, - mainState.value.lineHeight + settings.fontSize.value, + settings.lineHeight.value ) { - (mainState.value.fontSize + mainState.value.lineHeight).sp + (settings.fontSize.lastValue + settings.lineHeight.lastValue).sp } - val letterSpacing = remember(mainState.value.letterSpacing) { - (mainState.value.letterSpacing / 100f).em + val letterSpacing = remember(settings.letterSpacing.value) { + (settings.letterSpacing.lastValue / 100f).em } - val sidePadding = remember(mainState.value.sidePadding) { - (mainState.value.sidePadding * 3).dp + val sidePadding = remember(settings.sidePadding.value) { + (settings.sidePadding.lastValue * 3).dp } - val verticalPadding = remember(mainState.value.verticalPadding) { - (mainState.value.verticalPadding * 4.5f).dp + val verticalPadding = remember(settings.verticalPadding.value) { + (settings.verticalPadding.lastValue * 4.5f).dp } val paragraphHeight = remember( - mainState.value.paragraphHeight, - mainState.value.lineHeight + settings.paragraphHeight.value, + settings.lineHeight.value ) { - ((mainState.value.paragraphHeight * 3).dp).coerceAtLeast( - with(density) { mainState.value.lineHeight.sp.toDp().value * 0.5f }.dp + ((settings.paragraphHeight.lastValue * 3).dp).coerceAtLeast( + with(density) { settings.lineHeight.lastValue.sp.toDp().value * 0.5f }.dp ) } - val fontStyle = remember(mainState.value.isItalic) { - when (mainState.value.isItalic) { + val fontStyle = remember(settings.italic.value) { + when (settings.italic.lastValue) { true -> FontStyle.Italic false -> FontStyle.Normal } } val paragraphIndentation = remember( - mainState.value.paragraphIndentation, - mainState.value.textAlignment + settings.paragraphIndentation.value, + settings.textAlignment.value ) { if ( - mainState.value.textAlignment == ReaderTextAlignment.CENTER || - mainState.value.textAlignment == ReaderTextAlignment.END - ) { - return@remember 0.sp - } - (mainState.value.paragraphIndentation * 6).sp + settings.textAlignment.lastValue == ReaderTextAlignment.CENTER || + settings.textAlignment.lastValue == ReaderTextAlignment.END + ) return@remember 0.sp + (settings.paragraphIndentation.lastValue * 6).sp } val perceptionExpanderPadding = remember( sidePadding, - mainState.value.perceptionExpanderPadding + settings.perceptionExpanderPadding.value ) { - sidePadding + (mainState.value.perceptionExpanderPadding * 8).dp + sidePadding + (settings.perceptionExpanderPadding.lastValue * 8).dp } val perceptionExpanderThickness = remember( - mainState.value.perceptionExpanderThickness + settings.perceptionExpanderThickness.value ) { - (mainState.value.perceptionExpanderThickness * 0.25f).dp + (settings.perceptionExpanderThickness.lastValue * 0.25f).dp } - val horizontalGestureSensitivity = remember(mainState.value.horizontalGestureSensitivity) { - (36f + mainState.value.horizontalGestureSensitivity * (4f - 36f)).dp + val horizontalGestureSensitivity = remember(settings.horizontalGestureSensitivity.value) { + (36f + settings.horizontalGestureSensitivity.lastValue * (4f - 36f)).dp } - val highlightedReadingThickness = remember(mainState.value.highlightedReadingThickness) { - when (mainState.value.highlightedReadingThickness) { + val highlightedReadingThickness = remember(settings.highlightedReadingThickness.value) { + when (settings.highlightedReadingThickness.lastValue) { 2 -> FontWeight.SemiBold 3 -> FontWeight.Bold else -> FontWeight.Medium } } - val horizontalAlignment = remember(mainState.value.textAlignment) { - when (mainState.value.textAlignment) { + val horizontalAlignment = remember(settings.textAlignment.value) { + when (settings.textAlignment.lastValue) { ReaderTextAlignment.START, ReaderTextAlignment.JUSTIFY -> Alignment.Start ReaderTextAlignment.CENTER -> Alignment.CenterHorizontally ReaderTextAlignment.END -> Alignment.End } } - val imagesWidth = remember(mainState.value.imagesWidth) { - mainState.value.imagesWidth.coerceAtLeast(0.01f) + val imagesWidth = remember(settings.imagesWidth.value) { + settings.imagesWidth.lastValue.coerceAtLeast(0.01f) } val imagesCornersRoundness = remember( - mainState.value.imagesCornersRoundness, - mainState.value.imagesWidth + settings.imagesCornersRoundness.value, + settings.imagesWidth.value ) { - (mainState.value.imagesCornersRoundness * 3 * imagesWidth).dp + (settings.imagesCornersRoundness.lastValue * 3 * imagesWidth).dp } val imagesColorEffects = remember( - mainState.value.imagesColorEffects, + settings.imagesColorEffects.value, fontColor.value, backgroundColor.value ) { - when (mainState.value.imagesColorEffects) { + when (settings.imagesColorEffects.lastValue) { ReaderColorEffects.OFF -> null ReaderColorEffects.GRAYSCALE -> ColorFilter.colorMatrix( @@ -230,21 +219,21 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { ) } } - val progressBarPadding = remember(mainState.value.progressBarPadding) { - (mainState.value.progressBarPadding * 3).dp + val progressBarPadding = remember(settings.progressBarPadding.value) { + (settings.progressBarPadding.lastValue * 3).dp } - val progressBarFontSize = remember(mainState.value.progressBarFontSize) { - (mainState.value.progressBarFontSize * 2).sp + val progressBarFontSize = remember(settings.progressBarFontSize.value) { + (settings.progressBarFontSize.lastValue * 2).sp } val layoutDirection = LocalLayoutDirection.current val cutoutInsets = WindowInsets.displayCutout val systemBarsInsets = WindowInsets.systemBarsIgnoringVisibility - val cutoutInsetsPadding = remember(mainState.value.cutoutPadding) { + val cutoutInsetsPadding = remember(settings.cutoutPadding.value) { derivedStateOf { cutoutInsets.asPaddingValues(density = density).run { - if (mainState.value.cutoutPadding) PaddingValues( + if (settings.cutoutPadding.lastValue) PaddingValues( top = calculateTopPadding(), start = calculateStartPadding(layoutDirection), end = calculateEndPadding(layoutDirection), @@ -253,10 +242,10 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { } } } - val systemBarsInsetsPadding = remember(mainState.value.fullscreen) { + val systemBarsInsetsPadding = remember(settings.fullscreen.value) { derivedStateOf { systemBarsInsets.asPaddingValues(density = density).run { - if (!mainState.value.fullscreen) PaddingValues( + if (!settings.fullscreen.lastValue) PaddingValues( top = calculateTopPadding(), start = calculateStartPadding(layoutDirection), end = calculateEndPadding(layoutDirection), @@ -292,16 +281,16 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { } ) } - val bottomBarPadding = remember(mainState.value.bottomBarPadding) { - (mainState.value.bottomBarPadding * 4f).dp + val bottomBarPadding = remember(settings.bottomBarPadding.value) { + (settings.bottomBarPadding.lastValue * 4f).dp } val bookProgress = remember( state.value.book.progress, state.value.text, - mainState.value.progressCount + settings.progressCount.value ) { - when (mainState.value.progressCount) { + when (settings.progressCount.lastValue) { ReaderProgressCount.PERCENTAGE -> { "${state.value.book.progress.calculateProgress(2)}%" } @@ -318,10 +307,10 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { state.value.book.progress, state.value.currentChapter, state.value.currentChapterProgress, - mainState.value.progressCount + settings.progressCount.value ) { if (state.value.currentChapter == null) return@remember "" - when (mainState.value.progressCount) { + when (settings.progressCount.lastValue) { ReaderProgressCount.PERCENTAGE -> { " (${state.value.currentChapterProgress.calculateProgress(2)}%)" } @@ -341,18 +330,18 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { LaunchedEffect(Unit) { screenModel.init( bookId = bookId, - fullscreenMode = mainState.value.fullscreen, + fullscreenMode = settings.fullscreen.lastValue, activity = activity, navigateBack = { navigator.pop() } ) } - LaunchedEffect(mainState.value.fullscreen) { + LaunchedEffect(settings.fullscreen.value) { screenModel.onEvent( ReaderEvent.OnMenuVisibility( show = state.value.showMenu, - fullscreenMode = mainState.value.fullscreen, + fullscreenMode = settings.fullscreen.lastValue, saveCheckpoint = false, activity = activity ) @@ -362,18 +351,18 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { screenModel.updateProgress(listState) } - DisposableEffect(mainState.value.screenOrientation) { - activity.requestedOrientation = mainState.value.screenOrientation.code + DisposableEffect(settings.screenOrientation.value) { + activity.requestedOrientation = settings.screenOrientation.lastValue.code onDispose { activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } } DisposableEffect( - mainState.value.screenBrightness, - mainState.value.customScreenBrightness + settings.screenBrightness.value, + settings.customScreenBrightness.value ) { - when (mainState.value.customScreenBrightness) { - true -> activity.setBrightness(brightness = mainState.value.screenBrightness) + when (settings.customScreenBrightness.lastValue) { + true -> activity.setBrightness(brightness = settings.screenBrightness.lastValue) false -> activity.setBrightness(brightness = null) } @@ -381,8 +370,8 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { activity.setBrightness(brightness = null) } } - DisposableEffect(mainState.value.keepScreenOn) { - when (mainState.value.keepScreenOn) { + DisposableEffect(settings.keepScreenOn.value) { + when (settings.keepScreenOn.lastValue) { true -> activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) false -> activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } @@ -409,8 +398,8 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { listState = listState, currentChapter = state.value.currentChapter, nestedScrollConnection = nestedScrollConnection.value, - fastColorPresetChange = mainState.value.fastColorPresetChange, - perceptionExpander = mainState.value.perceptionExpander, + fastColorPresetChange = settings.fastColorPresetChange.value, + perceptionExpander = settings.perceptionExpander.value, perceptionExpanderPadding = perceptionExpanderPadding, perceptionExpanderThickness = perceptionExpanderThickness, currentChapterProgress = state.value.currentChapterProgress, @@ -421,41 +410,41 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable { lockMenu = state.value.lockMenu, contentPadding = contentPadding, verticalPadding = verticalPadding, - horizontalGesture = mainState.value.horizontalGesture, - horizontalGestureScroll = mainState.value.horizontalGestureScroll, + horizontalGesture = settings.horizontalGesture.value, + horizontalGestureScroll = settings.horizontalGestureScroll.value, horizontalGestureSensitivity = horizontalGestureSensitivity, - horizontalGestureAlphaAnim = mainState.value.horizontalGestureAlphaAnim, - horizontalGesturePullAnim = mainState.value.horizontalGesturePullAnim, - highlightedReading = mainState.value.highlightedReading, + horizontalGestureAlphaAnim = settings.horizontalGestureAlphaAnim.value, + horizontalGesturePullAnim = settings.horizontalGesturePullAnim.value, + highlightedReading = settings.highlightedReading.value, highlightedReadingThickness = highlightedReadingThickness, progress = progress, - progressBar = mainState.value.progressBar, + progressBar = settings.progressBar.value, progressBarPadding = progressBarPadding, - progressBarAlignment = mainState.value.progressBarAlignment, + progressBarAlignment = settings.progressBarAlignment.value, progressBarFontSize = progressBarFontSize, paragraphHeight = paragraphHeight, sidePadding = sidePadding, bottomBarPadding = bottomBarPadding, backgroundColor = backgroundColor.value, fontColor = fontColor.value, - images = mainState.value.images, - imagesCaptions = mainState.value.imagesCaptions, + images = settings.images.value, + imagesCaptions = settings.imagesCaptions.value, imagesCornersRoundness = imagesCornersRoundness, - imagesAlignment = mainState.value.imagesAlignment, + imagesAlignment = settings.imagesAlignment.value, imagesWidth = imagesWidth, imagesColorEffects = imagesColorEffects, - fontFamily = fontFamily, + fontFamily = settings.fontFamily.value, lineHeight = lineHeight, - fontThickness = mainState.value.fontThickness, + fontThickness = settings.fontThickness.value, fontStyle = fontStyle, - chapterTitleAlignment = mainState.value.chapterTitleAlignment, - textAlignment = mainState.value.textAlignment, + chapterTitleAlignment = settings.chapterTitleAlignment.value, + textAlignment = settings.textAlignment.value, horizontalAlignment = horizontalAlignment, - fontSize = mainState.value.fontSize.sp, + fontSize = settings.fontSize.value.sp, letterSpacing = letterSpacing, paragraphIndentation = paragraphIndentation, - doubleClickTranslation = mainState.value.doubleClickTranslation, - fullscreenMode = mainState.value.fullscreen, + doubleClickTranslation = settings.doubleClickTranslation.value, + fullscreenMode = settings.fullscreen.value, selectPreviousPreset = settingsModel::onEvent, selectNextPreset = settingsModel::onEvent, leave = screenModel::onEvent, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsEvent.kt index d1d64ebb..698d845f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsEvent.kt @@ -16,6 +16,10 @@ import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder @Immutable sealed class SettingsEvent { + data class OnUpdateLanguage( + val language: String + ) : SettingsEvent() + data class OnGrantPersistableUriPermission( val uri: Uri ) : SettingsEvent() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsModel.kt index d0c44173..de486166 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/settings/SettingsModel.kt @@ -36,12 +36,14 @@ import ua.acclorite.book_story.domain.use_case.color_preset.SelectColorPresetUse import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPresetUseCase import ua.acclorite.book_story.domain.use_case.permission.GrantPersistableUriPermissionUseCase import ua.acclorite.book_story.domain.use_case.permission.ReleasePersistableUriPermissionUseCase +import ua.acclorite.book_story.domain.use_case.settings.UpdateLanguageUseCase import ua.acclorite.book_story.ui.common.helpers.showToast import javax.inject.Inject import kotlin.random.Random @HiltViewModel class SettingsModel @Inject constructor( + private val updateLanguageUseCase: UpdateLanguageUseCase, private val getColorPresetsUseCase: GetColorPresetsUseCase, private val updateColorPresetUseCase: UpdateColorPresetUseCase, private val selectColorPresetUseCase: SelectColorPresetUseCase, @@ -112,6 +114,8 @@ class SettingsModel @Inject constructor( fun onEvent(event: SettingsEvent) { when (event) { + is SettingsEvent.OnUpdateLanguage -> updateLanguageUseCase(event.language) + is SettingsEvent.OnGrantPersistableUriPermission -> { viewModelScope.launch { grantPersistableUriPermissionUseCase( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/start/StartScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/start/StartScreen.kt index 061bcc4d..5e171b25 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/start/StartScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/start/StartScreen.kt @@ -14,17 +14,17 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.text.TextStyle import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import ua.acclorite.book_story.core.data.CoreData import ua.acclorite.book_story.presentation.browse.BrowseScreen import ua.acclorite.book_story.presentation.help.HelpScreen -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.navigator.Screen import ua.acclorite.book_story.presentation.navigator.StackEvent +import ua.acclorite.book_story.presentation.settings.SettingsEvent +import ua.acclorite.book_story.presentation.settings.SettingsModel import ua.acclorite.book_story.ui.common.helpers.LocalActivity +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.navigator.LocalNavigator import ua.acclorite.book_story.ui.start.StartContent @@ -51,22 +51,20 @@ object StartScreen : Screen, Parcelable { @Composable override fun Content() { val navigator = LocalNavigator.current - val mainModel = hiltViewModel() - - val mainState = mainModel.state.collectAsStateWithLifecycle() - + val settingsModel = hiltViewModel() + val settings = LocalSettings.current val activity = LocalActivity.current val currentPage = remember { mutableIntStateOf(0) } val stackEvent = remember { mutableStateOf(StackEvent.Default) } - val languages = remember(mainState.value.language) { + val languages = remember(settings.language.value) { CoreData.languages.sortedBy { it.second }.map { ButtonItem( id = it.first, title = it.second, textStyle = TextStyle(), - selected = it.first == mainState.value.language + selected = it.first == settings.language.lastValue ) }.sortedBy { it.title } } @@ -75,7 +73,7 @@ object StartScreen : Screen, Parcelable { currentPage = currentPage.intValue, stackEvent = stackEvent.value, languages = languages, - changeLanguage = mainModel::onEvent, + updateLanguage = { settingsModel.onEvent(SettingsEvent.OnUpdateLanguage(it)) }, navigateForward = { if (currentPage.intValue + 1 == 4) { return@StartContent @@ -98,7 +96,7 @@ object StartScreen : Screen, Parcelable { saveInBackStack = false ) BrowseScreen.refreshListChannel.trySend(Unit) - mainModel.onEvent(MainEvent.OnChangeShowStartScreen(false)) + settings.showStartScreen.update(false) }, navigateToHelp = { navigator.push( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseContent.kt index 580dbcf4..b4a0097e 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseContent.kt @@ -18,7 +18,6 @@ import ua.acclorite.book_story.presentation.browse.BrowseEvent import ua.acclorite.book_story.presentation.browse.model.BrowseLayout import ua.acclorite.book_story.presentation.browse.model.SelectableFile import ua.acclorite.book_story.presentation.library.model.SelectableNullableBook -import ua.acclorite.book_story.presentation.main.MainEvent @OptIn(ExperimentalMaterialApi::class) @Composable @@ -60,7 +59,7 @@ fun BrowseContent( dismissAddDialog: (BrowseEvent.OnDismissAddDialog) -> Unit, actionAddDialog: (BrowseEvent.OnActionAddDialog) -> Unit, selectAddDialog: (BrowseEvent.OnSelectAddDialog) -> Unit, - changePinnedPaths: (MainEvent.OnChangeBrowsePinnedPaths) -> Unit, + updatePinnedPaths: (String) -> Unit, navigateToLibrary: () -> Unit, navigateToBrowseSettings: () -> Unit, ) { @@ -109,7 +108,7 @@ fun BrowseContent( selectFile = selectFile, showFilterBottomSheet = showFilterBottomSheet, showAddDialog = showAddDialog, - changePinnedPaths = changePinnedPaths, + updatePinnedPaths = updatePinnedPaths, navigateToBrowseSettings = navigateToBrowseSettings ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseScaffold.kt b/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseScaffold.kt index aa7ae5a2..cd49a9fc 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseScaffold.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/browse/BrowseScaffold.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.presentation.browse.BrowseEvent import ua.acclorite.book_story.presentation.browse.model.BrowseLayout import ua.acclorite.book_story.presentation.browse.model.SelectableFile -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.ui.theme.DefaultTransition @OptIn(ExperimentalMaterialApi::class) @@ -57,7 +56,7 @@ fun BrowseScaffold( selectFile: (BrowseEvent.OnSelectFile) -> Unit, showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit, showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit, - changePinnedPaths: (MainEvent.OnChangeBrowsePinnedPaths) -> Unit, + updatePinnedPaths: (String) -> Unit, navigateToBrowseSettings: () -> Unit, ) { Scaffold( @@ -107,11 +106,7 @@ fun BrowseScaffold( header = header, pinned = pinned, pin = { - changePinnedPaths( - MainEvent.OnChangeBrowsePinnedPaths( - value = header - ) - ) + updatePinnedPaths(header) } ) }, diff --git a/app/src/main/java/ua/acclorite/book_story/ui/common/helpers/SettingsHelpers.kt b/app/src/main/java/ua/acclorite/book_story/ui/common/helpers/SettingsHelpers.kt new file mode 100644 index 00000000..31411d75 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/ui/common/helpers/SettingsHelpers.kt @@ -0,0 +1,23 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.ui.common.helpers + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.staticCompositionLocalOf +import ua.acclorite.book_story.data.settings.SettingsManager + +val LocalSettings = staticCompositionLocalOf { + error("No settings provided") +} + +@Composable +fun ProvideSettings(settings: SettingsManager, content: @Composable () -> Unit) { + CompositionLocalProvider(LocalSettings provides settings) { + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpBottomBar.kt b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpBottomBar.kt index 127f3b60..7ef7789c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpBottomBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpBottomBar.kt @@ -6,10 +6,7 @@ package ua.acclorite.book_story.ui.help -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button @@ -19,29 +16,25 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.browse.BrowseScreen -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.ui.common.components.common.StyledText @Composable fun HelpBottomBar( - changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit, + changeShowStartScreen: (Boolean) -> Unit, navigateToBrowse: () -> Unit ) { - Column(Modifier.fillMaxWidth()) { - Spacer(modifier = Modifier.height(18.dp)) - Button( - modifier = Modifier - .navigationBarsPadding() - .padding(bottom = 8.dp) - .padding(horizontal = 18.dp) - .fillMaxWidth(), - onClick = { - BrowseScreen.refreshListChannel.trySend(Unit) - changeShowStartScreen(MainEvent.OnChangeShowStartScreen(false)) - navigateToBrowse() - } - ) { - StyledText(text = stringResource(id = R.string.done)) + Button( + modifier = Modifier + .navigationBarsPadding() + .padding(top = 18.dp, bottom = 8.dp) + .padding(horizontal = 18.dp) + .fillMaxWidth(), + onClick = { + BrowseScreen.refreshListChannel.trySend(Unit) + changeShowStartScreen(false) + navigateToBrowse() } + ) { + StyledText(text = stringResource(id = R.string.done)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpContent.kt index 3fea2274..7e661bc1 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpContent.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable -import ua.acclorite.book_story.presentation.main.MainEvent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -18,7 +17,7 @@ fun HelpContent( fromStart: Boolean, scrollBehavior: TopAppBarScrollBehavior, listState: LazyListState, - changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit, + changeShowStartScreen: (Boolean) -> Unit, navigateToBrowse: () -> Unit, navigateToStart: () -> Unit, navigateBack: () -> Unit diff --git a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpScaffold.kt b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpScaffold.kt index 80d54161..dbbfb7e3 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/help/HelpScaffold.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/help/HelpScaffold.kt @@ -18,7 +18,6 @@ import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll -import ua.acclorite.book_story.presentation.main.MainEvent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -26,7 +25,7 @@ fun HelpScaffold( fromStart: Boolean, listState: LazyListState, scrollBehavior: TopAppBarScrollBehavior, - changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit, + changeShowStartScreen: (Boolean) -> Unit, navigateToBrowse: () -> Unit, navigateToStart: () -> Unit, navigateBack: () -> Unit diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryBottomSheet.kt index 267fb02e..083ee4a8 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryBottomSheet.kt @@ -14,7 +14,6 @@ import ua.acclorite.book_story.domain.model.library.CategorySort import ua.acclorite.book_story.presentation.library.LibraryEvent import ua.acclorite.book_story.presentation.library.LibraryScreen import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.presentation.settings.SettingsEvent @Composable @@ -27,8 +26,8 @@ fun LibraryBottomSheet( sortOrder: LibrarySortOrder, sortOrderDescending: Boolean, perCategorySort: Boolean, - changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit, - changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit, + changeSortOrder: (LibrarySortOrder) -> Unit, + changeSortOrderDescending: (Boolean) -> Unit, updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit, dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit ) { @@ -42,8 +41,8 @@ fun LibraryBottomSheet( sortOrderDescending = sortOrderDescending, categoriesSort = categoriesSort, perCategorySort = perCategorySort, - changeLibrarySortOrder = changeLibrarySortOrder, - changeLibrarySortOrderDescending = changeLibrarySortOrderDescending, + changeSortOrder = changeSortOrder, + changeSortOrderDescending = changeSortOrderDescending, updateCategorySort = updateCategorySort, dismissBottomSheet = dismissBottomSheet ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt index 9c53f569..bae81a4b 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt @@ -20,7 +20,6 @@ import ua.acclorite.book_story.presentation.library.model.LibraryLayout import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition import ua.acclorite.book_story.presentation.library.model.SelectableBook -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.presentation.settings.SettingsEvent @OptIn(ExperimentalMaterialApi::class) @@ -55,8 +54,8 @@ fun LibraryContent( dialog: Dialog?, bottomSheet: BottomSheet?, updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit, - changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit, - changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit, + changeSortOrder: (LibrarySortOrder) -> Unit, + changeSortOrderDescending: (Boolean) -> Unit, selectBook: (LibraryEvent.OnSelectBook) -> Unit, searchVisibility: (LibraryEvent.OnSearchVisibility) -> Unit, requestFocus: (LibraryEvent.OnRequestFocus) -> Unit, @@ -95,8 +94,8 @@ fun LibraryContent( sortOrder = sortOrder, sortOrderDescending = sortOrderDescending, perCategorySort = perCategorySort, - changeLibrarySortOrder = changeLibrarySortOrder, - changeLibrarySortOrderDescending = changeLibrarySortOrderDescending, + changeSortOrder = changeSortOrder, + changeSortOrderDescending = changeSortOrderDescending, updateCategorySort = updateCategorySort, dismissBottomSheet = dismissBottomSheet ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryFilterBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryFilterBottomSheet.kt index 371fa6a8..fccb760b 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryFilterBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryFilterBottomSheet.kt @@ -26,7 +26,6 @@ import ua.acclorite.book_story.domain.model.library.Category import ua.acclorite.book_story.domain.model.library.CategorySort import ua.acclorite.book_story.presentation.library.LibraryEvent import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.presentation.settings.SettingsEvent import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar import ua.acclorite.book_story.ui.common.components.modal_bottom_sheet.ModalBottomSheet @@ -45,8 +44,8 @@ fun LibraryFilterBottomSheet( sortOrderDescending: Boolean, categoriesSort: List, perCategorySort: Boolean, - changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit, - changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit, + changeSortOrder: (LibrarySortOrder) -> Unit, + changeSortOrderDescending: (Boolean) -> Unit, updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit, dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit ) { @@ -123,16 +122,8 @@ fun LibraryFilterBottomSheet( ) ) } else { - changeLibrarySortOrder( - MainEvent.OnChangeLibrarySortOrder( - sortOrder.name - ) - ) - changeLibrarySortOrderDescending( - MainEvent.OnChangeLibrarySortOrderDescending( - sortOrderDescending - ) - ) + changeSortOrder(sortOrder) + changeSortOrderDescending(sortOrderDescending) } } ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderContent.kt index 534b2211..002ecf78 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderContent.kt @@ -24,7 +24,6 @@ import ua.acclorite.book_story.core.ui.UIText import ua.acclorite.book_story.domain.model.library.Book import ua.acclorite.book_story.domain.model.reader.ReaderText import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.presentation.reader.ReaderEvent import ua.acclorite.book_story.presentation.reader.model.Checkpoint import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness @@ -32,6 +31,7 @@ import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.presentation.settings.SettingsEvent import ua.acclorite.book_story.ui.reader.model.FontWithName +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun ReaderContent( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayout.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayout.kt index e7b88697..f254328b 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayout.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayout.kt @@ -34,7 +34,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.reader.ReaderText -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.presentation.reader.ReaderEvent import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture @@ -47,6 +46,7 @@ import ua.acclorite.book_story.ui.common.helpers.LocalActivity import ua.acclorite.book_story.ui.common.helpers.noRippleClickable import ua.acclorite.book_story.ui.common.helpers.showToast import ua.acclorite.book_story.ui.reader.model.FontWithName +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun ReaderLayout( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutText.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutText.kt index 07a71e94..f267a7a8 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutText.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutText.kt @@ -17,11 +17,11 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit import ua.acclorite.book_story.domain.model.reader.ReaderText -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.presentation.reader.ReaderEvent import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.ui.reader.model.FontWithName +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun LazyItemScope.ReaderLayoutText( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutTextImage.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutTextImage.kt index 1775fbcc..a32f4b0f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutTextImage.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderLayoutTextImage.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.Dp import ua.acclorite.book_story.domain.model.reader.ReaderText -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun LazyItemScope.ReaderLayoutTextImage( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderProgressBar.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderProgressBar.kt index 2c4ea75b..1f8b0ea6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderProgressBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderProgressBar.kt @@ -16,8 +16,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.ui.common.components.common.StyledText +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun ReaderProgressBar( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderScaffold.kt b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderScaffold.kt index 3dc9eed7..6cb4ccfe 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderScaffold.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/reader/ReaderScaffold.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.unit.TextUnit import ua.acclorite.book_story.domain.model.library.Book import ua.acclorite.book_story.domain.model.reader.ReaderText import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.presentation.reader.ReaderEvent import ua.acclorite.book_story.presentation.reader.model.Checkpoint import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness @@ -38,6 +37,7 @@ import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.presentation.settings.SettingsEvent import ua.acclorite.book_story.ui.common.components.common.AnimatedVisibility import ua.acclorite.book_story.ui.reader.model.FontWithName +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/colors/components/FastColorPresetChangeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/colors/components/FastColorPresetChangeOption.kt index 8f57b8ac..4378087b 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/colors/components/FastColorPresetChangeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/colors/components/FastColorPresetChangeOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.appearance.colors.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun FastColorPresetChangeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.fastColorPresetChange, + selected = settings.fastColorPresetChange.value, title = stringResource(id = R.string.fast_color_preset_change_option), description = stringResource(id = R.string.fast_color_preset_change_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeFastColorPresetChange( - !state.value.fastColorPresetChange - ) - ) + settings.fastColorPresetChange.update(!settings.fastColorPresetChange.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AbsoluteDarkOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AbsoluteDarkOption.kt index 4123d93e..42e9da39 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AbsoluteDarkOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AbsoluteDarkOption.kt @@ -9,36 +9,26 @@ package ua.acclorite.book_story.ui.settings.appearance.theme_preferences.compone import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.isDark -import ua.acclorite.book_story.presentation.main.model.isPureDark import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun AbsoluteDarkOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current val context = LocalContext.current ExpandingTransition( - visible = state.value.pureDark.isPureDark(context) - && state.value.darkTheme.isDark() + visible = settings.pureDark.value.isPureDark(context) + && settings.darkTheme.value.isDark() ) { SwitchWithTitle( - selected = state.value.absoluteDark, + selected = settings.absoluteDark.value, title = stringResource(id = R.string.absolute_dark_option), description = stringResource(id = R.string.absolute_dark_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeAbsoluteDark( - !state.value.absoluteDark - ) - ) + settings.absoluteDark.update(!settings.absoluteDark.lastValue) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AppThemeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AppThemeOption.kt index b5f25c61..2c426a29 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AppThemeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/AppThemeOption.kt @@ -39,24 +39,18 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.ThemeContrast -import ua.acclorite.book_story.presentation.main.model.isDark -import ua.acclorite.book_story.presentation.main.model.isPureDark import ua.acclorite.book_story.ui.common.components.common.AnimatedVisibility import ua.acclorite.book_story.ui.common.components.common.StyledText +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle -import ua.acclorite.book_story.ui.theme.Theme import ua.acclorite.book_story.ui.theme.animatedColorScheme +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast @Composable fun AppThemeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current Column( Modifier @@ -76,15 +70,15 @@ fun AppThemeOption() { items( Theme.entries(), key = { theme -> theme.name } - ) { theme -> + ) { themeEntry -> AppThemeOptionItem( - theme = theme, - darkTheme = state.value.darkTheme.isDark(), - themeContrast = state.value.themeContrast, - isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current), - selected = state.value.theme == theme + theme = themeEntry, + darkTheme = settings.darkTheme.value.isDark(), + themeContrast = settings.themeContrast.value, + isPureDark = settings.pureDark.value.isPureDark(context = LocalContext.current), + selected = settings.theme.value == themeEntry ) { - mainModel.onEvent(MainEvent.OnChangeTheme(theme.name)) + settings.theme.update(themeEntry) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/DarkThemeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/DarkThemeOption.kt index d8bd17c5..ed222dde 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/DarkThemeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/DarkThemeOption.kt @@ -9,35 +9,31 @@ package ua.acclorite.book_story.ui.settings.appearance.theme_preferences.compone import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.DarkTheme import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem +import ua.acclorite.book_story.ui.theme.model.DarkTheme @Composable fun DarkThemeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.dark_theme_option), buttons = DarkTheme.entries.map { ButtonItem( - it.toString(), + it.name, title = when (it) { DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off) DarkTheme.ON -> stringResource(id = R.string.dark_theme_on) DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.darkTheme + selected = it == settings.darkTheme.value ) } ) { - mainModel.onEvent(MainEvent.OnChangeDarkTheme(it.id)) + settings.darkTheme.update(DarkTheme.valueOf(it.id)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/PureDarkOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/PureDarkOption.kt index d081007f..74bf3627 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/PureDarkOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/PureDarkOption.kt @@ -9,23 +9,18 @@ package ua.acclorite.book_story.ui.settings.appearance.theme_preferences.compone import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.PureDark -import ua.acclorite.book_story.presentation.main.model.isDark import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.ExpandingTransition +import ua.acclorite.book_story.ui.theme.model.PureDark @Composable fun PureDarkOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.darkTheme.isDark()) { + ExpandingTransition(visible = settings.darkTheme.value.isDark()) { SegmentedButtonWithTitle( title = stringResource(id = R.string.pure_dark_option), buttons = PureDark.entries.map { @@ -37,15 +32,11 @@ fun PureDarkOption() { PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.pureDark + selected = it == settings.pureDark.value ) } ) { - mainModel.onEvent( - MainEvent.OnChangePureDark( - it.id - ) - ) + settings.pureDark.update(PureDark.valueOf(it.id)) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/ThemeContrastOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/ThemeContrastOption.kt index 39227bcf..939d4682 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/ThemeContrastOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/appearance/theme_preferences/components/ThemeContrastOption.kt @@ -13,41 +13,35 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.ThemeContrast -import ua.acclorite.book_story.presentation.main.model.isDark -import ua.acclorite.book_story.presentation.main.model.isPureDark import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.BookStoryTheme import ua.acclorite.book_story.ui.theme.ExpandingTransition +import ua.acclorite.book_story.ui.theme.model.ThemeContrast @Composable fun ThemeContrastOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - val themeContrastTheme = remember { mutableStateOf(state.value.theme) } - LaunchedEffect(state.value.theme) { - if (state.value.theme.hasThemeContrast) { - themeContrastTheme.value = state.value.theme + val themeContrastTheme = remember { mutableStateOf(settings.theme.lastValue) } + LaunchedEffect(settings.theme.value) { + if (settings.theme.lastValue.hasThemeContrast) { + themeContrastTheme.value = settings.theme.lastValue } } BookStoryTheme( theme = themeContrastTheme.value, - isDark = state.value.darkTheme.isDark(), - isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current), - themeContrast = state.value.themeContrast + isDark = settings.darkTheme.value.isDark(), + isPureDark = settings.pureDark.value.isPureDark(context = LocalContext.current), + themeContrast = settings.themeContrast.value ) { - ExpandingTransition(visible = state.value.theme.hasThemeContrast) { + ExpandingTransition(visible = settings.theme.value.hasThemeContrast) { SegmentedButtonWithTitle( title = stringResource(id = R.string.theme_contrast_option), - enabled = state.value.theme.hasThemeContrast, + enabled = settings.theme.value.hasThemeContrast, buttons = ThemeContrast.entries.map { ButtonItem( id = it.toString(), @@ -57,15 +51,11 @@ fun ThemeContrastOption() { ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.themeContrast + selected = it == settings.themeContrast.value ) } ) { - mainModel.onEvent( - MainEvent.OnChangeThemeContrast( - it.id - ) - ) + settings.themeContrast.update(ThemeContrast.valueOf(it.id)) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseGridSizeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseGridSizeOption.kt index a6d681e5..38aaf3dc 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseGridSizeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseGridSizeOption.kt @@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.browse.display.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.browse.model.BrowseLayout -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun BrowseGridSizeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) { + ExpandingTransition(visible = settings.browseLayout.value == BrowseLayout.GRID) { SliderWithTitle( - value = state.value.browseGridSize + value = settings.browseGridSize.value to " ${stringResource(R.string.grid_size_per_row)}", valuePlaceholder = stringResource(id = R.string.grid_size_auto), - showPlaceholder = state.value.browseAutoGridSize, + showPlaceholder = settings.browseAutoGridSize.value, fromValue = 0, toValue = 10, title = stringResource(id = R.string.grid_size_option), onValueChange = { - mainModel.onEvent(MainEvent.OnChangeBrowseAutoGridSize(it == 0)) - mainModel.onEvent( - MainEvent.OnChangeBrowseGridSize(it) - ) + settings.browseAutoGridSize.update(it == 0) + settings.browseGridSize.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseLayoutOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseLayoutOption.kt index 9d259da6..2eb8f63e 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseLayoutOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/display/components/BrowseLayoutOption.kt @@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.browse.display.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.browse.model.BrowseLayout -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun BrowseLayoutOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.layout_option), @@ -33,14 +29,10 @@ fun BrowseLayoutOption() { BrowseLayout.GRID -> stringResource(id = R.string.layout_grid) }, MaterialTheme.typography.labelLarge, - it == state.value.browseLayout + it == settings.browseLayout.value ) } ) { - mainModel.onEvent( - MainEvent.OnChangeBrowseLayout( - it.id - ) - ) + settings.browseLayout.update(BrowseLayout.valueOf(it.id)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/filter/components/BrowseFilterOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/filter/components/BrowseFilterOption.kt index 06bce028..ceeb9dc6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/filter/components/BrowseFilterOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/filter/components/BrowseFilterOption.kt @@ -23,26 +23,21 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.core.data.ExtensionsData -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel +import ua.acclorite.book_story.core.helpers.toggle import ua.acclorite.book_story.ui.common.components.common.StyledText +import ua.acclorite.book_story.ui.common.helpers.LocalSettings fun LazyListScope.BrowseFilterOption() { items(ExtensionsData.fileExtensions, key = { it }) { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current BrowseFilterOptionItem( item = it, - isSelected = state.value.browseIncludedFilterItems.any { item -> - item == it - } + isSelected = settings.browseIncludedFilterItems.value.any { item -> item == it } ) { - mainModel.onEvent( - MainEvent.OnChangeBrowseIncludedFilterItem(it) + settings.browseIncludedFilterItems.update( + settings.browseIncludedFilterItems.lastValue.toggle(it) ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/sort/components/BrowseSortOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/sort/components/BrowseSortOption.kt index a287548c..b0286070 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/sort/components/BrowseSortOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/browse/sort/components/BrowseSortOption.kt @@ -28,33 +28,25 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.common.StyledText +import ua.acclorite.book_story.ui.common.helpers.LocalSettings fun LazyListScope.BrowseSortOption() { items(BrowseSortOrder.entries, key = { it.name }) { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current BrowseSortOptionItem( item = it, - isSelected = state.value.browseSortOrder == it, - isDescending = state.value.browseSortOrderDescending + isSelected = settings.browseSortOrder.value == it, + isDescending = settings.browseSortOrderDescending.value ) { - if (state.value.browseSortOrder == it) { - mainModel.onEvent( - MainEvent.OnChangeBrowseSortOrderDescending( - !state.value.browseSortOrderDescending - ) - ) + if (settings.browseSortOrder.lastValue == it) { + settings.browseSortOrderDescending.update(!settings.browseSortOrderDescending.lastValue) } else { - mainModel.onEvent(MainEvent.OnChangeBrowseSortOrderDescending(true)) - mainModel.onEvent(MainEvent.OnChangeBrowseSortOrder(it.name)) + settings.browseSortOrderDescending.update(true) + settings.browseSortOrder.update(it) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/AppLanguageOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/AppLanguageOption.kt index f11df697..9bc21c7f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/AppLanguageOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/AppLanguageOption.kt @@ -10,18 +10,18 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.core.data.CoreData -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel +import ua.acclorite.book_story.presentation.settings.SettingsEvent +import ua.acclorite.book_story.presentation.settings.SettingsModel import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun AppLanguageOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settingsModel = hiltViewModel() + val settings = LocalSettings.current ChipsWithTitle( title = stringResource(id = R.string.language_option), @@ -30,10 +30,10 @@ fun AppLanguageOption() { it.first, it.second, MaterialTheme.typography.labelLarge, - it.first == state.value.language + it.first == settings.language.value ) - }.sortedBy { it.title } + } ) { - mainModel.onEvent(MainEvent.OnChangeLanguage(it.id)) + settingsModel.onEvent(SettingsEvent.OnUpdateLanguage(it.id)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/DoublePressExitOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/DoublePressExitOption.kt index 5a6dfbeb..8b9aba07 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/DoublePressExitOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/general/components/DoublePressExitOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.general.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun DoublePressExitOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.doublePressExit, + selected = settings.doublePressExit.value, title = stringResource(id = R.string.double_press_exit_option), description = stringResource(id = R.string.double_press_exit_option_desc) ) { - mainModel.onEvent( - MainEvent.OnChangeDoublePressExit( - !state.value.doublePressExit - ) - ) + settings.doublePressExit.update(!settings.doublePressExit.lastValue) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryGridSizeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryGridSizeOption.kt index 6a991b11..f34e004c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryGridSizeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryGridSizeOption.kt @@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.library.display.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.library.model.LibraryLayout -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun LibraryGridSizeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.libraryLayout == LibraryLayout.GRID) { + ExpandingTransition(visible = settings.libraryLayout.value == LibraryLayout.GRID) { SliderWithTitle( - value = state.value.libraryGridSize + value = settings.libraryGridSize.value to " ${stringResource(R.string.grid_size_per_row)}", valuePlaceholder = stringResource(id = R.string.grid_size_auto), - showPlaceholder = state.value.libraryAutoGridSize, + showPlaceholder = settings.libraryAutoGridSize.value, fromValue = 0, toValue = 10, title = stringResource(id = R.string.grid_size_option), onValueChange = { - mainModel.onEvent(MainEvent.OnChangeLibraryAutoGridSize(it == 0)) - mainModel.onEvent( - MainEvent.OnChangeLibraryGridSize(it) - ) + settings.libraryAutoGridSize.update(it == 0) + settings.libraryGridSize.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryLayoutOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryLayoutOption.kt index c2540783..79b44b8d 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryLayoutOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryLayoutOption.kt @@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.library.display.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.library.model.LibraryLayout -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun LibraryLayoutOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.layout_option), @@ -33,14 +29,10 @@ fun LibraryLayoutOption() { LibraryLayout.GRID -> stringResource(id = R.string.layout_grid) }, MaterialTheme.typography.labelLarge, - it == state.value.libraryLayout + it == settings.libraryLayout.value ) } ) { - mainModel.onEvent( - MainEvent.OnChangeLibraryLayout( - it.id - ) - ) + settings.libraryLayout.update(LibraryLayout.valueOf(it.id)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryReadButtonOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryReadButtonOption.kt index 5be090e3..60681bf0 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryReadButtonOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryReadButtonOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.display.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryReadButtonOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryReadButton, + selected = settings.libraryShowReadButton.value, title = stringResource(id = R.string.read_button_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryReadButton( - !state.value.libraryReadButton - ) - ) + settings.libraryShowReadButton.update(!settings.libraryShowReadButton.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryShowProgressOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryShowProgressOption.kt index 7ac29d8c..e9a0d1b3 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryShowProgressOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryShowProgressOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.display.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryShowProgressOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryShowProgress, + selected = settings.libraryShowProgress.value, title = stringResource(id = R.string.show_progress_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryShowProgress( - !state.value.libraryShowProgress - ) - ) + settings.libraryShowProgress.update(!settings.libraryShowProgress.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryTitlePositionOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryTitlePositionOption.kt index 1a8ab0ef..0ab3c17c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryTitlePositionOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/display/components/LibraryTitlePositionOption.kt @@ -9,51 +9,35 @@ package ua.acclorite.book_story.ui.settings.library.display.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.library.model.LibraryLayout import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun LibraryTitlePositionOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.libraryLayout == LibraryLayout.GRID) { + ExpandingTransition(visible = settings.libraryLayout.value == LibraryLayout.GRID) { ChipsWithTitle( title = stringResource(id = R.string.title_position_option), chips = LibraryTitlePosition.entries.map { ButtonItem( - it.toString(), + it.name, when (it) { - LibraryTitlePosition.OFF -> { - stringResource(id = R.string.library_title_position_off) - } - - LibraryTitlePosition.BELOW -> { - stringResource(id = R.string.library_title_position_below) - } - - LibraryTitlePosition.INSIDE -> { - stringResource(id = R.string.library_title_position_inside) - } + LibraryTitlePosition.OFF -> stringResource(id = R.string.library_title_position_off) + LibraryTitlePosition.BELOW -> stringResource(id = R.string.library_title_position_below) + LibraryTitlePosition.INSIDE -> stringResource(id = R.string.library_title_position_inside) }, MaterialTheme.typography.labelLarge, - it == state.value.libraryTitlePosition + it == settings.libraryTitlePosition.value ) } ) { - mainModel.onEvent( - MainEvent.OnChangeLibraryTitlePosition( - it.id - ) - ) + settings.libraryTitlePosition.update(LibraryTitlePosition.valueOf(it.id)) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/sort/components/LibraryPerCategorySortOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/sort/components/LibraryPerCategorySortOption.kt index adef17f3..b794fb98 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/sort/components/LibraryPerCategorySortOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/sort/components/LibraryPerCategorySortOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.sort.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryPerCategorySortOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryPerCategorySort, + selected = settings.libraryPerCategorySort.value, title = stringResource(id = R.string.per_category_sort_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryPerCategorySort( - !state.value.libraryPerCategorySort - ) - ) + settings.libraryPerCategorySort.update(!settings.libraryPerCategorySort.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryAlwaysShowDefaultTabOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryAlwaysShowDefaultTabOption.kt index 6b3af0f3..2b022088 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryAlwaysShowDefaultTabOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryAlwaysShowDefaultTabOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryAlwaysShowDefaultTabOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryAlwaysShowDefaultTab, + selected = settings.libraryShowDefaultTab.value, title = stringResource(id = R.string.always_show_default_tab_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryAlwaysShowDefaultTab( - !state.value.libraryAlwaysShowDefaultTab - ) - ) + settings.libraryShowDefaultTab.update(!settings.libraryShowDefaultTab.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowBookCountOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowBookCountOption.kt index d54d4c64..dfafe142 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowBookCountOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowBookCountOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryShowBookCountOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryShowBookCount, + selected = settings.libraryShowBookCount.value, title = stringResource(id = R.string.show_book_count_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryShowBookCount( - !state.value.libraryShowBookCount - ) - ) + settings.libraryShowBookCount.update(!settings.libraryShowBookCount.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowCategoryTabsOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowCategoryTabsOption.kt index 34a936a6..b24fef2d 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowCategoryTabsOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/library/tabs/components/LibraryShowCategoryTabsOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LibraryShowCategoryTabsOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.libraryShowCategoryTabs, + selected = settings.libraryShowCategoryTabs.value, title = stringResource(id = R.string.show_category_tabs_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeLibraryShowCategoryTabs( - !state.value.libraryShowCategoryTabs - ) - ) + settings.libraryShowCategoryTabs.update(!settings.libraryShowCategoryTabs.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/chapters/components/ChapterTitleAlignmentOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/chapters/components/ChapterTitleAlignmentOption.kt index 5993e681..933a30ab 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/chapters/components/ChapterTitleAlignmentOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/chapters/components/ChapterTitleAlignmentOption.kt @@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.reader.chapters.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun ChapterTitleAlignmentOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.chapter_title_alignment_option), @@ -35,15 +31,11 @@ fun ChapterTitleAlignmentOption() { ReaderTextAlignment.END -> stringResource(id = R.string.alignment_end) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.chapterTitleAlignment + selected = it == settings.chapterTitleAlignment.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeChapterTitleAlignment( - it.id - ) - ) + settings.chapterTitleAlignment.update(ReaderTextAlignment.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontFamilyOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontFamilyOption.kt index a8fd10cf..5237dd68 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontFamilyOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontFamilyOption.kt @@ -8,48 +8,33 @@ package ua.acclorite.book_story.ui.settings.reader.font.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.reader.data.ReaderData @Composable fun FontFamilyOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() - - val fontFamily = remember(state.value.fontFamily) { - ReaderData.fonts.run { - find { - it.id == state.value.fontFamily - } ?: get(0) - } - } + val settings = LocalSettings.current ChipsWithTitle( title = stringResource(id = R.string.font_family_option), - chips = ReaderData.fonts - .map { - ButtonItem( - id = it.id, - title = it.fontName.asString(), - textStyle = MaterialTheme.typography.labelLarge.copy( - fontFamily = it.font - ), - selected = it.id == fontFamily.id - ) - }, + chips = ReaderData.fonts.map { + ButtonItem( + id = it.id, + title = it.fontName.asString(), + textStyle = MaterialTheme.typography.labelLarge.copy( + fontFamily = it.font + ), + selected = it == settings.fontFamily.value + ) + }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeFontFamily( - it.id - ) + settings.fontFamily.update( + ReaderData.fonts.find { font -> font.id == it.id } + ?: ReaderData.fonts[0] ) } ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontSizeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontSizeOption.kt index 67bc5432..3f53ba41 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontSizeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontSizeOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.font.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun FontSizeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.fontSize to "pt", + value = settings.fontSize.value to "pt", fromValue = 10, toValue = 35, title = stringResource(id = R.string.font_size_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeFontSize(it) - ) + settings.fontSize.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontStyleOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontStyleOption.kt index 158013ca..c4da815c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontStyleOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontStyleOption.kt @@ -8,30 +8,16 @@ package ua.acclorite.book_story.ui.settings.reader.font.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem -import ua.acclorite.book_story.ui.reader.data.ReaderData @Composable fun FontStyleOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() - - val fontFamily = remember(state.value.fontFamily) { - ReaderData.fonts.run { - find { - it.id == state.value.fontFamily - } ?: get(0) - } - } + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.font_style_option), @@ -40,29 +26,27 @@ fun FontStyleOption() { id = "normal", title = stringResource(id = R.string.font_style_normal), textStyle = MaterialTheme.typography.labelLarge.copy( - fontFamily = fontFamily.font, + fontFamily = settings.fontFamily.value.font, fontStyle = FontStyle.Normal ), - selected = !state.value.isItalic + selected = !settings.italic.value ), ButtonItem( id = "italic", title = stringResource(id = R.string.font_style_italic), textStyle = MaterialTheme.typography.labelLarge.copy( - fontFamily = fontFamily.font, + fontFamily = settings.fontFamily.value.font, fontStyle = FontStyle.Italic ), - selected = state.value.isItalic + selected = settings.italic.value ) ), onClick = { - mainModel.onEvent( - MainEvent.OnChangeFontStyle( - when (it.id) { - "italic" -> true - else -> false - } - ) + settings.italic.update( + when (it.id) { + "italic" -> true + else -> false + } ) } ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontThicknessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontThicknessOption.kt index 5be8bb55..a25a8842 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontThicknessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/FontThicknessOption.kt @@ -8,30 +8,16 @@ package ua.acclorite.book_story.ui.settings.reader.font.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem -import ua.acclorite.book_story.ui.reader.data.ReaderData @Composable fun FontThicknessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() - - val fontFamily = remember(state.value.fontFamily) { - ReaderData.fonts.run { - find { - it.id == state.value.fontFamily - } ?: get(0) - } - } + val settings = LocalSettings.current ChipsWithTitle( title = stringResource(id = R.string.font_thickness_option), @@ -46,18 +32,14 @@ fun FontThicknessOption() { ReaderFontThickness.MEDIUM -> stringResource(id = R.string.font_thickness_medium) }, textStyle = MaterialTheme.typography.labelLarge.copy( - fontFamily = fontFamily.font, + fontFamily = settings.fontFamily.value.font, fontWeight = it.thickness ), - selected = it == state.value.fontThickness + selected = it == settings.fontThickness.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeFontThickness( - it.id - ) - ) + settings.fontThickness.update(ReaderFontThickness.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/LetterSpacingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/LetterSpacingOption.kt index 0925d3f7..cf9e3459 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/LetterSpacingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/font/components/LetterSpacingOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.font.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LetterSpacingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.letterSpacing to "pt", + value = settings.letterSpacing.value to "pt", fromValue = -8, toValue = 16, title = stringResource(id = R.string.letter_spacing_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeLetterSpacing(it) - ) + settings.letterSpacing.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesAlignmentOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesAlignmentOption.kt index f0f96554..cb3563e7 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesAlignmentOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesAlignmentOption.kt @@ -9,42 +9,34 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.ExpandingTransition +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun ImagesAlignmentOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.images) { + ExpandingTransition(visible = settings.images.value) { SegmentedButtonWithTitle( title = stringResource(id = R.string.images_alignment_option), buttons = HorizontalAlignment.entries.map { ButtonItem( - id = it.toString(), + id = it.name, title = when (it) { HorizontalAlignment.START -> stringResource(id = R.string.alignment_start) HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center) HorizontalAlignment.END -> stringResource(id = R.string.alignment_end) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.imagesAlignment + selected = it == settings.imagesAlignment.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeImagesAlignment( - it.id - ) - ) + settings.imagesAlignment.update(HorizontalAlignment.valueOf(it.id)) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCaptionsOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCaptionsOption.kt index 9b6437bc..ea0a758f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCaptionsOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCaptionsOption.kt @@ -8,30 +8,22 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ImagesCaptionsOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.images) { + ExpandingTransition(visible = settings.images.value) { SwitchWithTitle( - selected = state.value.imagesCaptions, + selected = settings.imagesCaptions.value, title = stringResource(id = R.string.images_captions_option), description = stringResource(id = R.string.images_captions_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeImagesCaptions( - !state.value.imagesCaptions - ) - ) + settings.imagesCaptions.update(!settings.imagesCaptions.lastValue) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesColorEffectsOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesColorEffectsOption.kt index f1a7365d..02eb5eca 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesColorEffectsOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesColorEffectsOption.kt @@ -9,54 +9,35 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ImagesColorEffectsOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.images) { + ExpandingTransition(visible = settings.images.value) { ChipsWithTitle( title = stringResource(id = R.string.images_color_effects_option), chips = ReaderColorEffects.entries.map { ButtonItem( - id = it.toString(), + id = it.name, title = when (it) { - ReaderColorEffects.OFF -> { - stringResource(R.string.color_effects_off) - } - - ReaderColorEffects.GRAYSCALE -> { - stringResource(R.string.color_effects_grayscale) - } - - ReaderColorEffects.FONT -> { - stringResource(R.string.color_effects_font) - } - - ReaderColorEffects.BACKGROUND -> { - stringResource(R.string.color_effects_background) - } + ReaderColorEffects.OFF -> stringResource(R.string.color_effects_off) + ReaderColorEffects.GRAYSCALE -> stringResource(R.string.color_effects_grayscale) + ReaderColorEffects.FONT -> stringResource(R.string.color_effects_font) + ReaderColorEffects.BACKGROUND -> stringResource(R.string.color_effects_background) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.imagesColorEffects + selected = it == settings.imagesColorEffects.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeImagesColorEffects( - it.id - ) - ) + settings.imagesColorEffects.update(ReaderColorEffects.valueOf(it.id)) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCornersRoundnessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCornersRoundnessOption.kt index e8760ca5..bffec477 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCornersRoundnessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesCornersRoundnessOption.kt @@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ImagesCornersRoundnessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.images) { + ExpandingTransition(visible = settings.images.value) { SliderWithTitle( - value = state.value.imagesCornersRoundness to "pt", + value = settings.imagesCornersRoundness.value to "pt", fromValue = 0, toValue = 24, title = stringResource(id = R.string.images_corners_roundness_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeImagesCornersRoundness(it) - ) + settings.imagesCornersRoundness.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesOption.kt index e8727907..d9facf10 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun ImagesOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.images, + selected = settings.images.value, title = stringResource(id = R.string.images_option), description = stringResource(id = R.string.images_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeImages( - !state.value.images - ) - ) + settings.images.update(!settings.images.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesWidthOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesWidthOption.kt index d7901b6e..07e4c3b7 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesWidthOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/images/components/ImagesWidthOption.kt @@ -8,28 +8,22 @@ package ua.acclorite.book_story.ui.settings.reader.images.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ImagesWidthOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.images) { + ExpandingTransition(visible = settings.images.value) { SliderWithTitle( - value = state.value.imagesWidth to "%", + value = settings.imagesWidth.value to "%", toValue = 100, title = stringResource(id = R.string.images_width_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeImagesWidth(it) - ) + settings.imagesWidth.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/FullscreenOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/FullscreenOption.kt index 29fcd838..5452a64c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/FullscreenOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/FullscreenOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun FullscreenOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.fullscreen, + selected = settings.fullscreen.value, title = stringResource(id = R.string.fullscreen_option), description = stringResource(id = R.string.fullscreen_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeFullscreen( - !state.value.fullscreen - ) - ) + settings.fullscreen.update(!settings.fullscreen.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/HideBarsOnFastScrollOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/HideBarsOnFastScrollOption.kt index 46e6d780..cd85514c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/HideBarsOnFastScrollOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/HideBarsOnFastScrollOption.kt @@ -8,24 +8,18 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun HideBarsOnFastScrollOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.hideBarsOnFastScroll, + selected = settings.hideBarsOnFastScroll.value, title = stringResource(id = R.string.hide_bars_on_fast_scroll_option) ) { - mainModel.onEvent( - MainEvent.OnChangeHideBarsOnFastScroll(!state.value.hideBarsOnFastScroll) - ) + settings.hideBarsOnFastScroll.update(!settings.hideBarsOnFastScroll.lastValue) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/KeepScreenOnOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/KeepScreenOnOption.kt index ce045704..d2c6fa03 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/KeepScreenOnOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/misc/components/KeepScreenOnOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun KeepScreenOnOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.keepScreenOn, + selected = settings.keepScreenOn.value, title = stringResource(id = R.string.keep_screen_on_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeKeepScreenOn( - !state.value.keepScreenOn - ) - ) + settings.keepScreenOn.update(!settings.keepScreenOn.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/BottomBarPaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/BottomBarPaddingOption.kt index 925c61bb..8539976a 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/BottomBarPaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/BottomBarPaddingOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun BottomBarPaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.bottomBarPadding to "pt", + value = settings.bottomBarPadding.value to "pt", fromValue = 0, toValue = 24, title = stringResource(id = R.string.bottom_bar_padding_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeBottomBarPadding(it) - ) + settings.bottomBarPadding.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/CutoutPaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/CutoutPaddingOption.kt index f9da8be8..906c218c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/CutoutPaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/CutoutPaddingOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun CutoutPaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.cutoutPadding, + selected = settings.cutoutPadding.value, title = stringResource(id = R.string.cutout_padding_option), description = stringResource(id = R.string.cutout_padding_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeCutoutPadding( - !state.value.cutoutPadding - ) - ) + settings.cutoutPadding.update(!settings.cutoutPadding.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/SidePaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/SidePaddingOption.kt index 51abcdd8..8de148ed 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/SidePaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/SidePaddingOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun SidePaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.sidePadding to "pt", + value = settings.sidePadding.value to "pt", fromValue = 1, toValue = 20, title = stringResource(id = R.string.side_padding_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeSidePadding(it) - ) + settings.sidePadding.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/VerticalPaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/VerticalPaddingOption.kt index 21fa45ba..678eb687 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/VerticalPaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/padding/components/VerticalPaddingOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun VerticalPaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.verticalPadding to "pt", + value = settings.verticalPadding.value to "pt", fromValue = 0, toValue = 24, title = stringResource(id = R.string.vertical_padding_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeVerticalPadding(it) - ) + settings.verticalPadding.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarAlignmentOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarAlignmentOption.kt index f8603cd5..85308b18 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarAlignmentOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarAlignmentOption.kt @@ -9,42 +9,34 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel -import ua.acclorite.book_story.presentation.main.model.HorizontalAlignment import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.theme.ExpandingTransition +import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment @Composable fun ProgressBarAlignmentOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.progressBar) { + ExpandingTransition(visible = settings.progressBar.value) { SegmentedButtonWithTitle( title = stringResource(id = R.string.progress_bar_alignment_option), buttons = HorizontalAlignment.entries.map { ButtonItem( - id = it.toString(), + id = it.name, title = when (it) { HorizontalAlignment.START -> stringResource(id = R.string.alignment_start) HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center) HorizontalAlignment.END -> stringResource(id = R.string.alignment_end) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.progressBarAlignment + selected = it == settings.progressBarAlignment.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeProgressBarAlignment( - it.id - ) - ) + settings.progressBarAlignment.update(HorizontalAlignment.valueOf(it.id)) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarFontSizeOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarFontSizeOption.kt index ac5e39b5..01c9e943 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarFontSizeOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarFontSizeOption.kt @@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ProgressBarFontSizeOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.progressBar) { + ExpandingTransition(visible = settings.progressBar.value) { SliderWithTitle( - value = state.value.progressBarFontSize to "pt", + value = settings.progressBarFontSize.value to "pt", fromValue = 4, toValue = 16, title = stringResource(id = R.string.progress_bar_font_size_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeProgressBarFontSize(it) - ) + settings.progressBarFontSize.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarOption.kt index 8e261a32..77d51d99 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun ProgressBarOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.progressBar, + selected = settings.progressBar.value, title = stringResource(id = R.string.progress_bar_option), description = stringResource(id = R.string.progress_bar_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeProgressBar( - !state.value.progressBar - ) - ) + settings.progressBar.update(!settings.progressBar.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarPaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarPaddingOption.kt index 9fdf14f7..d2002618 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarPaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressBarPaddingOption.kt @@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ProgressBarPaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.progressBar) { + ExpandingTransition(visible = settings.progressBar.value) { SliderWithTitle( - value = state.value.progressBarPadding to "pt", + value = settings.progressBarPadding.value to "pt", fromValue = 1, toValue = 12, title = stringResource(id = R.string.progress_bar_padding_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeProgressBarPadding(it) - ) + settings.progressBarPadding.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressCountOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressCountOption.kt index 3fe52c5a..375e4c87 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressCountOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/progress/components/ProgressCountOption.kt @@ -9,39 +9,31 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun ProgressCountOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.progress_count_option), buttons = ReaderProgressCount.entries.map { ButtonItem( - id = it.toString(), + id = it.name, title = when (it) { ReaderProgressCount.PERCENTAGE -> stringResource(id = R.string.progress_count_percentage) ReaderProgressCount.QUANTITY -> stringResource(id = R.string.progress_count_quantity) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.progressCount + selected = it == settings.progressCount.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeProgressCount( - it.id - ) - ) + settings.progressCount.update(ReaderProgressCount.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureAlphaAnimOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureAlphaAnimOption.kt index 2149107e..9961c287 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureAlphaAnimOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureAlphaAnimOption.kt @@ -8,36 +8,28 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun HorizontalGestureAlphaAnimOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ExpandingTransition( - visible = when (state.value.horizontalGesture) { + visible = when (settings.horizontalGesture.value) { ReaderHorizontalGesture.OFF -> false else -> true } ) { SwitchWithTitle( - selected = state.value.horizontalGestureAlphaAnim, + selected = settings.horizontalGestureAlphaAnim.value, title = stringResource(id = R.string.horizontal_gesture_alpha_anim_option), description = stringResource(id = R.string.horizontal_gesture_alpha_anim_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeHorizontalGestureAlphaAnim( - !state.value.horizontalGestureAlphaAnim - ) - ) + settings.horizontalGestureAlphaAnim.update(!settings.horizontalGestureAlphaAnim.lastValue) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureOption.kt index 49c9e9df..0661d692 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureOption.kt @@ -9,48 +9,32 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun HorizontalGestureOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ChipsWithTitle( title = stringResource(id = R.string.horizontal_gesture_option), chips = ReaderHorizontalGesture.entries.map { ButtonItem( - id = it.toString(), + id = it.name, title = when (it) { - ReaderHorizontalGesture.OFF -> { - stringResource(R.string.horizontal_gesture_off) - } - - ReaderHorizontalGesture.ON -> { - stringResource(R.string.horizontal_gesture_on) - } - - ReaderHorizontalGesture.INVERSE -> { - stringResource(R.string.horizontal_gesture_inverse) - } + ReaderHorizontalGesture.OFF -> stringResource(R.string.horizontal_gesture_off) + ReaderHorizontalGesture.ON -> stringResource(R.string.horizontal_gesture_on) + ReaderHorizontalGesture.INVERSE -> stringResource(R.string.horizontal_gesture_inverse) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.horizontalGesture + selected = it == settings.horizontalGesture.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeHorizontalGesture( - it.id - ) - ) + settings.horizontalGesture.update(ReaderHorizontalGesture.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGesturePullAnimOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGesturePullAnimOption.kt index 2b27e3e5..0864a4d7 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGesturePullAnimOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGesturePullAnimOption.kt @@ -8,36 +8,28 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun HorizontalGesturePullAnimOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ExpandingTransition( - visible = when (state.value.horizontalGesture) { + visible = when (settings.horizontalGesture.value) { ReaderHorizontalGesture.OFF -> false else -> true } ) { SwitchWithTitle( - selected = state.value.horizontalGesturePullAnim, + selected = settings.horizontalGesturePullAnim.value, title = stringResource(id = R.string.horizontal_gesture_pull_anim_option), description = stringResource(id = R.string.horizontal_gesture_pull_anim_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeHorizontalGesturePullAnim( - !state.value.horizontalGesturePullAnim - ) - ) + settings.horizontalGesturePullAnim.update(!settings.horizontalGesturePullAnim.lastValue) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureScrollOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureScrollOption.kt index 2c434d2e..13ef01e1 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureScrollOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureScrollOption.kt @@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun HorizontalGestureScrollOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ExpandingTransition( - visible = when (state.value.horizontalGesture) { + visible = when (settings.horizontalGesture.value) { ReaderHorizontalGesture.OFF -> false else -> true } ) { SliderWithTitle( - value = state.value.horizontalGestureScroll to "%", + value = settings.horizontalGestureScroll.value to "%", toValue = 100, title = stringResource(id = R.string.horizontal_gesture_scroll_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeHorizontalGestureScroll(it) - ) + settings.horizontalGestureScroll.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureSensitivityOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureSensitivityOption.kt index 56b42296..1079dde3 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureSensitivityOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_mode/components/HorizontalGestureSensitivityOption.kt @@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderHorizontalGesture import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun HorizontalGestureSensitivityOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ExpandingTransition( - visible = when (state.value.horizontalGesture) { + visible = when (settings.horizontalGesture.value) { ReaderHorizontalGesture.OFF -> false else -> true } ) { SliderWithTitle( - value = state.value.horizontalGestureSensitivity to "%", + value = settings.horizontalGestureSensitivity.value to "%", toValue = 100, title = stringResource(id = R.string.horizontal_gesture_sensitivity_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeHorizontalGestureSensitivity(it) - ) + settings.horizontalGestureSensitivity.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingOption.kt index fc79c390..e570e62d 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.reading_speed.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun HighlightedReadingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.highlightedReading, + selected = settings.highlightedReading.value, title = stringResource(id = R.string.highlighted_reading_option), description = stringResource(id = R.string.highlighted_reading_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeHighlightedReading( - !state.value.highlightedReading - ) - ) + settings.highlightedReading.update(!settings.highlightedReading.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingThicknessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingThicknessOption.kt index 118d8a42..4bcc2bfe 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingThicknessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/HighlightedReadingThicknessOption.kt @@ -8,30 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.reading_speed.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun HighlightedReadingThicknessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.highlightedReading) { + ExpandingTransition(visible = settings.highlightedReading.value) { SliderWithTitle( - value = state.value.highlightedReadingThickness - to " ${stringResource(R.string.highlighted_reading_level)}", + value = settings.highlightedReadingThickness.value to " ${stringResource(R.string.highlighted_reading_level)}", fromValue = 1, toValue = 3, title = stringResource(id = R.string.highlighted_reading_thickness_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeHighlightedReadingThickness(it) - ) + settings.highlightedReadingThickness.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderOption.kt index 63a1d6d8..b00ec1ae 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.reading_speed.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun PerceptionExpanderOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.perceptionExpander, + selected = settings.perceptionExpander.value, title = stringResource(id = R.string.perception_expander_option), description = stringResource(id = R.string.perception_expander_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangePerceptionExpander( - !state.value.perceptionExpander - ) - ) + settings.perceptionExpander.update(!settings.perceptionExpander.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderPaddingOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderPaddingOption.kt index 21283fbc..471ce36f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderPaddingOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderPaddingOption.kt @@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.reading_speed.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun PerceptionExpanderPaddingOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.perceptionExpander) { + ExpandingTransition(visible = settings.perceptionExpander.value) { SliderWithTitle( - value = state.value.perceptionExpanderPadding to "pt", + value = settings.perceptionExpanderPadding.value to "pt", fromValue = 0, toValue = 24, title = stringResource(id = R.string.perception_expander_padding_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangePerceptionExpanderPadding(it) - ) + settings.perceptionExpanderPadding.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderThicknessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderThicknessOption.kt index ed672440..a386c87f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderThicknessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/reading_speed/components/PerceptionExpanderThicknessOption.kt @@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.reading_speed.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun PerceptionExpanderThicknessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.perceptionExpander) { + ExpandingTransition(visible = settings.perceptionExpander.value) { SliderWithTitle( - value = state.value.perceptionExpanderThickness to "pt", + value = settings.perceptionExpanderThickness.value to "pt", fromValue = 1, toValue = 12, title = stringResource(id = R.string.perception_expander_thickness_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangePerceptionExpanderThickness(it) - ) + settings.perceptionExpanderThickness.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/CustomScreenBrightnessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/CustomScreenBrightnessOption.kt index 7f3270f3..c3a40c21 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/CustomScreenBrightnessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/CustomScreenBrightnessOption.kt @@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.reader.system.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun CustomScreenBrightnessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.customScreenBrightness, + selected = settings.customScreenBrightness.value, title = stringResource(id = R.string.custom_screen_brightness_option), onClick = { - mainModel.onEvent( - MainEvent.OnChangeCustomScreenBrightness( - !state.value.customScreenBrightness - ) - ) + settings.customScreenBrightness.update(!settings.customScreenBrightness.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenBrightnessOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenBrightnessOption.kt index 27f422ba..abff7a52 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenBrightnessOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenBrightnessOption.kt @@ -8,28 +8,22 @@ package ua.acclorite.book_story.ui.settings.reader.system.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ScreenBrightnessOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - ExpandingTransition(visible = state.value.customScreenBrightness) { + ExpandingTransition(visible = settings.customScreenBrightness.value) { SliderWithTitle( - value = state.value.screenBrightness to "", + value = settings.screenBrightness.value to "", toValue = 100, title = stringResource(id = R.string.screen_brightness_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeScreenBrightness(it) - ) + settings.screenBrightness.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenOrientationOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenOrientationOption.kt index 90604fb6..54f94dfc 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenOrientationOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/system/components/ScreenOrientationOption.kt @@ -9,43 +9,35 @@ package ua.acclorite.book_story.ui.settings.reader.system.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderScreenOrientation import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun ScreenOrientationOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ChipsWithTitle( title = stringResource(id = R.string.screen_orientation_option), chips = ReaderScreenOrientation.entries.map { ButtonItem( - id = it.toString(), - title = when (it.code) { - ReaderScreenOrientation.FREE.code -> stringResource(id = R.string.screen_orientation_free) - ReaderScreenOrientation.PORTRAIT.code -> stringResource(id = R.string.screen_orientation_portrait) - ReaderScreenOrientation.LANDSCAPE.code -> stringResource(id = R.string.screen_orientation_landscape) - ReaderScreenOrientation.LOCKED_PORTRAIT.code -> stringResource(id = R.string.screen_orientation_locked_portrait) - ReaderScreenOrientation.LOCKED_LANDSCAPE.code -> stringResource(id = R.string.screen_orientation_locked_landscape) + id = it.name, + title = when (it) { + ReaderScreenOrientation.FREE -> stringResource(id = R.string.screen_orientation_free) + ReaderScreenOrientation.PORTRAIT -> stringResource(id = R.string.screen_orientation_portrait) + ReaderScreenOrientation.LANDSCAPE -> stringResource(id = R.string.screen_orientation_landscape) + ReaderScreenOrientation.LOCKED_PORTRAIT -> stringResource(id = R.string.screen_orientation_locked_portrait) + ReaderScreenOrientation.LOCKED_LANDSCAPE -> stringResource(id = R.string.screen_orientation_locked_landscape) else -> stringResource(id = R.string.default_string) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.screenOrientation + selected = it == settings.screenOrientation.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeScreenOrientation( - it.id - ) - ) + settings.screenOrientation.update(ReaderScreenOrientation.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/LineHeightOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/LineHeightOption.kt index f0eb1cda..57ed9aec 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/LineHeightOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/LineHeightOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.text.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun LineHeightOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.lineHeight to "pt", + value = settings.lineHeight.value to "pt", fromValue = 1, toValue = 24, title = stringResource(id = R.string.line_height_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeLineHeight(it) - ) + settings.lineHeight.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphHeightOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphHeightOption.kt index 86cbea00..528b1df1 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphHeightOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphHeightOption.kt @@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.text.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun ParagraphHeightOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SliderWithTitle( - value = state.value.paragraphHeight to "pt", + value = settings.paragraphHeight.value to "pt", fromValue = 0, toValue = 36, title = stringResource(id = R.string.paragraph_height_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeParagraphHeight(it) - ) + settings.paragraphHeight.update(it) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphIndentationOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphIndentationOption.kt index 61933358..a3354bc8 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphIndentationOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/ParagraphIndentationOption.kt @@ -8,33 +8,27 @@ package ua.acclorite.book_story.ui.settings.reader.text.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.theme.ExpandingTransition @Composable fun ParagraphIndentationOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current ExpandingTransition( - visible = state.value.textAlignment != ReaderTextAlignment.CENTER && - state.value.textAlignment != ReaderTextAlignment.END + visible = settings.textAlignment.value != ReaderTextAlignment.CENTER && + settings.textAlignment.value != ReaderTextAlignment.END ) { SliderWithTitle( - value = state.value.paragraphIndentation to "pt", + value = settings.paragraphIndentation.value to "pt", fromValue = 0, toValue = 12, title = stringResource(id = R.string.paragraph_indentation_option), onValueChange = { - mainModel.onEvent( - MainEvent.OnChangeParagraphIndentation(it) - ) + settings.paragraphIndentation.update(it) } ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/TextAlignmentOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/TextAlignmentOption.kt index fbd7c4ee..486302b9 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/TextAlignmentOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/text/components/TextAlignmentOption.kt @@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.reader.text.components import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.common.model.ButtonItem @Composable fun TextAlignmentOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SegmentedButtonWithTitle( title = stringResource(id = R.string.text_alignment_option), @@ -35,15 +31,11 @@ fun TextAlignmentOption() { ReaderTextAlignment.END -> stringResource(id = R.string.alignment_end) }, textStyle = MaterialTheme.typography.labelLarge, - selected = it == state.value.textAlignment + selected = it == settings.textAlignment.value ) }, onClick = { - mainModel.onEvent( - MainEvent.OnChangeTextAlignment( - it.id - ) - ) + settings.textAlignment.update(ReaderTextAlignment.valueOf(it.id)) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/translator/components/DoubleClickTranslationOption.kt b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/translator/components/DoubleClickTranslationOption.kt index 8945e2ee..817ee4b6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/translator/components/DoubleClickTranslationOption.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/settings/reader/translator/components/DoubleClickTranslationOption.kt @@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.translator.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent -import ua.acclorite.book_story.presentation.main.MainModel import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun DoubleClickTranslationOption() { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current SwitchWithTitle( - selected = state.value.doubleClickTranslation, + selected = settings.doubleClickTranslation.value, title = stringResource(id = R.string.double_click_translation_option), description = stringResource(id = R.string.double_click_translation_option_desc), onClick = { - mainModel.onEvent( - MainEvent.OnChangeDoubleClickTranslation( - !state.value.doubleClickTranslation - ) - ) + settings.doubleClickTranslation.update(!settings.doubleClickTranslation.lastValue) } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/start/StartContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/start/StartContent.kt index 13d7195f..bff197c1 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/start/StartContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/start/StartContent.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.background import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.presentation.navigator.StackEvent import ua.acclorite.book_story.presentation.start.StartScreen import ua.acclorite.book_story.ui.common.model.ButtonItem @@ -20,7 +19,7 @@ fun StartContent( currentPage: Int, stackEvent: StackEvent, languages: List, - changeLanguage: (MainEvent.OnChangeLanguage) -> Unit, + updateLanguage: (String) -> Unit, navigateForward: () -> Unit, navigateBack: () -> Unit, navigateToBrowse: () -> Unit, @@ -40,7 +39,7 @@ fun StartContent( currentPage = currentPage, stackEvent = stackEvent, languages = languages, - changeLanguage = changeLanguage, + updateLanguage = updateLanguage, navigateForward = navigateForward ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettings.kt b/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettings.kt index b4784a25..e5299bfb 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettings.kt @@ -7,7 +7,6 @@ package ua.acclorite.book_story.ui.start import androidx.compose.runtime.Composable -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.presentation.navigator.StackEvent import ua.acclorite.book_story.presentation.start.StartScreen import ua.acclorite.book_story.ui.common.model.ButtonItem @@ -17,7 +16,7 @@ fun StartSettings( currentPage: Int, stackEvent: StackEvent, languages: List, - changeLanguage: (MainEvent.OnChangeLanguage) -> Unit, + updateLanguage: (String) -> Unit, navigateForward: () -> Unit ) { StartSettingsScaffold( @@ -36,7 +35,7 @@ fun StartSettings( StartScreen.GENERAL_SETTINGS -> { StartSettingsLayoutGeneral( languages = languages, - changeLanguage = changeLanguage + updateLanguage = updateLanguage ) } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettingsLayoutGeneral.kt b/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettingsLayoutGeneral.kt index f7233de2..de418303 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettingsLayoutGeneral.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/start/StartSettingsLayoutGeneral.kt @@ -17,14 +17,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.MainEvent import ua.acclorite.book_story.ui.common.components.dialog.SelectableDialogItem import ua.acclorite.book_story.ui.common.model.ButtonItem import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle fun LazyListScope.StartSettingsLayoutGeneral( languages: List, - changeLanguage: (MainEvent.OnChangeLanguage) -> Unit + updateLanguage: (String) -> Unit, ) { item { Spacer(modifier = Modifier.height(16.dp)) @@ -41,7 +40,7 @@ fun LazyListScope.StartSettingsLayoutGeneral( title = it.title, horizontalPadding = 18.dp ) { - changeLanguage(MainEvent.OnChangeLanguage(it.id)) + updateLanguage(it.id) } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/Animations.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/Animations.kt index 20825e89..b1a40df0 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/Animations.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/Animations.kt @@ -11,7 +11,8 @@ import androidx.compose.animation.core.tween import androidx.compose.material3.ColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast @Composable private fun animateColor(targetColor: Color): Color { diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/Color.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/Color.kt index a123d2e1..1cb52573 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/Color.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/Color.kt @@ -6,13 +6,8 @@ package ua.acclorite.book_story.ui.theme -import android.os.Build -import androidx.annotation.StringRes import androidx.compose.material3.ColorScheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.main.model.ThemeContrast import ua.acclorite.book_story.ui.theme.color.aquaTheme import ua.acclorite.book_story.ui.theme.color.blackTheme import ua.acclorite.book_story.ui.theme.color.blueTheme @@ -31,48 +26,10 @@ import ua.acclorite.book_story.ui.theme.color.redGrayTheme import ua.acclorite.book_story.ui.theme.color.redTheme import ua.acclorite.book_story.ui.theme.color.yellow2Theme import ua.acclorite.book_story.ui.theme.color.yellowTheme +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast -@Immutable -enum class Theme( - val hasThemeContrast: Boolean, - @StringRes val title: Int -) { - DYNAMIC(hasThemeContrast = false, title = R.string.dynamic_theme), - BLUE(hasThemeContrast = true, title = R.string.blue_theme), - GREEN(hasThemeContrast = true, title = R.string.green_theme), - GREEN2(hasThemeContrast = false, title = R.string.green2_theme), - GREEN_GRAY(hasThemeContrast = false, title = R.string.green_gray_theme), - MARSH(hasThemeContrast = true, title = R.string.marsh_theme), - RED(hasThemeContrast = true, title = R.string.red_theme), - RED_GRAY(hasThemeContrast = false, title = R.string.red_gray_theme), - PURPLE(hasThemeContrast = true, title = R.string.purple_theme), - PURPLE_GRAY(hasThemeContrast = false, title = R.string.purple_gray_theme), - LAVENDER(hasThemeContrast = true, title = R.string.lavender_theme), - PINK(hasThemeContrast = true, title = R.string.pink_theme), - PINK2(hasThemeContrast = false, title = R.string.pink2_theme), - YELLOW(hasThemeContrast = true, title = R.string.yellow_theme), - YELLOW2(hasThemeContrast = false, title = R.string.yellow2_theme), - AQUA(hasThemeContrast = true, title = R.string.aqua_theme), - GRAY(hasThemeContrast = false, title = R.string.gray_theme); - - companion object { - fun entries(): List { - return when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> entries - else -> entries.dropWhile { it == DYNAMIC } - } - } - } -} - -/** - * Creates a colorscheme based on [Theme]. - * - * @param theme a [Theme]. - * - * @return a [ColorScheme]. - */ @Composable fun colorScheme( theme: Theme, diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/Theme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/Theme.kt index 28e89f25..ce8d5727 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/Theme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/Theme.kt @@ -16,7 +16,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.Theme +import ua.acclorite.book_story.ui.theme.model.ThemeContrast @Composable fun BookStoryTheme( diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/AquaTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/AquaTheme.kt index ea9482a5..326a6407 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/AquaTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/AquaTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF116682) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlackTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlackTheme.kt index 8c8ee40e..6ab2928f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlackTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlackTheme.kt @@ -8,22 +8,22 @@ package ua.acclorite.book_story.ui.theme.color import androidx.compose.material3.ColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import ua.acclorite.book_story.presentation.main.MainModel +import ua.acclorite.book_story.ui.common.helpers.LocalSettings @Composable fun blackTheme(initialTheme: ColorScheme): ColorScheme { - val mainModel = hiltViewModel() - val state = mainModel.state.collectAsStateWithLifecycle() + val settings = LocalSettings.current - val surfaceDarker = 3f - val surfaceContainerDarker = if (state.value.absoluteDark) 3f else 1.95f + val surfaceDarker = remember { 3f } + val surfaceContainerDarker = remember(settings.absoluteDark.value) { + if (settings.absoluteDark.lastValue) 3f else 1.95f + } return initialTheme.copy( surface = initialTheme.surface.run { - if (state.value.absoluteDark) { + if (settings.absoluteDark.value) { return@run Color.Black } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlueTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlueTheme.kt index 46998191..e0596cb3 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlueTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/BlueTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF485D92) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/GreenTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/GreenTheme.kt index dd08c049..1a8f98c2 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/GreenTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/GreenTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF306A42) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/LavenderTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/LavenderTheme.kt index eee7d2d8..59f567dd 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/LavenderTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/LavenderTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF824C76) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/MarshTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/MarshTheme.kt index 5c813abc..facccf0f 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/MarshTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/MarshTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF006A65) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PinkTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PinkTheme.kt index 26f088fa..6aca8fe7 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PinkTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PinkTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF8C4A60) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PurpleTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PurpleTheme.kt index 05e9ab88..81b2baba 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PurpleTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/PurpleTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF725188) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/RedTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/RedTheme.kt index d593368d..aa21526c 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/RedTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/RedTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF904A42) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/YellowTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/YellowTheme.kt index 81edb962..38694a58 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/theme/color/YellowTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/color/YellowTheme.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import ua.acclorite.book_story.presentation.main.model.ThemeContrast +import ua.acclorite.book_story.ui.theme.model.ThemeContrast private val primaryLight = Color(0xFF845415) private val onPrimaryLight = Color(0xFFFFFFFF) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/DarkTheme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/DarkTheme.kt similarity index 50% rename from app/src/main/java/ua/acclorite/book_story/presentation/main/model/DarkTheme.kt rename to app/src/main/java/ua/acclorite/book_story/ui/theme/model/DarkTheme.kt index 3ca2e9cb..5ad21651 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/DarkTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/DarkTheme.kt @@ -4,24 +4,22 @@ * SPDX-License-Identifier: GPL-3.0-only */ -package ua.acclorite.book_story.presentation.main.model +package ua.acclorite.book_story.ui.theme.model import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -@Immutable enum class DarkTheme { FOLLOW_SYSTEM, OFF, - ON -} + ON; -@Composable -fun DarkTheme.isDark(): Boolean { - return when (this) { - DarkTheme.FOLLOW_SYSTEM -> isSystemInDarkTheme() - DarkTheme.ON -> true - DarkTheme.OFF -> false + @Composable + fun isDark(): Boolean { + return when (this) { + FOLLOW_SYSTEM -> isSystemInDarkTheme() + ON -> true + OFF -> false + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/HorizontalAlignment.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/HorizontalAlignment.kt similarity index 77% rename from app/src/main/java/ua/acclorite/book_story/presentation/main/model/HorizontalAlignment.kt rename to app/src/main/java/ua/acclorite/book_story/ui/theme/model/HorizontalAlignment.kt index fdb6543a..b92742ae 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/HorizontalAlignment.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/HorizontalAlignment.kt @@ -4,12 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-only */ -package ua.acclorite.book_story.presentation.main.model +package ua.acclorite.book_story.ui.theme.model -import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment -@Immutable enum class HorizontalAlignment(val alignment: Alignment) { START(Alignment.Companion.CenterStart), CENTER(Alignment.Companion.Center), diff --git a/app/src/main/java/ua/acclorite/book_story/ui/theme/model/Theme.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/Theme.kt new file mode 100644 index 00000000..9de6c242 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/Theme.kt @@ -0,0 +1,43 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.ui.theme.model + +import android.os.Build +import androidx.annotation.StringRes +import ua.acclorite.book_story.R + +enum class Theme( + val hasThemeContrast: Boolean, + @StringRes val title: Int +) { + DYNAMIC(hasThemeContrast = false, title = R.string.dynamic_theme), + BLUE(hasThemeContrast = true, title = R.string.blue_theme), + GREEN(hasThemeContrast = true, title = R.string.green_theme), + GREEN2(hasThemeContrast = false, title = R.string.green2_theme), + GREEN_GRAY(hasThemeContrast = false, title = R.string.green_gray_theme), + MARSH(hasThemeContrast = true, title = R.string.marsh_theme), + RED(hasThemeContrast = true, title = R.string.red_theme), + RED_GRAY(hasThemeContrast = false, title = R.string.red_gray_theme), + PURPLE(hasThemeContrast = true, title = R.string.purple_theme), + PURPLE_GRAY(hasThemeContrast = false, title = R.string.purple_gray_theme), + LAVENDER(hasThemeContrast = true, title = R.string.lavender_theme), + PINK(hasThemeContrast = true, title = R.string.pink_theme), + PINK2(hasThemeContrast = false, title = R.string.pink2_theme), + YELLOW(hasThemeContrast = true, title = R.string.yellow_theme), + YELLOW2(hasThemeContrast = false, title = R.string.yellow2_theme), + AQUA(hasThemeContrast = true, title = R.string.aqua_theme), + GRAY(hasThemeContrast = false, title = R.string.gray_theme); + + companion object { + fun entries(): List { + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> entries + else -> entries.dropWhile { it == DYNAMIC } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/ThemeContrast.kt b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/ThemeContrast.kt similarity index 66% rename from app/src/main/java/ua/acclorite/book_story/presentation/main/model/ThemeContrast.kt rename to app/src/main/java/ua/acclorite/book_story/ui/theme/model/ThemeContrast.kt index b2ea6ad8..b846cda6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/main/model/ThemeContrast.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/theme/model/ThemeContrast.kt @@ -4,11 +4,9 @@ * SPDX-License-Identifier: GPL-3.0-only */ -package ua.acclorite.book_story.presentation.main.model +package ua.acclorite.book_story.ui.theme.model -import androidx.compose.runtime.Immutable -@Immutable enum class ThemeContrast { STANDARD, MEDIUM, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c0691398..d431b9e5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -256,7 +256,7 @@ Show book count Show category tabs Always show default tab - Per-category sorting + Per-category sort Red