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>) {
|
fun <T> MutableList<T>.addAll(calculation: () -> List<T>) {
|
||||||
addAll(calculation())
|
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.BookRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.CategoryRepositoryImpl
|
import ua.acclorite.book_story.data.repository.CategoryRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl
|
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.FileSystemRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl
|
import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.PermissionRepositoryImpl
|
import ua.acclorite.book_story.data.repository.PermissionRepositoryImpl
|
||||||
import ua.acclorite.book_story.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import ua.acclorite.book_story.domain.repository.CategoryRepository
|
import ua.acclorite.book_story.domain.repository.CategoryRepository
|
||||||
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
|
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.FileSystemRepository
|
||||||
import ua.acclorite.book_story.domain.repository.HistoryRepository
|
import ua.acclorite.book_story.domain.repository.HistoryRepository
|
||||||
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
||||||
|
|
@ -71,12 +69,6 @@ abstract class RepositoryModule {
|
||||||
colorPresetRepositoryImpl: ColorPresetRepositoryImpl
|
colorPresetRepositoryImpl: ColorPresetRepositoryImpl
|
||||||
): ColorPresetRepository
|
): ColorPresetRepository
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun bindDataStoreRepository(
|
|
||||||
dataStoreRepositoryImpl: DataStoreRepositoryImpl
|
|
||||||
): DataStoreRepository
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@Singleton
|
@Singleton
|
||||||
abstract fun bindFileSystemRepository(
|
abstract fun bindFileSystemRepository(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,5 @@ import androidx.datastore.preferences.core.Preferences
|
||||||
|
|
||||||
interface DataStore {
|
interface DataStore {
|
||||||
suspend fun <T> getNullableData(key: Preferences.Key<T>): T?
|
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)
|
suspend fun <T> putData(key: Preferences.Key<T>, value: T)
|
||||||
}
|
}
|
||||||
|
|
@ -10,12 +10,8 @@ import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.emptyPreferences
|
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
import kotlinx.coroutines.flow.catch
|
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import java.io.IOException
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private val Context.dataStore by preferencesDataStore("data_store")
|
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 {
|
class DataStoreImpl @Inject constructor(context: Application) : DataStore {
|
||||||
private val dataStore = context.dataStore
|
private val dataStore = context.dataStore
|
||||||
|
|
||||||
/**
|
override suspend fun <T> getNullableData(key: Preferences.Key<T>): T? {
|
||||||
* Gets data from DataStore by given [key]. If no such [key] exists, returns null.
|
return try {
|
||||||
*/
|
dataStore.data.firstOrNull()?.get(key)
|
||||||
override suspend fun <T> getNullableData(key: Preferences.Key<T>): T? =
|
} catch (_: Exception) {
|
||||||
dataStore.data.catch { exception ->
|
null
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts data in DataStore by given [key].
|
|
||||||
*/
|
|
||||||
override suspend fun <T> putData(key: Preferences.Key<T>, value: T) {
|
override suspend fun <T> putData(key: Preferences.Key<T>, value: T) {
|
||||||
dataStore.edit { preferences ->
|
dataStore.edit { preferences ->
|
||||||
preferences[key] = value
|
preferences[key] = value
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ package ua.acclorite.book_story.data.model.common
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
import ua.acclorite.book_story.core.ui.UIText
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed class NullableBook(
|
sealed class NullableBook(
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@
|
||||||
|
|
||||||
package ua.acclorite.book_story.data.parser
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
|
|
||||||
|
|
||||||
interface FileParser {
|
interface FileParser {
|
||||||
suspend fun parse(cachedFile: CachedFile): BookWithCover?
|
suspend fun parse(cachedFile: CachedFile): BookWithCover?
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
package ua.acclorite.book_story.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import android.util.Log
|
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.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.epub.EpubFileParser
|
||||||
import ua.acclorite.book_story.data.parser.fb2.Fb2FileParser
|
import ua.acclorite.book_story.data.parser.fb2.Fb2FileParser
|
||||||
import ua.acclorite.book_story.data.parser.html.HtmlFileParser
|
import ua.acclorite.book_story.data.parser.html.HtmlFileParser
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import org.jsoup.Jsoup
|
||||||
import org.jsoup.parser.Parser
|
import org.jsoup.parser.Parser
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.library.Book
|
import ua.acclorite.book_story.domain.model.library.Book
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import org.jsoup.Jsoup
|
||||||
import org.jsoup.parser.Parser
|
import org.jsoup.parser.Parser
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.library.Book
|
import ua.acclorite.book_story.domain.model.library.Book
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import org.jsoup.Jsoup
|
||||||
import org.jsoup.parser.Parser
|
import org.jsoup.parser.Parser
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.library.Book
|
import ua.acclorite.book_story.domain.model.library.Book
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
|
||||||
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.library.Book
|
import ua.acclorite.book_story.domain.model.library.Book
|
||||||
import javax.inject.Inject
|
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.R
|
||||||
import ua.acclorite.book_story.core.ui.UIText
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.library.Book
|
import ua.acclorite.book_story.domain.model.library.Book
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ import ua.acclorite.book_story.domain.repository.ColorPresetRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
/**
|
|
||||||
* Color Preset repository.
|
|
||||||
* Manages all [ColorPreset] related work.
|
|
||||||
*/
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class ColorPresetRepositoryImpl @Inject constructor(
|
class ColorPresetRepositoryImpl @Inject constructor(
|
||||||
private val database: BookDao,
|
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.core.data.ExtensionsData
|
||||||
import ua.acclorite.book_story.data.local.room.BookDao
|
import ua.acclorite.book_story.data.local.room.BookDao
|
||||||
import ua.acclorite.book_story.data.mapper.file.FileMapper
|
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.file.CachedFile
|
||||||
import ua.acclorite.book_story.data.model.library.BookWithCover
|
|
||||||
import ua.acclorite.book_story.data.parser.FileParser
|
import ua.acclorite.book_story.data.parser.FileParser
|
||||||
import ua.acclorite.book_story.domain.model.file.File
|
import ua.acclorite.book_story.domain.model.file.File
|
||||||
import ua.acclorite.book_story.domain.repository.FileSystemRepository
|
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
|
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
|
import ua.acclorite.book_story.domain.model.file.File
|
||||||
|
|
||||||
interface FileSystemRepository {
|
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.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
|
@ -24,12 +23,13 @@ import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.parcelize.IgnoredOnParcel
|
import kotlinx.parcelize.IgnoredOnParcel
|
||||||
import kotlinx.parcelize.Parcelize
|
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.browse.model.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.library.LibraryScreen
|
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.navigator.Screen
|
||||||
import ua.acclorite.book_story.presentation.settings.BrowseSettingsScreen
|
import ua.acclorite.book_story.presentation.settings.BrowseSettingsScreen
|
||||||
import ua.acclorite.book_story.ui.browse.BrowseContent
|
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
|
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
|
@ -64,10 +64,9 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val screenModel = hiltViewModel<BrowseModel>()
|
val screenModel = hiltViewModel<BrowseModel>()
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
|
|
||||||
val state = screenModel.state.collectAsStateWithLifecycle()
|
val state = screenModel.state.collectAsStateWithLifecycle()
|
||||||
val mainState = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val listState = rememberLazyListState(initialListIndex, initialListOffset)
|
val listState = rememberLazyListState(initialListIndex, initialListOffset)
|
||||||
val gridState = rememberLazyGridState(initialGridIndex, initialGridOffset)
|
val gridState = rememberLazyGridState(initialGridIndex, initialGridOffset)
|
||||||
|
|
@ -85,16 +84,19 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val files = remember {
|
val files = remember(
|
||||||
derivedStateOf {
|
state.value.files,
|
||||||
|
settings.browseIncludedFilterItems.value,
|
||||||
|
settings.browseSortOrderDescending.value,
|
||||||
|
settings.browseSortOrder.value
|
||||||
|
) {
|
||||||
screenModel.filterList(
|
screenModel.filterList(
|
||||||
files = state.value.files,
|
files = state.value.files,
|
||||||
sortOrderDescending = mainState.value.browseSortOrderDescending,
|
sortOrderDescending = settings.browseSortOrderDescending.lastValue,
|
||||||
includedFilterItems = mainState.value.browseIncludedFilterItems,
|
includedFilterItems = settings.browseIncludedFilterItems.lastValue,
|
||||||
sortOrder = mainState.value.browseSortOrder
|
sortOrder = settings.browseSortOrder.lastValue
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
resetScrollPositionCompositionChannel.receiveAsFlow().collectLatest {
|
resetScrollPositionCompositionChannel.receiveAsFlow().collectLatest {
|
||||||
|
|
@ -112,7 +114,7 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
initialGridIndex = 0
|
initialGridIndex = 0
|
||||||
initialGridOffset = 0
|
initialGridOffset = 0
|
||||||
|
|
||||||
when (mainState.value.browseLayout) {
|
when (settings.browseLayout.lastValue) {
|
||||||
BrowseLayout.LIST -> {
|
BrowseLayout.LIST -> {
|
||||||
initialListIndex = listState.firstVisibleItemIndex
|
initialListIndex = listState.firstVisibleItemIndex
|
||||||
initialListOffset = listState.firstVisibleItemScrollOffset
|
initialListOffset = listState.firstVisibleItemScrollOffset
|
||||||
|
|
@ -127,7 +129,7 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowseContent(
|
BrowseContent(
|
||||||
files = files.value,
|
files = files,
|
||||||
selectedBooksAddDialog = state.value.selectedBooksAddDialog,
|
selectedBooksAddDialog = state.value.selectedBooksAddDialog,
|
||||||
refreshState = refreshState,
|
refreshState = refreshState,
|
||||||
loadingAddDialog = state.value.loadingAddDialog,
|
loadingAddDialog = state.value.loadingAddDialog,
|
||||||
|
|
@ -135,11 +137,11 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
bottomSheet = state.value.bottomSheet,
|
bottomSheet = state.value.bottomSheet,
|
||||||
listState = listState,
|
listState = listState,
|
||||||
gridState = gridState,
|
gridState = gridState,
|
||||||
layout = mainState.value.browseLayout,
|
layout = settings.browseLayout.value,
|
||||||
gridSize = mainState.value.browseGridSize,
|
gridSize = settings.browseGridSize.value,
|
||||||
autoGridSize = mainState.value.browseAutoGridSize,
|
autoGridSize = settings.browseAutoGridSize.value,
|
||||||
includedFilterItems = mainState.value.browseIncludedFilterItems,
|
includedFilterItems = settings.browseIncludedFilterItems.value,
|
||||||
pinnedPaths = mainState.value.browsePinnedPaths,
|
pinnedPaths = settings.browsePinnedPaths.value,
|
||||||
canScrollBackList = listState.canScrollBackward,
|
canScrollBackList = listState.canScrollBackward,
|
||||||
canScrollBackGrid = gridState.canScrollBackward,
|
canScrollBackGrid = gridState.canScrollBackward,
|
||||||
hasSelectedItems = state.value.hasSelectedItems,
|
hasSelectedItems = state.value.hasSelectedItems,
|
||||||
|
|
@ -147,7 +149,7 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
isRefreshing = state.value.isRefreshing,
|
isRefreshing = state.value.isRefreshing,
|
||||||
isLoading = state.value.isLoading,
|
isLoading = state.value.isLoading,
|
||||||
dialogHidden = state.value.dialog == null,
|
dialogHidden = state.value.dialog == null,
|
||||||
filesEmpty = files.value.isEmpty(),
|
filesEmpty = files.isEmpty(),
|
||||||
showSearch = state.value.showSearch,
|
showSearch = state.value.showSearch,
|
||||||
searchQuery = state.value.searchQuery,
|
searchQuery = state.value.searchQuery,
|
||||||
focusRequester = focusRequester,
|
focusRequester = focusRequester,
|
||||||
|
|
@ -164,7 +166,11 @@ object BrowseScreen : Screen, Parcelable {
|
||||||
dismissAddDialog = screenModel::onEvent,
|
dismissAddDialog = screenModel::onEvent,
|
||||||
selectAddDialog = screenModel::onEvent,
|
selectAddDialog = screenModel::onEvent,
|
||||||
actionAddDialog = screenModel::onEvent,
|
actionAddDialog = screenModel::onEvent,
|
||||||
changePinnedPaths = mainModel::onEvent,
|
updatePinnedPaths = {
|
||||||
|
settings.browsePinnedPaths.update(
|
||||||
|
settings.browsePinnedPaths.lastValue.toggle(it)
|
||||||
|
)
|
||||||
|
},
|
||||||
navigateToLibrary = {
|
navigateToLibrary = {
|
||||||
navigator.push(LibraryScreen, saveInBackStack = false)
|
navigator.push(LibraryScreen, saveInBackStack = false)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.core.view.WindowCompat
|
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.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() {
|
class CrashActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,12 @@ import android.os.Parcelable
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
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.navigator.Screen
|
||||||
import ua.acclorite.book_story.presentation.start.StartScreen
|
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.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.help.HelpContent
|
||||||
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
||||||
|
|
||||||
|
|
@ -28,7 +26,7 @@ data class HelpScreen(val fromStart: Boolean) : Screen, Parcelable {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
|
|
||||||
val (scrollBehavior, listState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
|
val (scrollBehavior, listState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
|
||||||
|
|
||||||
|
|
@ -36,12 +34,12 @@ data class HelpScreen(val fromStart: Boolean) : Screen, Parcelable {
|
||||||
fromStart = fromStart,
|
fromStart = fromStart,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
listState = listState,
|
listState = listState,
|
||||||
changeShowStartScreen = mainModel::onEvent,
|
changeShowStartScreen = { settings.showStartScreen.update(it) },
|
||||||
navigateToBrowse = {
|
navigateToBrowse = {
|
||||||
navigator.push(BrowseScreen, saveInBackStack = false)
|
navigator.push(BrowseScreen, saveInBackStack = false)
|
||||||
},
|
},
|
||||||
navigateToStart = {
|
navigateToStart = {
|
||||||
mainModel.onEvent(MainEvent.OnChangeShowStartScreen(true))
|
settings.showStartScreen.update(true)
|
||||||
navigator.push(StartScreen, saveInBackStack = false)
|
navigator.push(StartScreen, saveInBackStack = false)
|
||||||
},
|
},
|
||||||
navigateBack = {
|
navigateBack = {
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ import kotlinx.parcelize.Parcelize
|
||||||
import ua.acclorite.book_story.presentation.book_info.BookInfoScreen
|
import ua.acclorite.book_story.presentation.book_info.BookInfoScreen
|
||||||
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
||||||
import ua.acclorite.book_story.presentation.history.HistoryScreen
|
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.navigator.Screen
|
||||||
import ua.acclorite.book_story.presentation.reader.ReaderScreen
|
import ua.acclorite.book_story.presentation.reader.ReaderScreen
|
||||||
import ua.acclorite.book_story.presentation.settings.LibrarySettingsScreen
|
import ua.acclorite.book_story.presentation.settings.LibrarySettingsScreen
|
||||||
import ua.acclorite.book_story.presentation.settings.SettingsModel
|
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.library.LibraryContent
|
||||||
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
||||||
|
|
||||||
|
|
@ -59,22 +59,23 @@ object LibraryScreen : Screen, Parcelable {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
|
|
||||||
val screenModel = hiltViewModel<LibraryModel>()
|
val screenModel = hiltViewModel<LibraryModel>()
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
|
||||||
val settingsModel = hiltViewModel<SettingsModel>()
|
val settingsModel = hiltViewModel<SettingsModel>()
|
||||||
|
val settings = LocalSettings.current
|
||||||
|
|
||||||
val state = screenModel.state.collectAsStateWithLifecycle()
|
val state = screenModel.state.collectAsStateWithLifecycle()
|
||||||
val mainState = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
val settingsState = settingsModel.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 {
|
derivedStateOf {
|
||||||
val categoryIds = settingsState.value.categories.map { it.id }.toSet()
|
val categoryIds = settingsState.value.categories.map { it.id }.toSet()
|
||||||
state.value.books.any { book ->
|
state.value.books.any { book ->
|
||||||
book.data.categories.none { category -> category in categoryIds }
|
book.data.categories.none { category -> category in categoryIds }
|
||||||
} || settingsState.value.categories.isEmpty()
|
} || settingsState.value.categories.isEmpty() || settings.libraryShowDefaultTab.lastValue
|
||||||
|| mainState.value.libraryAlwaysShowDefaultTab
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,11 +109,11 @@ object LibraryScreen : Screen, Parcelable {
|
||||||
books = state.value.books,
|
books = state.value.books,
|
||||||
selectedItemsCount = state.value.selectedItemsCount,
|
selectedItemsCount = state.value.selectedItemsCount,
|
||||||
hasSelectedItems = state.value.hasSelectedItems,
|
hasSelectedItems = state.value.hasSelectedItems,
|
||||||
titlePosition = mainState.value.libraryTitlePosition,
|
titlePosition = settings.libraryTitlePosition.value,
|
||||||
readButton = mainState.value.libraryReadButton,
|
readButton = settings.libraryShowReadButton.value,
|
||||||
showProgress = mainState.value.libraryShowProgress,
|
showProgress = settings.libraryShowProgress.value,
|
||||||
showCategoryTabs = mainState.value.libraryShowCategoryTabs,
|
showCategoryTabs = settings.libraryShowCategoryTabs.value,
|
||||||
showBookCount = mainState.value.libraryShowBookCount,
|
showBookCount = settings.libraryShowBookCount.value,
|
||||||
showSearch = state.value.showSearch,
|
showSearch = state.value.showSearch,
|
||||||
searchQuery = state.value.searchQuery,
|
searchQuery = state.value.searchQuery,
|
||||||
bookCount = state.value.books.count(),
|
bookCount = state.value.books.count(),
|
||||||
|
|
@ -120,22 +121,22 @@ object LibraryScreen : Screen, Parcelable {
|
||||||
pagerState = pagerState,
|
pagerState = pagerState,
|
||||||
isLoading = state.value.isLoading,
|
isLoading = state.value.isLoading,
|
||||||
isRefreshing = state.value.isRefreshing,
|
isRefreshing = state.value.isRefreshing,
|
||||||
doublePressExit = mainState.value.doublePressExit,
|
doublePressExit = settings.doublePressExit.value,
|
||||||
layout = mainState.value.libraryLayout,
|
layout = settings.libraryLayout.value,
|
||||||
gridSize = mainState.value.libraryGridSize,
|
gridSize = settings.libraryGridSize.value,
|
||||||
autoGridSize = mainState.value.libraryAutoGridSize,
|
autoGridSize = settings.libraryAutoGridSize.value,
|
||||||
categories = settingsState.value.categories,
|
categories = settingsState.value.categories,
|
||||||
showDefaultCategory = showDefaultCategory.value,
|
showDefaultCategory = showDefaultCategory.value,
|
||||||
categoriesSort = settingsState.value.categoriesSort,
|
categoriesSort = settingsState.value.categoriesSort,
|
||||||
sortOrder = mainState.value.librarySortOrder,
|
sortOrder = settings.librarySortOrder.value,
|
||||||
sortOrderDescending = mainState.value.librarySortOrderDescending,
|
sortOrderDescending = settings.librarySortOrderDescending.value,
|
||||||
perCategorySort = mainState.value.libraryPerCategorySort,
|
perCategorySort = settings.libraryPerCategorySort.value,
|
||||||
refreshState = refreshState,
|
refreshState = refreshState,
|
||||||
dialog = state.value.dialog,
|
dialog = state.value.dialog,
|
||||||
bottomSheet = state.value.bottomSheet,
|
bottomSheet = state.value.bottomSheet,
|
||||||
updateCategorySort = settingsModel::onEvent,
|
updateCategorySort = settingsModel::onEvent,
|
||||||
changeLibrarySortOrder = mainModel::onEvent,
|
changeSortOrder = { settings.librarySortOrder.update(it) },
|
||||||
changeLibrarySortOrderDescending = mainModel::onEvent,
|
changeSortOrderDescending = { settings.librarySortOrderDescending.update(it) },
|
||||||
selectBook = screenModel::onEvent,
|
selectBook = screenModel::onEvent,
|
||||||
searchVisibility = screenModel::onEvent,
|
searchVisibility = screenModel::onEvent,
|
||||||
requestFocus = screenModel::onEvent,
|
requestFocus = screenModel::onEvent,
|
||||||
|
|
|
||||||
|
|
@ -23,44 +23,42 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import ua.acclorite.book_story.R
|
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.BrowseModel
|
||||||
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
||||||
import ua.acclorite.book_story.presentation.history.HistoryModel
|
import ua.acclorite.book_story.presentation.history.HistoryModel
|
||||||
import ua.acclorite.book_story.presentation.history.HistoryScreen
|
import ua.acclorite.book_story.presentation.history.HistoryScreen
|
||||||
import ua.acclorite.book_story.presentation.library.LibraryModel
|
import ua.acclorite.book_story.presentation.library.LibraryModel
|
||||||
import ua.acclorite.book_story.presentation.library.LibraryScreen
|
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.NavigatorItem
|
||||||
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
||||||
import ua.acclorite.book_story.presentation.settings.SettingsModel
|
import ua.acclorite.book_story.presentation.settings.SettingsModel
|
||||||
import ua.acclorite.book_story.presentation.start.StartScreen
|
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_bar.NavigationBar
|
||||||
import ua.acclorite.book_story.ui.common.components.navigation_rail.NavigationRail
|
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.main.MainActivityKeyboardManager
|
||||||
import ua.acclorite.book_story.ui.navigator.Navigator
|
import ua.acclorite.book_story.ui.navigator.Navigator
|
||||||
import ua.acclorite.book_story.ui.navigator.NavigatorTabs
|
import ua.acclorite.book_story.ui.navigator.NavigatorTabs
|
||||||
import ua.acclorite.book_story.ui.theme.BookStoryTheme
|
import ua.acclorite.book_story.ui.theme.BookStoryTheme
|
||||||
import ua.acclorite.book_story.ui.theme.Transitions
|
import ua.acclorite.book_story.ui.theme.Transitions
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("DiscouragedPrivateApi")
|
@SuppressLint("DiscouragedPrivateApi")
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
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()
|
private val settingsModel: SettingsModel by viewModels()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
// Splash screen
|
installSplashScreen().setKeepOnScreenCondition {
|
||||||
installSplashScreen().apply {
|
!settings.initialized.value || !settingsModel.isReady.value
|
||||||
setKeepOnScreenCondition {
|
|
||||||
!mainModel.isReady.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default super
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// Bigger Cursor size for Room
|
// Bigger Cursor size for Room
|
||||||
|
|
@ -72,9 +70,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializing the MainModel
|
|
||||||
mainModel.init(settingsModel.isReady)
|
|
||||||
|
|
||||||
// Edge to edge
|
// Edge to edge
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
@ -85,9 +80,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
val historyModel = hiltViewModel<HistoryModel>()
|
val historyModel = hiltViewModel<HistoryModel>()
|
||||||
val browseModel = hiltViewModel<BrowseModel>()
|
val browseModel = hiltViewModel<BrowseModel>()
|
||||||
|
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
ProvideSettings(settings) {
|
||||||
val isLoaded = mainModel.isReady.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val tabs = persistentListOf(
|
val tabs = persistentListOf(
|
||||||
NavigatorItem(
|
NavigatorItem(
|
||||||
screen = LibraryScreen,
|
screen = LibraryScreen,
|
||||||
|
|
@ -114,15 +107,15 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
MainActivityKeyboardManager()
|
MainActivityKeyboardManager()
|
||||||
|
|
||||||
if (isLoaded.value) {
|
if (settings.initialized.collectAsStateWithLifecycle().value) {
|
||||||
BookStoryTheme(
|
BookStoryTheme(
|
||||||
theme = state.value.theme,
|
theme = settings.theme.value,
|
||||||
isDark = state.value.darkTheme.isDark(),
|
isDark = settings.darkTheme.value.isDark(),
|
||||||
isPureDark = state.value.pureDark.isPureDark(this),
|
isPureDark = settings.pureDark.value.isPureDark(this),
|
||||||
themeContrast = state.value.themeContrast
|
themeContrast = settings.themeContrast.value
|
||||||
) {
|
) {
|
||||||
Navigator(
|
Navigator(
|
||||||
initialScreen = if (state.value.showStartScreen) StartScreen
|
initialScreen = if (settings.showStartScreen.value) StartScreen
|
||||||
else LibraryScreen,
|
else LibraryScreen,
|
||||||
transitionSpec = { lastEvent ->
|
transitionSpec = { lastEvent ->
|
||||||
when (lastEvent) {
|
when (lastEvent) {
|
||||||
|
|
@ -169,6 +162,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
cacheDir.deleteRecursively()
|
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 kotlinx.parcelize.Parcelize
|
||||||
import ua.acclorite.book_story.core.helpers.calculateProgress
|
import ua.acclorite.book_story.core.helpers.calculateProgress
|
||||||
import ua.acclorite.book_story.presentation.book_info.BookInfoScreen
|
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.navigator.Screen
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects
|
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.ReaderProgressCount
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment
|
import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.presentation.settings.SettingsModel
|
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.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.common.helpers.setBrightness
|
||||||
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
||||||
import ua.acclorite.book_story.ui.reader.ReaderContent
|
import ua.acclorite.book_story.ui.reader.ReaderContent
|
||||||
import ua.acclorite.book_story.ui.reader.data.ReaderData
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
|
@ -72,11 +71,10 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val screenModel = hiltViewModel<ReaderModel>()
|
val screenModel = hiltViewModel<ReaderModel>()
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
|
||||||
val settingsModel = hiltViewModel<SettingsModel>()
|
val settingsModel = hiltViewModel<SettingsModel>()
|
||||||
|
val settings = LocalSettings.current
|
||||||
|
|
||||||
val state = screenModel.state.collectAsStateWithLifecycle()
|
val state = screenModel.state.collectAsStateWithLifecycle()
|
||||||
val mainState = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
val settingsState = settingsModel.state.collectAsStateWithLifecycle()
|
val settingsState = settingsModel.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val activity = LocalActivity.current
|
val activity = LocalActivity.current
|
||||||
|
|
@ -99,12 +97,12 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
if (velocity in -70f..70f) return@let
|
if (velocity in -70f..70f) return@let
|
||||||
if (!state.value.showMenu) return@let
|
if (!state.value.showMenu) return@let
|
||||||
if (state.value.lockMenu) return@let
|
if (state.value.lockMenu) return@let
|
||||||
if (!mainState.value.hideBarsOnFastScroll) return@let
|
if (!settings.hideBarsOnFastScroll.lastValue) return@let
|
||||||
|
|
||||||
screenModel.onEvent(
|
screenModel.onEvent(
|
||||||
ReaderEvent.OnMenuVisibility(
|
ReaderEvent.OnMenuVisibility(
|
||||||
show = false,
|
show = false,
|
||||||
fullscreenMode = mainState.value.fullscreen,
|
fullscreenMode = settings.fullscreen.lastValue,
|
||||||
saveCheckpoint = false,
|
saveCheckpoint = false,
|
||||||
activity = activity
|
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(
|
val backgroundColor = animateColorAsState(
|
||||||
targetValue = settingsState.value.selectedColorPreset.backgroundColor
|
targetValue = settingsState.value.selectedColorPreset.backgroundColor
|
||||||
)
|
)
|
||||||
|
|
@ -130,89 +121,87 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
targetValue = settingsState.value.selectedColorPreset.fontColor
|
targetValue = settingsState.value.selectedColorPreset.fontColor
|
||||||
)
|
)
|
||||||
val lineHeight = remember(
|
val lineHeight = remember(
|
||||||
mainState.value.fontSize,
|
settings.fontSize.value,
|
||||||
mainState.value.lineHeight
|
settings.lineHeight.value
|
||||||
) {
|
) {
|
||||||
(mainState.value.fontSize + mainState.value.lineHeight).sp
|
(settings.fontSize.lastValue + settings.lineHeight.lastValue).sp
|
||||||
}
|
}
|
||||||
val letterSpacing = remember(mainState.value.letterSpacing) {
|
val letterSpacing = remember(settings.letterSpacing.value) {
|
||||||
(mainState.value.letterSpacing / 100f).em
|
(settings.letterSpacing.lastValue / 100f).em
|
||||||
}
|
}
|
||||||
val sidePadding = remember(mainState.value.sidePadding) {
|
val sidePadding = remember(settings.sidePadding.value) {
|
||||||
(mainState.value.sidePadding * 3).dp
|
(settings.sidePadding.lastValue * 3).dp
|
||||||
}
|
}
|
||||||
val verticalPadding = remember(mainState.value.verticalPadding) {
|
val verticalPadding = remember(settings.verticalPadding.value) {
|
||||||
(mainState.value.verticalPadding * 4.5f).dp
|
(settings.verticalPadding.lastValue * 4.5f).dp
|
||||||
}
|
}
|
||||||
val paragraphHeight = remember(
|
val paragraphHeight = remember(
|
||||||
mainState.value.paragraphHeight,
|
settings.paragraphHeight.value,
|
||||||
mainState.value.lineHeight
|
settings.lineHeight.value
|
||||||
) {
|
) {
|
||||||
((mainState.value.paragraphHeight * 3).dp).coerceAtLeast(
|
((settings.paragraphHeight.lastValue * 3).dp).coerceAtLeast(
|
||||||
with(density) { mainState.value.lineHeight.sp.toDp().value * 0.5f }.dp
|
with(density) { settings.lineHeight.lastValue.sp.toDp().value * 0.5f }.dp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val fontStyle = remember(mainState.value.isItalic) {
|
val fontStyle = remember(settings.italic.value) {
|
||||||
when (mainState.value.isItalic) {
|
when (settings.italic.lastValue) {
|
||||||
true -> FontStyle.Italic
|
true -> FontStyle.Italic
|
||||||
false -> FontStyle.Normal
|
false -> FontStyle.Normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val paragraphIndentation = remember(
|
val paragraphIndentation = remember(
|
||||||
mainState.value.paragraphIndentation,
|
settings.paragraphIndentation.value,
|
||||||
mainState.value.textAlignment
|
settings.textAlignment.value
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
mainState.value.textAlignment == ReaderTextAlignment.CENTER ||
|
settings.textAlignment.lastValue == ReaderTextAlignment.CENTER ||
|
||||||
mainState.value.textAlignment == ReaderTextAlignment.END
|
settings.textAlignment.lastValue == ReaderTextAlignment.END
|
||||||
) {
|
) return@remember 0.sp
|
||||||
return@remember 0.sp
|
(settings.paragraphIndentation.lastValue * 6).sp
|
||||||
}
|
|
||||||
(mainState.value.paragraphIndentation * 6).sp
|
|
||||||
}
|
}
|
||||||
val perceptionExpanderPadding = remember(
|
val perceptionExpanderPadding = remember(
|
||||||
sidePadding,
|
sidePadding,
|
||||||
mainState.value.perceptionExpanderPadding
|
settings.perceptionExpanderPadding.value
|
||||||
) {
|
) {
|
||||||
sidePadding + (mainState.value.perceptionExpanderPadding * 8).dp
|
sidePadding + (settings.perceptionExpanderPadding.lastValue * 8).dp
|
||||||
}
|
}
|
||||||
val perceptionExpanderThickness = remember(
|
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) {
|
val horizontalGestureSensitivity = remember(settings.horizontalGestureSensitivity.value) {
|
||||||
(36f + mainState.value.horizontalGestureSensitivity * (4f - 36f)).dp
|
(36f + settings.horizontalGestureSensitivity.lastValue * (4f - 36f)).dp
|
||||||
}
|
}
|
||||||
val highlightedReadingThickness = remember(mainState.value.highlightedReadingThickness) {
|
val highlightedReadingThickness = remember(settings.highlightedReadingThickness.value) {
|
||||||
when (mainState.value.highlightedReadingThickness) {
|
when (settings.highlightedReadingThickness.lastValue) {
|
||||||
2 -> FontWeight.SemiBold
|
2 -> FontWeight.SemiBold
|
||||||
3 -> FontWeight.Bold
|
3 -> FontWeight.Bold
|
||||||
else -> FontWeight.Medium
|
else -> FontWeight.Medium
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val horizontalAlignment = remember(mainState.value.textAlignment) {
|
val horizontalAlignment = remember(settings.textAlignment.value) {
|
||||||
when (mainState.value.textAlignment) {
|
when (settings.textAlignment.lastValue) {
|
||||||
ReaderTextAlignment.START, ReaderTextAlignment.JUSTIFY -> Alignment.Start
|
ReaderTextAlignment.START, ReaderTextAlignment.JUSTIFY -> Alignment.Start
|
||||||
ReaderTextAlignment.CENTER -> Alignment.CenterHorizontally
|
ReaderTextAlignment.CENTER -> Alignment.CenterHorizontally
|
||||||
ReaderTextAlignment.END -> Alignment.End
|
ReaderTextAlignment.END -> Alignment.End
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val imagesWidth = remember(mainState.value.imagesWidth) {
|
val imagesWidth = remember(settings.imagesWidth.value) {
|
||||||
mainState.value.imagesWidth.coerceAtLeast(0.01f)
|
settings.imagesWidth.lastValue.coerceAtLeast(0.01f)
|
||||||
}
|
}
|
||||||
val imagesCornersRoundness = remember(
|
val imagesCornersRoundness = remember(
|
||||||
mainState.value.imagesCornersRoundness,
|
settings.imagesCornersRoundness.value,
|
||||||
mainState.value.imagesWidth
|
settings.imagesWidth.value
|
||||||
) {
|
) {
|
||||||
(mainState.value.imagesCornersRoundness * 3 * imagesWidth).dp
|
(settings.imagesCornersRoundness.lastValue * 3 * imagesWidth).dp
|
||||||
}
|
}
|
||||||
val imagesColorEffects = remember(
|
val imagesColorEffects = remember(
|
||||||
mainState.value.imagesColorEffects,
|
settings.imagesColorEffects.value,
|
||||||
fontColor.value,
|
fontColor.value,
|
||||||
backgroundColor.value
|
backgroundColor.value
|
||||||
) {
|
) {
|
||||||
when (mainState.value.imagesColorEffects) {
|
when (settings.imagesColorEffects.lastValue) {
|
||||||
ReaderColorEffects.OFF -> null
|
ReaderColorEffects.OFF -> null
|
||||||
|
|
||||||
ReaderColorEffects.GRAYSCALE -> ColorFilter.colorMatrix(
|
ReaderColorEffects.GRAYSCALE -> ColorFilter.colorMatrix(
|
||||||
|
|
@ -230,21 +219,21 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val progressBarPadding = remember(mainState.value.progressBarPadding) {
|
val progressBarPadding = remember(settings.progressBarPadding.value) {
|
||||||
(mainState.value.progressBarPadding * 3).dp
|
(settings.progressBarPadding.lastValue * 3).dp
|
||||||
}
|
}
|
||||||
val progressBarFontSize = remember(mainState.value.progressBarFontSize) {
|
val progressBarFontSize = remember(settings.progressBarFontSize.value) {
|
||||||
(mainState.value.progressBarFontSize * 2).sp
|
(settings.progressBarFontSize.lastValue * 2).sp
|
||||||
}
|
}
|
||||||
|
|
||||||
val layoutDirection = LocalLayoutDirection.current
|
val layoutDirection = LocalLayoutDirection.current
|
||||||
val cutoutInsets = WindowInsets.displayCutout
|
val cutoutInsets = WindowInsets.displayCutout
|
||||||
val systemBarsInsets = WindowInsets.systemBarsIgnoringVisibility
|
val systemBarsInsets = WindowInsets.systemBarsIgnoringVisibility
|
||||||
|
|
||||||
val cutoutInsetsPadding = remember(mainState.value.cutoutPadding) {
|
val cutoutInsetsPadding = remember(settings.cutoutPadding.value) {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
cutoutInsets.asPaddingValues(density = density).run {
|
cutoutInsets.asPaddingValues(density = density).run {
|
||||||
if (mainState.value.cutoutPadding) PaddingValues(
|
if (settings.cutoutPadding.lastValue) PaddingValues(
|
||||||
top = calculateTopPadding(),
|
top = calculateTopPadding(),
|
||||||
start = calculateStartPadding(layoutDirection),
|
start = calculateStartPadding(layoutDirection),
|
||||||
end = calculateEndPadding(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 {
|
derivedStateOf {
|
||||||
systemBarsInsets.asPaddingValues(density = density).run {
|
systemBarsInsets.asPaddingValues(density = density).run {
|
||||||
if (!mainState.value.fullscreen) PaddingValues(
|
if (!settings.fullscreen.lastValue) PaddingValues(
|
||||||
top = calculateTopPadding(),
|
top = calculateTopPadding(),
|
||||||
start = calculateStartPadding(layoutDirection),
|
start = calculateStartPadding(layoutDirection),
|
||||||
end = calculateEndPadding(layoutDirection),
|
end = calculateEndPadding(layoutDirection),
|
||||||
|
|
@ -292,16 +281,16 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val bottomBarPadding = remember(mainState.value.bottomBarPadding) {
|
val bottomBarPadding = remember(settings.bottomBarPadding.value) {
|
||||||
(mainState.value.bottomBarPadding * 4f).dp
|
(settings.bottomBarPadding.lastValue * 4f).dp
|
||||||
}
|
}
|
||||||
|
|
||||||
val bookProgress = remember(
|
val bookProgress = remember(
|
||||||
state.value.book.progress,
|
state.value.book.progress,
|
||||||
state.value.text,
|
state.value.text,
|
||||||
mainState.value.progressCount
|
settings.progressCount.value
|
||||||
) {
|
) {
|
||||||
when (mainState.value.progressCount) {
|
when (settings.progressCount.lastValue) {
|
||||||
ReaderProgressCount.PERCENTAGE -> {
|
ReaderProgressCount.PERCENTAGE -> {
|
||||||
"${state.value.book.progress.calculateProgress(2)}%"
|
"${state.value.book.progress.calculateProgress(2)}%"
|
||||||
}
|
}
|
||||||
|
|
@ -318,10 +307,10 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
state.value.book.progress,
|
state.value.book.progress,
|
||||||
state.value.currentChapter,
|
state.value.currentChapter,
|
||||||
state.value.currentChapterProgress,
|
state.value.currentChapterProgress,
|
||||||
mainState.value.progressCount
|
settings.progressCount.value
|
||||||
) {
|
) {
|
||||||
if (state.value.currentChapter == null) return@remember ""
|
if (state.value.currentChapter == null) return@remember ""
|
||||||
when (mainState.value.progressCount) {
|
when (settings.progressCount.lastValue) {
|
||||||
ReaderProgressCount.PERCENTAGE -> {
|
ReaderProgressCount.PERCENTAGE -> {
|
||||||
" (${state.value.currentChapterProgress.calculateProgress(2)}%)"
|
" (${state.value.currentChapterProgress.calculateProgress(2)}%)"
|
||||||
}
|
}
|
||||||
|
|
@ -341,18 +330,18 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
screenModel.init(
|
screenModel.init(
|
||||||
bookId = bookId,
|
bookId = bookId,
|
||||||
fullscreenMode = mainState.value.fullscreen,
|
fullscreenMode = settings.fullscreen.lastValue,
|
||||||
activity = activity,
|
activity = activity,
|
||||||
navigateBack = {
|
navigateBack = {
|
||||||
navigator.pop()
|
navigator.pop()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
LaunchedEffect(mainState.value.fullscreen) {
|
LaunchedEffect(settings.fullscreen.value) {
|
||||||
screenModel.onEvent(
|
screenModel.onEvent(
|
||||||
ReaderEvent.OnMenuVisibility(
|
ReaderEvent.OnMenuVisibility(
|
||||||
show = state.value.showMenu,
|
show = state.value.showMenu,
|
||||||
fullscreenMode = mainState.value.fullscreen,
|
fullscreenMode = settings.fullscreen.lastValue,
|
||||||
saveCheckpoint = false,
|
saveCheckpoint = false,
|
||||||
activity = activity
|
activity = activity
|
||||||
)
|
)
|
||||||
|
|
@ -362,18 +351,18 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
screenModel.updateProgress(listState)
|
screenModel.updateProgress(listState)
|
||||||
}
|
}
|
||||||
|
|
||||||
DisposableEffect(mainState.value.screenOrientation) {
|
DisposableEffect(settings.screenOrientation.value) {
|
||||||
activity.requestedOrientation = mainState.value.screenOrientation.code
|
activity.requestedOrientation = settings.screenOrientation.lastValue.code
|
||||||
onDispose {
|
onDispose {
|
||||||
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DisposableEffect(
|
DisposableEffect(
|
||||||
mainState.value.screenBrightness,
|
settings.screenBrightness.value,
|
||||||
mainState.value.customScreenBrightness
|
settings.customScreenBrightness.value
|
||||||
) {
|
) {
|
||||||
when (mainState.value.customScreenBrightness) {
|
when (settings.customScreenBrightness.lastValue) {
|
||||||
true -> activity.setBrightness(brightness = mainState.value.screenBrightness)
|
true -> activity.setBrightness(brightness = settings.screenBrightness.lastValue)
|
||||||
false -> activity.setBrightness(brightness = null)
|
false -> activity.setBrightness(brightness = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -381,8 +370,8 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
activity.setBrightness(brightness = null)
|
activity.setBrightness(brightness = null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DisposableEffect(mainState.value.keepScreenOn) {
|
DisposableEffect(settings.keepScreenOn.value) {
|
||||||
when (mainState.value.keepScreenOn) {
|
when (settings.keepScreenOn.lastValue) {
|
||||||
true -> activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
true -> activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
false -> activity.window.clearFlags(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,
|
listState = listState,
|
||||||
currentChapter = state.value.currentChapter,
|
currentChapter = state.value.currentChapter,
|
||||||
nestedScrollConnection = nestedScrollConnection.value,
|
nestedScrollConnection = nestedScrollConnection.value,
|
||||||
fastColorPresetChange = mainState.value.fastColorPresetChange,
|
fastColorPresetChange = settings.fastColorPresetChange.value,
|
||||||
perceptionExpander = mainState.value.perceptionExpander,
|
perceptionExpander = settings.perceptionExpander.value,
|
||||||
perceptionExpanderPadding = perceptionExpanderPadding,
|
perceptionExpanderPadding = perceptionExpanderPadding,
|
||||||
perceptionExpanderThickness = perceptionExpanderThickness,
|
perceptionExpanderThickness = perceptionExpanderThickness,
|
||||||
currentChapterProgress = state.value.currentChapterProgress,
|
currentChapterProgress = state.value.currentChapterProgress,
|
||||||
|
|
@ -421,41 +410,41 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
|
||||||
lockMenu = state.value.lockMenu,
|
lockMenu = state.value.lockMenu,
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
verticalPadding = verticalPadding,
|
verticalPadding = verticalPadding,
|
||||||
horizontalGesture = mainState.value.horizontalGesture,
|
horizontalGesture = settings.horizontalGesture.value,
|
||||||
horizontalGestureScroll = mainState.value.horizontalGestureScroll,
|
horizontalGestureScroll = settings.horizontalGestureScroll.value,
|
||||||
horizontalGestureSensitivity = horizontalGestureSensitivity,
|
horizontalGestureSensitivity = horizontalGestureSensitivity,
|
||||||
horizontalGestureAlphaAnim = mainState.value.horizontalGestureAlphaAnim,
|
horizontalGestureAlphaAnim = settings.horizontalGestureAlphaAnim.value,
|
||||||
horizontalGesturePullAnim = mainState.value.horizontalGesturePullAnim,
|
horizontalGesturePullAnim = settings.horizontalGesturePullAnim.value,
|
||||||
highlightedReading = mainState.value.highlightedReading,
|
highlightedReading = settings.highlightedReading.value,
|
||||||
highlightedReadingThickness = highlightedReadingThickness,
|
highlightedReadingThickness = highlightedReadingThickness,
|
||||||
progress = progress,
|
progress = progress,
|
||||||
progressBar = mainState.value.progressBar,
|
progressBar = settings.progressBar.value,
|
||||||
progressBarPadding = progressBarPadding,
|
progressBarPadding = progressBarPadding,
|
||||||
progressBarAlignment = mainState.value.progressBarAlignment,
|
progressBarAlignment = settings.progressBarAlignment.value,
|
||||||
progressBarFontSize = progressBarFontSize,
|
progressBarFontSize = progressBarFontSize,
|
||||||
paragraphHeight = paragraphHeight,
|
paragraphHeight = paragraphHeight,
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
bottomBarPadding = bottomBarPadding,
|
bottomBarPadding = bottomBarPadding,
|
||||||
backgroundColor = backgroundColor.value,
|
backgroundColor = backgroundColor.value,
|
||||||
fontColor = fontColor.value,
|
fontColor = fontColor.value,
|
||||||
images = mainState.value.images,
|
images = settings.images.value,
|
||||||
imagesCaptions = mainState.value.imagesCaptions,
|
imagesCaptions = settings.imagesCaptions.value,
|
||||||
imagesCornersRoundness = imagesCornersRoundness,
|
imagesCornersRoundness = imagesCornersRoundness,
|
||||||
imagesAlignment = mainState.value.imagesAlignment,
|
imagesAlignment = settings.imagesAlignment.value,
|
||||||
imagesWidth = imagesWidth,
|
imagesWidth = imagesWidth,
|
||||||
imagesColorEffects = imagesColorEffects,
|
imagesColorEffects = imagesColorEffects,
|
||||||
fontFamily = fontFamily,
|
fontFamily = settings.fontFamily.value,
|
||||||
lineHeight = lineHeight,
|
lineHeight = lineHeight,
|
||||||
fontThickness = mainState.value.fontThickness,
|
fontThickness = settings.fontThickness.value,
|
||||||
fontStyle = fontStyle,
|
fontStyle = fontStyle,
|
||||||
chapterTitleAlignment = mainState.value.chapterTitleAlignment,
|
chapterTitleAlignment = settings.chapterTitleAlignment.value,
|
||||||
textAlignment = mainState.value.textAlignment,
|
textAlignment = settings.textAlignment.value,
|
||||||
horizontalAlignment = horizontalAlignment,
|
horizontalAlignment = horizontalAlignment,
|
||||||
fontSize = mainState.value.fontSize.sp,
|
fontSize = settings.fontSize.value.sp,
|
||||||
letterSpacing = letterSpacing,
|
letterSpacing = letterSpacing,
|
||||||
paragraphIndentation = paragraphIndentation,
|
paragraphIndentation = paragraphIndentation,
|
||||||
doubleClickTranslation = mainState.value.doubleClickTranslation,
|
doubleClickTranslation = settings.doubleClickTranslation.value,
|
||||||
fullscreenMode = mainState.value.fullscreen,
|
fullscreenMode = settings.fullscreen.value,
|
||||||
selectPreviousPreset = settingsModel::onEvent,
|
selectPreviousPreset = settingsModel::onEvent,
|
||||||
selectNextPreset = settingsModel::onEvent,
|
selectNextPreset = settingsModel::onEvent,
|
||||||
leave = screenModel::onEvent,
|
leave = screenModel::onEvent,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed class SettingsEvent {
|
sealed class SettingsEvent {
|
||||||
|
data class OnUpdateLanguage(
|
||||||
|
val language: String
|
||||||
|
) : SettingsEvent()
|
||||||
|
|
||||||
data class OnGrantPersistableUriPermission(
|
data class OnGrantPersistableUriPermission(
|
||||||
val uri: Uri
|
val uri: Uri
|
||||||
) : SettingsEvent()
|
) : 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.color_preset.UpdateColorPresetUseCase
|
||||||
import ua.acclorite.book_story.domain.use_case.permission.GrantPersistableUriPermissionUseCase
|
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.permission.ReleasePersistableUriPermissionUseCase
|
||||||
|
import ua.acclorite.book_story.domain.use_case.settings.UpdateLanguageUseCase
|
||||||
import ua.acclorite.book_story.ui.common.helpers.showToast
|
import ua.acclorite.book_story.ui.common.helpers.showToast
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SettingsModel @Inject constructor(
|
class SettingsModel @Inject constructor(
|
||||||
|
private val updateLanguageUseCase: UpdateLanguageUseCase,
|
||||||
private val getColorPresetsUseCase: GetColorPresetsUseCase,
|
private val getColorPresetsUseCase: GetColorPresetsUseCase,
|
||||||
private val updateColorPresetUseCase: UpdateColorPresetUseCase,
|
private val updateColorPresetUseCase: UpdateColorPresetUseCase,
|
||||||
private val selectColorPresetUseCase: SelectColorPresetUseCase,
|
private val selectColorPresetUseCase: SelectColorPresetUseCase,
|
||||||
|
|
@ -112,6 +114,8 @@ class SettingsModel @Inject constructor(
|
||||||
|
|
||||||
fun onEvent(event: SettingsEvent) {
|
fun onEvent(event: SettingsEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
|
is SettingsEvent.OnUpdateLanguage -> updateLanguageUseCase(event.language)
|
||||||
|
|
||||||
is SettingsEvent.OnGrantPersistableUriPermission -> {
|
is SettingsEvent.OnGrantPersistableUriPermission -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
grantPersistableUriPermissionUseCase(
|
grantPersistableUriPermissionUseCase(
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,17 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
||||||
import kotlinx.parcelize.IgnoredOnParcel
|
import kotlinx.parcelize.IgnoredOnParcel
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import ua.acclorite.book_story.core.data.CoreData
|
import ua.acclorite.book_story.core.data.CoreData
|
||||||
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
||||||
import ua.acclorite.book_story.presentation.help.HelpScreen
|
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.Screen
|
||||||
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
import ua.acclorite.book_story.ui.navigator.LocalNavigator
|
||||||
import ua.acclorite.book_story.ui.start.StartContent
|
import ua.acclorite.book_story.ui.start.StartContent
|
||||||
|
|
@ -51,22 +51,20 @@ object StartScreen : Screen, Parcelable {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settingsModel = hiltViewModel<SettingsModel>()
|
||||||
|
val settings = LocalSettings.current
|
||||||
val mainState = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val activity = LocalActivity.current
|
val activity = LocalActivity.current
|
||||||
|
|
||||||
val currentPage = remember { mutableIntStateOf(0) }
|
val currentPage = remember { mutableIntStateOf(0) }
|
||||||
val stackEvent = remember { mutableStateOf(StackEvent.Default) }
|
val stackEvent = remember { mutableStateOf(StackEvent.Default) }
|
||||||
|
|
||||||
val languages = remember(mainState.value.language) {
|
val languages = remember(settings.language.value) {
|
||||||
CoreData.languages.sortedBy { it.second }.map {
|
CoreData.languages.sortedBy { it.second }.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.first,
|
id = it.first,
|
||||||
title = it.second,
|
title = it.second,
|
||||||
textStyle = TextStyle(),
|
textStyle = TextStyle(),
|
||||||
selected = it.first == mainState.value.language
|
selected = it.first == settings.language.lastValue
|
||||||
)
|
)
|
||||||
}.sortedBy { it.title }
|
}.sortedBy { it.title }
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +73,7 @@ object StartScreen : Screen, Parcelable {
|
||||||
currentPage = currentPage.intValue,
|
currentPage = currentPage.intValue,
|
||||||
stackEvent = stackEvent.value,
|
stackEvent = stackEvent.value,
|
||||||
languages = languages,
|
languages = languages,
|
||||||
changeLanguage = mainModel::onEvent,
|
updateLanguage = { settingsModel.onEvent(SettingsEvent.OnUpdateLanguage(it)) },
|
||||||
navigateForward = {
|
navigateForward = {
|
||||||
if (currentPage.intValue + 1 == 4) {
|
if (currentPage.intValue + 1 == 4) {
|
||||||
return@StartContent
|
return@StartContent
|
||||||
|
|
@ -98,7 +96,7 @@ object StartScreen : Screen, Parcelable {
|
||||||
saveInBackStack = false
|
saveInBackStack = false
|
||||||
)
|
)
|
||||||
BrowseScreen.refreshListChannel.trySend(Unit)
|
BrowseScreen.refreshListChannel.trySend(Unit)
|
||||||
mainModel.onEvent(MainEvent.OnChangeShowStartScreen(false))
|
settings.showStartScreen.update(false)
|
||||||
},
|
},
|
||||||
navigateToHelp = {
|
navigateToHelp = {
|
||||||
navigator.push(
|
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.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
|
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
|
||||||
import ua.acclorite.book_story.presentation.library.model.SelectableNullableBook
|
import ua.acclorite.book_story.presentation.library.model.SelectableNullableBook
|
||||||
import ua.acclorite.book_story.presentation.main.MainEvent
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -60,7 +59,7 @@ fun BrowseContent(
|
||||||
dismissAddDialog: (BrowseEvent.OnDismissAddDialog) -> Unit,
|
dismissAddDialog: (BrowseEvent.OnDismissAddDialog) -> Unit,
|
||||||
actionAddDialog: (BrowseEvent.OnActionAddDialog) -> Unit,
|
actionAddDialog: (BrowseEvent.OnActionAddDialog) -> Unit,
|
||||||
selectAddDialog: (BrowseEvent.OnSelectAddDialog) -> Unit,
|
selectAddDialog: (BrowseEvent.OnSelectAddDialog) -> Unit,
|
||||||
changePinnedPaths: (MainEvent.OnChangeBrowsePinnedPaths) -> Unit,
|
updatePinnedPaths: (String) -> Unit,
|
||||||
navigateToLibrary: () -> Unit,
|
navigateToLibrary: () -> Unit,
|
||||||
navigateToBrowseSettings: () -> Unit,
|
navigateToBrowseSettings: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
|
@ -109,7 +108,7 @@ fun BrowseContent(
|
||||||
selectFile = selectFile,
|
selectFile = selectFile,
|
||||||
showFilterBottomSheet = showFilterBottomSheet,
|
showFilterBottomSheet = showFilterBottomSheet,
|
||||||
showAddDialog = showAddDialog,
|
showAddDialog = showAddDialog,
|
||||||
changePinnedPaths = changePinnedPaths,
|
updatePinnedPaths = updatePinnedPaths,
|
||||||
navigateToBrowseSettings = navigateToBrowseSettings
|
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.BrowseEvent
|
||||||
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
|
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
|
import ua.acclorite.book_story.ui.theme.DefaultTransition
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
|
@ -57,7 +56,7 @@ fun BrowseScaffold(
|
||||||
selectFile: (BrowseEvent.OnSelectFile) -> Unit,
|
selectFile: (BrowseEvent.OnSelectFile) -> Unit,
|
||||||
showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit,
|
showFilterBottomSheet: (BrowseEvent.OnShowFilterBottomSheet) -> Unit,
|
||||||
showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit,
|
showAddDialog: (BrowseEvent.OnShowAddDialog) -> Unit,
|
||||||
changePinnedPaths: (MainEvent.OnChangeBrowsePinnedPaths) -> Unit,
|
updatePinnedPaths: (String) -> Unit,
|
||||||
navigateToBrowseSettings: () -> Unit,
|
navigateToBrowseSettings: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -107,11 +106,7 @@ fun BrowseScaffold(
|
||||||
header = header,
|
header = header,
|
||||||
pinned = pinned,
|
pinned = pinned,
|
||||||
pin = {
|
pin = {
|
||||||
changePinnedPaths(
|
updatePinnedPaths(header)
|
||||||
MainEvent.OnChangeBrowsePinnedPaths(
|
|
||||||
value = 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
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
|
@ -19,29 +16,25 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.presentation.browse.BrowseScreen
|
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
|
import ua.acclorite.book_story.ui.common.components.common.StyledText
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HelpBottomBar(
|
fun HelpBottomBar(
|
||||||
changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit,
|
changeShowStartScreen: (Boolean) -> Unit,
|
||||||
navigateToBrowse: () -> Unit
|
navigateToBrowse: () -> Unit
|
||||||
) {
|
) {
|
||||||
Column(Modifier.fillMaxWidth()) {
|
|
||||||
Spacer(modifier = Modifier.height(18.dp))
|
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
.padding(bottom = 8.dp)
|
.padding(top = 18.dp, bottom = 8.dp)
|
||||||
.padding(horizontal = 18.dp)
|
.padding(horizontal = 18.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
onClick = {
|
onClick = {
|
||||||
BrowseScreen.refreshListChannel.trySend(Unit)
|
BrowseScreen.refreshListChannel.trySend(Unit)
|
||||||
changeShowStartScreen(MainEvent.OnChangeShowStartScreen(false))
|
changeShowStartScreen(false)
|
||||||
navigateToBrowse()
|
navigateToBrowse()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
StyledText(text = stringResource(id = R.string.done))
|
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.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import ua.acclorite.book_story.presentation.main.MainEvent
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -18,7 +17,7 @@ fun HelpContent(
|
||||||
fromStart: Boolean,
|
fromStart: Boolean,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit,
|
changeShowStartScreen: (Boolean) -> Unit,
|
||||||
navigateToBrowse: () -> Unit,
|
navigateToBrowse: () -> Unit,
|
||||||
navigateToStart: () -> Unit,
|
navigateToStart: () -> Unit,
|
||||||
navigateBack: () -> Unit
|
navigateBack: () -> Unit
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import ua.acclorite.book_story.presentation.main.MainEvent
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -26,7 +25,7 @@ fun HelpScaffold(
|
||||||
fromStart: Boolean,
|
fromStart: Boolean,
|
||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
changeShowStartScreen: (MainEvent.OnChangeShowStartScreen) -> Unit,
|
changeShowStartScreen: (Boolean) -> Unit,
|
||||||
navigateToBrowse: () -> Unit,
|
navigateToBrowse: () -> Unit,
|
||||||
navigateToStart: () -> Unit,
|
navigateToStart: () -> Unit,
|
||||||
navigateBack: () -> 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.LibraryEvent
|
||||||
import ua.acclorite.book_story.presentation.library.LibraryScreen
|
import ua.acclorite.book_story.presentation.library.LibraryScreen
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder
|
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.presentation.settings.SettingsEvent
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -27,8 +26,8 @@ fun LibraryBottomSheet(
|
||||||
sortOrder: LibrarySortOrder,
|
sortOrder: LibrarySortOrder,
|
||||||
sortOrderDescending: Boolean,
|
sortOrderDescending: Boolean,
|
||||||
perCategorySort: Boolean,
|
perCategorySort: Boolean,
|
||||||
changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit,
|
changeSortOrder: (LibrarySortOrder) -> Unit,
|
||||||
changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit,
|
changeSortOrderDescending: (Boolean) -> Unit,
|
||||||
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
||||||
dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit
|
dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
@ -42,8 +41,8 @@ fun LibraryBottomSheet(
|
||||||
sortOrderDescending = sortOrderDescending,
|
sortOrderDescending = sortOrderDescending,
|
||||||
categoriesSort = categoriesSort,
|
categoriesSort = categoriesSort,
|
||||||
perCategorySort = perCategorySort,
|
perCategorySort = perCategorySort,
|
||||||
changeLibrarySortOrder = changeLibrarySortOrder,
|
changeSortOrder = changeSortOrder,
|
||||||
changeLibrarySortOrderDescending = changeLibrarySortOrderDescending,
|
changeSortOrderDescending = changeSortOrderDescending,
|
||||||
updateCategorySort = updateCategorySort,
|
updateCategorySort = updateCategorySort,
|
||||||
dismissBottomSheet = dismissBottomSheet
|
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.LibrarySortOrder
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition
|
import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition
|
||||||
import ua.acclorite.book_story.presentation.library.model.SelectableBook
|
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
|
import ua.acclorite.book_story.presentation.settings.SettingsEvent
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
|
@ -55,8 +54,8 @@ fun LibraryContent(
|
||||||
dialog: Dialog?,
|
dialog: Dialog?,
|
||||||
bottomSheet: BottomSheet?,
|
bottomSheet: BottomSheet?,
|
||||||
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
||||||
changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit,
|
changeSortOrder: (LibrarySortOrder) -> Unit,
|
||||||
changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit,
|
changeSortOrderDescending: (Boolean) -> Unit,
|
||||||
selectBook: (LibraryEvent.OnSelectBook) -> Unit,
|
selectBook: (LibraryEvent.OnSelectBook) -> Unit,
|
||||||
searchVisibility: (LibraryEvent.OnSearchVisibility) -> Unit,
|
searchVisibility: (LibraryEvent.OnSearchVisibility) -> Unit,
|
||||||
requestFocus: (LibraryEvent.OnRequestFocus) -> Unit,
|
requestFocus: (LibraryEvent.OnRequestFocus) -> Unit,
|
||||||
|
|
@ -95,8 +94,8 @@ fun LibraryContent(
|
||||||
sortOrder = sortOrder,
|
sortOrder = sortOrder,
|
||||||
sortOrderDescending = sortOrderDescending,
|
sortOrderDescending = sortOrderDescending,
|
||||||
perCategorySort = perCategorySort,
|
perCategorySort = perCategorySort,
|
||||||
changeLibrarySortOrder = changeLibrarySortOrder,
|
changeSortOrder = changeSortOrder,
|
||||||
changeLibrarySortOrderDescending = changeLibrarySortOrderDescending,
|
changeSortOrderDescending = changeSortOrderDescending,
|
||||||
updateCategorySort = updateCategorySort,
|
updateCategorySort = updateCategorySort,
|
||||||
dismissBottomSheet = dismissBottomSheet
|
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.domain.model.library.CategorySort
|
||||||
import ua.acclorite.book_story.presentation.library.LibraryEvent
|
import ua.acclorite.book_story.presentation.library.LibraryEvent
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder
|
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.presentation.settings.SettingsEvent
|
||||||
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
|
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
|
||||||
import ua.acclorite.book_story.ui.common.components.modal_bottom_sheet.ModalBottomSheet
|
import ua.acclorite.book_story.ui.common.components.modal_bottom_sheet.ModalBottomSheet
|
||||||
|
|
@ -45,8 +44,8 @@ fun LibraryFilterBottomSheet(
|
||||||
sortOrderDescending: Boolean,
|
sortOrderDescending: Boolean,
|
||||||
categoriesSort: List<CategorySort>,
|
categoriesSort: List<CategorySort>,
|
||||||
perCategorySort: Boolean,
|
perCategorySort: Boolean,
|
||||||
changeLibrarySortOrder: (MainEvent.OnChangeLibrarySortOrder) -> Unit,
|
changeSortOrder: (LibrarySortOrder) -> Unit,
|
||||||
changeLibrarySortOrderDescending: (MainEvent.OnChangeLibrarySortOrderDescending) -> Unit,
|
changeSortOrderDescending: (Boolean) -> Unit,
|
||||||
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
updateCategorySort: (SettingsEvent.OnUpdateCategorySort) -> Unit,
|
||||||
dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit
|
dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
@ -123,16 +122,8 @@ fun LibraryFilterBottomSheet(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
changeLibrarySortOrder(
|
changeSortOrder(sortOrder)
|
||||||
MainEvent.OnChangeLibrarySortOrder(
|
changeSortOrderDescending(sortOrderDescending)
|
||||||
sortOrder.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
changeLibrarySortOrderDescending(
|
|
||||||
MainEvent.OnChangeLibrarySortOrderDescending(
|
|
||||||
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.library.Book
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter
|
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.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
|
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness
|
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.reader.model.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.presentation.settings.SettingsEvent
|
import ua.acclorite.book_story.presentation.settings.SettingsEvent
|
||||||
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderContent(
|
fun ReaderContent(
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
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.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness
|
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.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.noRippleClickable
|
||||||
import ua.acclorite.book_story.ui.common.helpers.showToast
|
import ua.acclorite.book_story.ui.common.helpers.showToast
|
||||||
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderLayout(
|
fun ReaderLayout(
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
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.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness
|
import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment
|
import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
import ua.acclorite.book_story.ui.reader.model.FontWithName
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LazyItemScope.ReaderLayoutText(
|
fun LazyItemScope.ReaderLayoutText(
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
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
|
@Composable
|
||||||
fun LazyItemScope.ReaderLayoutTextImage(
|
fun LazyItemScope.ReaderLayoutTextImage(
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.TextUnit
|
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.common.components.common.StyledText
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderProgressBar(
|
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.library.Book
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
import ua.acclorite.book_story.domain.model.reader.ReaderText
|
||||||
import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter
|
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.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
|
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
|
||||||
import ua.acclorite.book_story.presentation.reader.model.ReaderFontThickness
|
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.presentation.settings.SettingsEvent
|
||||||
import ua.acclorite.book_story.ui.common.components.common.AnimatedVisibility
|
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.reader.model.FontWithName
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.appearance.colors.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FastColorPresetChangeOption() {
|
fun FastColorPresetChangeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.fastColorPresetChange,
|
selected = settings.fastColorPresetChange.value,
|
||||||
title = stringResource(id = R.string.fast_color_preset_change_option),
|
title = stringResource(id = R.string.fast_color_preset_change_option),
|
||||||
description = stringResource(id = R.string.fast_color_preset_change_option_desc),
|
description = stringResource(id = R.string.fast_color_preset_change_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.fastColorPresetChange.update(!settings.fastColorPresetChange.lastValue)
|
||||||
MainEvent.OnChangeFastColorPresetChange(
|
|
||||||
!state.value.fastColorPresetChange
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -9,36 +9,26 @@ package ua.acclorite.book_story.ui.settings.appearance.theme_preferences.compone
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AbsoluteDarkOption() {
|
fun AbsoluteDarkOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
ExpandingTransition(
|
ExpandingTransition(
|
||||||
visible = state.value.pureDark.isPureDark(context)
|
visible = settings.pureDark.value.isPureDark(context)
|
||||||
&& state.value.darkTheme.isDark()
|
&& settings.darkTheme.value.isDark()
|
||||||
) {
|
) {
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.absoluteDark,
|
selected = settings.absoluteDark.value,
|
||||||
title = stringResource(id = R.string.absolute_dark_option),
|
title = stringResource(id = R.string.absolute_dark_option),
|
||||||
description = stringResource(id = R.string.absolute_dark_option_desc),
|
description = stringResource(id = R.string.absolute_dark_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.absoluteDark.update(!settings.absoluteDark.lastValue)
|
||||||
MainEvent.OnChangeAbsoluteDark(
|
|
||||||
!state.value.absoluteDark
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,24 +39,18 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
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.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.AnimatedVisibility
|
||||||
import ua.acclorite.book_story.ui.common.components.common.StyledText
|
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.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.animatedColorScheme
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.Theme
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.ThemeContrast
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppThemeOption() {
|
fun AppThemeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
|
|
@ -76,15 +70,15 @@ fun AppThemeOption() {
|
||||||
items(
|
items(
|
||||||
Theme.entries(),
|
Theme.entries(),
|
||||||
key = { theme -> theme.name }
|
key = { theme -> theme.name }
|
||||||
) { theme ->
|
) { themeEntry ->
|
||||||
AppThemeOptionItem(
|
AppThemeOptionItem(
|
||||||
theme = theme,
|
theme = themeEntry,
|
||||||
darkTheme = state.value.darkTheme.isDark(),
|
darkTheme = settings.darkTheme.value.isDark(),
|
||||||
themeContrast = state.value.themeContrast,
|
themeContrast = settings.themeContrast.value,
|
||||||
isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
|
isPureDark = settings.pureDark.value.isPureDark(context = LocalContext.current),
|
||||||
selected = state.value.theme == theme
|
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.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.DarkTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DarkThemeOption() {
|
fun DarkThemeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.dark_theme_option),
|
title = stringResource(id = R.string.dark_theme_option),
|
||||||
buttons = DarkTheme.entries.map {
|
buttons = DarkTheme.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
it.toString(),
|
it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off)
|
DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off)
|
||||||
DarkTheme.ON -> stringResource(id = R.string.dark_theme_on)
|
DarkTheme.ON -> stringResource(id = R.string.dark_theme_on)
|
||||||
DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system)
|
DarkTheme.FOLLOW_SYSTEM -> stringResource(id = R.string.dark_theme_follow_system)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
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.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.PureDark
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PureDarkOption() {
|
fun PureDarkOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.darkTheme.isDark()) {
|
ExpandingTransition(visible = settings.darkTheme.value.isDark()) {
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.pure_dark_option),
|
title = stringResource(id = R.string.pure_dark_option),
|
||||||
buttons = PureDark.entries.map {
|
buttons = PureDark.entries.map {
|
||||||
|
|
@ -37,15 +32,11 @@ fun PureDarkOption() {
|
||||||
PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver)
|
PureDark.SAVER -> stringResource(id = R.string.pure_dark_power_saver)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.pureDark
|
selected = it == settings.pureDark.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.pureDark.update(PureDark.valueOf(it.id))
|
||||||
MainEvent.OnChangePureDark(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,41 +13,35 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.BookStoryTheme
|
import ua.acclorite.book_story.ui.theme.BookStoryTheme
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.ThemeContrast
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ThemeContrastOption() {
|
fun ThemeContrastOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val themeContrastTheme = remember { mutableStateOf(state.value.theme) }
|
val themeContrastTheme = remember { mutableStateOf(settings.theme.lastValue) }
|
||||||
LaunchedEffect(state.value.theme) {
|
LaunchedEffect(settings.theme.value) {
|
||||||
if (state.value.theme.hasThemeContrast) {
|
if (settings.theme.lastValue.hasThemeContrast) {
|
||||||
themeContrastTheme.value = state.value.theme
|
themeContrastTheme.value = settings.theme.lastValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BookStoryTheme(
|
BookStoryTheme(
|
||||||
theme = themeContrastTheme.value,
|
theme = themeContrastTheme.value,
|
||||||
isDark = state.value.darkTheme.isDark(),
|
isDark = settings.darkTheme.value.isDark(),
|
||||||
isPureDark = state.value.pureDark.isPureDark(context = LocalContext.current),
|
isPureDark = settings.pureDark.value.isPureDark(context = LocalContext.current),
|
||||||
themeContrast = state.value.themeContrast
|
themeContrast = settings.themeContrast.value
|
||||||
) {
|
) {
|
||||||
ExpandingTransition(visible = state.value.theme.hasThemeContrast) {
|
ExpandingTransition(visible = settings.theme.value.hasThemeContrast) {
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.theme_contrast_option),
|
title = stringResource(id = R.string.theme_contrast_option),
|
||||||
enabled = state.value.theme.hasThemeContrast,
|
enabled = settings.theme.value.hasThemeContrast,
|
||||||
buttons = ThemeContrast.entries.map {
|
buttons = ThemeContrast.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.toString(),
|
||||||
|
|
@ -57,15 +51,11 @@ fun ThemeContrastOption() {
|
||||||
ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high)
|
ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.themeContrast
|
selected = it == settings.themeContrast.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.themeContrast.update(ThemeContrast.valueOf(it.id))
|
||||||
MainEvent.OnChangeThemeContrast(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.browse.display.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseGridSizeOption() {
|
fun BrowseGridSizeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) {
|
ExpandingTransition(visible = settings.browseLayout.value == BrowseLayout.GRID) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.browseGridSize
|
value = settings.browseGridSize.value
|
||||||
to " ${stringResource(R.string.grid_size_per_row)}",
|
to " ${stringResource(R.string.grid_size_per_row)}",
|
||||||
valuePlaceholder = stringResource(id = R.string.grid_size_auto),
|
valuePlaceholder = stringResource(id = R.string.grid_size_auto),
|
||||||
showPlaceholder = state.value.browseAutoGridSize,
|
showPlaceholder = settings.browseAutoGridSize.value,
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
toValue = 10,
|
toValue = 10,
|
||||||
title = stringResource(id = R.string.grid_size_option),
|
title = stringResource(id = R.string.grid_size_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(MainEvent.OnChangeBrowseAutoGridSize(it == 0))
|
settings.browseAutoGridSize.update(it == 0)
|
||||||
mainModel.onEvent(
|
settings.browseGridSize.update(it)
|
||||||
MainEvent.OnChangeBrowseGridSize(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.browse.display.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
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.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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseLayoutOption() {
|
fun BrowseLayoutOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.layout_option),
|
title = stringResource(id = R.string.layout_option),
|
||||||
|
|
@ -33,14 +29,10 @@ fun BrowseLayoutOption() {
|
||||||
BrowseLayout.GRID -> stringResource(id = R.string.layout_grid)
|
BrowseLayout.GRID -> stringResource(id = R.string.layout_grid)
|
||||||
},
|
},
|
||||||
MaterialTheme.typography.labelLarge,
|
MaterialTheme.typography.labelLarge,
|
||||||
it == state.value.browseLayout
|
it == settings.browseLayout.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.browseLayout.update(BrowseLayout.valueOf(it.id))
|
||||||
MainEvent.OnChangeBrowseLayout(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,26 +23,21 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
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.core.data.ExtensionsData
|
||||||
import ua.acclorite.book_story.presentation.main.MainEvent
|
import ua.acclorite.book_story.core.helpers.toggle
|
||||||
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.components.common.StyledText
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
fun LazyListScope.BrowseFilterOption() {
|
fun LazyListScope.BrowseFilterOption() {
|
||||||
items(ExtensionsData.fileExtensions, key = { it }) {
|
items(ExtensionsData.fileExtensions, key = { it }) {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
BrowseFilterOptionItem(
|
BrowseFilterOptionItem(
|
||||||
item = it,
|
item = it,
|
||||||
isSelected = state.value.browseIncludedFilterItems.any { item ->
|
isSelected = settings.browseIncludedFilterItems.value.any { item -> item == it }
|
||||||
item == it
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.browseIncludedFilterItems.update(
|
||||||
MainEvent.OnChangeBrowseIncludedFilterItem(it)
|
settings.browseIncludedFilterItems.lastValue.toggle(it)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,33 +28,25 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder
|
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.components.common.StyledText
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
fun LazyListScope.BrowseSortOption() {
|
fun LazyListScope.BrowseSortOption() {
|
||||||
items(BrowseSortOrder.entries, key = { it.name }) {
|
items(BrowseSortOrder.entries, key = { it.name }) {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
BrowseSortOptionItem(
|
BrowseSortOptionItem(
|
||||||
item = it,
|
item = it,
|
||||||
isSelected = state.value.browseSortOrder == it,
|
isSelected = settings.browseSortOrder.value == it,
|
||||||
isDescending = state.value.browseSortOrderDescending
|
isDescending = settings.browseSortOrderDescending.value
|
||||||
) {
|
) {
|
||||||
if (state.value.browseSortOrder == it) {
|
if (settings.browseSortOrder.lastValue == it) {
|
||||||
mainModel.onEvent(
|
settings.browseSortOrderDescending.update(!settings.browseSortOrderDescending.lastValue)
|
||||||
MainEvent.OnChangeBrowseSortOrderDescending(
|
|
||||||
!state.value.browseSortOrderDescending
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
mainModel.onEvent(MainEvent.OnChangeBrowseSortOrderDescending(true))
|
settings.browseSortOrderDescending.update(true)
|
||||||
mainModel.onEvent(MainEvent.OnChangeBrowseSortOrder(it.name))
|
settings.browseSortOrder.update(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,18 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.core.data.CoreData
|
import ua.acclorite.book_story.core.data.CoreData
|
||||||
import ua.acclorite.book_story.presentation.main.MainEvent
|
import ua.acclorite.book_story.presentation.settings.SettingsEvent
|
||||||
import ua.acclorite.book_story.presentation.main.MainModel
|
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.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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppLanguageOption() {
|
fun AppLanguageOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settingsModel = hiltViewModel<SettingsModel>()
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
val settings = LocalSettings.current
|
||||||
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.language_option),
|
title = stringResource(id = R.string.language_option),
|
||||||
|
|
@ -30,10 +30,10 @@ fun AppLanguageOption() {
|
||||||
it.first,
|
it.first,
|
||||||
it.second,
|
it.second,
|
||||||
MaterialTheme.typography.labelLarge,
|
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.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DoublePressExitOption() {
|
fun DoublePressExitOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.doublePressExit,
|
selected = settings.doublePressExit.value,
|
||||||
title = stringResource(id = R.string.double_press_exit_option),
|
title = stringResource(id = R.string.double_press_exit_option),
|
||||||
description = stringResource(id = R.string.double_press_exit_option_desc)
|
description = stringResource(id = R.string.double_press_exit_option_desc)
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.doublePressExit.update(!settings.doublePressExit.lastValue)
|
||||||
MainEvent.OnChangeDoublePressExit(
|
|
||||||
!state.value.doublePressExit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.library.display.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibraryLayout
|
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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryGridSizeOption() {
|
fun LibraryGridSizeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.libraryLayout == LibraryLayout.GRID) {
|
ExpandingTransition(visible = settings.libraryLayout.value == LibraryLayout.GRID) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.libraryGridSize
|
value = settings.libraryGridSize.value
|
||||||
to " ${stringResource(R.string.grid_size_per_row)}",
|
to " ${stringResource(R.string.grid_size_per_row)}",
|
||||||
valuePlaceholder = stringResource(id = R.string.grid_size_auto),
|
valuePlaceholder = stringResource(id = R.string.grid_size_auto),
|
||||||
showPlaceholder = state.value.libraryAutoGridSize,
|
showPlaceholder = settings.libraryAutoGridSize.value,
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
toValue = 10,
|
toValue = 10,
|
||||||
title = stringResource(id = R.string.grid_size_option),
|
title = stringResource(id = R.string.grid_size_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(MainEvent.OnChangeLibraryAutoGridSize(it == 0))
|
settings.libraryAutoGridSize.update(it == 0)
|
||||||
mainModel.onEvent(
|
settings.libraryGridSize.update(it)
|
||||||
MainEvent.OnChangeLibraryGridSize(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.library.display.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibraryLayout
|
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.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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryLayoutOption() {
|
fun LibraryLayoutOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.layout_option),
|
title = stringResource(id = R.string.layout_option),
|
||||||
|
|
@ -33,14 +29,10 @@ fun LibraryLayoutOption() {
|
||||||
LibraryLayout.GRID -> stringResource(id = R.string.layout_grid)
|
LibraryLayout.GRID -> stringResource(id = R.string.layout_grid)
|
||||||
},
|
},
|
||||||
MaterialTheme.typography.labelLarge,
|
MaterialTheme.typography.labelLarge,
|
||||||
it == state.value.libraryLayout
|
it == settings.libraryLayout.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.libraryLayout.update(LibraryLayout.valueOf(it.id))
|
||||||
MainEvent.OnChangeLibraryLayout(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.display.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryReadButtonOption() {
|
fun LibraryReadButtonOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryReadButton,
|
selected = settings.libraryShowReadButton.value,
|
||||||
title = stringResource(id = R.string.read_button_option),
|
title = stringResource(id = R.string.read_button_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryShowReadButton.update(!settings.libraryShowReadButton.lastValue)
|
||||||
MainEvent.OnChangeLibraryReadButton(
|
|
||||||
!state.value.libraryReadButton
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.display.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryShowProgressOption() {
|
fun LibraryShowProgressOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryShowProgress,
|
selected = settings.libraryShowProgress.value,
|
||||||
title = stringResource(id = R.string.show_progress_option),
|
title = stringResource(id = R.string.show_progress_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryShowProgress.update(!settings.libraryShowProgress.lastValue)
|
||||||
MainEvent.OnChangeLibraryShowProgress(
|
|
||||||
!state.value.libraryShowProgress
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -9,51 +9,35 @@ package ua.acclorite.book_story.ui.settings.library.display.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibraryLayout
|
import ua.acclorite.book_story.presentation.library.model.LibraryLayout
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibraryTitlePosition
|
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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryTitlePositionOption() {
|
fun LibraryTitlePositionOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.libraryLayout == LibraryLayout.GRID) {
|
ExpandingTransition(visible = settings.libraryLayout.value == LibraryLayout.GRID) {
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.title_position_option),
|
title = stringResource(id = R.string.title_position_option),
|
||||||
chips = LibraryTitlePosition.entries.map {
|
chips = LibraryTitlePosition.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
it.toString(),
|
it.name,
|
||||||
when (it) {
|
when (it) {
|
||||||
LibraryTitlePosition.OFF -> {
|
LibraryTitlePosition.OFF -> stringResource(id = R.string.library_title_position_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.BELOW -> {
|
|
||||||
stringResource(id = R.string.library_title_position_below)
|
|
||||||
}
|
|
||||||
|
|
||||||
LibraryTitlePosition.INSIDE -> {
|
|
||||||
stringResource(id = R.string.library_title_position_inside)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
MaterialTheme.typography.labelLarge,
|
MaterialTheme.typography.labelLarge,
|
||||||
it == state.value.libraryTitlePosition
|
it == settings.libraryTitlePosition.value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.libraryTitlePosition.update(LibraryTitlePosition.valueOf(it.id))
|
||||||
MainEvent.OnChangeLibraryTitlePosition(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.sort.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryPerCategorySortOption() {
|
fun LibraryPerCategorySortOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryPerCategorySort,
|
selected = settings.libraryPerCategorySort.value,
|
||||||
title = stringResource(id = R.string.per_category_sort_option),
|
title = stringResource(id = R.string.per_category_sort_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryPerCategorySort.update(!settings.libraryPerCategorySort.lastValue)
|
||||||
MainEvent.OnChangeLibraryPerCategorySort(
|
|
||||||
!state.value.libraryPerCategorySort
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryAlwaysShowDefaultTabOption() {
|
fun LibraryAlwaysShowDefaultTabOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryAlwaysShowDefaultTab,
|
selected = settings.libraryShowDefaultTab.value,
|
||||||
title = stringResource(id = R.string.always_show_default_tab_option),
|
title = stringResource(id = R.string.always_show_default_tab_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryShowDefaultTab.update(!settings.libraryShowDefaultTab.lastValue)
|
||||||
MainEvent.OnChangeLibraryAlwaysShowDefaultTab(
|
|
||||||
!state.value.libraryAlwaysShowDefaultTab
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryShowBookCountOption() {
|
fun LibraryShowBookCountOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryShowBookCount,
|
selected = settings.libraryShowBookCount.value,
|
||||||
title = stringResource(id = R.string.show_book_count_option),
|
title = stringResource(id = R.string.show_book_count_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryShowBookCount.update(!settings.libraryShowBookCount.lastValue)
|
||||||
MainEvent.OnChangeLibraryShowBookCount(
|
|
||||||
!state.value.libraryShowBookCount
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.library.tabs.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryShowCategoryTabsOption() {
|
fun LibraryShowCategoryTabsOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.libraryShowCategoryTabs,
|
selected = settings.libraryShowCategoryTabs.value,
|
||||||
title = stringResource(id = R.string.show_category_tabs_option),
|
title = stringResource(id = R.string.show_category_tabs_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.libraryShowCategoryTabs.update(!settings.libraryShowCategoryTabs.lastValue)
|
||||||
MainEvent.OnChangeLibraryShowCategoryTabs(
|
|
||||||
!state.value.libraryShowCategoryTabs
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -9,19 +9,15 @@ package ua.acclorite.book_story.ui.settings.reader.chapters.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderTextAlignment
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle
|
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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChapterTitleAlignmentOption() {
|
fun ChapterTitleAlignmentOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.chapter_title_alignment_option),
|
title = stringResource(id = R.string.chapter_title_alignment_option),
|
||||||
|
|
@ -35,15 +31,11 @@ fun ChapterTitleAlignmentOption() {
|
||||||
ReaderTextAlignment.END -> stringResource(id = R.string.alignment_end)
|
ReaderTextAlignment.END -> stringResource(id = R.string.alignment_end)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.chapterTitleAlignment
|
selected = it == settings.chapterTitleAlignment.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.chapterTitleAlignment.update(ReaderTextAlignment.valueOf(it.id))
|
||||||
MainEvent.OnChangeChapterTitleAlignment(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,48 +8,33 @@ package ua.acclorite.book_story.ui.settings.reader.font.components
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.reader.data.ReaderData
|
import ua.acclorite.book_story.ui.reader.data.ReaderData
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FontFamilyOption() {
|
fun FontFamilyOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
|
||||||
ReaderData.fonts.run {
|
|
||||||
find {
|
|
||||||
it.id == state.value.fontFamily
|
|
||||||
} ?: get(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.font_family_option),
|
title = stringResource(id = R.string.font_family_option),
|
||||||
chips = ReaderData.fonts
|
chips = ReaderData.fonts.map {
|
||||||
.map {
|
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.id,
|
id = it.id,
|
||||||
title = it.fontName.asString(),
|
title = it.fontName.asString(),
|
||||||
textStyle = MaterialTheme.typography.labelLarge.copy(
|
textStyle = MaterialTheme.typography.labelLarge.copy(
|
||||||
fontFamily = it.font
|
fontFamily = it.font
|
||||||
),
|
),
|
||||||
selected = it.id == fontFamily.id
|
selected = it == settings.fontFamily.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.fontFamily.update(
|
||||||
MainEvent.OnChangeFontFamily(
|
ReaderData.fonts.find { font -> font.id == it.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.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FontSizeOption() {
|
fun FontSizeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.fontSize to "pt",
|
value = settings.fontSize.value to "pt",
|
||||||
fromValue = 10,
|
fromValue = 10,
|
||||||
toValue = 35,
|
toValue = 35,
|
||||||
title = stringResource(id = R.string.font_size_option),
|
title = stringResource(id = R.string.font_size_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.fontSize.update(it)
|
||||||
MainEvent.OnChangeFontSize(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,30 +8,16 @@ package ua.acclorite.book_story.ui.settings.reader.font.components
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.reader.data.ReaderData
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FontStyleOption() {
|
fun FontStyleOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
|
||||||
ReaderData.fonts.run {
|
|
||||||
find {
|
|
||||||
it.id == state.value.fontFamily
|
|
||||||
} ?: get(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.font_style_option),
|
title = stringResource(id = R.string.font_style_option),
|
||||||
|
|
@ -40,30 +26,28 @@ fun FontStyleOption() {
|
||||||
id = "normal",
|
id = "normal",
|
||||||
title = stringResource(id = R.string.font_style_normal),
|
title = stringResource(id = R.string.font_style_normal),
|
||||||
textStyle = MaterialTheme.typography.labelLarge.copy(
|
textStyle = MaterialTheme.typography.labelLarge.copy(
|
||||||
fontFamily = fontFamily.font,
|
fontFamily = settings.fontFamily.value.font,
|
||||||
fontStyle = FontStyle.Normal
|
fontStyle = FontStyle.Normal
|
||||||
),
|
),
|
||||||
selected = !state.value.isItalic
|
selected = !settings.italic.value
|
||||||
),
|
),
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = "italic",
|
id = "italic",
|
||||||
title = stringResource(id = R.string.font_style_italic),
|
title = stringResource(id = R.string.font_style_italic),
|
||||||
textStyle = MaterialTheme.typography.labelLarge.copy(
|
textStyle = MaterialTheme.typography.labelLarge.copy(
|
||||||
fontFamily = fontFamily.font,
|
fontFamily = settings.fontFamily.value.font,
|
||||||
fontStyle = FontStyle.Italic
|
fontStyle = FontStyle.Italic
|
||||||
),
|
),
|
||||||
selected = state.value.isItalic
|
selected = settings.italic.value
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.italic.update(
|
||||||
MainEvent.OnChangeFontStyle(
|
|
||||||
when (it.id) {
|
when (it.id) {
|
||||||
"italic" -> true
|
"italic" -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,30 +8,16 @@ package ua.acclorite.book_story.ui.settings.reader.font.components
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderFontThickness
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle
|
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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.reader.data.ReaderData
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FontThicknessOption() {
|
fun FontThicknessOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
|
||||||
ReaderData.fonts.run {
|
|
||||||
find {
|
|
||||||
it.id == state.value.fontFamily
|
|
||||||
} ?: get(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.font_thickness_option),
|
title = stringResource(id = R.string.font_thickness_option),
|
||||||
|
|
@ -46,18 +32,14 @@ fun FontThicknessOption() {
|
||||||
ReaderFontThickness.MEDIUM -> stringResource(id = R.string.font_thickness_medium)
|
ReaderFontThickness.MEDIUM -> stringResource(id = R.string.font_thickness_medium)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge.copy(
|
textStyle = MaterialTheme.typography.labelLarge.copy(
|
||||||
fontFamily = fontFamily.font,
|
fontFamily = settings.fontFamily.value.font,
|
||||||
fontWeight = it.thickness
|
fontWeight = it.thickness
|
||||||
),
|
),
|
||||||
selected = it == state.value.fontThickness
|
selected = it == settings.fontThickness.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.fontThickness.update(ReaderFontThickness.valueOf(it.id))
|
||||||
MainEvent.OnChangeFontThickness(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.font.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LetterSpacingOption() {
|
fun LetterSpacingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.letterSpacing to "pt",
|
value = settings.letterSpacing.value to "pt",
|
||||||
fromValue = -8,
|
fromValue = -8,
|
||||||
toValue = 16,
|
toValue = 16,
|
||||||
title = stringResource(id = R.string.letter_spacing_option),
|
title = stringResource(id = R.string.letter_spacing_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.letterSpacing.update(it)
|
||||||
MainEvent.OnChangeLetterSpacing(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -9,42 +9,34 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesAlignmentOption() {
|
fun ImagesAlignmentOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.images) {
|
ExpandingTransition(visible = settings.images.value) {
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.images_alignment_option),
|
title = stringResource(id = R.string.images_alignment_option),
|
||||||
buttons = HorizontalAlignment.entries.map {
|
buttons = HorizontalAlignment.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
HorizontalAlignment.START -> stringResource(id = R.string.alignment_start)
|
HorizontalAlignment.START -> stringResource(id = R.string.alignment_start)
|
||||||
HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center)
|
HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center)
|
||||||
HorizontalAlignment.END -> stringResource(id = R.string.alignment_end)
|
HorizontalAlignment.END -> stringResource(id = R.string.alignment_end)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.imagesAlignment
|
selected = it == settings.imagesAlignment.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.imagesAlignment.update(HorizontalAlignment.valueOf(it.id))
|
||||||
MainEvent.OnChangeImagesAlignment(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,30 +8,22 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesCaptionsOption() {
|
fun ImagesCaptionsOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.images) {
|
ExpandingTransition(visible = settings.images.value) {
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.imagesCaptions,
|
selected = settings.imagesCaptions.value,
|
||||||
title = stringResource(id = R.string.images_captions_option),
|
title = stringResource(id = R.string.images_captions_option),
|
||||||
description = stringResource(id = R.string.images_captions_option_desc),
|
description = stringResource(id = R.string.images_captions_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.imagesCaptions.update(!settings.imagesCaptions.lastValue)
|
||||||
MainEvent.OnChangeImagesCaptions(
|
|
||||||
!state.value.imagesCaptions
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,54 +9,35 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderColorEffects
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle
|
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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesColorEffectsOption() {
|
fun ImagesColorEffectsOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.images) {
|
ExpandingTransition(visible = settings.images.value) {
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.images_color_effects_option),
|
title = stringResource(id = R.string.images_color_effects_option),
|
||||||
chips = ReaderColorEffects.entries.map {
|
chips = ReaderColorEffects.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
ReaderColorEffects.OFF -> {
|
ReaderColorEffects.OFF -> stringResource(R.string.color_effects_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.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,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.imagesColorEffects
|
selected = it == settings.imagesColorEffects.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.imagesColorEffects.update(ReaderColorEffects.valueOf(it.id))
|
||||||
MainEvent.OnChangeImagesColorEffects(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesCornersRoundnessOption() {
|
fun ImagesCornersRoundnessOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.images) {
|
ExpandingTransition(visible = settings.images.value) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.imagesCornersRoundness to "pt",
|
value = settings.imagesCornersRoundness.value to "pt",
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
toValue = 24,
|
toValue = 24,
|
||||||
title = stringResource(id = R.string.images_corners_roundness_option),
|
title = stringResource(id = R.string.images_corners_roundness_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.imagesCornersRoundness.update(it)
|
||||||
MainEvent.OnChangeImagesCornersRoundness(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesOption() {
|
fun ImagesOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.images,
|
selected = settings.images.value,
|
||||||
title = stringResource(id = R.string.images_option),
|
title = stringResource(id = R.string.images_option),
|
||||||
description = stringResource(id = R.string.images_option_desc),
|
description = stringResource(id = R.string.images_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.images.update(!settings.images.lastValue)
|
||||||
MainEvent.OnChangeImages(
|
|
||||||
!state.value.images
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,28 +8,22 @@ package ua.acclorite.book_story.ui.settings.reader.images.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImagesWidthOption() {
|
fun ImagesWidthOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.images) {
|
ExpandingTransition(visible = settings.images.value) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.imagesWidth to "%",
|
value = settings.imagesWidth.value to "%",
|
||||||
toValue = 100,
|
toValue = 100,
|
||||||
title = stringResource(id = R.string.images_width_option),
|
title = stringResource(id = R.string.images_width_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.imagesWidth.update(it)
|
||||||
MainEvent.OnChangeImagesWidth(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FullscreenOption() {
|
fun FullscreenOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.fullscreen,
|
selected = settings.fullscreen.value,
|
||||||
title = stringResource(id = R.string.fullscreen_option),
|
title = stringResource(id = R.string.fullscreen_option),
|
||||||
description = stringResource(id = R.string.fullscreen_option_desc),
|
description = stringResource(id = R.string.fullscreen_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.fullscreen.update(!settings.fullscreen.lastValue)
|
||||||
MainEvent.OnChangeFullscreen(
|
|
||||||
!state.value.fullscreen
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,24 +8,18 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HideBarsOnFastScrollOption() {
|
fun HideBarsOnFastScrollOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.hideBarsOnFastScroll,
|
selected = settings.hideBarsOnFastScroll.value,
|
||||||
title = stringResource(id = R.string.hide_bars_on_fast_scroll_option)
|
title = stringResource(id = R.string.hide_bars_on_fast_scroll_option)
|
||||||
) {
|
) {
|
||||||
mainModel.onEvent(
|
settings.hideBarsOnFastScroll.update(!settings.hideBarsOnFastScroll.lastValue)
|
||||||
MainEvent.OnChangeHideBarsOnFastScroll(!state.value.hideBarsOnFastScroll)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,19 @@ package ua.acclorite.book_story.ui.settings.reader.misc.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun KeepScreenOnOption() {
|
fun KeepScreenOnOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.keepScreenOn,
|
selected = settings.keepScreenOn.value,
|
||||||
title = stringResource(id = R.string.keep_screen_on_option),
|
title = stringResource(id = R.string.keep_screen_on_option),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.keepScreenOn.update(!settings.keepScreenOn.lastValue)
|
||||||
MainEvent.OnChangeKeepScreenOn(
|
|
||||||
!state.value.keepScreenOn
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BottomBarPaddingOption() {
|
fun BottomBarPaddingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.bottomBarPadding to "pt",
|
value = settings.bottomBarPadding.value to "pt",
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
toValue = 24,
|
toValue = 24,
|
||||||
title = stringResource(id = R.string.bottom_bar_padding_option),
|
title = stringResource(id = R.string.bottom_bar_padding_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.bottomBarPadding.update(it)
|
||||||
MainEvent.OnChangeBottomBarPadding(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CutoutPaddingOption() {
|
fun CutoutPaddingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.cutoutPadding,
|
selected = settings.cutoutPadding.value,
|
||||||
title = stringResource(id = R.string.cutout_padding_option),
|
title = stringResource(id = R.string.cutout_padding_option),
|
||||||
description = stringResource(id = R.string.cutout_padding_option_desc),
|
description = stringResource(id = R.string.cutout_padding_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.cutoutPadding.update(!settings.cutoutPadding.lastValue)
|
||||||
MainEvent.OnChangeCutoutPadding(
|
|
||||||
!state.value.cutoutPadding
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SidePaddingOption() {
|
fun SidePaddingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.sidePadding to "pt",
|
value = settings.sidePadding.value to "pt",
|
||||||
fromValue = 1,
|
fromValue = 1,
|
||||||
toValue = 20,
|
toValue = 20,
|
||||||
title = stringResource(id = R.string.side_padding_option),
|
title = stringResource(id = R.string.side_padding_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.sidePadding.update(it)
|
||||||
MainEvent.OnChangeSidePadding(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,27 +8,21 @@ package ua.acclorite.book_story.ui.settings.reader.padding.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VerticalPaddingOption() {
|
fun VerticalPaddingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.verticalPadding to "pt",
|
value = settings.verticalPadding.value to "pt",
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
toValue = 24,
|
toValue = 24,
|
||||||
title = stringResource(id = R.string.vertical_padding_option),
|
title = stringResource(id = R.string.vertical_padding_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.verticalPadding.update(it)
|
||||||
MainEvent.OnChangeVerticalPadding(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -9,42 +9,34 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.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.common.model.ButtonItem
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
import ua.acclorite.book_story.ui.theme.model.HorizontalAlignment
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressBarAlignmentOption() {
|
fun ProgressBarAlignmentOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.progressBar) {
|
ExpandingTransition(visible = settings.progressBar.value) {
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.progress_bar_alignment_option),
|
title = stringResource(id = R.string.progress_bar_alignment_option),
|
||||||
buttons = HorizontalAlignment.entries.map {
|
buttons = HorizontalAlignment.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
HorizontalAlignment.START -> stringResource(id = R.string.alignment_start)
|
HorizontalAlignment.START -> stringResource(id = R.string.alignment_start)
|
||||||
HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center)
|
HorizontalAlignment.CENTER -> stringResource(id = R.string.alignment_center)
|
||||||
HorizontalAlignment.END -> stringResource(id = R.string.alignment_end)
|
HorizontalAlignment.END -> stringResource(id = R.string.alignment_end)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.progressBarAlignment
|
selected = it == settings.progressBarAlignment.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.progressBarAlignment.update(HorizontalAlignment.valueOf(it.id))
|
||||||
MainEvent.OnChangeProgressBarAlignment(
|
|
||||||
it.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressBarFontSizeOption() {
|
fun ProgressBarFontSizeOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.progressBar) {
|
ExpandingTransition(visible = settings.progressBar.value) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.progressBarFontSize to "pt",
|
value = settings.progressBarFontSize.value to "pt",
|
||||||
fromValue = 4,
|
fromValue = 4,
|
||||||
toValue = 16,
|
toValue = 16,
|
||||||
title = stringResource(id = R.string.progress_bar_font_size_option),
|
title = stringResource(id = R.string.progress_bar_font_size_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.progressBarFontSize.update(it)
|
||||||
MainEvent.OnChangeProgressBarFontSize(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,20 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SwitchWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressBarOption() {
|
fun ProgressBarOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.progressBar,
|
selected = settings.progressBar.value,
|
||||||
title = stringResource(id = R.string.progress_bar_option),
|
title = stringResource(id = R.string.progress_bar_option),
|
||||||
description = stringResource(id = R.string.progress_bar_option_desc),
|
description = stringResource(id = R.string.progress_bar_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.progressBar.update(!settings.progressBar.lastValue)
|
||||||
MainEvent.OnChangeProgressBar(
|
|
||||||
!state.value.progressBar
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -8,29 +8,23 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.components.settings.SliderWithTitle
|
||||||
|
import ua.acclorite.book_story.ui.common.helpers.LocalSettings
|
||||||
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressBarPaddingOption() {
|
fun ProgressBarPaddingOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(visible = state.value.progressBar) {
|
ExpandingTransition(visible = settings.progressBar.value) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.progressBarPadding to "pt",
|
value = settings.progressBarPadding.value to "pt",
|
||||||
fromValue = 1,
|
fromValue = 1,
|
||||||
toValue = 12,
|
toValue = 12,
|
||||||
title = stringResource(id = R.string.progress_bar_padding_option),
|
title = stringResource(id = R.string.progress_bar_padding_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.progressBarPadding.update(it)
|
||||||
MainEvent.OnChangeProgressBarPadding(it)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,39 +9,31 @@ package ua.acclorite.book_story.ui.settings.reader.progress.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderProgressCount
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.SegmentedButtonWithTitle
|
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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressCountOption() {
|
fun ProgressCountOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.progress_count_option),
|
title = stringResource(id = R.string.progress_count_option),
|
||||||
buttons = ReaderProgressCount.entries.map {
|
buttons = ReaderProgressCount.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
ReaderProgressCount.PERCENTAGE -> stringResource(id = R.string.progress_count_percentage)
|
ReaderProgressCount.PERCENTAGE -> stringResource(id = R.string.progress_count_percentage)
|
||||||
ReaderProgressCount.QUANTITY -> stringResource(id = R.string.progress_count_quantity)
|
ReaderProgressCount.QUANTITY -> stringResource(id = R.string.progress_count_quantity)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.progressCount
|
selected = it == settings.progressCount.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.progressCount.update(ReaderProgressCount.valueOf(it.id))
|
||||||
MainEvent.OnChangeProgressCount(
|
|
||||||
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.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle
|
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
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HorizontalGestureAlphaAnimOption() {
|
fun HorizontalGestureAlphaAnimOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(
|
ExpandingTransition(
|
||||||
visible = when (state.value.horizontalGesture) {
|
visible = when (settings.horizontalGesture.value) {
|
||||||
ReaderHorizontalGesture.OFF -> false
|
ReaderHorizontalGesture.OFF -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.horizontalGestureAlphaAnim,
|
selected = settings.horizontalGestureAlphaAnim.value,
|
||||||
title = stringResource(id = R.string.horizontal_gesture_alpha_anim_option),
|
title = stringResource(id = R.string.horizontal_gesture_alpha_anim_option),
|
||||||
description = stringResource(id = R.string.horizontal_gesture_alpha_anim_option_desc),
|
description = stringResource(id = R.string.horizontal_gesture_alpha_anim_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.horizontalGestureAlphaAnim.update(!settings.horizontalGestureAlphaAnim.lastValue)
|
||||||
MainEvent.OnChangeHorizontalGestureAlphaAnim(
|
|
||||||
!state.value.horizontalGestureAlphaAnim
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,48 +9,32 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.ChipsWithTitle
|
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.common.model.ButtonItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HorizontalGestureOption() {
|
fun HorizontalGestureOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.horizontal_gesture_option),
|
title = stringResource(id = R.string.horizontal_gesture_option),
|
||||||
chips = ReaderHorizontalGesture.entries.map {
|
chips = ReaderHorizontalGesture.entries.map {
|
||||||
ButtonItem(
|
ButtonItem(
|
||||||
id = it.toString(),
|
id = it.name,
|
||||||
title = when (it) {
|
title = when (it) {
|
||||||
ReaderHorizontalGesture.OFF -> {
|
ReaderHorizontalGesture.OFF -> stringResource(R.string.horizontal_gesture_off)
|
||||||
stringResource(R.string.horizontal_gesture_off)
|
ReaderHorizontalGesture.ON -> stringResource(R.string.horizontal_gesture_on)
|
||||||
}
|
ReaderHorizontalGesture.INVERSE -> stringResource(R.string.horizontal_gesture_inverse)
|
||||||
|
|
||||||
ReaderHorizontalGesture.ON -> {
|
|
||||||
stringResource(R.string.horizontal_gesture_on)
|
|
||||||
}
|
|
||||||
|
|
||||||
ReaderHorizontalGesture.INVERSE -> {
|
|
||||||
stringResource(R.string.horizontal_gesture_inverse)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = MaterialTheme.typography.labelLarge,
|
||||||
selected = it == state.value.horizontalGesture
|
selected = it == settings.horizontalGesture.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.horizontalGesture.update(ReaderHorizontalGesture.valueOf(it.id))
|
||||||
MainEvent.OnChangeHorizontalGesture(
|
|
||||||
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.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.SwitchWithTitle
|
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
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HorizontalGesturePullAnimOption() {
|
fun HorizontalGesturePullAnimOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(
|
ExpandingTransition(
|
||||||
visible = when (state.value.horizontalGesture) {
|
visible = when (settings.horizontalGesture.value) {
|
||||||
ReaderHorizontalGesture.OFF -> false
|
ReaderHorizontalGesture.OFF -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.horizontalGesturePullAnim,
|
selected = settings.horizontalGesturePullAnim.value,
|
||||||
title = stringResource(id = R.string.horizontal_gesture_pull_anim_option),
|
title = stringResource(id = R.string.horizontal_gesture_pull_anim_option),
|
||||||
description = stringResource(id = R.string.horizontal_gesture_pull_anim_option_desc),
|
description = stringResource(id = R.string.horizontal_gesture_pull_anim_option_desc),
|
||||||
onClick = {
|
onClick = {
|
||||||
mainModel.onEvent(
|
settings.horizontalGesturePullAnim.update(!settings.horizontalGesturePullAnim.lastValue)
|
||||||
MainEvent.OnChangeHorizontalGesturePullAnim(
|
|
||||||
!state.value.horizontalGesturePullAnim
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,34 +8,28 @@ package ua.acclorite.book_story.ui.settings.reader.reading_mode.components
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.presentation.reader.model.ReaderHorizontalGesture
|
||||||
import ua.acclorite.book_story.ui.common.components.settings.SliderWithTitle
|
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
|
import ua.acclorite.book_story.ui.theme.ExpandingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HorizontalGestureScrollOption() {
|
fun HorizontalGestureScrollOption() {
|
||||||
val mainModel = hiltViewModel<MainModel>()
|
val settings = LocalSettings.current
|
||||||
val state = mainModel.state.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
ExpandingTransition(
|
ExpandingTransition(
|
||||||
visible = when (state.value.horizontalGesture) {
|
visible = when (settings.horizontalGesture.value) {
|
||||||
ReaderHorizontalGesture.OFF -> false
|
ReaderHorizontalGesture.OFF -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.horizontalGestureScroll to "%",
|
value = settings.horizontalGestureScroll.value to "%",
|
||||||
toValue = 100,
|
toValue = 100,
|
||||||
title = stringResource(id = R.string.horizontal_gesture_scroll_option),
|
title = stringResource(id = R.string.horizontal_gesture_scroll_option),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
mainModel.onEvent(
|
settings.horizontalGestureScroll.update(it)
|
||||||
MainEvent.OnChangeHorizontalGestureScroll(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