🚀 Random font & Constants reformat

This commit is contained in:
Acclorite 2024-10-18 08:53:36 +03:00
parent 8309af3d4d
commit 3f0e9a512c
36 changed files with 802 additions and 730 deletions

View file

@ -11,6 +11,8 @@ import android.net.Uri
import ua.acclorite.book_story.R
import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideDownloadLatestReleasePage
import ua.acclorite.book_story.presentation.core.constants.provideReleasesPage
import javax.inject.Inject
class UpdatesNotificationServiceImpl @Inject constructor(
@ -28,11 +30,11 @@ class UpdatesNotificationServiceImpl @Inject constructor(
override fun postNotification(releaseInfo: LatestReleaseInfo) {
val downloadLatestVersionIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse(Constants.DOWNLOAD_LATEST_RELEASE_PAGE)
Uri.parse(Constants.provideDownloadLatestReleasePage())
)
val latestReleaseIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse(Constants.RELEASES_PAGE)
Uri.parse(Constants.provideReleasesPage())
)
val downloadLatestVersionPendingIntent = PendingIntent.getActivity(

View file

@ -16,6 +16,7 @@ import ua.acclorite.book_story.domain.repository.FileSystemRepository
import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideSupportedExtensions
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton
@ -47,7 +48,7 @@ class FileSystemRepositoryImpl @Inject constructor(
val existingBooks = database
.searchBooks("")
.map { bookMapper.toBook(it) }
val supportedExtensions = Constants.EXTENSIONS
val supportedExtensions = Constants.provideSupportedExtensions()
fun File.isValid(): Boolean {
if (!exists()) {

View file

@ -15,6 +15,7 @@ import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.InternalLazyColumnScrollbar
import my.nanihadesuka.compose.ScrollbarSettings
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideSecondaryScrollbar
/**
* Custom Lazy Column.
@ -22,7 +23,7 @@ import ua.acclorite.book_story.presentation.core.constants.Constants
*
* @param modifier Modifier.
* @param state [LazyListState].
* @param scrollbarSettings [ScrollbarSettings]. [Constants.SECONDARY_SCROLLBAR] by default.
* @param scrollbarSettings [ScrollbarSettings]. [provideSecondaryScrollbar] by default.
* @param enableScrollbar Whether scrollbar is enabled.
* @param contentPadding [PaddingValues].
* @param verticalArrangement Vertical item arrangement.
@ -32,7 +33,7 @@ import ua.acclorite.book_story.presentation.core.constants.Constants
fun CustomLazyColumn(
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
scrollbarSettings: ScrollbarSettings = Constants.SECONDARY_SCROLLBAR,
scrollbarSettings: ScrollbarSettings = Constants.provideSecondaryScrollbar(),
enableScrollbar: Boolean = true,
contentPadding: PaddingValues = PaddingValues(0.dp),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,

View file

@ -9,6 +9,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import ua.acclorite.book_story.domain.util.Route
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideNavigationItems
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance
/**
@ -22,7 +23,7 @@ fun BottomNavigationBar() {
LaunchedEffect(Unit) {
navigator.currentScreen.collect { route ->
if (
Constants.NAVIGATION_ITEMS.any {
Constants.provideNavigationItems().any {
navigator.run { it.screen.getRoute() } == route
}
) {
@ -32,7 +33,7 @@ fun BottomNavigationBar() {
}
NavigationBar {
Constants.NAVIGATION_ITEMS.forEach {
Constants.provideNavigationItems().forEach {
BottomNavigationBarItem(
item = it,
isSelected = currentScreen == navigator.run { it.screen.getRoute() }

View file

@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.providePrimaryScrollbar
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
/**
@ -127,7 +128,7 @@ fun CustomModalDrawer(
CustomLazyColumn(
state = rememberLazyListState(startIndex),
modifier = Modifier.fillMaxSize(),
scrollbarSettings = Constants.PRIMARY_SCROLLBAR,
scrollbarSettings = Constants.providePrimaryScrollbar(),
contentPadding = PaddingValues(vertical = 9.dp)
) {
content()

View file

@ -25,6 +25,7 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.util.Route
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideNavigationItems
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance
/**
@ -39,7 +40,7 @@ fun CustomNavigationRail() {
LaunchedEffect(Unit) {
navigator.currentScreen.collect { route ->
if (
Constants.NAVIGATION_ITEMS.any {
Constants.provideNavigationItems().any {
navigator.run { it.screen.getRoute() } == route
}
) {
@ -70,7 +71,7 @@ fun CustomNavigationRail() {
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
) {
Constants.NAVIGATION_ITEMS.forEach {
Constants.provideNavigationItems().forEach {
CustomNavigationRailItem(
item = it,
isSelected = currentScreen == navigator.run { it.screen.getRoute() }

View file

@ -0,0 +1,44 @@
package ua.acclorite.book_story.presentation.core.constants
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Badge
fun Constants.provideAboutBadges() = listOf(
Badge(
id = "x",
drawable = R.drawable.x_logo,
imageVector = null,
contentDescription = R.string.x_content_desc,
url = "https://www.x.com/acclorite"
),
Badge(
id = "reddit",
drawable = R.drawable.reddit,
imageVector = null,
contentDescription = R.string.reddit_content_desc,
url = "https://www.reddit.com/user/Acclorite/"
),
Badge(
id = "tryzub",
drawable = R.drawable.tryzub,
imageVector = null,
contentDescription = R.string.tryzub_content_desc,
url = null
),
Badge(
id = "patreon",
drawable = R.drawable.patreon,
imageVector = null,
contentDescription = R.string.patreon_content_desc,
url = "https://www.patreon.com/Acclorite"
),
Badge(
id = "github_profile",
drawable = null,
imageVector = Icons.Default.Person,
contentDescription = R.string.github_profile_content_desc,
url = "https://www.github.com/Acclorite"
),
)

View file

@ -1,686 +1,3 @@
@file:Suppress("unused")
package ua.acclorite.book_story.presentation.core.constants
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.ScrollbarSelectionMode
import my.nanihadesuka.compose.ScrollbarSettings
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Badge
import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.domain.model.ColorPreset
import ua.acclorite.book_story.domain.model.Credit
import ua.acclorite.book_story.domain.model.FontWithName
import ua.acclorite.book_story.domain.model.HelpTip
import ua.acclorite.book_story.domain.model.NavigationItem
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.ui.Theme
object Constants {
// Main State Constant
const val MAIN_STATE = "main_state"
// Supported file extensions
val EXTENSIONS = provideSupportedExtensions()
// Supported languages
val LANGUAGES = provideLanguages()
// Navigation items for NavigationBars.
val NAVIGATION_ITEMS = provideNavigationItems()
// Supported themes
val THEMES = provideThemes()
// Credits
val CREDITS = provideCredits()
// Help Tips
val HELP_TIPS = provideHelpTips()
// About Badges
val ABOUT_BADGES = provideAboutBadges()
// Fonts for Reader
val FONTS = provideFonts()
// Empty Book (Used for Default Screen values)
val EMPTY_BOOK = provideEmptyBook()
// Default Color Preset (Used when creating new color presets)
val DEFAULT_COLOR_PRESET = provideDefaultColorPreset()
// Empty Chapter
val EMPTY_CHAPTER = provideEmptyChapter()
// Scrollbars (Primary unused, awaiting for fixes)
val PRIMARY_SCROLLBAR @Composable get() = providePrimaryScrollbar()
val SECONDARY_SCROLLBAR @Composable get() = provideSecondaryScrollbar()
// Links
const val DOWNLOAD_LATEST_RELEASE_PAGE =
"https://www.github.com/Acclorite/book-story/releases/latest/download/book-story.apk"
const val RELEASES_PAGE = "https://www.github.com/Acclorite/book-story/releases/latest"
const val ISSUES_PAGE = "https://www.github.com/Acclorite/book-story/issues"
const val CONTRIBUTORS_PAGE = "https://github.com/Acclorite/book-story/graphs/contributors"
const val TRANSLATION_PAGE = "https://hosted.weblate.org/projects/book-story"
}
private fun provideSupportedExtensions() = listOf(
".epub", ".pdf", ".fb2", ".txt", ".zip", ".html", ".htm"
)
private 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", "汉语"),
)
private fun provideNavigationItems() = listOf(
NavigationItem(
screen = Screen.Library,
title = R.string.library_screen,
tooltip = R.string.library_content_desc,
selectedIcon = R.drawable.library_screen_filled,
unselectedIcon = R.drawable.library_screen_outlined
),
NavigationItem(
screen = Screen.History,
title = R.string.history_screen,
tooltip = R.string.history_content_desc,
selectedIcon = R.drawable.history_screen_filled,
unselectedIcon = R.drawable.history_screen_outlined
),
NavigationItem(
screen = Screen.Browse,
title = R.string.browse_screen,
tooltip = R.string.browse_content_desc,
selectedIcon = R.drawable.browse_screen_filled,
unselectedIcon = R.drawable.browse_screen_outlined
)
)
private fun provideThemes() = listOf(
Pair(Theme.DYNAMIC, UIText.StringResource(R.string.dynamic_theme)),
Pair(Theme.BLUE, UIText.StringResource(R.string.blue_theme)),
Pair(Theme.GREEN, UIText.StringResource(R.string.green_theme)),
Pair(Theme.MARSH, UIText.StringResource(R.string.marsh_theme)),
Pair(Theme.RED, UIText.StringResource(R.string.red_theme)),
Pair(Theme.PURPLE, UIText.StringResource(R.string.purple_theme)),
Pair(Theme.LAVENDER, UIText.StringResource(R.string.lavender_theme)),
Pair(Theme.PINK, UIText.StringResource(R.string.pink_theme)),
Pair(Theme.YELLOW, UIText.StringResource(R.string.yellow_theme)),
Pair(Theme.AQUA, UIText.StringResource(R.string.aqua_theme)),
)
private 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 = "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"
),
)
private fun provideHelpTips() = listOf(
HelpTip(
title = R.string.help_title_how_to_add_books,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_add_books_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Browse, useBackAnimation = true)
}
}
}
) {
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(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
append(stringResource(id = R.string.help_desc_how_to_add_books_4))
}
append(".")
}
),
HelpTip(
title = R.string.help_title_how_to_customize_app,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_customize_app_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Settings, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_edit_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_read_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_customize_reader_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Settings, useBackAnimation = true)
}
}
}
) {
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_update_book,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_update_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
append(stringResource(id = R.string.help_desc_how_to_update_book_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_update_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_manage_history,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_manage_history_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.History, useBackAnimation = true)
}
}
}
) {
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_title_how_to_use_perception_expander_1))
}
),
)
private fun provideAboutBadges() = listOf(
Badge(
id = "x",
drawable = R.drawable.x_logo,
imageVector = null,
contentDescription = R.string.x_content_desc,
url = "https://www.x.com/acclorite"
),
Badge(
id = "reddit",
drawable = R.drawable.reddit,
imageVector = null,
contentDescription = R.string.reddit_content_desc,
url = "https://www.reddit.com/user/Acclorite/"
),
Badge(
id = "tryzub",
drawable = R.drawable.tryzub,
imageVector = null,
contentDescription = R.string.tryzub_content_desc,
url = null
),
Badge(
id = "patreon",
drawable = R.drawable.patreon,
imageVector = null,
contentDescription = R.string.patreon_content_desc,
url = "https://www.patreon.com/Acclorite"
),
Badge(
id = "github_profile",
drawable = null,
imageVector = Icons.Default.Person,
contentDescription = R.string.github_profile_content_desc,
url = "https://www.github.com/Acclorite"
),
)
private fun provideFonts() = listOf(
FontWithName(
"default",
UIText.StringResource(R.string.default_string),
FontFamily.Default
),
FontWithName(
"raleway",
UIText.StringValue("Raleway"),
FontFamily(
Font(R.font.raleway_regular),
Font(R.font.raleway_regular_italic, style = FontStyle.Italic),
Font(R.font.raleway_medium, weight = FontWeight.Medium),
Font(R.font.raleway_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"open_sans",
UIText.StringValue("Open Sans"),
FontFamily(
Font(R.font.opensans_regular),
Font(R.font.opensans_regular_italic, style = FontStyle.Italic),
Font(R.font.opensans_medium, weight = FontWeight.Medium),
Font(
R.font.opensans_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"mulish",
UIText.StringValue("Mulish"),
FontFamily(
Font(R.font.mulish_regular),
Font(R.font.mulish_regular_italic, style = FontStyle.Italic),
Font(R.font.mulish_medium, weight = FontWeight.Medium),
Font(R.font.mulish_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"arimo",
UIText.StringValue("Arimo"),
FontFamily(
Font(R.font.arimo_regular),
Font(R.font.arimo_regular_italic, style = FontStyle.Italic),
Font(R.font.arimo_medium, weight = FontWeight.Medium),
Font(R.font.arimo_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"garamond",
UIText.StringValue("Garamond"),
FontFamily(
Font(R.font.garamond_regular),
Font(R.font.garamond_regular_italic, style = FontStyle.Italic),
Font(R.font.garamond_medium, weight = FontWeight.Medium),
Font(
R.font.garamond_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"roboto_serif",
UIText.StringValue("Roboto Serif"),
FontFamily(
Font(R.font.robotoserif_regular),
Font(R.font.robotoserif_regular_italic, style = FontStyle.Italic),
Font(R.font.robotoserif_medium, weight = FontWeight.Medium),
Font(
R.font.robotoserif_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"noto_serif",
UIText.StringValue("Noto Serif"),
FontFamily(
Font(R.font.notoserif_regular),
Font(R.font.notoserif_regular_italic, style = FontStyle.Italic),
Font(R.font.notoserif_medium, weight = FontWeight.Medium),
Font(
R.font.notoserif_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"noto_sans",
UIText.StringValue("Noto Sans"),
FontFamily(
Font(R.font.notosans_regular),
Font(R.font.notosans_regular_italic, style = FontStyle.Italic),
Font(R.font.notosans_medium, weight = FontWeight.Medium),
Font(
R.font.notosans_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"roboto",
UIText.StringValue("Roboto"),
FontFamily(
Font(R.font.roboto_regular),
Font(R.font.roboto_regular_italic, style = FontStyle.Italic),
Font(R.font.roboto_medium, weight = FontWeight.Medium),
Font(R.font.roboto_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"jost",
UIText.StringValue("Jost"),
FontFamily(
Font(R.font.jost_regular),
Font(R.font.jost_regular_italic, style = FontStyle.Italic),
Font(R.font.jost_medium, weight = FontWeight.Medium),
Font(R.font.jost_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"merriweather",
UIText.StringValue("Merriweather"),
FontFamily(
Font(R.font.merriweather_regular),
Font(R.font.merriweather_regular_italic, style = FontStyle.Italic),
Font(R.font.merriweather_medium, weight = FontWeight.Medium),
Font(
R.font.merriweather_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"montserrat",
UIText.StringValue("Montserrat"),
FontFamily(
Font(R.font.montserrat_regular),
Font(R.font.montserrat_regular_italic, style = FontStyle.Italic),
Font(R.font.montserrat_medium, weight = FontWeight.Medium),
Font(
R.font.montserrat_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"nunito",
UIText.StringValue("Nunito"),
FontFamily(
Font(R.font.nunito_regular),
Font(R.font.nunito_regular_italic, style = FontStyle.Italic),
Font(R.font.nunito_medium, weight = FontWeight.Medium),
Font(R.font.nunito_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
),
FontWithName(
"roboto_slab",
UIText.StringValue("Roboto Slab"),
FontFamily(
Font(R.font.robotoslab_regular),
Font(R.font.robotoslab_medium, weight = FontWeight.Medium),
)
),
FontWithName(
"lora",
UIText.StringValue("Lora"),
FontFamily(
Font(R.font.lora_regular),
Font(R.font.lora_regular_italic, style = FontStyle.Italic),
Font(R.font.lora_medium, weight = FontWeight.Medium),
Font(R.font.lora_medium_italic, weight = FontWeight.Medium, style = FontStyle.Italic)
)
)
)
private fun provideEmptyBook() = Book(
id = -1,
title = "",
author = UIText.StringValue(""),
description = null,
textPath = "",
filePath = "",
coverImage = null,
scrollIndex = 0,
scrollOffset = 0,
progress = 0f,
lastOpened = null,
category = Category.READING
)
private fun provideDefaultColorPreset() = ColorPreset(
id = -1,
name = null,
backgroundColor = Color(0xFFFAF8FF), // Blue Light Surface (hardcoded)
fontColor = Color(0xFF44464F), // Blue Light OnSurfaceVariant (hardcoded)
isSelected = false
)
private fun provideEmptyChapter() = Chapter(
index = 0,
title = "",
startIndex = 0,
endIndex = 0
)
@Composable
private fun providePrimaryScrollbar() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.primary,
thumbSelectedColor = MaterialTheme.colorScheme.primary.copy(0.8f),
hideDelayMillis = 2000,
durationAnimationMillis = 300,
selectionMode = ScrollbarSelectionMode.Thumb,
thumbThickness = 8.dp,
scrollbarPadding = 4.dp
)
@Composable
private 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
)
object Constants

View file

@ -0,0 +1,52 @@
package ua.acclorite.book_story.presentation.core.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Credit
import ua.acclorite.book_story.domain.util.UIText
fun Constants.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 = "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"
),
)

View file

@ -0,0 +1,234 @@
package ua.acclorite.book_story.presentation.core.constants
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.FontWithName
import ua.acclorite.book_story.domain.util.UIText
fun Constants.provideFonts(withRandom: Boolean): List<FontWithName> {
return mutableListOf(
FontWithName(
"default",
UIText.StringResource(R.string.default_string),
FontFamily.Default
),
FontWithName(
"raleway",
UIText.StringValue("Raleway"),
FontFamily(
Font(R.font.raleway_regular),
Font(R.font.raleway_regular_italic, style = FontStyle.Italic),
Font(R.font.raleway_medium, weight = FontWeight.Medium),
Font(
R.font.raleway_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"open_sans",
UIText.StringValue("Open Sans"),
FontFamily(
Font(R.font.opensans_regular),
Font(R.font.opensans_regular_italic, style = FontStyle.Italic),
Font(R.font.opensans_medium, weight = FontWeight.Medium),
Font(
R.font.opensans_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"mulish",
UIText.StringValue("Mulish"),
FontFamily(
Font(R.font.mulish_regular),
Font(R.font.mulish_regular_italic, style = FontStyle.Italic),
Font(R.font.mulish_medium, weight = FontWeight.Medium),
Font(
R.font.mulish_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"arimo",
UIText.StringValue("Arimo"),
FontFamily(
Font(R.font.arimo_regular),
Font(R.font.arimo_regular_italic, style = FontStyle.Italic),
Font(R.font.arimo_medium, weight = FontWeight.Medium),
Font(
R.font.arimo_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"garamond",
UIText.StringValue("Garamond"),
FontFamily(
Font(R.font.garamond_regular),
Font(R.font.garamond_regular_italic, style = FontStyle.Italic),
Font(R.font.garamond_medium, weight = FontWeight.Medium),
Font(
R.font.garamond_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"roboto_serif",
UIText.StringValue("Roboto Serif"),
FontFamily(
Font(R.font.robotoserif_regular),
Font(R.font.robotoserif_regular_italic, style = FontStyle.Italic),
Font(R.font.robotoserif_medium, weight = FontWeight.Medium),
Font(
R.font.robotoserif_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"noto_serif",
UIText.StringValue("Noto Serif"),
FontFamily(
Font(R.font.notoserif_regular),
Font(R.font.notoserif_regular_italic, style = FontStyle.Italic),
Font(R.font.notoserif_medium, weight = FontWeight.Medium),
Font(
R.font.notoserif_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"noto_sans",
UIText.StringValue("Noto Sans"),
FontFamily(
Font(R.font.notosans_regular),
Font(R.font.notosans_regular_italic, style = FontStyle.Italic),
Font(R.font.notosans_medium, weight = FontWeight.Medium),
Font(
R.font.notosans_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"roboto",
UIText.StringValue("Roboto"),
FontFamily(
Font(R.font.roboto_regular),
Font(R.font.roboto_regular_italic, style = FontStyle.Italic),
Font(R.font.roboto_medium, weight = FontWeight.Medium),
Font(
R.font.roboto_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"jost",
UIText.StringValue("Jost"),
FontFamily(
Font(R.font.jost_regular),
Font(R.font.jost_regular_italic, style = FontStyle.Italic),
Font(R.font.jost_medium, weight = FontWeight.Medium),
Font(
R.font.jost_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"merriweather",
UIText.StringValue("Merriweather"),
FontFamily(
Font(R.font.merriweather_regular),
Font(R.font.merriweather_regular_italic, style = FontStyle.Italic),
Font(R.font.merriweather_medium, weight = FontWeight.Medium),
Font(
R.font.merriweather_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"montserrat",
UIText.StringValue("Montserrat"),
FontFamily(
Font(R.font.montserrat_regular),
Font(R.font.montserrat_regular_italic, style = FontStyle.Italic),
Font(R.font.montserrat_medium, weight = FontWeight.Medium),
Font(
R.font.montserrat_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"nunito",
UIText.StringValue("Nunito"),
FontFamily(
Font(R.font.nunito_regular),
Font(R.font.nunito_regular_italic, style = FontStyle.Italic),
Font(R.font.nunito_medium, weight = FontWeight.Medium),
Font(
R.font.nunito_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
),
FontWithName(
"roboto_slab",
UIText.StringValue("Roboto Slab"),
FontFamily(
Font(R.font.robotoslab_regular),
Font(R.font.robotoslab_medium, weight = FontWeight.Medium),
)
),
FontWithName(
"lora",
UIText.StringValue("Lora"),
FontFamily(
Font(R.font.lora_regular),
Font(R.font.lora_regular_italic, style = FontStyle.Italic),
Font(R.font.lora_medium, weight = FontWeight.Medium),
Font(
R.font.lora_medium_italic,
weight = FontWeight.Medium,
style = FontStyle.Italic
)
)
)
).apply {
if (withRandom) {
add(
1,
FontWithName(
"random",
UIText.StringResource(R.string.random_string),
provideFonts(withRandom = false).random().font
)
)
}
}
}

View file

@ -0,0 +1,83 @@
package ua.acclorite.book_story.presentation.core.constants
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.ScrollbarSelectionMode
import my.nanihadesuka.compose.ScrollbarSettings
import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.domain.model.ColorPreset
import ua.acclorite.book_story.domain.util.UIText
// Main State
fun Constants.provideMainState() = "main_state"
// Empty Book
fun Constants.provideEmptyBook() = Book(
id = -1,
title = "",
author = UIText.StringValue(""),
description = null,
textPath = "",
filePath = "",
coverImage = null,
scrollIndex = 0,
scrollOffset = 0,
progress = 0f,
lastOpened = null,
category = Category.READING
)
// Default Color Preset
fun Constants.provideDefaultColorPreset() = ColorPreset(
id = -1,
name = null,
backgroundColor = Color(0xFFFAF8FF), // Blue Light Surface (hardcoded)
fontColor = Color(0xFF44464F), // Blue Light OnSurfaceVariant (hardcoded)
isSelected = false
)
// Primary Scrollbar
@Composable
fun Constants.providePrimaryScrollbar() = ScrollbarSettings(
thumbUnselectedColor = MaterialTheme.colorScheme.primary,
thumbSelectedColor = MaterialTheme.colorScheme.primary.copy(0.8f),
hideDelayMillis = 2000,
durationAnimationMillis = 300,
selectionMode = ScrollbarSelectionMode.Thumb,
thumbThickness = 8.dp,
scrollbarPadding = 4.dp
)
// Secondary Scrollbar
@Composable
fun Constants.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
)
// Links
fun Constants.provideDownloadLatestReleasePage() =
"https://www.github.com/Acclorite/book-story/releases/latest/download/book-story.apk"
fun Constants.provideReleasesPage() =
"https://www.github.com/Acclorite/book-story/releases/latest"
fun Constants.provideIssuesPage() =
"https://www.github.com/Acclorite/book-story/issues"
fun Constants.provideContributorsPage() =
"https://github.com/Acclorite/book-story/graphs/contributors"
fun Constants.provideTranslationPage() =
"https://hosted.weblate.org/projects/book-story"

View file

@ -0,0 +1,233 @@
package ua.acclorite.book_story.presentation.core.constants
import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.HelpTip
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
fun Constants.provideHelpTips() = listOf(
HelpTip(
title = R.string.help_title_how_to_add_books,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_add_books_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Browse, useBackAnimation = true)
}
}
}
) {
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(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
append(stringResource(id = R.string.help_desc_how_to_add_books_4))
}
append(".")
}
),
HelpTip(
title = R.string.help_title_how_to_customize_app,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_customize_app_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Settings, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_move_or_delete_books_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_edit_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_read_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
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 = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_customize_reader_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Settings, useBackAnimation = true)
}
}
}
) {
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_update_book,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_update_book_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
}
}
) {
append(stringResource(id = R.string.help_desc_how_to_update_book_2))
}
append(" ")
append(stringResource(id = R.string.help_desc_how_to_update_book_3))
}
),
HelpTip(
title = R.string.help_title_how_to_manage_history,
description = { onNavigate, fromStart ->
append(stringResource(id = R.string.help_desc_how_to_manage_history_1) + " ")
HelpAnnotation(
onClick = {
if (!fromStart) {
onNavigate {
navigate(Screen.History, useBackAnimation = true)
}
}
}
) {
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_title_how_to_use_perception_expander_1))
}
),
)

View file

@ -0,0 +1,14 @@
package ua.acclorite.book_story.presentation.core.constants
fun Constants.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", "汉语"),
)

View file

@ -0,0 +1,29 @@
package ua.acclorite.book_story.presentation.core.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.NavigationItem
import ua.acclorite.book_story.presentation.core.navigation.Screen
fun Constants.provideNavigationItems() = listOf(
NavigationItem(
screen = Screen.Library,
title = R.string.library_screen,
tooltip = R.string.library_content_desc,
selectedIcon = R.drawable.library_screen_filled,
unselectedIcon = R.drawable.library_screen_outlined
),
NavigationItem(
screen = Screen.History,
title = R.string.history_screen,
tooltip = R.string.history_content_desc,
selectedIcon = R.drawable.history_screen_filled,
unselectedIcon = R.drawable.history_screen_outlined
),
NavigationItem(
screen = Screen.Browse,
title = R.string.browse_screen,
tooltip = R.string.browse_content_desc,
selectedIcon = R.drawable.browse_screen_filled,
unselectedIcon = R.drawable.browse_screen_outlined
)
)

View file

@ -0,0 +1,11 @@
package ua.acclorite.book_story.presentation.core.constants
fun Constants.provideSupportedExtensions() = listOf(
".epub",
".pdf",
".fb2",
".txt",
".zip",
".html",
".htm"
)

View file

@ -0,0 +1,18 @@
package ua.acclorite.book_story.presentation.core.constants
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.ui.Theme
fun Constants.provideThemes() = listOf(
Pair(Theme.DYNAMIC, UIText.StringResource(R.string.dynamic_theme)),
Pair(Theme.BLUE, UIText.StringResource(R.string.blue_theme)),
Pair(Theme.GREEN, UIText.StringResource(R.string.green_theme)),
Pair(Theme.MARSH, UIText.StringResource(R.string.marsh_theme)),
Pair(Theme.RED, UIText.StringResource(R.string.red_theme)),
Pair(Theme.PURPLE, UIText.StringResource(R.string.purple_theme)),
Pair(Theme.LAVENDER, UIText.StringResource(R.string.lavender_theme)),
Pair(Theme.PINK, UIText.StringResource(R.string.pink_theme)),
Pair(Theme.YELLOW, UIText.StringResource(R.string.yellow_theme)),
Pair(Theme.AQUA, UIText.StringResource(R.string.aqua_theme)),
)

View file

@ -10,6 +10,8 @@ import androidx.datastore.preferences.core.Preferences
import kotlinx.parcelize.Parcelize
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants
import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.core.constants.provideLanguages
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseSortOrder
@ -42,7 +44,7 @@ data class MainState(
// General Settings
val language: String = provideDefaultValue {
val locale = Locale.getDefault().language.take(2)
Constants.LANGUAGES.any { locale == it.first }.run {
Constants.provideLanguages().any { locale == it.first }.run {
if (this) locale
else "en"// Default language.
}
@ -60,7 +62,7 @@ data class MainState(
val doublePressExit: Boolean = provideDefaultValue { false },
// Reader Settings
val fontFamily: String = provideDefaultValue { Constants.FONTS[0].id },
val fontFamily: String = provideDefaultValue { Constants.provideFonts(withRandom = false)[0].id },
val isItalic: Boolean = provideDefaultValue { false },
val fontSize: Int = provideDefaultValue { 16 },
val lineHeight: Int = provideDefaultValue { 4 },

View file

@ -19,6 +19,8 @@ import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore
import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants
import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.core.constants.provideMainState
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseFilesStructure
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseLayout
@ -57,7 +59,7 @@ class MainViewModel @Inject constructor(
private val isViewModelReady = MutableStateFlow(false)
private val _state: MutableStateFlow<MainState> = MutableStateFlow(
stateHandle[Constants.MAIN_STATE] ?: MainState()
stateHandle[Constants.provideMainState()] ?: MainState()
)
override val state = _state.asStateFlow()
@ -104,8 +106,9 @@ class MainViewModel @Inject constructor(
value = event.value,
updateState = {
it.copy(
fontFamily = Constants.FONTS.find { font -> font.id == event.value }?.id
?: Constants.FONTS[0].id
fontFamily = Constants.provideFonts(withRandom = true)
.find { font -> font.id == event.value }?.id
?: Constants.provideFonts(withRandom = false)[0].id
)
}
)
@ -472,7 +475,7 @@ class MainViewModel @Inject constructor(
function: (MainState) -> MainState
) {
_state.update {
stateHandle[Constants.MAIN_STATE] = function(it)
stateHandle[Constants.provideMainState()] = function(it)
function(it)
}
}

View file

@ -32,6 +32,10 @@ import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideContributorsPage
import ua.acclorite.book_story.presentation.core.constants.provideIssuesPage
import ua.acclorite.book_story.presentation.core.constants.provideReleasesPage
import ua.acclorite.book_story.presentation.core.constants.provideTranslationPage
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast
@ -159,7 +163,7 @@ private fun AboutScreen() {
) {
onEvent(
AboutEvent.OnNavigateToBrowserPage(
Constants.ISSUES_PAGE,
Constants.provideIssuesPage(),
context,
noAppsFound = {
context.getString(R.string.error_no_browser)
@ -178,7 +182,7 @@ private fun AboutScreen() {
) {
onEvent(
AboutEvent.OnNavigateToBrowserPage(
Constants.CONTRIBUTORS_PAGE,
Constants.provideContributorsPage(),
context,
noAppsFound = {
context.getString(R.string.error_no_browser)
@ -196,7 +200,7 @@ private fun AboutScreen() {
) {
onEvent(
AboutEvent.OnNavigateToBrowserPage(
Constants.RELEASES_PAGE,
Constants.provideReleasesPage(),
context,
noAppsFound = {
context.getString(R.string.error_no_browser)
@ -236,7 +240,7 @@ private fun AboutScreen() {
) {
onEvent(
AboutEvent.OnNavigateToBrowserPage(
Constants.TRANSLATION_PAGE,
Constants.provideTranslationPage(),
context,
noAppsFound = {
context.getString(R.string.error_no_browser)

View file

@ -9,6 +9,7 @@ import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideReleasesPage
import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
@ -39,7 +40,7 @@ fun AboutUpdateDialog() {
onAction = {
onEvent(
AboutEvent.OnNavigateToBrowserPage(
page = Constants.RELEASES_PAGE,
page = Constants.provideReleasesPage(),
context = context,
noAppsFound = {
context.getString(R.string.error_no_browser).showToast(

View file

@ -14,6 +14,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideAboutBadges
import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
@ -39,7 +40,7 @@ fun AboutBadges(verticalPadding: Dp = 18.dp) {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(13.dp)
) {
items(Constants.ABOUT_BADGES, key = { it.id }) { badge ->
items(Constants.provideAboutBadges(), key = { it.id }) { badge ->
AboutBadgeItem(badge = badge) {
when (badge.id) {
"tryzub" -> {

View file

@ -22,6 +22,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideCredits
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
@ -70,7 +71,7 @@ private fun CreditsScreen() {
.padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second
) {
items(Constants.CREDITS, key = { it.name }) {
items(Constants.provideCredits(), key = { it.name }) {
CreditItem(credit = it) {
it.website?.let { website ->
onEvent(

View file

@ -5,10 +5,11 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideEmptyBook
@Immutable
data class BookInfoState(
val book: Book = Constants.EMPTY_BOOK,
val book: Book = Constants.provideEmptyBook(),
val checkingForUpdate: Boolean = false,
val updating: Boolean = false,

View file

@ -34,6 +34,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideHelpTips
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.data.MainEvent
@ -158,14 +159,14 @@ private fun HelpScreen() {
}
itemsIndexed(
Constants.HELP_TIPS,
Constants.provideHelpTips(),
key = { _, helpTip -> helpTip.title }
) { index, helpTip ->
HelpItem(
helpTip = helpTip,
position = when (index) {
0 -> Position.TOP
Constants.HELP_TIPS.lastIndex -> Position.BOTTOM
Constants.provideHelpTips().lastIndex -> Position.BOTTOM
else -> Position.CENTER
},
fromStart = state.value.fromStart

View file

@ -63,6 +63,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibi
import ua.acclorite.book_story.presentation.core.components.CustomSelectionContainer
import ua.acclorite.book_story.presentation.core.components.is_messages.IsError
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.noRippleClickable
@ -240,9 +241,9 @@ private fun ReaderScreen(lazyListState: LazyListState) {
}
val fontFamily = remember(mainState.value.fontFamily) {
Constants.FONTS.find {
Constants.provideFonts(withRandom = true).find {
it.id == mainState.value.fontFamily
} ?: Constants.FONTS[0]
} ?: Constants.provideFonts(withRandom = false)[0]
}
val backgroundColor = animateColorAsState(
settingsState.value.selectedColorPreset.backgroundColor,

View file

@ -7,10 +7,11 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideEmptyBook
@Immutable
data class ReaderState(
val book: Book = Constants.EMPTY_BOOK,
val book: Book = Constants.provideEmptyBook(),
val text: List<AnnotatedString> = emptyList(),
val listState: LazyListState = LazyListState(),

View file

@ -4,11 +4,12 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.model.ColorPreset
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideDefaultColorPreset
@Immutable
data class SettingsState(
val colorPresets: List<ColorPreset> = emptyList(),
val selectedColorPreset: ColorPreset = Constants.DEFAULT_COLOR_PRESET,
val selectedColorPreset: ColorPreset = Constants.provideDefaultColorPreset(),
val animateColorPreset: Boolean = false,
val colorPresetsListState: LazyListState = LazyListState()
)

View file

@ -27,6 +27,7 @@ import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPreset
import ua.acclorite.book_story.domain.util.ID
import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideDefaultColorPreset
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject
@ -69,7 +70,7 @@ class SettingsViewModel @Inject constructor(
var colorPresets = getColorPresets.execute()
if (colorPresets.isEmpty()) {
updateColorPreset.execute(Constants.DEFAULT_COLOR_PRESET)
updateColorPreset.execute(Constants.provideDefaultColorPreset())
onSelectColorPreset(getColorPresets.execute().first())
colorPresets = getColorPresets.execute()
}
@ -409,7 +410,7 @@ class SettingsViewModel @Inject constructor(
addColorPresetJob = launch {
yield()
val newColorPreset = Constants.DEFAULT_COLOR_PRESET.copy(
val newColorPreset = Constants.provideDefaultColorPreset().copy(
backgroundColor = event.backgroundColor,
fontColor = event.fontColor
)
@ -523,7 +524,7 @@ class SettingsViewModel @Inject constructor(
val selectedPreset = presets.firstOrNull { it.isSelected }
if (selectedPreset == null) {
return Constants.DEFAULT_COLOR_PRESET
return Constants.provideDefaultColorPreset()
}
return selectedPreset

View file

@ -42,6 +42,7 @@ import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideThemes
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.ui.Theme
@ -52,7 +53,7 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
/**
* Theme setting.
* Lets user change app's theme from available in [Constants.THEMES].
* Lets user change app's theme from available in [provideThemes].
*/
@Composable
fun ThemeSetting(
@ -63,8 +64,8 @@ fun ThemeSetting(
val onMainEvent = MainViewModel.getEvent()
val themes = remember {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES
else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.provideThemes()
else Constants.provideThemes().dropWhile { it.first == Theme.DYNAMIC }
}
Column(

View file

@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideSupportedExtensions
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
@ -27,7 +28,7 @@ import ua.acclorite.book_story.presentation.data.MainViewModel
* Lets user choose which items to filter in Browse.
*/
fun LazyListScope.BrowseFilterSetting() {
items(Constants.EXTENSIONS, key = { it }) {
items(Constants.provideSupportedExtensions(), key = { it }) {
val state = MainViewModel.getState()
val onMainEvent = MainViewModel.getEvent()

View file

@ -6,6 +6,7 @@ import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideLanguages
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
@ -21,7 +22,7 @@ fun AppLanguageSetting() {
ChipsWithTitle(
title = stringResource(id = R.string.language_option),
chips = Constants.LANGUAGES.sortedBy { it.second }.map {
chips = Constants.provideLanguages().sortedBy { it.second }.map {
ButtonItem(
it.first,
it.second,

View file

@ -4,16 +4,18 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
/**
* Font Family setting.
* Changes Reader's font, uses fonts from [Constants.FONTS].
* Changes Reader's font, uses fonts from [provideFonts].
*/
@Composable
fun FontFamilySetting() {
@ -21,20 +23,23 @@ fun FontFamilySetting() {
val onMainEvent = MainViewModel.getEvent()
val fontFamily = remember(state.value.fontFamily) {
Constants.FONTS.find {
Constants.provideFonts(withRandom = true).find {
it.id == state.value.fontFamily
} ?: Constants.FONTS[0]
} ?: Constants.provideFonts(withRandom = false)[0]
}
ChipsWithTitle(
title = stringResource(id = R.string.font_family_option),
chips = Constants.FONTS
chips = Constants.provideFonts(withRandom = true)
.map {
ButtonItem(
id = it.id,
title = it.fontName.asString(),
textStyle = MaterialTheme.typography.labelLarge.copy(
fontFamily = it.font
fontFamily = when (it.id) {
"random" -> FontFamily.Default
else -> it.font
}
),
selected = it.id == fontFamily.id
)

View file

@ -8,6 +8,7 @@ import androidx.compose.ui.text.font.FontStyle
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
@ -22,9 +23,9 @@ fun FontStyleSetting() {
val onMainEvent = MainViewModel.getEvent()
val fontFamily = remember(state.value.fontFamily) {
Constants.FONTS.find {
Constants.provideFonts(withRandom = false).find {
it.id == state.value.fontFamily
} ?: Constants.FONTS[0]
} ?: Constants.provideFonts(withRandom = false)[0]
}
SegmentedButtonWithTitle(

View file

@ -31,6 +31,7 @@ import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideLanguages
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.start.components.permissions.startPermissionsScreen
import ua.acclorite.book_story.presentation.screens.start.data.StartEvent
@ -56,7 +57,7 @@ fun StartSettings(
val activity = LocalContext.current as ComponentActivity
val languages = remember(mainState.value.language) {
Constants.LANGUAGES.sortedBy { it.second }.map {
Constants.provideLanguages().sortedBy { it.second }.map {
ButtonItem(
id = it.first,
title = it.second,

View file

@ -2,6 +2,7 @@
<resources>
<!-- Basic Strings -->
<string name="default_string">За замовчуванням</string>
<string name="random_string">Випадково</string>
<!-- Notifications -->
<string name="updates_notification_channel">Нові оновлення</string>

View file

@ -3,6 +3,7 @@
<string name="app_version" translatable="false">1.3.0</string>
<string name="app_name" translatable="false">Book\'s Story</string>
<string name="default_string">Default</string>
<string name="random_string">Random</string>
<!-- Notifications -->
<string name="updates_notification_channel">New updates</string>