refactor: datastore(settings) refactor
This commit is contained in:
parent
aed85c0d6a
commit
b4c6a63878
135 changed files with 1173 additions and 2844 deletions
|
|
@ -9,3 +9,12 @@ package ua.acclorite.book_story.core.helpers
|
|||
fun <T> MutableList<T>.addAll(calculation: () -> List<T>) {
|
||||
addAll(calculation())
|
||||
}
|
||||
|
||||
fun <T> List<T>.toggle(item: T): List<T> {
|
||||
return toMutableList().apply { toggle(item) }
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.toggle(item: T) {
|
||||
if (contains(item)) remove(item)
|
||||
else add(item)
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,5 @@ import androidx.datastore.preferences.core.Preferences
|
|||
|
||||
interface DataStore {
|
||||
suspend fun <T> getNullableData(key: Preferences.Key<T>): T?
|
||||
suspend fun getAllData(): Set<Preferences.Key<*>>?
|
||||
suspend fun <T> putData(key: Preferences.Key<T>, value: T)
|
||||
}
|
||||
|
|
@ -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 <T> getNullableData(key: Preferences.Key<T>): 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<Preferences.Key<*>>? {
|
||||
return dataStore.data
|
||||
.map {
|
||||
it.asMap().keys
|
||||
}.firstOrNull()
|
||||
override suspend fun <T> getNullableData(key: Preferences.Key<T>): T? {
|
||||
return try {
|
||||
dataStore.data.firstOrNull()?.get(key)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts data in DataStore by given [key].
|
||||
*/
|
||||
override suspend fun <T> putData(key: Preferences.Key<T>, value: T) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[key] = value
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 <T> putPreference(
|
||||
key: Preferences.Key<T>,
|
||||
value: T
|
||||
): Result<Unit> = runCatching {
|
||||
dataStore.putData(key, value)
|
||||
}
|
||||
|
||||
override suspend fun <T> getPreference(
|
||||
key: Preferences.Key<T>
|
||||
): Result<T> = runCatching {
|
||||
dataStore.getNullableData(key) ?: throw NoSuchElementException("Could not get preference.")
|
||||
}
|
||||
|
||||
override suspend fun getAllPreferences(): Result<Set<Preferences.Key<*>>> = runCatching {
|
||||
dataStore.getAllData() ?: throw NoSuchElementException("Could not get all preferences.")
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<String, String>(
|
||||
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<Theme, String>(
|
||||
key = stringPreferencesKey("theme"), default = Theme.Companion.entries().first(),
|
||||
serialize = { it.name }, deserialize = { Theme.valueOf(it) }
|
||||
)
|
||||
val darkTheme = setting<DarkTheme, String>(
|
||||
key = stringPreferencesKey("dark_theme"), default = DarkTheme.FOLLOW_SYSTEM,
|
||||
serialize = { it.name }, deserialize = { DarkTheme.valueOf(it) }
|
||||
)
|
||||
val pureDark = setting<PureDark, String>(
|
||||
key = stringPreferencesKey("pure_dark"), default = PureDark.OFF,
|
||||
serialize = { it.name }, deserialize = { PureDark.valueOf(it) }
|
||||
)
|
||||
val absoluteDark = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("absolute_dark"), default = false
|
||||
)
|
||||
val themeContrast = setting<ThemeContrast, String>(
|
||||
key = stringPreferencesKey("theme_contrast"), default = ThemeContrast.STANDARD,
|
||||
serialize = { it.name }, deserialize = { ThemeContrast.valueOf(it) }
|
||||
)
|
||||
val showStartScreen = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("guide"), default = true
|
||||
)
|
||||
val doublePressExit = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("double_press_exit"), default = false
|
||||
)
|
||||
|
||||
/* ------ Reader ----------------------------- */
|
||||
val fontFamily = setting<FontWithName, String>(
|
||||
key = stringPreferencesKey("font"), default = ReaderData.fonts[0],
|
||||
serialize = { it.id }, deserialize = { id ->
|
||||
ReaderData.fonts.find { it.id == id } ?: ReaderData.fonts[0]
|
||||
}
|
||||
)
|
||||
val fontThickness = setting<ReaderFontThickness, String>(
|
||||
key = stringPreferencesKey("font_thickness"), default = ReaderFontThickness.NORMAL,
|
||||
serialize = { it.name }, deserialize = { ReaderFontThickness.valueOf(it) }
|
||||
)
|
||||
val italic = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("font_style"), default = false
|
||||
)
|
||||
val fontSize = setting<Int, Int>(
|
||||
key = intPreferencesKey("font_size"), default = 16
|
||||
)
|
||||
val lineHeight = setting<Int, Int>(
|
||||
key = intPreferencesKey("line_height"), default = 4
|
||||
)
|
||||
val paragraphHeight = setting<Int, Int>(
|
||||
key = intPreferencesKey("paragraph_height"), default = 8
|
||||
)
|
||||
val paragraphIndentation = setting<Int, Int>(
|
||||
key = intPreferencesKey("paragraph_indentation_int"), default = 0
|
||||
)
|
||||
val sidePadding = setting<Int, Int>(
|
||||
key = intPreferencesKey("side_padding"), default = 6
|
||||
)
|
||||
val verticalPadding = setting<Int, Int>(
|
||||
key = intPreferencesKey("vertical_padding"), default = 0
|
||||
)
|
||||
val doubleClickTranslation = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("double_click_translation"), default = false
|
||||
)
|
||||
val fastColorPresetChange = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("fast_color_preset_change"), default = true
|
||||
)
|
||||
val textAlignment = setting<ReaderTextAlignment, String>(
|
||||
key = stringPreferencesKey("text_alignment"), default = ReaderTextAlignment.JUSTIFY,
|
||||
serialize = { it.name }, deserialize = { ReaderTextAlignment.valueOf(it) }
|
||||
)
|
||||
val letterSpacing = setting<Int, Int>(
|
||||
key = intPreferencesKey("letter_spacing"), default = 0
|
||||
)
|
||||
val cutoutPadding = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("cutout_padding"), default = false
|
||||
)
|
||||
val fullscreen = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("fullscreen"), default = true
|
||||
)
|
||||
val keepScreenOn = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("keep_screen_on"), default = true
|
||||
)
|
||||
val hideBarsOnFastScroll = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("hide_bars_on_fast_scroll"), default = false
|
||||
)
|
||||
val perceptionExpander = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("perception_expander"), default = false
|
||||
)
|
||||
val perceptionExpanderPadding = setting<Int, Int>(
|
||||
key = intPreferencesKey("perception_expander_padding"), default = 5
|
||||
)
|
||||
val perceptionExpanderThickness = setting<Int, Int>(
|
||||
key = intPreferencesKey("perception_expander_thickness"), default = 4
|
||||
)
|
||||
val screenOrientation = setting<ReaderScreenOrientation, String>(
|
||||
key = stringPreferencesKey("screen_orientation"), default = ReaderScreenOrientation.DEFAULT,
|
||||
serialize = { it.name }, deserialize = { ReaderScreenOrientation.valueOf(it) }
|
||||
)
|
||||
val customScreenBrightness = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("custom_screen_brightness"), default = false
|
||||
)
|
||||
val screenBrightness = setting<Float, Double>(
|
||||
key = doublePreferencesKey("screen_brightness"), default = 0.5f,
|
||||
serialize = { it.toDouble() }, deserialize = { it.toFloat() }
|
||||
)
|
||||
val horizontalGesture = setting<ReaderHorizontalGesture, String>(
|
||||
key = stringPreferencesKey("horizontal_gesture"), default = ReaderHorizontalGesture.OFF,
|
||||
serialize = { it.name }, deserialize = { ReaderHorizontalGesture.valueOf(it) }
|
||||
)
|
||||
val horizontalGestureScroll = setting<Float, Double>(
|
||||
key = doublePreferencesKey("horizontal_gesture_scroll"), default = 0.7f,
|
||||
serialize = { it.toDouble() }, deserialize = { it.toFloat() }
|
||||
)
|
||||
val horizontalGestureSensitivity = setting<Float, Double>(
|
||||
key = doublePreferencesKey("horizontal_gesture_sensitivity"), default = 0.6f,
|
||||
serialize = { it.toDouble() }, deserialize = { it.toFloat() }
|
||||
)
|
||||
val horizontalGestureAlphaAnim = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("horizontal_gesture_alpha_anim_bool"), default = true
|
||||
)
|
||||
val horizontalGesturePullAnim = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("horizontal_gesture_pull_anim"), default = true
|
||||
)
|
||||
val bottomBarPadding = setting<Int, Int>(
|
||||
key = intPreferencesKey("bottom_bar_padding"), default = 0
|
||||
)
|
||||
val highlightedReading = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("highlighted_reading"), default = false
|
||||
)
|
||||
val highlightedReadingThickness = setting<Int, Int>(
|
||||
key = intPreferencesKey("highlighted_reading_thickness"), default = 2
|
||||
)
|
||||
val chapterTitleAlignment = setting<ReaderTextAlignment, String>(
|
||||
key = stringPreferencesKey("chapter_title_alignment"),
|
||||
default = ReaderTextAlignment.JUSTIFY,
|
||||
serialize = { it.name }, deserialize = { ReaderTextAlignment.valueOf(it) }
|
||||
)
|
||||
val images = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("images"), default = true
|
||||
)
|
||||
val imagesCaptions = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("images_captions"), default = true
|
||||
)
|
||||
val imagesCornersRoundness = setting<Int, Int>(
|
||||
key = intPreferencesKey("images_corners_roundness"), default = 8
|
||||
)
|
||||
val imagesAlignment = setting<HorizontalAlignment, String>(
|
||||
key = stringPreferencesKey("images_alignment"), default = HorizontalAlignment.START,
|
||||
serialize = { it.name }, deserialize = { HorizontalAlignment.valueOf(it) }
|
||||
)
|
||||
val imagesWidth = setting<Float, Double>(
|
||||
key = doublePreferencesKey("images_width"), default = 0.8f,
|
||||
serialize = { it.toDouble() }, deserialize = { it.toFloat() }
|
||||
)
|
||||
val imagesColorEffects = setting<ReaderColorEffects, String>(
|
||||
key = stringPreferencesKey("images_color_effects"), default = ReaderColorEffects.OFF,
|
||||
serialize = { it.name }, deserialize = { ReaderColorEffects.valueOf(it) }
|
||||
)
|
||||
val progressBar = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("progress_bar"), default = false
|
||||
)
|
||||
val progressBarPadding = setting<Int, Int>(
|
||||
key = intPreferencesKey("progress_bar_padding"), default = 4
|
||||
)
|
||||
val progressBarAlignment = setting<HorizontalAlignment, String>(
|
||||
key = stringPreferencesKey("progress_bar_alignment"), default = HorizontalAlignment.CENTER,
|
||||
serialize = { it.name }, deserialize = { HorizontalAlignment.valueOf(it) }
|
||||
)
|
||||
val progressBarFontSize = setting<Int, Int>(
|
||||
key = intPreferencesKey("progress_bar_font_size"), default = 8
|
||||
)
|
||||
val progressCount = setting<ReaderProgressCount, String>(
|
||||
key = stringPreferencesKey("progress_count"), default = ReaderProgressCount.PERCENTAGE,
|
||||
serialize = { it.name }, deserialize = { ReaderProgressCount.valueOf(it) }
|
||||
)
|
||||
|
||||
/* ------ Library ---------------------------- */
|
||||
val libraryLayout = setting<LibraryLayout, String>(
|
||||
key = stringPreferencesKey("library_layout"), default = LibraryLayout.GRID,
|
||||
serialize = { it.name }, deserialize = { LibraryLayout.valueOf(it) }
|
||||
)
|
||||
val libraryAutoGridSize = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_auto_grid_size"), default = true
|
||||
)
|
||||
val libraryGridSize = setting<Int, Int>(
|
||||
key = intPreferencesKey("library_grid_size"), default = 0
|
||||
)
|
||||
val libraryTitlePosition = setting<LibraryTitlePosition, String>(
|
||||
key = stringPreferencesKey("library_title_position"), default = LibraryTitlePosition.BELOW,
|
||||
serialize = { it.name }, deserialize = { LibraryTitlePosition.valueOf(it) }
|
||||
)
|
||||
val libraryShowReadButton = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_show_read_button"), default = true
|
||||
)
|
||||
val libraryShowProgress = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_show_progress"), default = true
|
||||
)
|
||||
val libraryShowBookCount = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_show_book_count"), default = true
|
||||
)
|
||||
val libraryShowCategoryTabs = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_show_category_tabs"), default = true
|
||||
)
|
||||
val libraryShowDefaultTab = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_show_default_tab"), default = false
|
||||
)
|
||||
val librarySortOrder = setting<LibrarySortOrder, String>(
|
||||
key = stringPreferencesKey("library_sort_order"), default = LibrarySortOrder.LAST_READ,
|
||||
serialize = { it.name }, deserialize = { LibrarySortOrder.valueOf(it) }
|
||||
)
|
||||
val librarySortOrderDescending = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_sort_order_descending"), default = true
|
||||
)
|
||||
val libraryPerCategorySort = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("library_per_category_sort"), default = false
|
||||
)
|
||||
|
||||
/* ------ Browse ----------------------------- */
|
||||
val browseLayout = setting<BrowseLayout, String>(
|
||||
key = stringPreferencesKey("browse_layout"), default = BrowseLayout.LIST,
|
||||
serialize = { it.name }, deserialize = { BrowseLayout.valueOf(it) }
|
||||
)
|
||||
val browseAutoGridSize = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("browse_auto_grid_size"), default = true
|
||||
)
|
||||
val browseGridSize = setting<Int, Int>(
|
||||
key = intPreferencesKey("browse_grid_size"), default = 0
|
||||
)
|
||||
val browseSortOrder = setting<BrowseSortOrder, String>(
|
||||
key = stringPreferencesKey("browse_sort_order"), default = BrowseSortOrder.LAST_MODIFIED,
|
||||
serialize = { it.name }, deserialize = { BrowseSortOrder.valueOf(it) }
|
||||
)
|
||||
val browseSortOrderDescending = setting<Boolean, Boolean>(
|
||||
key = booleanPreferencesKey("browse_sort_order_descending"), default = true
|
||||
)
|
||||
val browseIncludedFilterItems = setting<List<String>, Set<String>>(
|
||||
key = stringSetPreferencesKey("browse_included_filter_items"), default = emptyList(),
|
||||
serialize = { it.toSet() }, deserialize = { it.toList() }
|
||||
)
|
||||
val browsePinnedPaths = setting<List<String>, Set<String>>(
|
||||
key = stringSetPreferencesKey("browse_pinned_paths"), default = emptyList(),
|
||||
serialize = { it.toSet() }, deserialize = { it.toList() }
|
||||
)
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
private fun <T, P> setting(
|
||||
key: Preferences.Key<P>,
|
||||
default: T,
|
||||
serialize: (T) -> P = { it as P },
|
||||
deserialize: (P) -> T = { it as T }
|
||||
): Setting<T, P> {
|
||||
settingsCount.incrementAndGet()
|
||||
|
||||
return Setting<T, P>(
|
||||
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<P>(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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<T, P>(
|
||||
val key: Preferences.Key<P>,
|
||||
default: T,
|
||||
private val setSetting: (P) -> Unit,
|
||||
private val serialize: (T) -> P,
|
||||
private val deserialize: (P) -> T
|
||||
) {
|
||||
private val _value = MutableStateFlow<T>(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) }
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <T> putPreference(
|
||||
key: Preferences.Key<T>,
|
||||
value: T
|
||||
): Result<Unit>
|
||||
|
||||
suspend fun <T> getPreference(
|
||||
key: Preferences.Key<T>,
|
||||
): Result<T>
|
||||
|
||||
suspend fun getAllPreferences(): Result<Set<Preferences.Key<*>>>
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String, Any>()
|
||||
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()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <T> invoke(key: Preferences.Key<T>, 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}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<BrowseModel>()
|
||||
val mainModel = hiltViewModel<MainModel>()
|
||||
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,16 +84,19 @@ object BrowseScreen : Screen, Parcelable {
|
|||
}
|
||||
)
|
||||
|
||||
val files = remember {
|
||||
derivedStateOf {
|
||||
val files = remember(
|
||||
state.value.files,
|
||||
settings.browseIncludedFilterItems.value,
|
||||
settings.browseSortOrderDescending.value,
|
||||
settings.browseSortOrder.value
|
||||
) {
|
||||
screenModel.filterList(
|
||||
files = state.value.files,
|
||||
sortOrderDescending = mainState.value.browseSortOrderDescending,
|
||||
includedFilterItems = mainState.value.browseIncludedFilterItems,
|
||||
sortOrder = mainState.value.browseSortOrder
|
||||
sortOrderDescending = settings.browseSortOrderDescending.lastValue,
|
||||
includedFilterItems = settings.browseIncludedFilterItems.lastValue,
|
||||
sortOrder = settings.browseSortOrder.lastValue
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
resetScrollPositionCompositionChannel.receiveAsFlow().collectLatest {
|
||||
|
|
@ -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)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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 = {
|
||||
|
|
|
|||
|
|
@ -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<LibraryModel>()
|
||||
val mainModel = hiltViewModel<MainModel>()
|
||||
val settingsModel = hiltViewModel<SettingsModel>()
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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,9 +80,7 @@ class MainActivity : AppCompatActivity() {
|
|||
val historyModel = hiltViewModel<HistoryModel>()
|
||||
val browseModel = hiltViewModel<BrowseModel>()
|
||||
|
||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||
val isLoaded = mainModel.isReady.collectAsStateWithLifecycle()
|
||||
|
||||
ProvideSettings(settings) {
|
||||
val tabs = persistentListOf(
|
||||
NavigatorItem(
|
||||
screen = LibraryScreen,
|
||||
|
|
@ -114,15 +107,15 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
MainActivityKeyboardManager()
|
||||
|
||||
if (isLoaded.value) {
|
||||
if (settings.initialized.collectAsStateWithLifecycle().value) {
|
||||
BookStoryTheme(
|
||||
theme = state.value.theme,
|
||||
isDark = state.value.darkTheme.isDark(),
|
||||
isPureDark = state.value.pureDark.isPureDark(this),
|
||||
themeContrast = state.value.themeContrast
|
||||
theme = settings.theme.value,
|
||||
isDark = settings.darkTheme.value.isDark(),
|
||||
isPureDark = settings.pureDark.value.isPureDark(this),
|
||||
themeContrast = settings.themeContrast.value
|
||||
) {
|
||||
Navigator(
|
||||
initialScreen = if (state.value.showStartScreen) StartScreen
|
||||
initialScreen = if (settings.showStartScreen.value) StartScreen
|
||||
else LibraryScreen,
|
||||
transitionSpec = { lastEvent ->
|
||||
when (lastEvent) {
|
||||
|
|
@ -169,6 +162,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
cacheDir.deleteRecursively()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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<MainState> = 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<Boolean>) {
|
||||
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 <V> handleDatastoreUpdate(
|
||||
key: Preferences.Key<V>,
|
||||
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 <T> MutableStateFlow<T>.update(function: (T) -> T) {
|
||||
mutex.withLock {
|
||||
yield()
|
||||
this.value = function(this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> = provideDefaultValue { emptyList() },
|
||||
val browsePinnedPaths: List<String> = provideDefaultValue { emptyList() },
|
||||
) : Parcelable {
|
||||
companion object {
|
||||
private fun <D> provideDefaultValue(calculation: () -> D): D {
|
||||
return calculation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes [MainState] by given [Map].
|
||||
* If no value provided in [data], assigns default value.
|
||||
*/
|
||||
fun initialize(data: Map<String, Any>): MainState {
|
||||
val defaultState = MainState()
|
||||
fun <V, T> provideValue(
|
||||
key: Preferences.Key<T>,
|
||||
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 },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
|
|
@ -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<ReaderModel>()
|
||||
val mainModel = hiltViewModel<MainModel>()
|
||||
val settingsModel = hiltViewModel<SettingsModel>()
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
|
||||
val mainState = mainModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
val settingsModel = hiltViewModel<SettingsModel>()
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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<SettingsManager> {
|
||||
error("No settings provided")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ProvideSettings(settings: SettingsManager, content: @Composable () -> Unit) {
|
||||
CompositionLocalProvider(LocalSettings provides settings) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
|
@ -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(top = 18.dp, bottom = 8.dp)
|
||||
.padding(horizontal = 18.dp)
|
||||
.fillMaxWidth(),
|
||||
onClick = {
|
||||
BrowseScreen.refreshListChannel.trySend(Unit)
|
||||
changeShowStartScreen(MainEvent.OnChangeShowStartScreen(false))
|
||||
changeShowStartScreen(false)
|
||||
navigateToBrowse()
|
||||
}
|
||||
) {
|
||||
StyledText(text = stringResource(id = R.string.done))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<CategorySort>,
|
||||
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)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
||||
val settingsModel = hiltViewModel<SettingsModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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 {
|
||||
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
|
||||
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]
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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,30 +26,28 @@ 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(
|
||||
settings.italic.update(
|
||||
when (it.id) {
|
||||
"italic" -> true
|
||||
else -> false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MainModel>()
|
||||
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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue