refactor(ui): refactor ui layer

This commit is contained in:
Acclorite 2025-06-05 22:40:27 +03:00
parent 731329879d
commit eefcb4ef90
No known key found for this signature in database
GPG key ID: 6E54C611F6EE8593
127 changed files with 773 additions and 762 deletions

View file

@ -9,7 +9,7 @@ package ua.acclorite.book_story.core.crash
import android.content.Context
import android.content.Intent
import android.os.Process
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.presentation.crash.CrashActivity
import kotlin.system.exitProcess

View file

@ -0,0 +1,33 @@
/*
* 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.core.data
import kotlinx.collections.immutable.persistentListOf
object CoreData {
val languages = persistentListOf(
Pair("en", "English"),
Pair("uk", "Українська"),
Pair("de", "Deutsch"),
Pair("ar", "اَلْعَرَبِيَّةُ"),
Pair("es", "Español"),
Pair("tr", "Türkçe"),
Pair("fr", "Français"),
Pair("pl", "Polski"),
Pair("it", "Italiano"),
Pair("zh", "汉语"),
Pair("hi", "हिन्दी"),
// Currently as "pt" (which is Portuguese) instead of "pt-BR"
Pair("pt", "Português (Brasil)"),
Pair("ta", "தமிழ்"),
Pair("ml", "മലയാളം"),
Pair("cs", "Čeština"),
Pair("ro", "Română"),
Pair("be", "Беларуская"),
Pair("ja", "日本語")
)
}

View file

@ -0,0 +1,28 @@
/*
* 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.core.data
import kotlinx.collections.immutable.persistentListOf
object ExtensionsData {
val fileExtensions = persistentListOf(
".epub",
".pdf",
".fb2",
".txt",
".html",
".htm",
".md"
)
val imageExtensions = persistentListOf(
".png",
".jpg",
".jpeg",
".gif"
)
}

View file

@ -0,0 +1,15 @@
/*
* 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.core.data
object LinkData {
const val RELEASES = "https://www.github.com/Acclorite/book-story/releases/latest"
const val ISSUES = "https://www.github.com/Acclorite/book-story/issues"
const val CONTRIBUTORS = "https://github.com/Acclorite/book-story/graphs/contributors"
const val TRANSLATION = "https://hosted.weblate.org/projects/book-story"
const val SUPPORT = "https://patreon.com/Acclorite"
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.util
package ua.acclorite.book_story.core.helpers
fun <T> MutableList<T>.addAll(calculation: () -> List<T>) {
addAll(calculation())

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.util
package ua.acclorite.book_story.core.helpers
fun String.removeTrailingZero(): String {
if (!this.contains('.'))
@ -66,14 +66,3 @@ fun Char.isVisibleCharacter(): Boolean {
else -> false
}
}
fun <T> compareByWithOrder(
descending: Boolean,
selector: (T) -> Comparable<*>?
): Comparator<T> {
return if (descending) {
compareByDescending(selector)
} else {
compareBy(selector)
}
}

View file

@ -0,0 +1,18 @@
/*
* 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.core.helpers
fun <T> compareByWithOrder(
descending: Boolean,
selector: (T) -> Comparable<*>?
): Comparator<T> {
return if (descending) {
compareByDescending(selector)
} else {
compareBy(selector)
}
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.core
package ua.acclorite.book_story.core.log
import android.util.Log

View file

@ -11,10 +11,10 @@ import android.graphics.BitmapFactory
import androidx.compose.ui.graphics.asImageBitmap
import kotlinx.coroutines.yield
import org.jsoup.nodes.Document
import ua.acclorite.book_story.core.helpers.clearAllMarkdown
import ua.acclorite.book_story.core.helpers.clearMarkdown
import ua.acclorite.book_story.core.helpers.containsVisibleText
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.ui.common.util.clearAllMarkdown
import ua.acclorite.book_story.ui.common.util.clearMarkdown
import ua.acclorite.book_story.ui.common.util.containsVisibleText
import java.io.File
import java.util.zip.ZipEntry
import java.util.zip.ZipFile

View file

@ -23,7 +23,7 @@ import org.commonmark.node.Node
import org.commonmark.node.StrongEmphasis
import org.commonmark.node.Text
import org.commonmark.parser.Parser
import ua.acclorite.book_story.ui.common.util.clearMarkdown
import ua.acclorite.book_story.core.helpers.clearMarkdown
import javax.inject.Inject
class MarkdownParser @Inject constructor(

View file

@ -17,13 +17,13 @@ import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.jsoup.Jsoup
import ua.acclorite.book_story.core.data.ExtensionsData
import ua.acclorite.book_story.core.helpers.addAll
import ua.acclorite.book_story.core.helpers.containsVisibleText
import ua.acclorite.book_story.data.model.file.CachedFile
import ua.acclorite.book_story.data.parser.DocumentParser
import ua.acclorite.book_story.data.parser.TextParser
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.ui.common.constants.provideImageExtensions
import ua.acclorite.book_story.ui.common.util.addAll
import ua.acclorite.book_story.ui.common.util.containsVisibleText
import java.io.File
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.zip.ZipEntry
@ -60,7 +60,7 @@ class EpubTextParser @Inject constructor(
val chapterEntries = zip.getChapterEntries(opfEntry)
val imageEntries = zip.entries().toList().filter {
provideImageExtensions().any { format ->
ExtensionsData.imageExtensions.any { format ->
it.name.endsWith(format, ignoreCase = true)
}
}

View file

@ -12,11 +12,11 @@ import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
import com.tom_roush.pdfbox.pdmodel.PDDocument
import com.tom_roush.pdfbox.text.PDFTextStripper
import kotlinx.coroutines.yield
import ua.acclorite.book_story.core.helpers.clearAllMarkdown
import ua.acclorite.book_story.data.model.file.CachedFile
import ua.acclorite.book_story.data.parser.MarkdownParser
import ua.acclorite.book_story.data.parser.TextParser
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.ui.common.util.clearAllMarkdown
import javax.inject.Inject
private const val PDF_TAG = "PDF Parser"

View file

@ -10,11 +10,11 @@ import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import ua.acclorite.book_story.core.helpers.clearAllMarkdown
import ua.acclorite.book_story.data.model.file.CachedFile
import ua.acclorite.book_story.data.parser.MarkdownParser
import ua.acclorite.book_story.data.parser.TextParser
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.ui.common.util.clearAllMarkdown
import javax.inject.Inject
private const val TXT_TAG = "TXT Parser"

View file

@ -6,6 +6,7 @@
package ua.acclorite.book_story.data.repository
import ua.acclorite.book_story.core.data.ExtensionsData
import ua.acclorite.book_story.data.local.room.BookDao
import ua.acclorite.book_story.data.mapper.file.FileMapper
import ua.acclorite.book_story.data.model.file.CachedFile
@ -14,7 +15,6 @@ import ua.acclorite.book_story.data.parser.FileParser
import ua.acclorite.book_story.domain.model.file.File
import ua.acclorite.book_story.domain.repository.FileSystemRepository
import ua.acclorite.book_story.domain.service.FileProvider
import ua.acclorite.book_story.ui.common.constants.provideExtensions
import javax.inject.Inject
import javax.inject.Singleton
@ -47,7 +47,14 @@ class FileSystemRepositoryImpl @Inject constructor(
query: String,
existingFiles: List<String>
): Boolean {
if (provideExtensions().none { name.endsWith(it, ignoreCase = true) }) return false
if (
ExtensionsData.fileExtensions.none {
name.endsWith(
it,
ignoreCase = true
)
}
) return false
if (query.isNotBlank() && !name.contains(query.trim(), ignoreCase = true)) return false
if (existingFiles.any { it.equals(path, ignoreCase = true) }) return false
return true

View file

@ -30,4 +30,20 @@ data class Book(
val lastOpened: Long?,
val categories: List<Int>
) : Parcelable
) : Parcelable {
companion object {
val default = Book(
id = -1,
title = "",
author = UIText.StringValue(""),
description = null,
filePath = "",
coverImage = null,
scrollIndex = 0,
scrollOffset = 0,
progress = 0f,
lastOpened = null,
categories = emptyList()
)
}
}

View file

@ -17,4 +17,14 @@ data class ColorPreset(
val backgroundColor: Color,
val fontColor: Color,
val isSelected: Selected
) {
companion object {
val default = ColorPreset(
id = -1,
name = null,
backgroundColor = Color(0xFFFAF8FF), // Blue Light Surface (hardcoded)
fontColor = Color(0xFF44464F), // Blue Light OnSurfaceVariant (hardcoded)
isSelected = false
)
}
}

View file

@ -8,9 +8,9 @@ package ua.acclorite.book_story.domain.use_case.book
import androidx.core.net.toUri
import ua.acclorite.book_story.core.CoverImage
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.logW
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.model.library.Book
import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.service.CoverImageHandler

View file

@ -8,8 +8,8 @@ package ua.acclorite.book_story.domain.use_case.book
import android.app.Application
import android.graphics.BitmapFactory
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.service.CoverImageHandler
import javax.inject.Inject

View file

@ -6,9 +6,9 @@
package ua.acclorite.book_story.domain.use_case.book
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.logW
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.model.library.Book
import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.repository.HistoryRepository

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.book
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.repository.HistoryRepository

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.book
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject

View file

@ -7,9 +7,9 @@
package ua.acclorite.book_story.domain.use_case.book
import androidx.core.net.toUri
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.logW
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.BookRepository
import ua.acclorite.book_story.domain.service.CoverImageHandler
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.book
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.repository.HistoryRepository

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.book
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject

View file

@ -8,9 +8,9 @@ package ua.acclorite.book_story.domain.use_case.book
import androidx.core.net.toUri
import ua.acclorite.book_story.core.CoverImage
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.logW
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.BookRepository
import ua.acclorite.book_story.domain.service.CoverImageHandler
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Category
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,7 +6,7 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Category
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Category
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.CategorySort
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,7 +6,7 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Category
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.CategorySort
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,7 +6,7 @@
package ua.acclorite.book_story.domain.use_case.category
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.library.Category
import ua.acclorite.book_story.domain.repository.CategoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ColorPreset
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ColorPreset
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ColorPreset
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ColorPreset
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.reader.ColorPreset
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
import javax.inject.Inject

View file

@ -8,10 +8,10 @@ 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.logE
import ua.acclorite.book_story.core.logI
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.ui.common.constants.DataStoreConstants
import ua.acclorite.book_story.presentation.main.data.DataStoreData
import javax.inject.Inject
class ChangeLanguagePreferenceUseCase @Inject constructor(
@ -22,7 +22,7 @@ class ChangeLanguagePreferenceUseCase @Inject constructor(
logI("Changing language preference.")
dataStoreRepository.putPreference(
DataStoreConstants.LANGUAGE,
DataStoreData.LANGUAGE,
language
).fold(
onSuccess = {

View file

@ -10,9 +10,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.logW
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

View file

@ -7,8 +7,8 @@
package ua.acclorite.book_story.domain.use_case.data_store
import androidx.datastore.preferences.core.Preferences
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
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

View file

@ -7,8 +7,8 @@
package ua.acclorite.book_story.domain.use_case.file_system
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.core.ui.UIText
import ua.acclorite.book_story.data.model.common.NullableBook
import ua.acclorite.book_story.data.model.common.NullableBook.NotNull

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.file_system
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.file.File
import ua.acclorite.book_story.domain.repository.FileSystemRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.history.History
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.history.History
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.history.History
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.model.history.History
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.permission
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.repository.PermissionRepository
import javax.inject.Inject

View file

@ -6,8 +6,8 @@
package ua.acclorite.book_story.domain.use_case.permission
import ua.acclorite.book_story.core.logE
import ua.acclorite.book_story.core.logI
import ua.acclorite.book_story.core.log.logE
import ua.acclorite.book_story.core.log.logI
import ua.acclorite.book_story.domain.repository.PermissionRepository
import javax.inject.Inject

View file

@ -16,8 +16,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.common.util.launchActivity
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.launchActivity
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
@HiltViewModel

View file

@ -30,7 +30,7 @@ import ua.acclorite.book_story.domain.use_case.book.UpdateCoverImageUseCase
import ua.acclorite.book_story.presentation.browse.BrowseScreen
import ua.acclorite.book_story.presentation.history.HistoryScreen
import ua.acclorite.book_story.presentation.library.LibraryScreen
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
@HiltViewModel

View file

@ -10,11 +10,10 @@ import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.core.BottomSheet
import ua.acclorite.book_story.core.Dialog
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.ui.common.constants.provideEmptyBook
@Immutable
data class BookInfoState(
val book: Book = provideEmptyBook(),
val book: Book = Book.default,
val canResetCover: Boolean = false,

View file

@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.helpers.compareByWithOrder
import ua.acclorite.book_story.data.model.common.NullableBook
import ua.acclorite.book_story.domain.model.file.File
import ua.acclorite.book_story.domain.use_case.book.AddBookUseCase
@ -32,8 +33,7 @@ import ua.acclorite.book_story.presentation.browse.model.BrowseSortOrder
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
import ua.acclorite.book_story.presentation.library.LibraryScreen
import ua.acclorite.book_story.presentation.library.model.SelectableNullableBook
import ua.acclorite.book_story.ui.common.util.compareByWithOrder
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
@HiltViewModel

View file

@ -21,9 +21,9 @@ import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.crash.CrashUtils
import ua.acclorite.book_story.presentation.navigator.Screen
import ua.acclorite.book_story.ui.common.util.LocalActivity
import ua.acclorite.book_story.ui.common.util.launchActivity
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.LocalActivity
import ua.acclorite.book_story.ui.common.helpers.launchActivity
import ua.acclorite.book_story.ui.common.helpers.showToast
import ua.acclorite.book_story.ui.crash.CrashContent
@Parcelize

View file

@ -31,7 +31,7 @@ import ua.acclorite.book_story.domain.use_case.history.DeleteWholeHistoryUseCase
import ua.acclorite.book_story.domain.use_case.history.GetHistoryUseCase
import ua.acclorite.book_story.presentation.history.model.GroupedHistory
import ua.acclorite.book_story.presentation.library.LibraryScreen
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date

View file

@ -29,7 +29,7 @@ import ua.acclorite.book_story.domain.use_case.book.UpdateBookUseCase
import ua.acclorite.book_story.presentation.browse.BrowseScreen
import ua.acclorite.book_story.presentation.history.HistoryScreen
import ua.acclorite.book_story.presentation.library.model.SelectableBook
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
@HiltViewModel

View file

@ -30,6 +30,7 @@ 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
@ -40,10 +41,8 @@ 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.common.constants.DataStoreConstants
import ua.acclorite.book_story.ui.common.constants.provideFonts
import ua.acclorite.book_story.ui.common.constants.provideMainState
import ua.acclorite.book_story.ui.theme.toTheme
import ua.acclorite.book_story.ui.reader.data.ReaderData
import ua.acclorite.book_story.ui.theme.Theme
import javax.inject.Inject
@ -63,7 +62,7 @@ class MainModel @Inject constructor(
private val mainModelReady = MutableStateFlow(false)
private val _state: MutableStateFlow<MainState> = MutableStateFlow(
stateHandle[provideMainState()] ?: MainState()
stateHandle["main_state"] ?: MainState()
)
val state = _state.asStateFlow()
@ -72,7 +71,7 @@ class MainModel @Inject constructor(
is MainEvent.OnChangeLanguage -> handleLanguageUpdate(event)
is MainEvent.OnChangeDarkTheme -> handleDatastoreUpdate(
key = DataStoreConstants.DARK_THEME,
key = DataStoreData.DARK_THEME,
value = event.value,
updateState = {
it.copy(darkTheme = DarkTheme.valueOf(this))
@ -80,7 +79,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangePureDark -> handleDatastoreUpdate(
key = DataStoreConstants.PURE_DARK,
key = DataStoreData.PURE_DARK,
value = event.value,
updateState = {
it.copy(pureDark = PureDark.valueOf(this))
@ -88,7 +87,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeThemeContrast -> handleDatastoreUpdate(
key = DataStoreConstants.THEME_CONTRAST,
key = DataStoreData.THEME_CONTRAST,
value = event.value,
updateState = {
it.copy(themeContrast = ThemeContrast.valueOf(this))
@ -96,19 +95,19 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeTheme -> handleDatastoreUpdate(
key = DataStoreConstants.THEME,
key = DataStoreData.THEME,
value = event.value,
updateState = {
it.copy(theme = toTheme())
it.copy(theme = Theme.valueOf(this))
}
)
is MainEvent.OnChangeFontFamily -> handleDatastoreUpdate(
key = DataStoreConstants.FONT,
key = DataStoreData.FONT,
value = event.value,
updateState = {
it.copy(
fontFamily = provideFonts().run {
fontFamily = ReaderData.fonts.run {
find { font ->
font.id == event.value
}?.id ?: get(0).id
@ -118,7 +117,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeFontStyle -> handleDatastoreUpdate(
key = DataStoreConstants.IS_ITALIC,
key = DataStoreData.IS_ITALIC,
value = event.value,
updateState = {
it.copy(isItalic = this)
@ -126,7 +125,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeFontSize -> handleDatastoreUpdate(
key = DataStoreConstants.FONT_SIZE,
key = DataStoreData.FONT_SIZE,
value = event.value,
updateState = {
it.copy(fontSize = this)
@ -134,7 +133,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLineHeight -> handleDatastoreUpdate(
key = DataStoreConstants.LINE_HEIGHT,
key = DataStoreData.LINE_HEIGHT,
value = event.value,
updateState = {
it.copy(lineHeight = this)
@ -142,7 +141,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeParagraphHeight -> handleDatastoreUpdate(
key = DataStoreConstants.PARAGRAPH_HEIGHT,
key = DataStoreData.PARAGRAPH_HEIGHT,
value = event.value,
updateState = {
it.copy(paragraphHeight = this)
@ -150,7 +149,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeParagraphIndentation -> handleDatastoreUpdate(
key = DataStoreConstants.PARAGRAPH_INDENTATION,
key = DataStoreData.PARAGRAPH_INDENTATION,
value = event.value,
updateState = {
it.copy(paragraphIndentation = this)
@ -158,7 +157,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeShowStartScreen -> handleDatastoreUpdate(
key = DataStoreConstants.SHOW_START_SCREEN,
key = DataStoreData.SHOW_START_SCREEN,
value = event.value,
updateState = {
it.copy(showStartScreen = this)
@ -166,7 +165,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeSidePadding -> handleDatastoreUpdate(
key = DataStoreConstants.SIDE_PADDING,
key = DataStoreData.SIDE_PADDING,
value = event.value,
updateState = {
it.copy(sidePadding = this)
@ -174,7 +173,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeDoubleClickTranslation -> handleDatastoreUpdate(
key = DataStoreConstants.DOUBLE_CLICK_TRANSLATION,
key = DataStoreData.DOUBLE_CLICK_TRANSLATION,
value = event.value,
updateState = {
it.copy(doubleClickTranslation = this)
@ -182,7 +181,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeFastColorPresetChange -> handleDatastoreUpdate(
key = DataStoreConstants.FAST_COLOR_PRESET_CHANGE,
key = DataStoreData.FAST_COLOR_PRESET_CHANGE,
value = event.value,
updateState = {
it.copy(fastColorPresetChange = this)
@ -190,7 +189,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBrowseLayout -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_LAYOUT,
key = DataStoreData.BROWSE_LAYOUT,
value = event.value,
updateState = {
it.copy(browseLayout = BrowseLayout.valueOf(this))
@ -198,7 +197,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBrowseAutoGridSize -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_AUTO_GRID_SIZE,
key = DataStoreData.BROWSE_AUTO_GRID_SIZE,
value = event.value,
updateState = {
it.copy(browseAutoGridSize = this)
@ -206,7 +205,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBrowseGridSize -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_GRID_SIZE,
key = DataStoreData.BROWSE_GRID_SIZE,
value = event.value,
updateState = {
it.copy(browseGridSize = this)
@ -214,7 +213,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBrowseSortOrder -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_SORT_ORDER,
key = DataStoreData.BROWSE_SORT_ORDER,
value = event.value,
updateState = {
it.copy(browseSortOrder = BrowseSortOrder.valueOf(this))
@ -222,7 +221,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBrowseSortOrderDescending -> handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_SORT_ORDER_DESCENDING,
key = DataStoreData.BROWSE_SORT_ORDER_DESCENDING,
value = event.value,
updateState = {
it.copy(browseSortOrderDescending = this)
@ -234,7 +233,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeTextAlignment -> handleDatastoreUpdate(
key = DataStoreConstants.TEXT_ALIGNMENT,
key = DataStoreData.TEXT_ALIGNMENT,
value = event.value,
updateState = {
it.copy(textAlignment = ReaderTextAlignment.valueOf(this))
@ -242,7 +241,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeDoublePressExit -> handleDatastoreUpdate(
key = DataStoreConstants.DOUBLE_PRESS_EXIT,
key = DataStoreData.DOUBLE_PRESS_EXIT,
value = event.value,
updateState = {
it.copy(doublePressExit = this)
@ -250,7 +249,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLetterSpacing -> handleDatastoreUpdate(
key = DataStoreConstants.LETTER_SPACING,
key = DataStoreData.LETTER_SPACING,
value = event.value,
updateState = {
it.copy(letterSpacing = this)
@ -258,7 +257,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeAbsoluteDark -> handleDatastoreUpdate(
key = DataStoreConstants.ABSOLUTE_DARK,
key = DataStoreData.ABSOLUTE_DARK,
value = event.value,
updateState = {
it.copy(absoluteDark = this)
@ -266,7 +265,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeCutoutPadding -> handleDatastoreUpdate(
key = DataStoreConstants.CUTOUT_PADDING,
key = DataStoreData.CUTOUT_PADDING,
value = event.value,
updateState = {
it.copy(cutoutPadding = this)
@ -274,7 +273,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeFullscreen -> handleDatastoreUpdate(
key = DataStoreConstants.FULLSCREEN,
key = DataStoreData.FULLSCREEN,
value = event.value,
updateState = {
it.copy(fullscreen = this)
@ -282,7 +281,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeKeepScreenOn -> handleDatastoreUpdate(
key = DataStoreConstants.KEEP_SCREEN_ON,
key = DataStoreData.KEEP_SCREEN_ON,
value = event.value,
updateState = {
it.copy(keepScreenOn = this)
@ -290,7 +289,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeVerticalPadding -> handleDatastoreUpdate(
key = DataStoreConstants.VERTICAL_PADDING,
key = DataStoreData.VERTICAL_PADDING,
value = event.value,
updateState = {
it.copy(verticalPadding = this)
@ -298,7 +297,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHideBarsOnFastScroll -> handleDatastoreUpdate(
key = DataStoreConstants.HIDE_BARS_ON_FAST_SCROLL,
key = DataStoreData.HIDE_BARS_ON_FAST_SCROLL,
value = event.value,
updateState = {
it.copy(hideBarsOnFastScroll = this)
@ -306,7 +305,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangePerceptionExpander -> handleDatastoreUpdate(
key = DataStoreConstants.PERCEPTION_EXPANDER,
key = DataStoreData.PERCEPTION_EXPANDER,
value = event.value,
updateState = {
it.copy(perceptionExpander = this)
@ -314,7 +313,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangePerceptionExpanderPadding -> handleDatastoreUpdate(
key = DataStoreConstants.PERCEPTION_EXPANDER_PADDING,
key = DataStoreData.PERCEPTION_EXPANDER_PADDING,
value = event.value,
updateState = {
it.copy(perceptionExpanderPadding = this)
@ -322,7 +321,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangePerceptionExpanderThickness -> handleDatastoreUpdate(
key = DataStoreConstants.PERCEPTION_EXPANDER_THICKNESS,
key = DataStoreData.PERCEPTION_EXPANDER_THICKNESS,
value = event.value,
updateState = {
it.copy(perceptionExpanderThickness = this)
@ -330,7 +329,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeScreenOrientation -> handleDatastoreUpdate(
key = DataStoreConstants.SCREEN_ORIENTATION,
key = DataStoreData.SCREEN_ORIENTATION,
value = event.value,
updateState = {
it.copy(screenOrientation = ReaderScreenOrientation.valueOf(this))
@ -338,7 +337,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeCustomScreenBrightness -> handleDatastoreUpdate(
key = DataStoreConstants.CUSTOM_SCREEN_BRIGHTNESS,
key = DataStoreData.CUSTOM_SCREEN_BRIGHTNESS,
value = event.value,
updateState = {
it.copy(customScreenBrightness = this)
@ -346,7 +345,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeScreenBrightness -> handleDatastoreUpdate(
key = DataStoreConstants.SCREEN_BRIGHTNESS,
key = DataStoreData.SCREEN_BRIGHTNESS,
value = event.value.toDouble(),
updateState = {
it.copy(screenBrightness = this.toFloat())
@ -354,7 +353,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHorizontalGesture -> handleDatastoreUpdate(
key = DataStoreConstants.HORIZONTAL_GESTURE,
key = DataStoreData.HORIZONTAL_GESTURE,
value = event.value,
updateState = {
it.copy(horizontalGesture = ReaderHorizontalGesture.valueOf(this))
@ -362,7 +361,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHorizontalGestureScroll -> handleDatastoreUpdate(
key = DataStoreConstants.HORIZONTAL_GESTURE_SCROLL,
key = DataStoreData.HORIZONTAL_GESTURE_SCROLL,
value = event.value.toDouble(),
updateState = {
it.copy(horizontalGestureScroll = this.toFloat())
@ -370,7 +369,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHorizontalGestureSensitivity -> handleDatastoreUpdate(
key = DataStoreConstants.HORIZONTAL_GESTURE_SENSITIVITY,
key = DataStoreData.HORIZONTAL_GESTURE_SENSITIVITY,
value = event.value.toDouble(),
updateState = {
it.copy(horizontalGestureSensitivity = this.toFloat())
@ -378,7 +377,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeBottomBarPadding -> handleDatastoreUpdate(
key = DataStoreConstants.BOTTOM_BAR_PADDING,
key = DataStoreData.BOTTOM_BAR_PADDING,
value = event.value,
updateState = {
it.copy(bottomBarPadding = this)
@ -386,7 +385,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHighlightedReading -> handleDatastoreUpdate(
key = DataStoreConstants.HIGHLIGHTED_READING,
key = DataStoreData.HIGHLIGHTED_READING,
value = event.value,
updateState = {
it.copy(highlightedReading = this)
@ -394,7 +393,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHighlightedReadingThickness -> handleDatastoreUpdate(
key = DataStoreConstants.HIGHLIGHTED_READING_THICKNESS,
key = DataStoreData.HIGHLIGHTED_READING_THICKNESS,
value = event.value,
updateState = {
it.copy(highlightedReadingThickness = this)
@ -402,7 +401,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeChapterTitleAlignment -> handleDatastoreUpdate(
key = DataStoreConstants.CHAPTER_TITLE_ALIGNMENT,
key = DataStoreData.CHAPTER_TITLE_ALIGNMENT,
value = event.value,
updateState = {
it.copy(chapterTitleAlignment = ReaderTextAlignment.valueOf(this))
@ -410,7 +409,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeImages -> handleDatastoreUpdate(
key = DataStoreConstants.IMAGES,
key = DataStoreData.IMAGES,
value = event.value,
updateState = {
it.copy(images = this)
@ -418,7 +417,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeImagesCornersRoundness -> handleDatastoreUpdate(
key = DataStoreConstants.IMAGES_CORNERS_ROUNDNESS,
key = DataStoreData.IMAGES_CORNERS_ROUNDNESS,
value = event.value,
updateState = {
it.copy(imagesCornersRoundness = this)
@ -426,7 +425,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeImagesAlignment -> handleDatastoreUpdate(
key = DataStoreConstants.IMAGES_ALIGNMENT,
key = DataStoreData.IMAGES_ALIGNMENT,
value = event.value,
updateState = {
it.copy(imagesAlignment = HorizontalAlignment.valueOf(this))
@ -434,7 +433,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeImagesWidth -> handleDatastoreUpdate(
key = DataStoreConstants.IMAGES_WIDTH,
key = DataStoreData.IMAGES_WIDTH,
value = event.value.toDouble(),
updateState = {
it.copy(imagesWidth = this.toFloat())
@ -442,7 +441,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeImagesColorEffects -> handleDatastoreUpdate(
key = DataStoreConstants.IMAGES_COLOR_EFFECTS,
key = DataStoreData.IMAGES_COLOR_EFFECTS,
value = event.value,
updateState = {
it.copy(imagesColorEffects = ReaderColorEffects.valueOf(this))
@ -450,7 +449,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeProgressBar -> handleDatastoreUpdate(
key = DataStoreConstants.PROGRESS_BAR,
key = DataStoreData.PROGRESS_BAR,
value = event.value,
updateState = {
it.copy(progressBar = this)
@ -458,7 +457,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeProgressBarPadding -> handleDatastoreUpdate(
key = DataStoreConstants.PROGRESS_BAR_PADDING,
key = DataStoreData.PROGRESS_BAR_PADDING,
value = event.value,
updateState = {
it.copy(progressBarPadding = this)
@ -466,7 +465,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeProgressBarAlignment -> handleDatastoreUpdate(
key = DataStoreConstants.PROGRESS_BAR_ALIGNMENT,
key = DataStoreData.PROGRESS_BAR_ALIGNMENT,
value = event.value,
updateState = {
it.copy(progressBarAlignment = HorizontalAlignment.valueOf(this))
@ -474,7 +473,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeProgressBarFontSize -> handleDatastoreUpdate(
key = DataStoreConstants.PROGRESS_BAR_FONT_SIZE,
key = DataStoreData.PROGRESS_BAR_FONT_SIZE,
value = event.value,
updateState = {
it.copy(progressBarFontSize = this)
@ -486,7 +485,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeFontThickness -> handleDatastoreUpdate(
key = DataStoreConstants.FONT_THICKNESS,
key = DataStoreData.FONT_THICKNESS,
value = event.value,
updateState = {
it.copy(fontThickness = ReaderFontThickness.valueOf(this))
@ -494,7 +493,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeProgressCount -> handleDatastoreUpdate(
key = DataStoreConstants.PROGRESS_COUNT,
key = DataStoreData.PROGRESS_COUNT,
value = event.value,
updateState = {
it.copy(progressCount = ReaderProgressCount.valueOf(this))
@ -502,7 +501,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHorizontalGestureAlphaAnim -> handleDatastoreUpdate(
key = DataStoreConstants.HORIZONTAL_GESTURE_ALPHA_ANIM,
key = DataStoreData.HORIZONTAL_GESTURE_ALPHA_ANIM,
value = event.value,
updateState = {
it.copy(horizontalGestureAlphaAnim = this)
@ -510,7 +509,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeHorizontalGesturePullAnim -> handleDatastoreUpdate(
key = DataStoreConstants.HORIZONTAL_GESTURE_PULL_ANIM,
key = DataStoreData.HORIZONTAL_GESTURE_PULL_ANIM,
value = event.value,
updateState = {
it.copy(horizontalGesturePullAnim = this)
@ -518,7 +517,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryLayout -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_LAYOUT,
key = DataStoreData.LIBRARY_LAYOUT,
value = event.value,
updateState = {
it.copy(libraryLayout = LibraryLayout.valueOf(this))
@ -526,7 +525,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryAutoGridSize -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_AUTO_GRID_SIZE,
key = DataStoreData.LIBRARY_AUTO_GRID_SIZE,
value = event.value,
updateState = {
it.copy(libraryAutoGridSize = this)
@ -534,7 +533,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryGridSize -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_GRID_SIZE,
key = DataStoreData.LIBRARY_GRID_SIZE,
value = event.value,
updateState = {
it.copy(libraryGridSize = this)
@ -542,7 +541,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryReadButton -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_READ_BUTTON,
key = DataStoreData.LIBRARY_READ_BUTTON,
value = event.value,
updateState = {
it.copy(libraryReadButton = this)
@ -550,7 +549,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryShowProgress -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_SHOW_PROGRESS,
key = DataStoreData.LIBRARY_SHOW_PROGRESS,
value = event.value,
updateState = {
it.copy(libraryShowProgress = this)
@ -558,7 +557,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryTitlePosition -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_TITLE_POSITION,
key = DataStoreData.LIBRARY_TITLE_POSITION,
value = event.value,
updateState = {
it.copy(libraryTitlePosition = LibraryTitlePosition.valueOf(this))
@ -566,7 +565,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryShowBookCount -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_SHOW_BOOK_COUNT,
key = DataStoreData.LIBRARY_SHOW_BOOK_COUNT,
value = event.value,
updateState = {
it.copy(libraryShowBookCount = this)
@ -574,7 +573,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryShowCategoryTabs -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_SHOW_CATEGORY_TABS,
key = DataStoreData.LIBRARY_SHOW_CATEGORY_TABS,
value = event.value,
updateState = {
it.copy(libraryShowCategoryTabs = this)
@ -582,7 +581,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryAlwaysShowDefaultTab -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_ALWAYS_SHOW_DEFAULT_TAB,
key = DataStoreData.LIBRARY_ALWAYS_SHOW_DEFAULT_TAB,
value = event.value,
updateState = {
it.copy(libraryAlwaysShowDefaultTab = this)
@ -590,7 +589,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibrarySortOrder -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_SORT_ORDER,
key = DataStoreData.LIBRARY_SORT_ORDER,
value = event.value,
updateState = {
it.copy(librarySortOrder = LibrarySortOrder.valueOf(this))
@ -598,7 +597,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibrarySortOrderDescending -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_SORT_ORDER_DESCENDING,
key = DataStoreData.LIBRARY_SORT_ORDER_DESCENDING,
value = event.value,
updateState = {
it.copy(librarySortOrderDescending = this)
@ -606,7 +605,7 @@ class MainModel @Inject constructor(
)
is MainEvent.OnChangeLibraryPerCategorySort -> handleDatastoreUpdate(
key = DataStoreConstants.LIBRARY_PER_CATEGORY_SORT,
key = DataStoreData.LIBRARY_PER_CATEGORY_SORT,
value = event.value,
updateState = {
it.copy(libraryPerCategorySort = this)
@ -662,7 +661,7 @@ class MainModel @Inject constructor(
set.remove(event.value)
}
handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_INCLUDED_FILTER_ITEMS,
key = DataStoreData.BROWSE_INCLUDED_FILTER_ITEMS,
value = set,
updateState = {
it.copy(browseIncludedFilterItems = toList())
@ -678,7 +677,7 @@ class MainModel @Inject constructor(
set.remove(event.value)
}
handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_PINNED_PATHS,
key = DataStoreData.BROWSE_PINNED_PATHS,
value = set,
updateState = {
it.copy(browsePinnedPaths = toList())
@ -710,7 +709,7 @@ class MainModel @Inject constructor(
) {
withContext(Dispatchers.Main.immediate) {
_state.update {
stateHandle[provideMainState()] = function(it)
stateHandle["main_state"] = function(it)
function(it)
}
}

View file

@ -13,11 +13,13 @@ 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
@ -28,11 +30,8 @@ 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.common.constants.DataStoreConstants
import ua.acclorite.book_story.ui.common.constants.provideFonts
import ua.acclorite.book_story.ui.common.constants.provideLanguages
import ua.acclorite.book_story.ui.reader.data.ReaderData
import ua.acclorite.book_story.ui.theme.Theme
import ua.acclorite.book_story.ui.theme.toTheme
import java.util.Locale
/**
@ -47,7 +46,7 @@ data class MainState(
// General Settings
val language: String = provideDefaultValue {
val locale = Locale.getDefault().language.take(2)
provideLanguages().any { locale == it.first }.run {
CoreData.languages.any { locale == it.first }.run {
if (this) locale
else "en"// Default language.
}
@ -61,7 +60,7 @@ data class MainState(
val doublePressExit: Boolean = provideDefaultValue { false },
// Reader Settings
val fontFamily: String = provideDefaultValue { provideFonts()[0].id },
val fontFamily: String = provideDefaultValue { ReaderData.fonts[0].id },
val fontThickness: ReaderFontThickness = provideDefaultValue { ReaderFontThickness.NORMAL },
val isItalic: Boolean = provideDefaultValue { false },
val fontSize: Int = provideDefaultValue { 16 },
@ -150,14 +149,14 @@ data class MainState(
return (data[key.name] as? T)?.convert() ?: defaultState.default()
}
return DataStoreConstants.run {
return DataStoreData.run {
MainState(
language = provideValue(
LANGUAGE
) { language },
theme = provideValue(
THEME, convert = { toTheme() }
THEME, convert = { Theme.valueOf(this) }
) { theme },
darkTheme = provideValue(

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.constants
package ua.acclorite.book_story.presentation.main.data
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.doublePreferencesKey
@ -12,7 +12,7 @@ import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
object DataStoreConstants {
object DataStoreData {
// General settings
val LANGUAGE = stringPreferencesKey("language")
val THEME = stringPreferencesKey("theme")

View file

@ -35,6 +35,7 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.helpers.coerceAndPreventNaN
import ua.acclorite.book_story.core.ui.UIText
import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter
import ua.acclorite.book_story.domain.use_case.book.GetBookUseCase
@ -44,10 +45,9 @@ import ua.acclorite.book_story.domain.use_case.history.GetHistoryForBookUseCase
import ua.acclorite.book_story.presentation.history.HistoryScreen
import ua.acclorite.book_story.presentation.library.LibraryScreen
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
import ua.acclorite.book_story.ui.common.util.coerceAndPreventNaN
import ua.acclorite.book_story.ui.common.util.launchActivity
import ua.acclorite.book_story.ui.common.util.setBrightness
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.launchActivity
import ua.acclorite.book_story.ui.common.helpers.setBrightness
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
import kotlin.math.roundToInt

View file

@ -44,6 +44,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.core.helpers.calculateProgress
import ua.acclorite.book_story.presentation.book_info.BookInfoScreen
import ua.acclorite.book_story.presentation.main.MainModel
import ua.acclorite.book_story.presentation.navigator.Screen
@ -51,12 +52,11 @@ import ua.acclorite.book_story.presentation.reader.model.ReaderColorEffects
import ua.acclorite.book_story.presentation.reader.model.ReaderProgressCount
import ua.acclorite.book_story.presentation.reader.model.ReaderTextAlignment
import ua.acclorite.book_story.presentation.settings.SettingsModel
import ua.acclorite.book_story.ui.common.constants.provideFonts
import ua.acclorite.book_story.ui.common.util.LocalActivity
import ua.acclorite.book_story.ui.common.util.calculateProgress
import ua.acclorite.book_story.ui.common.util.setBrightness
import ua.acclorite.book_story.ui.common.helpers.LocalActivity
import ua.acclorite.book_story.ui.common.helpers.setBrightness
import ua.acclorite.book_story.ui.navigator.LocalNavigator
import ua.acclorite.book_story.ui.reader.ReaderContent
import ua.acclorite.book_story.ui.reader.data.ReaderData
import kotlin.math.roundToInt
@Parcelize
@ -117,7 +117,7 @@ data class ReaderScreen(val bookId: Int) : Screen, Parcelable {
}
val fontFamily = remember(mainState.value.fontFamily) {
provideFonts().run {
ReaderData.fonts.run {
find {
it.id == mainState.value.fontFamily
} ?: get(0)

View file

@ -15,11 +15,10 @@ import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.domain.model.reader.ReaderText
import ua.acclorite.book_story.domain.model.reader.ReaderText.Chapter
import ua.acclorite.book_story.presentation.reader.model.Checkpoint
import ua.acclorite.book_story.ui.common.constants.provideEmptyBook
@Immutable
data class ReaderState(
val book: Book = provideEmptyBook(),
val book: Book = Book.default,
val text: List<ReaderText> = emptyList(),
val listState: LazyListState = LazyListState(),

View file

@ -36,8 +36,7 @@ import ua.acclorite.book_story.domain.use_case.color_preset.SelectColorPresetUse
import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPresetUseCase
import ua.acclorite.book_story.domain.use_case.permission.GrantPersistableUriPermissionUseCase
import ua.acclorite.book_story.domain.use_case.permission.ReleasePersistableUriPermissionUseCase
import ua.acclorite.book_story.ui.common.constants.provideDefaultColorPreset
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import javax.inject.Inject
import kotlin.random.Random
@ -79,7 +78,7 @@ class SettingsModel @Inject constructor(
var colorPresets = getColorPresetsUseCase()
if (colorPresets.isEmpty()) {
updateColorPresetUseCase(provideDefaultColorPreset())
updateColorPresetUseCase(ColorPreset.default)
getColorPresetsUseCase().first().select()
colorPresets = getColorPresetsUseCase()
}
@ -453,7 +452,7 @@ class SettingsModel @Inject constructor(
addColorPresetJob = launch {
yield()
val newColorPreset = provideDefaultColorPreset().copy(
val newColorPreset = ColorPreset.default.copy(
backgroundColor = event.backgroundColor,
fontColor = event.fontColor
)
@ -572,7 +571,7 @@ class SettingsModel @Inject constructor(
val selectedPreset = presets.firstOrNull { it.isSelected }
if (selectedPreset == null) {
return provideDefaultColorPreset()
return ColorPreset.default
}
return selectedPreset

View file

@ -11,12 +11,11 @@ import androidx.compose.runtime.Immutable
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.reader.ColorPreset
import ua.acclorite.book_story.ui.common.constants.provideDefaultColorPreset
@Immutable
data class SettingsState(
val colorPresets: List<ColorPreset> = emptyList(),
val selectedColorPreset: ColorPreset = provideDefaultColorPreset(),
val selectedColorPreset: ColorPreset = ColorPreset.default,
val animateColorPreset: Boolean = false,
val colorPresetListState: LazyListState = LazyListState(),

View file

@ -17,15 +17,15 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.core.data.CoreData
import ua.acclorite.book_story.presentation.browse.BrowseScreen
import ua.acclorite.book_story.presentation.help.HelpScreen
import ua.acclorite.book_story.presentation.main.MainEvent
import ua.acclorite.book_story.presentation.main.MainModel
import ua.acclorite.book_story.presentation.navigator.Screen
import ua.acclorite.book_story.presentation.navigator.StackEvent
import ua.acclorite.book_story.ui.common.constants.provideLanguages
import ua.acclorite.book_story.ui.common.helpers.LocalActivity
import ua.acclorite.book_story.ui.common.model.ButtonItem
import ua.acclorite.book_story.ui.common.util.LocalActivity
import ua.acclorite.book_story.ui.navigator.LocalNavigator
import ua.acclorite.book_story.ui.start.StartContent
@ -61,7 +61,7 @@ object StartScreen : Screen, Parcelable {
val stackEvent = remember { mutableStateOf(StackEvent.Default) }
val languages = remember(mainState.value.language) {
provideLanguages().sortedBy { it.second }.map {
CoreData.languages.sortedBy { it.second }.map {
ButtonItem(
id = it.first,
title = it.second,

View file

@ -19,8 +19,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.about.AboutEvent
import ua.acclorite.book_story.ui.common.constants.provideAboutBadges
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.about.data.AboutData
import ua.acclorite.book_story.ui.common.helpers.showToast
@Composable
fun AboutBadges(
@ -38,7 +38,7 @@ fun AboutBadges(
horizontalArrangement = Arrangement.spacedBy(13.dp)
) {
items(
provideAboutBadges(),
AboutData.badges,
key = { it.id }
) { badge ->
AboutBadgeItem(badge = badge) {

View file

@ -26,13 +26,9 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.data.LinkData
import ua.acclorite.book_story.presentation.about.AboutEvent
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.provideContributorsPage
import ua.acclorite.book_story.ui.common.constants.provideIssuesPage
import ua.acclorite.book_story.ui.common.constants.provideReleasesPage
import ua.acclorite.book_story.ui.common.constants.provideSupportPage
import ua.acclorite.book_story.ui.common.constants.provideTranslationPage
@Composable
fun AboutLayout(
@ -85,7 +81,7 @@ fun AboutLayout(
) {
navigateToBrowserPage(
AboutEvent.OnNavigateToBrowserPage(
page = provideReleasesPage(),
page = LinkData.RELEASES,
context = context
)
)
@ -99,7 +95,7 @@ fun AboutLayout(
) {
navigateToBrowserPage(
AboutEvent.OnNavigateToBrowserPage(
page = provideIssuesPage(),
page = LinkData.ISSUES,
context = context
)
)
@ -114,7 +110,7 @@ fun AboutLayout(
) {
navigateToBrowserPage(
AboutEvent.OnNavigateToBrowserPage(
page = provideContributorsPage(),
page = LinkData.CONTRIBUTORS,
context = context
)
)
@ -146,7 +142,7 @@ fun AboutLayout(
) {
navigateToBrowserPage(
AboutEvent.OnNavigateToBrowserPage(
page = provideTranslationPage(),
page = LinkData.TRANSLATION,
context = context
)
)
@ -160,7 +156,7 @@ fun AboutLayout(
) {
navigateToBrowserPage(
AboutEvent.OnNavigateToBrowserPage(
page = provideSupportPage(),
page = LinkData.SUPPORT,
context = context
)
)

View file

@ -0,0 +1,51 @@
/*
* 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.about.data
import kotlinx.collections.immutable.persistentListOf
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.about.model.Badge
object AboutData {
val badges = persistentListOf(
Badge(
id = "github",
drawable = R.drawable.github,
imageVector = null,
contentDescription = R.string.github_badge,
url = "https://www.github.com/Acclorite"
),
Badge(
id = "reddit",
drawable = R.drawable.reddit,
imageVector = null,
contentDescription = R.string.reddit_badge,
url = "https://www.reddit.com/user/Acclorite/"
),
Badge(
id = "tryzub",
drawable = R.drawable.tryzub,
imageVector = null,
contentDescription = R.string.tryzub_badge,
url = null
),
Badge(
id = "gitlab",
drawable = R.drawable.gitlab,
imageVector = null,
contentDescription = R.string.gitlab_badge,
url = "https://www.gitlab.com/Acclorite"
),
Badge(
id = "codeberg",
drawable = R.drawable.codeberg,
imageVector = null,
contentDescription = R.string.codeberg_badge,
url = "https://www.codeberg.org/Acclorite"
)
)
}

View file

@ -18,12 +18,12 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.data.ExtensionsData
import ua.acclorite.book_story.data.model.file.CachedFileCompat
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
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.constants.provideExtensions
import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle
import java.text.SimpleDateFormat
import java.util.Date
@ -60,7 +60,7 @@ fun BookInfoDetailsBottomSheet(
val fileExists = remember(cachedFile) {
cachedFile.let {
it != null && it.canAccess() && !it.isDirectory && provideExtensions()
it != null && it.canAccess() && !it.isDirectory && ExtensionsData.fileExtensions
.any { ext ->
it.name.endsWith(ext, ignoreCase = true)
}

View file

@ -20,7 +20,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.providePrimaryScrollbar
import ua.acclorite.book_story.ui.common.data.ScrollbarData
@Composable
fun BookInfoLayout(
@ -38,7 +38,7 @@ fun BookInfoLayout(
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize(),
state = listState,
scrollbarSettings = providePrimaryScrollbar(false),
scrollbarSettings = ScrollbarData.primaryScrollbar,
contentPadding = PaddingValues(bottom = 18.dp)
) {
item {

View file

@ -15,9 +15,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.helpers.calculateProgress
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.calculateProgress
@Composable
fun BookInfoLayoutButton(

View file

@ -42,7 +42,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
@Composable
fun BookInfoLayoutDescription(

View file

@ -23,7 +23,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
@Composable
fun BookInfoLayoutInfoAuthor(

View file

@ -28,7 +28,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
import ua.acclorite.book_story.ui.common.components.common.AsyncCoverImage
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
@Composable
fun BookInfoLayoutInfoCover(

View file

@ -17,9 +17,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.core.helpers.calculateProgress
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.calculateProgress
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable

View file

@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.presentation.book_info.BookInfoEvent
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
@Composable
fun BookInfoLayoutInfoTitle(

View file

@ -25,7 +25,7 @@ import ua.acclorite.book_story.presentation.browse.BrowseEvent
import ua.acclorite.book_story.presentation.library.model.SelectableNullableBook
import ua.acclorite.book_story.ui.common.components.dialog.Dialog
import ua.acclorite.book_story.ui.common.components.progress_indicator.CircularProgressIndicator
import ua.acclorite.book_story.ui.common.util.showToast
import ua.acclorite.book_story.ui.common.helpers.showToast
import java.util.UUID
@Composable

View file

@ -21,7 +21,7 @@ import ua.acclorite.book_story.presentation.browse.model.GroupedFiles
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
import ua.acclorite.book_story.ui.common.components.common.LazyVerticalGridWithScrollbar
import ua.acclorite.book_story.ui.common.components.common.header
import ua.acclorite.book_story.ui.common.constants.providePrimaryScrollbar
import ua.acclorite.book_story.ui.common.data.ScrollbarData
@Composable
fun BrowseGridLayout(
@ -38,7 +38,7 @@ fun BrowseGridLayout(
state = gridState,
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 8.dp),
scrollbarSettings = providePrimaryScrollbar(false)
scrollbarSettings = ScrollbarData.primaryScrollbar
) {
groupedFiles.forEach { group ->
stickyHeader {

View file

@ -24,7 +24,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
@Composable
fun BrowseLayoutHeader(

View file

@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.browse.model.GroupedFiles
import ua.acclorite.book_story.presentation.browse.model.SelectableFile
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.providePrimaryScrollbar
import ua.acclorite.book_story.ui.common.data.ScrollbarData
@Composable
fun BrowseListLayout(
@ -32,7 +32,7 @@ fun BrowseListLayout(
state = listState,
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 8.dp),
scrollbarSettings = providePrimaryScrollbar(false)
scrollbarSettings = ScrollbarData.primaryScrollbar
) {
groupedFiles.forEach { group ->
stickyHeader {

View file

@ -20,14 +20,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.InternalLazyColumnScrollbar
import my.nanihadesuka.compose.ScrollbarSettings
import ua.acclorite.book_story.ui.common.constants.provideSecondaryScrollbar
import ua.acclorite.book_story.ui.common.data.ScrollbarData
@Composable
fun LazyColumnWithScrollbar(
modifier: Modifier = Modifier,
parentModifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
scrollbarSettings: ScrollbarSettings = provideSecondaryScrollbar(),
scrollbarSettings: ScrollbarSettings = ScrollbarData.secondaryScrollbar,
enableScrollbar: Boolean = true,
contentPadding: PaddingValues = PaddingValues(0.dp),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,

View file

@ -21,14 +21,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.InternalLazyVerticalGridScrollbar
import my.nanihadesuka.compose.ScrollbarSettings
import ua.acclorite.book_story.ui.common.constants.provideSecondaryScrollbar
import ua.acclorite.book_story.ui.common.data.ScrollbarData
@Composable
fun LazyVerticalGridWithScrollbar(
modifier: Modifier = Modifier,
columns: GridCells,
state: LazyGridState = rememberLazyGridState(),
scrollbarSettings: ScrollbarSettings = provideSecondaryScrollbar(),
scrollbarSettings: ScrollbarSettings = ScrollbarData.secondaryScrollbar,
enableScrollbar: Boolean = true,
contentPadding: PaddingValues = PaddingValues(0.dp),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,

View file

@ -41,8 +41,8 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.ui.common.components.common.AnimatedVisibility
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.providePrimaryScrollbar
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.common.data.ScrollbarData
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
/**
* Modal Drawer.
@ -145,7 +145,7 @@ fun ModalDrawer(
LazyColumnWithScrollbar(
state = rememberLazyListState(startIndex),
modifier = Modifier.fillMaxSize(),
scrollbarSettings = providePrimaryScrollbar(),
scrollbarSettings = ScrollbarData.primarySelectableScrollbar,
contentPadding = PaddingValues(vertical = 9.dp)
) {
content()

View file

@ -1,48 +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.ui.common.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.about.model.Badge
fun provideAboutBadges() = listOf(
Badge(
id = "github",
drawable = R.drawable.github,
imageVector = null,
contentDescription = R.string.github_badge,
url = "https://www.github.com/Acclorite"
),
Badge(
id = "reddit",
drawable = R.drawable.reddit,
imageVector = null,
contentDescription = R.string.reddit_badge,
url = "https://www.reddit.com/user/Acclorite/"
),
Badge(
id = "tryzub",
drawable = R.drawable.tryzub,
imageVector = null,
contentDescription = R.string.tryzub_badge,
url = null
),
Badge(
id = "gitlab",
drawable = R.drawable.gitlab,
imageVector = null,
contentDescription = R.string.gitlab_badge,
url = "https://www.gitlab.com/Acclorite"
),
Badge(
id = "codeberg",
drawable = R.drawable.codeberg,
imageVector = null,
contentDescription = R.string.codeberg_badge,
url = "https://www.codeberg.org/Acclorite"
),
)

View file

@ -1,41 +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("SameReturnValue")
package ua.acclorite.book_story.ui.common.constants
import androidx.compose.ui.graphics.Color
import ua.acclorite.book_story.core.ui.UIText
import ua.acclorite.book_story.domain.model.library.Book
import ua.acclorite.book_story.domain.model.reader.ColorPreset
// Main State
fun provideMainState() = "main_state"
// Empty Book
fun provideEmptyBook() = Book(
id = -1,
title = "",
author = UIText.StringValue(""),
description = null,
filePath = "",
coverImage = null,
scrollIndex = 0,
scrollOffset = 0,
progress = 0f,
lastOpened = null,
categories = emptyList()
)
// Default Color Preset
fun provideDefaultColorPreset() = ColorPreset(
id = -1,
name = null,
backgroundColor = Color(0xFFFAF8FF), // Blue Light Surface (hardcoded)
fontColor = Color(0xFF44464F), // Blue Light OnSurfaceVariant (hardcoded)
isSelected = false
)

View file

@ -1,98 +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.ui.common.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.ui.UIText
import ua.acclorite.book_story.ui.about.model.Credit
fun provideCredits() = listOf(
Credit(
name = "Tachiyomi (Mihon)",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_design),
UIText.StringResource(R.string.credits_ideas),
UIText.StringValue("Readme")
),
website = "https://www.github.com/mihonapp/mihon"
),
Credit(
name = "Kitsune",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_updates),
UIText.StringResource(R.string.credits_ideas)
),
website = "https://www.github.com/Drumber/Kitsune"
),
Credit(
name = "Voyager",
source = "Voyager Website",
credits = listOf(
UIText.StringResource(R.string.credits_ideas)
),
website = "https://voyager.adriel.cafe/"
),
Credit(
name = "Material Design Icons",
source = "Google Fonts",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://fonts.google.com/icons"
),
Credit(
name = "Material Design Fonts",
source = "Google Fonts",
credits = listOf(
UIText.StringResource(R.string.credits_fonts)
),
website = "https://fonts.google.com"
),
Credit(
name = "Weblate",
source = "Hosted Weblate",
credits = listOf(
UIText.StringResource(R.string.credits_translation),
UIText.StringResource(R.string.credits_contribution)
),
website = "https://hosted.weblate.org/projects/book-story"
),
Credit(
name = "OpenDyslexic Font",
source = "OpenDyslexic Website",
credits = listOf(
UIText.StringResource(R.string.credits_fonts)
),
website = "https://opendyslexic.org"
),
Credit(
name = "GitLab Badge",
source = "Censorship Website",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://censorship.no/en/index.html"
),
Credit(
name = "GitHub Badge",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://github.com/Kunzisoft/Github-badge"
),
Credit(
name = "Codeberg Badge",
source = "Codeberg",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://codeberg.org/Codeberg/GetItOnCodeberg"
),
)

View file

@ -1,152 +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.ui.common.constants
import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.help.HelpAnnotation
import ua.acclorite.book_story.ui.help.model.HelpTip
fun provideHelpTips() = listOf(
HelpTip(
title = R.string.help_title_how_to_add_books,
description = {
append(stringResource(id = R.string.help_desc_how_to_add_books_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_add_books_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_add_books_3) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_add_books_4))
}
append(".")
}
),
HelpTip(
title = R.string.help_title_how_to_customize_app,
description = {
append(stringResource(id = R.string.help_desc_how_to_customize_app_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_customize_app_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_customize_app_3))
}
),
HelpTip(
title = R.string.help_title_how_to_move_or_delete_books,
description = {
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_3))
}
),
HelpTip(
title = R.string.help_title_how_to_edit_book,
description = {
append(stringResource(id = R.string.help_desc_how_to_edit_book_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_edit_book_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_edit_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_read_book,
description = {
append(stringResource(id = R.string.help_desc_how_to_read_book_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_read_book_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_read_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_customize_reader,
description = {
append(stringResource(id = R.string.help_desc_how_to_customize_reader_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_customize_reader_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_customize_reader_3))
}
),
HelpTip(
title = R.string.help_title_how_to_manage_history,
description = {
append(stringResource(id = R.string.help_desc_how_to_manage_history_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_manage_history_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_manage_history_3))
}
),
HelpTip(
title = R.string.help_title_how_to_use_tooltip,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_tooltip_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_double_click_translation,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_double_click_translation_1))
}
),
HelpTip(
title = R.string.help_title_how_to_create_color_presets,
description = {
append(stringResource(id = R.string.help_desc_how_to_create_color_presets_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_color_presets,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_color_presets_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_perception_expander,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_perception_expander_1))
}
),
)

View file

@ -1,29 +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.ui.common.constants
fun provideLanguages() = listOf(
Pair("en", "English"),
Pair("uk", "Українська"),
Pair("de", "Deutsch"),
Pair("ar", "اَلْعَرَبِيَّةُ"),
Pair("es", "Español"),
Pair("tr", "Türkçe"),
Pair("fr", "Français"),
Pair("pl", "Polski"),
Pair("it", "Italiano"),
Pair("zh", "汉语"),
Pair("hi", "हिन्दी"),
// Currently as "pt" (which is Portuguese) instead of "pt-BR"
Pair("pt", "Português (Brasil)"),
Pair("ta", "தமிழ்"),
Pair("ml", "മലയാളം"),
Pair("cs", "Čeština"),
Pair("ro", "Română"),
Pair("be", "Беларуская"),
Pair("ja", "日本語"),
)

View file

@ -1,24 +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("SameReturnValue")
package ua.acclorite.book_story.ui.common.constants
fun provideReleasesPage() =
"https://www.github.com/Acclorite/book-story/releases/latest"
fun provideIssuesPage() =
"https://www.github.com/Acclorite/book-story/issues"
fun provideContributorsPage() =
"https://github.com/Acclorite/book-story/graphs/contributors"
fun provideTranslationPage() =
"https://hosted.weblate.org/projects/book-story"
fun provideSupportPage() =
"https://patreon.com/Acclorite"

View file

@ -1,38 +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.ui.common.constants
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.ScrollbarSelectionMode
import my.nanihadesuka.compose.ScrollbarSettings
@Composable
fun providePrimaryScrollbar(canSelect: Boolean = true) = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.secondary,
thumbSelectedColor = MaterialTheme.colorScheme.secondary.copy(0.8f),
hideDelayMillis = 2000,
durationAnimationMillis = 300,
selectionMode = if (canSelect) ScrollbarSelectionMode.Thumb else ScrollbarSelectionMode.Disabled,
thumbThickness = 8.dp,
scrollbarPadding = 4.dp
)
@Composable
fun provideSecondaryScrollbar() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.5f),
hideDelayMillis = 500,
durationAnimationMillis = 200,
thumbMinLength = 0.4f,
selectionMode = ScrollbarSelectionMode.Disabled,
thumbThickness = 4.dp,
thumbShape = RectangleShape,
hideDisplacement = 0.dp,
scrollbarPadding = 0.dp
)

View file

@ -1,24 +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.ui.common.constants
fun provideExtensions() = listOf(
".epub",
".pdf",
".fb2",
".txt",
".html",
".htm",
".md"
)
fun provideImageExtensions() = listOf(
".png",
".jpg",
".jpeg",
".gif"
)

View file

@ -0,0 +1,51 @@
/*
* 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.data
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.ScrollbarSelectionMode
import my.nanihadesuka.compose.ScrollbarSettings
object ScrollbarData {
val primarySelectableScrollbar
@Composable get() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.secondary,
thumbSelectedColor = MaterialTheme.colorScheme.secondary.copy(0.8f),
hideDelayMillis = 2000,
durationAnimationMillis = 300,
selectionMode = ScrollbarSelectionMode.Thumb,
thumbThickness = 8.dp,
scrollbarPadding = 4.dp
)
val primaryScrollbar
@Composable get() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.secondary,
thumbSelectedColor = MaterialTheme.colorScheme.secondary.copy(0.8f),
hideDelayMillis = 2000,
durationAnimationMillis = 300,
selectionMode = ScrollbarSelectionMode.Disabled,
thumbThickness = 8.dp,
scrollbarPadding = 4.dp
)
val secondaryScrollbar
@Composable get() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.5f),
hideDelayMillis = 500,
durationAnimationMillis = 200,
thumbMinLength = 0.4f,
selectionMode = ScrollbarSelectionMode.Disabled,
thumbThickness = 4.dp,
thumbShape = RectangleShape,
hideDisplacement = 0.dp,
scrollbarPadding = 0.dp
)
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.util
package ua.acclorite.book_story.ui.common.helpers
import android.annotation.SuppressLint
import android.content.Intent

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.util
package ua.acclorite.book_story.ui.common.helpers
import androidx.compose.foundation.combinedClickable
import androidx.compose.ui.Modifier

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
package ua.acclorite.book_story.ui.common.util
package ua.acclorite.book_story.ui.common.helpers
import android.content.Context
import android.widget.Toast

View file

@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import ua.acclorite.book_story.presentation.about.AboutEvent
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.provideCredits
import ua.acclorite.book_story.ui.credits.data.CreditData
@Composable
fun CreditsLayout(
@ -32,7 +32,7 @@ fun CreditsLayout(
state = listState
) {
items(
provideCredits(),
CreditData.credits,
key = { it.name }
) { credit ->
CreditItem(credit = credit) {

View file

@ -0,0 +1,101 @@
/*
* 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.credits.data
import kotlinx.collections.immutable.persistentListOf
import ua.acclorite.book_story.R
import ua.acclorite.book_story.core.ui.UIText
import ua.acclorite.book_story.ui.about.model.Credit
object CreditData {
val credits = persistentListOf(
Credit(
name = "Tachiyomi (Mihon)",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_design),
UIText.StringResource(R.string.credits_ideas),
UIText.StringValue("Readme")
),
website = "https://www.github.com/mihonapp/mihon"
),
Credit(
name = "Kitsune",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_updates),
UIText.StringResource(R.string.credits_ideas)
),
website = "https://www.github.com/Drumber/Kitsune"
),
Credit(
name = "Voyager",
source = "Voyager Website",
credits = listOf(
UIText.StringResource(R.string.credits_ideas)
),
website = "https://voyager.adriel.cafe/"
),
Credit(
name = "Material Design Icons",
source = "Google Fonts",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://fonts.google.com/icons"
),
Credit(
name = "Material Design Fonts",
source = "Google Fonts",
credits = listOf(
UIText.StringResource(R.string.credits_fonts)
),
website = "https://fonts.google.com"
),
Credit(
name = "Weblate",
source = "Hosted Weblate",
credits = listOf(
UIText.StringResource(R.string.credits_translation),
UIText.StringResource(R.string.credits_contribution)
),
website = "https://hosted.weblate.org/projects/book-story"
),
Credit(
name = "OpenDyslexic Font",
source = "OpenDyslexic Website",
credits = listOf(
UIText.StringResource(R.string.credits_fonts)
),
website = "https://opendyslexic.org"
),
Credit(
name = "GitLab Badge",
source = "Censorship Website",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://censorship.no/en/index.html"
),
Credit(
name = "GitHub Badge",
source = "GitHub",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://github.com/Kunzisoft/Github-badge"
),
Credit(
name = "Codeberg Badge",
source = "Codeberg",
credits = listOf(
UIText.StringResource(R.string.credits_icon)
),
website = "https://codeberg.org/Codeberg/GetItOnCodeberg"
)
)
}

View file

@ -39,8 +39,8 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.common.components.common.StyledText
import ua.acclorite.book_story.ui.common.helpers.noRippleClickable
import ua.acclorite.book_story.ui.common.model.Position
import ua.acclorite.book_story.ui.common.util.noRippleClickable
import ua.acclorite.book_story.ui.help.model.HelpTip
import ua.acclorite.book_story.ui.theme.ExpandingTransition

View file

@ -15,8 +15,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.ui.common.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.ui.common.constants.provideHelpTips
import ua.acclorite.book_story.ui.common.model.Position
import ua.acclorite.book_story.ui.help.data.HelpData
@Composable
fun HelpLayout(
@ -31,14 +31,14 @@ fun HelpLayout(
contentPadding = PaddingValues(vertical = 16.dp)
) {
itemsIndexed(
provideHelpTips(),
HelpData.tips,
key = { _, helpTip -> helpTip.title }
) { index, helpTip ->
HelpItem(
helpTip = helpTip,
position = when (index) {
0 -> Position.TOP
provideHelpTips().lastIndex -> Position.BOTTOM
HelpData.tips.lastIndex -> Position.BOTTOM
else -> Position.CENTER
}
)

View file

@ -0,0 +1,155 @@
/*
* 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.help.data
import androidx.compose.ui.res.stringResource
import kotlinx.collections.immutable.persistentListOf
import ua.acclorite.book_story.R
import ua.acclorite.book_story.ui.help.HelpAnnotation
import ua.acclorite.book_story.ui.help.model.HelpTip
object HelpData {
val tips = persistentListOf(
HelpTip(
title = R.string.help_title_how_to_add_books,
description = {
append(stringResource(id = R.string.help_desc_how_to_add_books_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_add_books_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_add_books_3) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_add_books_4))
}
append(".")
}
),
HelpTip(
title = R.string.help_title_how_to_customize_app,
description = {
append(stringResource(id = R.string.help_desc_how_to_customize_app_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_customize_app_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_customize_app_3))
}
),
HelpTip(
title = R.string.help_title_how_to_move_or_delete_books,
description = {
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_3))
}
),
HelpTip(
title = R.string.help_title_how_to_edit_book,
description = {
append(stringResource(id = R.string.help_desc_how_to_edit_book_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_edit_book_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_edit_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_read_book,
description = {
append(stringResource(id = R.string.help_desc_how_to_read_book_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_read_book_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_read_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_customize_reader,
description = {
append(stringResource(id = R.string.help_desc_how_to_customize_reader_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_customize_reader_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_customize_reader_3))
}
),
HelpTip(
title = R.string.help_title_how_to_manage_history,
description = {
append(stringResource(id = R.string.help_desc_how_to_manage_history_1) + " ")
HelpAnnotation {
append(stringResource(id = R.string.help_desc_how_to_manage_history_2))
}
append(". ")
append(stringResource(id = R.string.help_desc_how_to_manage_history_3))
}
),
HelpTip(
title = R.string.help_title_how_to_use_tooltip,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_tooltip_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_double_click_translation,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_double_click_translation_1))
}
),
HelpTip(
title = R.string.help_title_how_to_create_color_presets,
description = {
append(stringResource(id = R.string.help_desc_how_to_create_color_presets_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_color_presets,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_color_presets_1))
}
),
HelpTip(
title = R.string.help_title_how_to_use_perception_expander,
description = {
append(stringResource(id = R.string.help_desc_how_to_use_perception_expander_1))
}
)
)
}

Some files were not shown because too many files have changed in this diff Show more