From 76e1ca3e3ffab3c4f17f00e873f242f7a32b205d Mon Sep 17 00:00:00 2001 From: acclorite Date: Tue, 26 Mar 2024 17:40:18 +0200 Subject: [PATCH] 0.9.6 - UI(New themes appearance, Up to date Material3 components, General UI improvements, New color roles) + Fixed terrible scrolling lag in LibraryScreen + Loading async cover image animation + Tooltips for each IconButton + ThemeContrast option(changes contrast of the theme) --- app/build.gradle.kts | 15 +- .../java/ua/acclorite/book_story/Activity.kt | 12 +- .../book_story/data/local/dto/BookEntity.kt | 4 +- .../data/local/dto/HistoryEntity.kt | 2 +- .../data/mapper/book/BookMapperImpl.kt | 7 +- .../data/parser/epub/EpubFileParser.kt | 2 +- .../data/parser/pdf/PdfFileParser.kt | 2 +- .../data/parser/txt/TxtFileParser.kt | 2 +- .../data/repository/BookRepositoryImpl.kt | 201 ++++-- .../acclorite/book_story/domain/model/Book.kt | 4 +- .../model/{ChipItem.kt => ButtonItem.kt} | 2 +- .../book_story/domain/model/Category.kt | 7 + .../book_story/domain/model/History.kt | 2 +- .../domain/repository/BookRepository.kt | 13 +- .../book_story/domain/use_case/DeleteBooks.kt | 4 +- .../domain/use_case/FastGetBooks.kt | 12 - .../book_story/domain/use_case/GetBooks.kt | 4 +- .../book_story/domain/use_case/GetText.kt | 5 +- .../book_story/domain/use_case/InsertBooks.kt | 4 +- .../domain/use_case/UpdateBooksWithText.kt | 4 +- .../book_story/domain/util/Constants.kt | 1 + .../domain/util/DataStoreConstants.kt | 1 + .../book_story/domain/util/Resource.kt | 1 - .../components/AnimatedTopAppBar.kt | 3 +- .../presentation/components/CustomCheckbox.kt | 5 +- .../components/CustomCoverImage.kt | 31 + .../components/CustomIconButton.kt | 32 +- .../presentation/components/CustomSnackbar.kt | 18 +- .../presentation/components/CustomTooltip.kt | 26 + .../presentation/components/GoBackButton.kt | 3 +- .../presentation/components/MoreDropDown.kt | 7 +- .../BottomNavigationBar.kt | 6 +- .../BottomNavigationItem.kt | 14 +- .../custom_dialog/CustomDialogWithContent.kt | 13 +- .../CustomDialogWithLazyColumn.kt | 12 +- .../CustomNavigationRail.kt | 5 +- .../CustomNavigationRailItem.kt | 14 +- .../presentation/data/ArithmeticOperations.kt | 12 - .../book_story/presentation/data/MainEvent.kt | 1 + .../book_story/presentation/data/MainState.kt | 6 + .../presentation/data/MainViewModel.kt | 24 + .../presentation/data/Navigation.kt | 65 +- .../presentation/screens/about/AboutScreen.kt | 7 +- .../screens/book_info/BookInfoScreen.kt | 30 +- .../components/BookInfoBackground.kt | 13 +- .../components/BookInfoInfoSection.kt | 16 +- .../components/BookInfoMoreDropDown.kt | 23 +- .../components/BookInfoStatisticSection.kt | 4 +- .../BookInfoChangeCoverBottomSheet.kt | 4 +- .../BookInfoConfirmUpateDialog.kt | 78 +++ .../BookInfoConfirmUpdateDialogItem.kt | 18 + .../BookInfoDetailsBottomSheet.kt | 4 +- .../screens/book_info/data/BookInfoEvent.kt | 19 +- .../screens/book_info/data/BookInfoState.kt | 8 +- .../book_info/data/BookInfoViewModel.kt | 259 ++++++-- .../screens/browse/BrowseScreen.kt | 20 +- .../browse/components/BrowseFIleItem.kt | 24 +- .../adding_dialog/BrowseAddingDialog.kt | 21 +- .../adding_dialog/BrowseAddingDialogItem.kt | 5 +- .../screens/browse/data/BrowseEvent.kt | 10 +- .../screens/browse/data/BrowseViewModel.kt | 61 +- .../presentation/screens/help/HelpScreen.kt | 85 +++ .../help/components/HelpClickableNote.kt | 83 +++ .../screens/help/data/HelpEvent.kt | 11 + .../screens/help/data/HelpViewModel.kt | 43 ++ .../screens/history/HistoryScreen.kt | 24 +- .../screens/history/components/HistoryItem.kt | 35 +- .../screens/history/data/HistoryEvent.kt | 4 +- .../screens/history/data/HistoryViewModel.kt | 56 +- .../screens/library/LibraryScreen.kt | 93 ++- .../library/components/LibraryBookItem.kt | 52 +- .../library/components/LibraryTabRow.kt | 61 +- .../components/dialog/LibraryMoveDialog.kt | 2 - .../screens/library/data/LibraryEvent.kt | 4 +- .../screens/library/data/LibraryState.kt | 3 + .../screens/library/data/LibraryViewModel.kt | 68 +- .../screens/reader/ReaderScreen.kt | 12 +- .../reader/components/ReaderEndItem.kt | 13 +- .../reader/components/ReaderStartItem.kt | 16 +- .../components/app_bar/ReaderBottomBar.kt | 45 +- .../reader/components/app_bar/ReaderTopBar.kt | 8 +- .../ReaderSettingsBottomSheet.kt | 347 +++++------ .../ReaderSettingsBottomSheetTabRow.kt | 36 +- .../screens/reader/data/ReaderEvent.kt | 3 - .../screens/reader/data/ReaderState.kt | 3 + .../screens/reader/data/ReaderViewModel.kt | 131 ++-- .../screens/settings/SettingsScreen.kt | 3 +- .../settings/components/ChipsWithTitle.kt | 47 +- .../components/ColorPickerWithTitle.kt | 28 +- .../components/SegmentedButtonWithTitle.kt | 86 +++ .../settings/components/SliderWithTitle.kt | 13 +- .../nested/appearance/AppearanceSettings.kt | 43 +- .../AppearanceSettingsThemeSwitcher.kt | 13 +- .../AppearanceSettingsThemeSwitcherItem.kt | 50 +- .../nested/general/GeneralSettings.kt | 7 +- .../settings/nested/reader/ReaderSettings.kt | 11 +- .../book_story/presentation/ui/Color.kt | 18 +- .../book_story/presentation/ui/Elevation.kt | 8 - .../book_story/presentation/ui/Theme.kt | 104 +++- .../presentation/ui/theme/AquaTheme.kt | 582 ++++++++++++++---- .../presentation/ui/theme/BlueTheme.kt | 580 +++++++++++++---- .../presentation/ui/theme/GreenTheme.kt | 581 +++++++++++++---- .../presentation/ui/theme/PinkTheme.kt | 581 +++++++++++++---- .../presentation/ui/theme/PurpleTheme.kt | 580 +++++++++++++---- .../presentation/ui/theme/RedTheme.kt | 581 +++++++++++++---- .../presentation/ui/theme/YellowTheme.kt | 581 +++++++++++++---- app/src/main/res/values-uk/strings.xml | 47 +- app/src/main/res/values/strings.xml | 42 +- 108 files changed, 5205 insertions(+), 1851 deletions(-) rename app/src/main/java/ua/acclorite/book_story/domain/model/{ChipItem.kt => ButtonItem.kt} (91%) delete mode 100644 app/src/main/java/ua/acclorite/book_story/domain/use_case/FastGetBooks.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCoverImage.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/components/CustomTooltip.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpdateDialogItem.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpClickableNote.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SegmentedButtonWithTitle.kt delete mode 100644 app/src/main/java/ua/acclorite/book_story/presentation/ui/Elevation.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9517a289..7ab78bb7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,7 +15,7 @@ android { minSdk = 26 targetSdk = 34 versionCode = 1 - versionName = "0.9.3" + versionName = "0.9.6" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -66,13 +66,19 @@ dependencies { implementation("androidx.activity:activity-compose:1.8.2") // Compose BOM libraries - implementation(platform("androidx.compose:compose-bom:2024.01.00")) + implementation(platform("androidx.compose:compose-bom:2024.03.00")) + implementation("androidx.compose.foundation:foundation") + implementation("androidx.compose.animation:animation") + implementation("androidx.compose.animation:animation-core") + implementation("androidx.compose.animation:animation-graphics") + implementation("androidx.compose.foundation:foundation-layout") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-android") - implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material3:material3:latest.release") implementation("androidx.compose.material3:material3-window-size-class") + implementation("androidx.compose.material:material-icons-extended") implementation("androidx.compose.material:material") // Unit tests @@ -84,7 +90,7 @@ dependencies { testImplementation("androidx.test.ext:truth:1.5.0") testImplementation("com.squareup.okhttp3:mockwebserver:latest.release") testImplementation("io.mockk:mockk:latest.release") - debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.3") + debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.4") // Instrumentation tests androidTestImplementation("com.google.dagger:hilt-android-testing:latest.release") @@ -100,7 +106,6 @@ dependencies { // All dependencies implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") - implementation("androidx.compose.material:material-icons-extended") implementation("com.google.accompanist:accompanist-swiperefresh:0.24.2-alpha") // Dagger - Hilt diff --git a/app/src/main/java/ua/acclorite/book_story/Activity.kt b/app/src/main/java/ua/acclorite/book_story/Activity.kt index 65b14e2e..a3c8e867 100644 --- a/app/src/main/java/ua/acclorite/book_story/Activity.kt +++ b/app/src/main/java/ua/acclorite/book_story/Activity.kt @@ -38,6 +38,7 @@ import ua.acclorite.book_story.presentation.screens.book_info.BookInfoScreen import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel import ua.acclorite.book_story.presentation.screens.browse.BrowseScreen import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel +import ua.acclorite.book_story.presentation.screens.help.HelpScreen import ua.acclorite.book_story.presentation.screens.history.HistoryScreen import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel import ua.acclorite.book_story.presentation.screens.library.LibraryScreen @@ -111,7 +112,8 @@ class Activity : AppCompatActivity() { if (isLoaded) { BooksHistoryResurrectionTheme( theme = state.theme!!, - isDark = state.darkTheme!!.isDark() + isDark = state.darkTheme!!.isDark(), + themeContrast = state.themeContrast!! ) { NavigationHost(startScreen = Screen.LIBRARY) { val currentScreen by this.getCurrentScreen().collectAsState() @@ -269,6 +271,14 @@ class Activity : AppCompatActivity() { ) { AboutScreen(navigator = this@NavigationHost) } + // Help screen + composable( + screen = Screen.HELP, + enterAnim = Transitions.SlidingTransitionIn, + exitAnim = Transitions.SlidingTransitionOut + ) { + HelpScreen(navigator = this@NavigationHost) + } // Start screen (later) // composable(screen = Screen.START) { diff --git a/app/src/main/java/ua/acclorite/book_story/data/local/dto/BookEntity.kt b/app/src/main/java/ua/acclorite/book_story/data/local/dto/BookEntity.kt index 8254b5aa..581eac47 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/local/dto/BookEntity.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/local/dto/BookEntity.kt @@ -6,11 +6,11 @@ import ua.acclorite.book_story.domain.model.Category @Entity data class BookEntity( - @PrimaryKey(true) val id: Int? = null, + @PrimaryKey(true) val id: Int = 0, val title: String, val author: String?, val description: String?, - val text: String, + val textPath: String, val filePath: String, val scrollIndex: Int, val scrollOffset: Int, diff --git a/app/src/main/java/ua/acclorite/book_story/data/local/dto/HistoryEntity.kt b/app/src/main/java/ua/acclorite/book_story/data/local/dto/HistoryEntity.kt index dbdebc73..6ca7230d 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/local/dto/HistoryEntity.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/local/dto/HistoryEntity.kt @@ -6,7 +6,7 @@ import androidx.room.PrimaryKey @Entity data class HistoryEntity( @PrimaryKey(true) - val id: Int? = null, + val id: Int = 0, val bookId: Int, val time: Long ) diff --git a/app/src/main/java/ua/acclorite/book_story/data/mapper/book/BookMapperImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/mapper/book/BookMapperImpl.kt index d2e73a66..dbc32a88 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/mapper/book/BookMapperImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/mapper/book/BookMapperImpl.kt @@ -10,10 +10,6 @@ import javax.inject.Inject class BookMapperImpl @Inject constructor() : BookMapper { override suspend fun toBookEntity(book: Book): BookEntity { - val textAsString = book.text.joinToString("\n") { - it.line.trim() - } - return BookEntity( id = book.id, title = book.title, @@ -22,7 +18,7 @@ class BookMapperImpl @Inject constructor() : BookMapper { scrollOffset = book.scrollOffset, progress = book.progress, author = book.author.string, - text = textAsString, + textPath = book.textPath, description = book.description, image = if (book.coverImage != null) book.coverImage.toString() else null, category = book.category @@ -43,6 +39,7 @@ class BookMapperImpl @Inject constructor() : BookMapper { scrollOffset = bookEntity.scrollOffset, progress = bookEntity.progress, file = if (file.exists()) file else null, + textPath = bookEntity.textPath, text = emptyList(), letters = 0, words = 0, diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt index 96971bfc..3aa6aec8 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/epub/EpubFileParser.kt @@ -45,10 +45,10 @@ class EpubFileParser @Inject constructor() : FileParser { } return Book( - id = null, title = title, author = author, description = description?.toString(), + textPath = "", text = emptyList(), letters = 0, words = 0, diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt index fbd733fa..71e92f4a 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/pdf/PdfFileParser.kt @@ -33,10 +33,10 @@ class PdfFileParser @Inject constructor(private val application: Application) : document.close() return Book( - id = null, title = title, author = author, description = description, + textPath = "", text = emptyList(), letters = 0, words = 0, diff --git a/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt b/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt index 83d26fc8..12cb4493 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/parser/txt/TxtFileParser.kt @@ -21,10 +21,10 @@ class TxtFileParser @Inject constructor() : FileParser { val author = UIText.StringResource(R.string.unknown_author) return Book( - id = null, title = title, author = author, description = null, + textPath = "", text = emptyList(), letters = 0, words = 0, diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt index d6b24f9e..45baac80 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt @@ -4,6 +4,7 @@ import android.app.Application import android.graphics.Bitmap import android.net.Uri import android.os.Environment +import android.util.Log import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -46,35 +47,13 @@ class BookRepositoryImpl @Inject constructor( ) : BookRepository { - override suspend fun getBooks(query: String): Flow>> { - return flow { - emit(Resource.Loading(true)) - val books = database.searchBooks(query) - - emit( - Resource.Success( - data = books.map { entity -> - val book = bookMapper.toBook(entity) - val lastHistory = database.getLatestHistoryForBook( - book.id ?: -1 - ) - - book.copy( - lastOpened = lastHistory?.time - ) - } - ) - ) - } - } - - override suspend fun fastGetBooks(query: String): List { + override suspend fun getBooks(query: String): List { val books = database.searchBooks(query) return books.map { entity -> val book = bookMapper.toBook(entity) val lastHistory = database.getLatestHistoryForBook( - book.id ?: -1 + book.id ) book.copy( @@ -89,7 +68,7 @@ class BookRepositoryImpl @Inject constructor( return books.map { entity -> val book = bookMapper.toBook(entity) val lastHistory = database.getLatestHistoryForBook( - book.id ?: -1 + book.id ) book.copy( @@ -98,35 +77,73 @@ class BookRepositoryImpl @Inject constructor( } } - override suspend fun getBookTextById(bookId: Int): String { - val book = database.findBookById(bookId) - return book.text + override suspend fun getBookTextById(textPath: String): List { + val textFile = File(textPath) + + if (textPath.isBlank() || !textFile.exists()) { + Log.w("BOOK TEXT", "Failed to load file") + return emptyList() + } + + val text = textParser.parse(textFile) + + if (text.data.isNullOrEmpty()) { + return emptyList() + } + + return text.data } override suspend fun insertBooks( books: List> - ) { + ): Boolean { val filesDir = application.filesDir val coversDir = File(filesDir, "covers") + val booksDir = File(filesDir, "books") if (!coversDir.exists()) { coversDir.mkdirs() } + if (!booksDir.exists()) { + booksDir.mkdirs() + } - val booksWithCover = books.map { - var uri = "" + val booksWithCoverAndText = books.map { + var coverUri = "" + val textUri: String + + if (it.first.text.isEmpty()) { + return false + } + + try { + textUri = "${UUID.randomUUID()}.txt" + val text = File(booksDir, textUri) + + withContext(Dispatchers.IO) { + FileOutputStream(text).use { stream -> + it.first.text.forEach { line -> + stream.write(line.line.toByteArray()) + stream.write(System.lineSeparator().toByteArray()) + } + } + } + } catch (e: Exception) { + e.printStackTrace() + return false + } if (it.second != null) { try { - uri = "${UUID.randomUUID()}.webp" - val cover = File(coversDir, uri) + coverUri = "${UUID.randomUUID()}.webp" + val cover = File(coversDir, coverUri) withContext(Dispatchers.IO) { FileOutputStream(cover).use { stream -> if ( - !it.second!!.compress( + !it.second!!.copy(Bitmap.Config.RGB_565, false).compress( Bitmap.CompressFormat.WEBP, - 30, + 20, stream ) ) { @@ -135,33 +152,34 @@ class BookRepositoryImpl @Inject constructor( } } } catch (e: Exception) { - uri = "" + coverUri = "" e.printStackTrace() } } + val book = it.first.copy( - coverImage = if (uri.isNotBlank()) { - Uri.fromFile(File("$coversDir/$uri")) + textPath = "$booksDir/$textUri", + coverImage = if (coverUri.isNotBlank()) { + Uri.fromFile(File("$coversDir/$coverUri")) } else null ) bookMapper.toBookEntity(book) } - database.insertBooks(booksWithCover) + database.insertBooks(booksWithCoverAndText) + return true } override suspend fun updateBooks(books: List) { // without text and cover image database.updateBooks( books.map { - val book = database.findBookById(it.id ?: return) + val book = database.findBookById(it.id) bookMapper.toBookEntity( it.copy( - text = book.text - .split("\n") - .map { line -> StringWithId(line.trim()) }, + textPath = book.textPath, coverImage = if (book.image != null) Uri.parse(book.image) else null ) ) @@ -169,18 +187,66 @@ class BookRepositoryImpl @Inject constructor( ) } - override suspend fun updateBooksWithText(books: List) { + override suspend fun updateBooksWithText(books: List): Boolean { // without cover image - database.updateBooks( - books.map { - val book = database.findBookById(it.id ?: return) - bookMapper.toBookEntity( - it.copy( - coverImage = if (book.image != null) Uri.parse(book.image) else null - ) - ) + val filesDir = application.filesDir + val booksDir = File(filesDir, "books") + + if (!booksDir.exists()) { + booksDir.mkdirs() + } + + val booksWithText = books.map { + val textUri: String + val bookEntity = database.findBookById(it.id) + + if (it.text.isEmpty()) { + return false } + + try { + textUri = "${UUID.randomUUID()}.txt" + val text = File(booksDir, textUri) + + withContext(Dispatchers.IO) { + FileOutputStream(text).use { stream -> + it.text.forEach { line -> + stream.write(line.line.toByteArray()) + stream.write(System.lineSeparator().toByteArray()) + } + } + } + } catch (e: Exception) { + e.printStackTrace() + return false + } + + if (it.textPath.isNotBlank()) { + try { + val fileToDelete = File( + it.textPath + ) + + if (fileToDelete.exists()) { + fileToDelete.delete() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + bookMapper.toBookEntity( + it.copy( + textPath = "$booksDir/$textUri", + coverImage = if (bookEntity.image != null) Uri.parse(bookEntity.image) else null + ) + ) + } + + database.updateBooks( + booksWithText ) + return true } override suspend fun updateCoverImageOfBook( @@ -188,7 +254,7 @@ class BookRepositoryImpl @Inject constructor( newCoverImage: CoverImage? ) { // without text - val book = database.findBookById(bookWithOldCover.id ?: return) + val book = database.findBookById(bookWithOldCover.id) var uri: String? = null val filesDir = application.filesDir @@ -206,9 +272,9 @@ class BookRepositoryImpl @Inject constructor( withContext(Dispatchers.IO) { FileOutputStream(cover).use { stream -> if ( - !newCoverImage.compress( + !newCoverImage.copy(Bitmap.Config.RGB_565, false).compress( Bitmap.CompressFormat.WEBP, - 30, + 20, stream ) ) { @@ -243,9 +309,7 @@ class BookRepositoryImpl @Inject constructor( } val bookWithNewCover = bookWithOldCover.copy( - text = book.text - .split("\n") - .map { line -> StringWithId(line.trim()) }, + textPath = book.textPath, coverImage = newCoverImageUri ) @@ -261,14 +325,18 @@ class BookRepositoryImpl @Inject constructor( override suspend fun deleteBooks(books: List) { val filesDir = application.filesDir val coversDir = File(filesDir, "covers") + val booksDir = File(filesDir, "books") if (!coversDir.exists()) { coversDir.mkdirs() } + if (!booksDir.exists()) { + booksDir.mkdirs() + } database.deleteBooks( books.map { - val book = database.findBookById(it.id ?: return) + val book = database.findBookById(it.id) if (book.image != null) { try { @@ -284,6 +352,18 @@ class BookRepositoryImpl @Inject constructor( } } + if (book.textPath.isNotBlank()) { + try { + val fileToDelete = File(book.textPath) + + if (fileToDelete.exists()) { + fileToDelete.delete() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + book } ) @@ -424,7 +504,7 @@ class BookRepositoryImpl @Inject constructor( books.add( NullableBook.Null( file.name, - UIText.StringResource(R.string.error_something_went_wrong) + UIText.StringResource(R.string.error_something_went_wrong_with_file) ) ) continue @@ -469,7 +549,6 @@ class BookRepositoryImpl @Inject constructor( override suspend fun getHistory(): Flow>> { return flow { - emit(Resource.Loading(true)) val history = database.getHistory() emit( diff --git a/app/src/main/java/ua/acclorite/book_story/domain/model/Book.kt b/app/src/main/java/ua/acclorite/book_story/domain/model/Book.kt index 20b38271..6e89bbdf 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/model/Book.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/model/Book.kt @@ -7,13 +7,13 @@ import java.io.File @Immutable data class Book( - val id: Int?, + val id: Int = 0, val title: String, val author: UIText, val description: String?, -// val textPath: String, + val textPath: String, val text: List = emptyList(), val letters: Int, val words: Int, diff --git a/app/src/main/java/ua/acclorite/book_story/domain/model/ChipItem.kt b/app/src/main/java/ua/acclorite/book_story/domain/model/ButtonItem.kt similarity index 91% rename from app/src/main/java/ua/acclorite/book_story/domain/model/ChipItem.kt rename to app/src/main/java/ua/acclorite/book_story/domain/model/ButtonItem.kt index 185f16b1..c5f5d9ea 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/model/ChipItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/model/ButtonItem.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.ui.text.TextStyle @Immutable -data class ChipItem( +data class ButtonItem( val id: String, val title: String, val textStyle: TextStyle, diff --git a/app/src/main/java/ua/acclorite/book_story/domain/model/Category.kt b/app/src/main/java/ua/acclorite/book_story/domain/model/Category.kt index acab1534..0f8083bf 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/model/Category.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/model/Category.kt @@ -1,8 +1,15 @@ package ua.acclorite.book_story.domain.model import androidx.compose.runtime.Immutable +import ua.acclorite.book_story.domain.util.Selected @Immutable enum class Category { READING, ALREADY_READ, PLANNING, DROPPED } + +@Immutable +data class CategorizedBooks( + val category: Category, + val books: List> +) \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/model/History.kt b/app/src/main/java/ua/acclorite/book_story/domain/model/History.kt index 46b82b99..dca5300c 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/model/History.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/model/History.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Immutable @Immutable data class History( - val id: Int?, + val id: Int = 0, val bookId: Int, val book: Book?, val time: Long diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt index b2f43946..f37991d8 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt @@ -5,6 +5,7 @@ import kotlinx.coroutines.flow.Flow import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.History import ua.acclorite.book_story.domain.model.NullableBook +import ua.acclorite.book_story.domain.model.StringWithId import ua.acclorite.book_story.domain.util.CoverImage import ua.acclorite.book_story.domain.util.Resource import java.io.File @@ -13,10 +14,6 @@ interface BookRepository { suspend fun getBooks( query: String - ): Flow>> - - suspend fun fastGetBooks( - query: String ): List suspend fun getBooksById( @@ -24,12 +21,12 @@ interface BookRepository { ): List suspend fun getBookTextById( - bookId: Int - ): String + textPath: String + ): List suspend fun insertBooks( books: List> - ) + ): Boolean suspend fun updateBooks( books: List @@ -37,7 +34,7 @@ interface BookRepository { suspend fun updateBooksWithText( books: List - ) + ): Boolean suspend fun updateCoverImageOfBook( bookWithOldCover: Book, diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/DeleteBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/DeleteBooks.kt index b1f1236f..bc5ad151 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/DeleteBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/DeleteBooks.kt @@ -9,9 +9,7 @@ class DeleteBooks @Inject constructor(private val repository: BookRepository) { suspend fun execute(books: List) { repository.deleteBooks(books) books.forEach { - if (it.id != null) { - repository.deleteBookHistory(it.id) - } + repository.deleteBookHistory(it.id) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/FastGetBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/FastGetBooks.kt deleted file mode 100644 index 8f1628a8..00000000 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/FastGetBooks.kt +++ /dev/null @@ -1,12 +0,0 @@ -package ua.acclorite.book_story.domain.use_case - -import ua.acclorite.book_story.domain.model.Book -import ua.acclorite.book_story.domain.repository.BookRepository -import javax.inject.Inject - -class FastGetBooks @Inject constructor(private val repository: BookRepository) { - - suspend fun execute(query: String): List { - return repository.fastGetBooks(query) - } -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetBooks.kt index 76af9fb6..d294f885 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetBooks.kt @@ -1,14 +1,12 @@ package ua.acclorite.book_story.domain.use_case -import kotlinx.coroutines.flow.Flow import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository -import ua.acclorite.book_story.domain.util.Resource import javax.inject.Inject class GetBooks @Inject constructor(private val repository: BookRepository) { - suspend fun execute(query: String): Flow>> { + suspend fun execute(query: String): List { return repository.getBooks(query) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetText.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetText.kt index 3b84f33f..34ef9c7a 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetText.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/GetText.kt @@ -1,11 +1,12 @@ package ua.acclorite.book_story.domain.use_case +import ua.acclorite.book_story.domain.model.StringWithId import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject class GetText @Inject constructor(private val repository: BookRepository) { - suspend fun execute(id: Int): String { - return repository.getBookTextById(bookId = id) + suspend fun execute(textPath: String): List { + return repository.getBookTextById(textPath = textPath) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/InsertBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/InsertBooks.kt index 028c4441..0ec0fc5b 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/InsertBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/InsertBooks.kt @@ -6,7 +6,7 @@ import ua.acclorite.book_story.domain.util.CoverImage import javax.inject.Inject class InsertBooks @Inject constructor(private val repository: BookRepository) { - suspend fun execute(books: List>) { - repository.insertBooks(books) + suspend fun execute(books: List>): Boolean { + return repository.insertBooks(books) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/UpdateBooksWithText.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/UpdateBooksWithText.kt index 6aad3df0..182fccab 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/UpdateBooksWithText.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/UpdateBooksWithText.kt @@ -6,7 +6,7 @@ import javax.inject.Inject class UpdateBooksWithText @Inject constructor(private val repository: BookRepository) { - suspend fun execute(books: List) { - repository.updateBooksWithText(books) + suspend fun execute(books: List): Boolean { + return repository.updateBooksWithText(books) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/util/Constants.kt b/app/src/main/java/ua/acclorite/book_story/domain/util/Constants.kt index 8483c930..13adb7e2 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/util/Constants.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/util/Constants.kt @@ -170,6 +170,7 @@ object Constants { "", UIText.StringValue(""), null, + "", emptyList(), 0, 0, diff --git a/app/src/main/java/ua/acclorite/book_story/domain/util/DataStoreConstants.kt b/app/src/main/java/ua/acclorite/book_story/domain/util/DataStoreConstants.kt index 365d26a0..d119c3c3 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/util/DataStoreConstants.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/util/DataStoreConstants.kt @@ -9,6 +9,7 @@ object DataStoreConstants { val LANGUAGE = stringPreferencesKey("language") val THEME = stringPreferencesKey("theme") val DARK_THEME = stringPreferencesKey("dark_theme") + val THEME_CONTRAST = stringPreferencesKey("theme_contrast") val SHOW_START_SCREEN = booleanPreferencesKey("guide") val BACKGROUND_COLOR = longPreferencesKey("background_color") val FONT_COLOR = longPreferencesKey("font_color") diff --git a/app/src/main/java/ua/acclorite/book_story/domain/util/Resource.kt b/app/src/main/java/ua/acclorite/book_story/domain/util/Resource.kt index 60f0705e..22a2f162 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/util/Resource.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/util/Resource.kt @@ -3,5 +3,4 @@ package ua.acclorite.book_story.domain.util sealed class Resource(val data: T? = null, val message: UIText? = null) { class Success(data: T?) : Resource(data) class Error(message: UIText, data: T? = null) : Resource(data, message) - class Loading(val isLoading: Boolean = true) : Resource() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/AnimatedTopAppBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/AnimatedTopAppBar.kt index 424e449f..61109d8a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/AnimatedTopAppBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/AnimatedTopAppBar.kt @@ -28,7 +28,6 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.ui.elevation /** * Animated top app bar. Has up to 3 different top bars inside it. Follow [TopAppBar] for more info. @@ -42,7 +41,7 @@ import ua.acclorite.book_story.presentation.ui.elevation @Composable fun AnimatedTopAppBar( containerColor: Color = MaterialTheme.colorScheme.surface, - scrolledContainerColor: Color = MaterialTheme.elevation(), + scrolledContainerColor: Color = MaterialTheme.colorScheme.surfaceContainer, scrollBehavior: TopAppBarScrollBehavior?, isTopBarScrolled: Boolean?, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCheckbox.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCheckbox.kt index 94ddcb5d..5390f7d8 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCheckbox.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCheckbox.kt @@ -17,16 +17,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.ui.elevation /** * Custom Checkbox. Has a Circle shape. */ @Composable -fun CustomCheckbox(selected: Boolean, size: Dp = 22.dp) { +fun CustomCheckbox(selected: Boolean, containerColor: Color, size: Dp = 22.dp) { Icon( imageVector = Icons.Default.Check, - tint = if (selected) MaterialTheme.elevation(elevation = 2.dp) else Color.Transparent, + tint = if (selected) containerColor else Color.Transparent, modifier = Modifier .clip(CircleShape) .border( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCoverImage.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCoverImage.kt new file mode 100644 index 00000000..c616ef22 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomCoverImage.kt @@ -0,0 +1,31 @@ +package ua.acclorite.book_story.presentation.components + +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import coil.compose.AsyncImage +import coil.request.ImageRequest +import ua.acclorite.book_story.R + +@Composable +fun CustomCoverImage( + uri: Uri, + animationDurationMillis: Int = 100, + contentDescription: String? = stringResource(id = R.string.cover_image_content_desc), + modifier: Modifier, + alpha: Float = 1f, +) { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(uri) + .crossfade(animationDurationMillis) + .build(), + contentDescription = contentDescription, + modifier = modifier, + alpha = alpha, + contentScale = ContentScale.Crop + ) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomIconButton.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomIconButton.kt index 69604482..44a01dcf 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomIconButton.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomIconButton.kt @@ -1,5 +1,6 @@ package ua.acclorite.book_story.presentation.components +import androidx.annotation.StringRes import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalContentColor @@ -11,6 +12,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource /** * Custom Icon Button. Can be disabled after click, so user can't press button fast 2 or 3 times. @@ -19,27 +21,29 @@ import androidx.compose.ui.graphics.vector.ImageVector fun CustomIconButton( modifier: Modifier = Modifier, icon: ImageVector, - contentDescription: String, + @StringRes contentDescription: Int, disableOnClick: Boolean, enabled: Boolean = true, color: Color = LocalContentColor.current, onClick: () -> Unit ) { var isClicked by remember { mutableStateOf(false) } - IconButton( - enabled = enabled && !isClicked, - onClick = { - if (disableOnClick) { - isClicked = true + CustomTooltip(text = stringResource(id = contentDescription)) { + IconButton( + enabled = enabled && !isClicked, + onClick = { + if (disableOnClick) { + isClicked = true + } + onClick() } - onClick() + ) { + Icon( + imageVector = icon, + modifier = modifier, + contentDescription = stringResource(id = contentDescription), + tint = color + ) } - ) { - Icon( - imageVector = icon, - modifier = modifier, - contentDescription = contentDescription, - tint = color - ) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSnackbar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSnackbar.kt index 46e76aac..6cf8a871 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSnackbar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSnackbar.kt @@ -20,6 +20,7 @@ import androidx.compose.material3.Snackbar import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf @@ -27,6 +28,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp @@ -44,10 +46,18 @@ fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostSta var snackbarData by remember { mutableStateOf(snackbarState.currentSnackbarData) } var offset by remember { mutableFloatStateOf(0f) } + val density = LocalDensity.current val mutableInteractionSource = remember { MutableInteractionSource() } val isDragged by mutableInteractionSource.collectIsDraggedAsState() + val alpha by remember { + derivedStateOf { + 1f - ((offset / 2f) / 100f) + } + } + + LaunchedEffect(offset, isDragged) { val offsetDp = with(density) { offset.toDp() } if (offsetDp > 35.dp && !isDragged) { @@ -74,8 +84,8 @@ fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostSta AnimatedVisibility( visible = showSnackbar, - enter = slideInVertically(tween(250)) { it } + fadeIn(tween(250)), - exit = slideOutVertically(tween(100)) { it } + fadeOut(tween(100)) + enter = slideInVertically(tween(350)) { it } + fadeIn(tween(350)), + exit = slideOutVertically(tween(200)) { it } + fadeOut(tween(100)) ) { Box( modifier = modifier @@ -91,7 +101,9 @@ fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostSta ) ) { Snackbar( - modifier = Modifier.align(Alignment.Center), + modifier = Modifier + .align(Alignment.Center) + .alpha(alpha), snackbarData = snackbarData!!, shape = MaterialTheme.shapes.medium ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomTooltip.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomTooltip.kt new file mode 100644 index 00000000..8d5eb394 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomTooltip.kt @@ -0,0 +1,26 @@ +package ua.acclorite.book_story.presentation.components + +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.PlainTooltip +import androidx.compose.material3.Text +import androidx.compose.material3.TooltipBox +import androidx.compose.material3.TooltipDefaults +import androidx.compose.material3.rememberTooltipState +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CustomTooltip(text: String, content: @Composable () -> Unit) { + TooltipBox( + positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(12.dp), + tooltip = { + PlainTooltip { + Text(text = text) + } + }, + state = rememberTooltipState() + ) { + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/GoBackButton.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/GoBackButton.kt index 58fee9b1..6a5b5075 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/GoBackButton.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/GoBackButton.kt @@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.components import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.data.Navigator @@ -14,7 +13,7 @@ import ua.acclorite.book_story.presentation.data.Navigator fun GoBackButton(navigator: Navigator, enabled: Boolean = true, customOnClick: () -> Unit = {}) { CustomIconButton( icon = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = stringResource(id = R.string.go_back_content_desc), + contentDescription = R.string.go_back_content_desc, disableOnClick = true, enabled = enabled ) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/MoreDropDown.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/MoreDropDown.kt index 877ff562..ccc3c36a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/MoreDropDown.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/MoreDropDown.kt @@ -33,7 +33,7 @@ fun MoreDropDown(navigator: Navigator) { Box { CustomIconButton( icon = Icons.Default.MoreVert, - contentDescription = stringResource(id = R.string.show_dropdown_content_desc), + contentDescription = R.string.show_dropdown_content_desc, disableOnClick = false, enabled = !showDropDown ) { @@ -43,7 +43,7 @@ fun MoreDropDown(navigator: Navigator) { DropdownMenu( expanded = showDropDown, onDismissRequest = { showDropDown = false }, - offset = DpOffset(10.dp, 0.dp) + offset = DpOffset((-15).dp, 0.dp) ) { DropdownMenuItem( text = { @@ -55,7 +55,6 @@ fun MoreDropDown(navigator: Navigator) { }, onClick = { navigator.navigate(Screen.SETTINGS, false) - showDropDown = false }, contentPadding = PaddingValues(start = startPadding, end = endPadding) ) @@ -69,7 +68,6 @@ fun MoreDropDown(navigator: Navigator) { }, onClick = { navigator.navigate(Screen.HELP, false) - showDropDown = false }, contentPadding = PaddingValues(start = startPadding, end = endPadding) ) @@ -83,7 +81,6 @@ fun MoreDropDown(navigator: Navigator) { }, onClick = { navigator.navigate(Screen.ABOUT, false) - showDropDown = false }, contentPadding = PaddingValues(start = startPadding, end = endPadding) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationBar.kt index db283aa6..e3cdcf32 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationBar.kt @@ -1,6 +1,5 @@ package ua.acclorite.book_story.presentation.components.bottom_navigation_bar -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -14,7 +13,6 @@ import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.NavigationItem import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen -import ua.acclorite.book_story.presentation.ui.elevation /** * Bottom navigation bar, uses default [NavigationBar]. @@ -35,9 +33,7 @@ fun BottomNavigationBar( } } - NavigationBar( - containerColor = MaterialTheme.elevation() - ) { + NavigationBar { BottomNavigationBarItem( item = NavigationItem( stringResource(id = R.string.library_screen), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationItem.kt index 4ab1c43c..a87c9831 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/bottom_navigation_bar/BottomNavigationItem.kt @@ -3,9 +3,7 @@ package ua.acclorite.book_story.presentation.components.bottom_navigation_bar import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -33,27 +31,19 @@ fun RowScope.BottomNavigationBarItem( label = { Text( text = item.title, - style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) }, selected = isSelected, - enabled = !isSelected, onClick = { onClick() }, icon = { Icon( painter = icon, - contentDescription = item.title, + contentDescription = null, modifier = Modifier.size(24.dp) ) }, - modifier = modifier, - colors = NavigationBarItemDefaults.colors( - unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant, - disabledIconColor = MaterialTheme.colorScheme.onSurface, - disabledTextColor = MaterialTheme.colorScheme.onSurface - ) + modifier = modifier ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithContent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithContent.kt index 1a631584..1275ae40 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithContent.kt @@ -12,9 +12,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Divider +import androidx.compose.material3.BasicAlertDialog import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -36,8 +36,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.ui.ElevationDefaults -import ua.acclorite.book_story.presentation.ui.elevation /** * Custom Dialog with custom content. @@ -72,7 +70,8 @@ fun CustomDialogWithContent( customContent: @Composable (ColumnScope.() -> Unit) = {} ) { var actionClicked by remember { mutableStateOf(false) } - AlertDialog( + + BasicAlertDialog( onDismissRequest = { onDismiss() }, properties = DialogProperties( dismissOnBackPress = !actionClicked, @@ -88,7 +87,7 @@ fun CustomDialogWithContent( .navigationBarsPadding() .statusBarsPadding() .clip(MaterialTheme.shapes.extraLarge) - .background(MaterialTheme.elevation(ElevationDefaults.Dialog)) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) .padding(top = 24.dp, bottom = 12.dp) ) { if (drawableIcon != null) { @@ -140,7 +139,7 @@ fun CustomDialogWithContent( } if (withDivider) { Spacer(modifier = Modifier.height(12.dp)) - Divider( + HorizontalDivider( modifier = Modifier.padding(horizontal = 24.dp), color = MaterialTheme.colorScheme.outlineVariant ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithLazyColumn.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithLazyColumn.kt index 5f7c8ce0..702980c9 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithLazyColumn.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_dialog/CustomDialogWithLazyColumn.kt @@ -13,9 +13,9 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Divider +import androidx.compose.material3.BasicAlertDialog import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -37,8 +37,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.ui.ElevationDefaults -import ua.acclorite.book_story.presentation.ui.elevation /** @@ -74,7 +72,7 @@ fun CustomDialogWithLazyColumn( items: (LazyListScope.() -> Unit) = {} ) { var actionClicked by remember { mutableStateOf(false) } - AlertDialog( + BasicAlertDialog( onDismissRequest = { onDismiss() }, properties = DialogProperties( dismissOnBackPress = !actionClicked, @@ -90,7 +88,7 @@ fun CustomDialogWithLazyColumn( .navigationBarsPadding() .statusBarsPadding() .clip(MaterialTheme.shapes.extraLarge) - .background(MaterialTheme.elevation(ElevationDefaults.Dialog)) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) .padding(top = 24.dp, bottom = 12.dp) ) { if (drawableIcon != null) { @@ -142,7 +140,7 @@ fun CustomDialogWithLazyColumn( } if (withDivider) { Spacer(modifier = Modifier.height(12.dp)) - Divider( + HorizontalDivider( modifier = Modifier.padding(horizontal = 24.dp), color = MaterialTheme.colorScheme.outlineVariant ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRail.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRail.kt index 8bc8a27a..075ffbae 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRail.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRail.kt @@ -29,7 +29,6 @@ import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.NavigationItem import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen -import ua.acclorite.book_story.presentation.ui.elevation /** * Custom Navigation Rail. It is used to be shown on Tablets. @@ -54,7 +53,7 @@ fun BoxScope.CustomNavigationRail( .align( Alignment.CenterStart ) - .background(MaterialTheme.elevation()) + .background(MaterialTheme.colorScheme.surfaceContainer) .padding( start = WindowInsets.navigationBars .asPaddingValues() @@ -62,7 +61,7 @@ fun BoxScope.CustomNavigationRail( ) .width(80.dp) .padding(horizontal = 12.dp), - containerColor = MaterialTheme.elevation(), + containerColor = MaterialTheme.colorScheme.surfaceContainer, windowInsets = WindowInsets(0, 0, 0, 0) ) { Column( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRailItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRailItem.kt index 3339ec92..0083ddd3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRailItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/custom_navigation_rail/CustomNavigationRailItem.kt @@ -2,9 +2,7 @@ package ua.acclorite.book_story.presentation.components.custom_navigation_rail import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationRailItem -import androidx.compose.material3.NavigationRailItemDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -32,27 +30,19 @@ fun CustomNavigationRailItem( label = { Text( text = item.title, - style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) }, selected = isSelected, - enabled = !isSelected, onClick = { onClick() }, icon = { Icon( painter = icon, - contentDescription = item.title, + contentDescription = null, modifier = Modifier.size(24.dp) ) }, - modifier = modifier, - colors = NavigationRailItemDefaults.colors( - unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant, - disabledIconColor = MaterialTheme.colorScheme.onSurface, - disabledTextColor = MaterialTheme.colorScheme.onSurface - ) + modifier = modifier ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/ArithmeticOperations.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/ArithmeticOperations.kt index e80b1fc2..03c0b79c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/ArithmeticOperations.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/ArithmeticOperations.kt @@ -1,9 +1,5 @@ package ua.acclorite.book_story.presentation.data -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Path -import kotlin.math.abs - fun String.removeTrailingZero(): String { if (!this.contains('.')) return this @@ -20,11 +16,3 @@ fun calculateFamiliarity(string: String, target: String): Int { return familiarity } -fun Path.standardQuadFromTo(from: Offset, to: Offset) { - quadraticTo( - from.x, - from.y, - abs(from.x + to.x) / 2f, - abs(from.y + to.y) / 2f - ) -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt index a3c965eb..863c2a7b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainEvent.kt @@ -4,6 +4,7 @@ sealed class MainEvent { data class OnChangeLanguage(val lang: String) : MainEvent() data class OnChangeTheme(val theme: String) : MainEvent() data class OnChangeDarkTheme(val darkTheme: String) : MainEvent() + data class OnChangeThemeContrast(val themeContrast: String) : MainEvent() data class OnChangeFontFamily(val fontFamily: String) : MainEvent() data class OnChangeFontStyle(val fontStyle: Boolean) : MainEvent() data class OnChangeFontSize(val fontSize: Int) : MainEvent() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt index 0791ebfe..d0e77fff 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt @@ -5,6 +5,7 @@ import android.os.Parcelable import androidx.compose.runtime.Immutable import ua.acclorite.book_story.presentation.ui.DarkTheme import ua.acclorite.book_story.presentation.ui.Theme +import ua.acclorite.book_story.presentation.ui.ThemeContrast /** * Main State. All app's settings are here. Wrapped in SavedStateHandle, so it won't reset. @@ -14,6 +15,7 @@ data class MainState( val language: String? = null, val theme: Theme? = null, val darkTheme: DarkTheme? = null, + val themeContrast: ThemeContrast? = null, val fontFamily: String? = null, val isItalic: Boolean? = null, val fontSize: Int? = null, @@ -32,6 +34,8 @@ data class MainState( // String darkTheme = DarkTheme.valueOf(parcel.readString() ?: DarkTheme.FOLLOW_SYSTEM.name), // String + themeContrast = ThemeContrast.valueOf(parcel.readString() ?: ThemeContrast.STANDARD.name), + // String fontFamily = parcel.readString(), // Boolean isItalic = if (parcel.readByte().toInt() != 0) parcel.readByte().toInt() == 1 else null, @@ -60,6 +64,8 @@ data class MainState( parcel.writeString(theme?.name) // Dark Theme parcel.writeString(darkTheme?.name) + // Contrast Level + parcel.writeString(themeContrast?.name) // Font Family parcel.writeString(fontFamily) // Is Italic diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt index b31313c3..6dec42d2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt @@ -21,8 +21,10 @@ import ua.acclorite.book_story.domain.util.DataStoreConstants import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DarkTheme import ua.acclorite.book_story.presentation.ui.Theme +import ua.acclorite.book_story.presentation.ui.ThemeContrast import ua.acclorite.book_story.presentation.ui.toDarkTheme import ua.acclorite.book_story.presentation.ui.toTheme +import ua.acclorite.book_story.presentation.ui.toThemeContrast import java.util.Locale import javax.inject.Inject @@ -70,6 +72,17 @@ class MainViewModel @Inject constructor( } } + is MainEvent.OnChangeThemeContrast -> { + viewModelScope.launch(Dispatchers.IO) { + setDatastore.execute(DataStoreConstants.THEME_CONTRAST, event.themeContrast) + _state.updateWithSavedHandle { + it.copy( + themeContrast = event.themeContrast.toThemeContrast() + ) + } + } + } + is MainEvent.OnChangeTheme -> { viewModelScope.launch(Dispatchers.IO) { setDatastore.execute(DataStoreConstants.THEME, event.theme) @@ -200,6 +213,7 @@ class MainViewModel @Inject constructor( return@combine value.language != null && value.theme != null && value.darkTheme != null && + value.themeContrast != null && value.fontFamily != null && value.isItalic != null && value.fontSize != null && @@ -270,6 +284,16 @@ class MainViewModel @Inject constructor( } } + // Theme Contrast + viewModelScope.launch(Dispatchers.IO) { + getDatastore + .execute(DataStoreConstants.THEME_CONTRAST, ThemeContrast.STANDARD.name) + .first { + onEvent(MainEvent.OnChangeThemeContrast(it)) + it.isNotBlank() + } + } + // Show Start Screen viewModelScope.launch(Dispatchers.IO) { getDatastore diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt index 72f96578..df0047fa 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt @@ -1,6 +1,7 @@ package ua.acclorite.book_story.presentation.data import android.annotation.SuppressLint +import android.os.Parcelable import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler import androidx.activity.viewModels @@ -14,7 +15,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.mutableStateListOf import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext @@ -29,12 +29,15 @@ import dagger.hilt.android.lifecycle.withCreationCallback import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import kotlinx.parcelize.Parcelize import ua.acclorite.book_story.presentation.ui.Transitions +import java.io.Serializable private const val CURRENT_SCREEN = "current_screen" private const val BACKSTACK = "back_stack" private const val USE_BACK_ANIM = "use_back_animation" +private const val ARGUMENTS = "arguments" /** * All screens are listed here, later each screen will be passed as a param for [Navigator.composable] function. @@ -57,11 +60,15 @@ enum class Screen { START } +/** + * Navigation Argument. + */ @Immutable -data class Argument( +@Parcelize +data class Argument( val key: String, - val arg: Any? -) + val value: T +) : Parcelable /** * Navigator. Using for navigation between screens. @@ -78,38 +85,39 @@ class Navigator @AssistedInject constructor( private val currentScreen = savedStateHandle.getStateFlow(CURRENT_SCREEN, startScreen) private val useBackAnimation = savedStateHandle.getStateFlow(USE_BACK_ANIM, false) private val backStack = savedStateHandle.getStateFlow(BACKSTACK, mutableListOf()) - private val arguments = mutableStateListOf() + private val arguments = savedStateHandle + .getStateFlow(ARGUMENTS, mutableListOf>()) - fun putArgument(argument: Argument) { + fun putArgument(argument: Argument) { var found = false - for ((index, arg) in arguments.withIndex()) { + for ((index, arg) in arguments.value.withIndex()) { if (arg.key == argument.key) { - arguments[index] = argument + arguments.value[index] = argument found = true break } } if (!found) { - arguments.add(argument) + arguments.value.add(argument) } } - fun retrieveArgument(key: String): Any? { - for (arg in arguments) { + fun retrieveArgument(key: String): Serializable? { + for (arg in arguments.value) { if (arg.key == key) { - return arg.arg + return arg.value } } return null } fun clearArgument(key: String) { - arguments.removeIf { it.key == key } + arguments.value.removeIf { it.key == key } } - fun navigate(screen: Screen, useBackAnimation: Boolean, vararg args: Argument) = + fun navigate(screen: Screen, useBackAnimation: Boolean, vararg args: Argument) = viewModelScope.launch(Dispatchers.Default) { backStack.value.add(currentScreen.value) @@ -121,20 +129,23 @@ class Navigator @AssistedInject constructor( savedStateHandle[CURRENT_SCREEN] = screen } - fun navigateWithoutBackStack(screen: Screen, useBackAnimation: Boolean, vararg args: Argument) = - viewModelScope.launch(Dispatchers.Default) { - if (backStack.value.last() == screen) { - backStack.value.removeLast() - } - - args.forEach { - putArgument(it) - } - - savedStateHandle[USE_BACK_ANIM] = useBackAnimation - savedStateHandle[CURRENT_SCREEN] = screen + fun navigateWithoutBackStack( + screen: Screen, + useBackAnimation: Boolean, + vararg args: Argument + ) = viewModelScope.launch(Dispatchers.Default) { + if (backStack.value.last() == screen) { + backStack.value.removeLast() } + args.forEach { + putArgument(it) + } + + savedStateHandle[USE_BACK_ANIM] = useBackAnimation + savedStateHandle[CURRENT_SCREEN] = screen + } + fun navigateBack(useBackAnimation: Boolean = true) = viewModelScope.launch(Dispatchers.Default) { if (canGoBack()) { @@ -153,7 +164,7 @@ class Navigator @AssistedInject constructor( } /** - * Animated Screen. Using in [NavigationHost]. Be sure to not use the same [screen] parameter twice, it'll override the highest one in your code. + * Animated Screen. Used in [NavigationHost]. Be sure to not use the same [screen] parameter twice, it'll override the highest one in your code. * * @param screen The [Screen] that represents [content]. * @param enterAnim Enter Animation. diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt index adf50af6..80df794e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt @@ -13,8 +13,8 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.MaterialTheme @@ -36,7 +36,6 @@ import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.screens.about.components.AboutItem import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -69,7 +68,7 @@ fun AboutScreen( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation() + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer ) ) } @@ -101,7 +100,7 @@ fun AboutScreen( item { Spacer(modifier = Modifier.height(36.dp)) - Divider( + HorizontalDivider( modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colorScheme.outlineVariant ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt index f36169db..204b9d61 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt @@ -63,6 +63,7 @@ import ua.acclorite.book_story.presentation.screens.book_info.components.BookInf import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoMoreDropDown import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoStatisticSection import ua.acclorite.book_story.presentation.screens.book_info.components.change_cover_bottom_sheet.BookInfoChangeCoverBottomSheet +import ua.acclorite.book_story.presentation.screens.book_info.components.confirm_update_dialog.BookInfoConfirmUpdateDialog import ua.acclorite.book_story.presentation.screens.book_info.components.details_bottom_sheet.BookInfoDetailsBottomSheet import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoDeleteDialog import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoMoveDialog @@ -75,7 +76,6 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @Composable @@ -96,11 +96,7 @@ fun BookInfoScreen( refreshing = state.isRefreshing, onRefresh = { viewModel.onEvent( - BookInfoEvent.OnUpdateBook( - refreshList = { - libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) - historyViewModel.onEvent(HistoryEvent.OnUpdateBook(it)) - }, + BookInfoEvent.OnLoadUpdate( snackbarState, context ) @@ -142,6 +138,14 @@ fun BookInfoScreen( navigator = navigator ) } + if (state.showConfirmUpdateDialog) { + BookInfoConfirmUpdateDialog( + libraryViewModel = libraryViewModel, + historyViewModel = historyViewModel, + viewModel = viewModel, + snackbarHostState = snackbarState + ) + } Scaffold( Modifier @@ -153,7 +157,6 @@ fun BookInfoScreen( topBar = { AnimatedTopAppBar( containerColor = Color.Transparent, - scrolledContainerColor = MaterialTheme.elevation(), scrollBehavior = scrollBehavior, isTopBarScrolled = null, @@ -174,16 +177,12 @@ fun BookInfoScreen( content1Actions = { CustomIconButton( icon = Icons.Default.Refresh, - contentDescription = stringResource(id = R.string.refresh_book_content_desc), + contentDescription = R.string.refresh_book_content_desc, disableOnClick = false, enabled = !state.isRefreshing ) { viewModel.onEvent( - BookInfoEvent.OnUpdateBook( - refreshList = { - libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) - historyViewModel.onEvent(HistoryEvent.OnUpdateBook(it)) - }, + BookInfoEvent.OnLoadUpdate( snackbarState, context ) @@ -206,9 +205,10 @@ fun BookInfoScreen( ) { CustomIconButton( icon = Icons.Default.Done, - contentDescription = stringResource(id = R.string.apply_changes_content_desc), + contentDescription = R.string.apply_changes_content_desc, disableOnClick = true, - enabled = state.titleValue.isNotBlank() && + enabled = !state.isRefreshing && + state.titleValue.isNotBlank() && state.titleValue.trim() != state.book.title.trim(), color = if (state.titleValue.isNotBlank() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoBackground.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoBackground.kt index 867c5c6a..3fb3b866 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoBackground.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoBackground.kt @@ -10,20 +10,20 @@ import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage +import ua.acclorite.book_story.presentation.components.CustomCoverImage /** * Background of the BookInfoScreen. */ @Composable fun BookInfoBackground(height: Dp, image: Uri) { - val background = MaterialTheme.colorScheme.background + val background = MaterialTheme.colorScheme.surface - AsyncImage( - model = image, + CustomCoverImage( + uri = image, + animationDurationMillis = 300, contentDescription = null, modifier = Modifier .fillMaxWidth() @@ -38,7 +38,6 @@ fun BookInfoBackground(height: Dp, image: Uri) { ) } .blur(3.dp), - alpha = 0.4f, - contentScale = ContentScale.Crop + alpha = 0.4f ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt index 98011d93..2ab841f0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt @@ -33,19 +33,17 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Book +import ua.acclorite.book_story.presentation.components.CustomCoverImage import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel -import ua.acclorite.book_story.presentation.ui.elevation /** * Info section. @@ -66,7 +64,7 @@ fun BookInfoInfoSection(viewModel: BookInfoViewModel, book: Book) { .height(195.dp) .width(130.dp) .clip(MaterialTheme.shapes.medium) - .background(MaterialTheme.elevation()) + .background(MaterialTheme.colorScheme.surfaceContainerLow) .combinedClickable( interactionSource = remember { MutableInteractionSource() }, indication = null, @@ -77,13 +75,11 @@ fun BookInfoInfoSection(viewModel: BookInfoViewModel, book: Book) { ) ) { if (book.coverImage != null) { - AsyncImage( - model = book.coverImage, - contentDescription = stringResource(id = R.string.cover_image_content_desc), + CustomCoverImage( + uri = book.coverImage, modifier = Modifier .fillMaxSize() - .clip(MaterialTheme.shapes.medium), - contentScale = ContentScale.Crop + .clip(MaterialTheme.shapes.medium) ) } else { Icon( @@ -93,7 +89,7 @@ fun BookInfoInfoSection(viewModel: BookInfoViewModel, book: Book) { .align(Alignment.Center) .fillMaxWidth(0.7f) .aspectRatio(1f), - tint = MaterialTheme.elevation(12.dp) + tint = MaterialTheme.colorScheme.surfaceContainerHigh ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt index 6610347d..0324b020 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt @@ -11,6 +11,9 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp @@ -26,37 +29,39 @@ import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewM @Composable fun BookInfoMoreDropDown(viewModel: BookInfoViewModel, snackbarState: SnackbarHostState) { val state by viewModel.state.collectAsState() + var showDropDown by remember { mutableStateOf(false) } Box { CustomIconButton( icon = Icons.Default.MoreVert, - contentDescription = stringResource(id = R.string.show_dropdown_content_desc), + contentDescription = R.string.show_dropdown_content_desc, disableOnClick = false, - enabled = !state.showMoreDropDown + enabled = !showDropDown && + !state.isRefreshing ) { - viewModel.onEvent(BookInfoEvent.OnShowHideMoreDropDown) + showDropDown = true } DropdownMenu( - expanded = state.showMoreDropDown, + expanded = showDropDown, onDismissRequest = { - viewModel.onEvent(BookInfoEvent.OnShowHideMoreDropDown) + showDropDown = false }, - offset = DpOffset(10.dp, 0.dp) + offset = DpOffset((-15).dp, 0.dp) ) { CustomDropDownMenuItem( leadingIcon = Icons.AutoMirrored.Outlined.DriveFileMove, text = stringResource(id = R.string.move_this_book) ) { viewModel.onEvent(BookInfoEvent.OnShowHideMoveDialog) - viewModel.onEvent(BookInfoEvent.OnShowHideMoreDropDown) + showDropDown = false } CustomDropDownMenuItem( leadingIcon = Icons.Outlined.Delete, text = stringResource(id = R.string.delete_this_book) ) { viewModel.onEvent(BookInfoEvent.OnShowHideDeleteDialog) - viewModel.onEvent(BookInfoEvent.OnShowHideMoreDropDown) + showDropDown = false } CustomDropDownMenuItem( leadingIcon = Icons.Outlined.Info, @@ -64,7 +69,7 @@ fun BookInfoMoreDropDown(viewModel: BookInfoViewModel, snackbarState: SnackbarHo ) { snackbarState.currentSnackbarData?.dismiss() viewModel.onEvent(BookInfoEvent.OnShowHideDetailsBottomSheet) - viewModel.onEvent(BookInfoEvent.OnShowHideMoreDropDown) + showDropDown = false } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt index f2407008..0c4a8dab 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt @@ -53,11 +53,11 @@ fun BookInfoStatisticSection(book: Book) { Spacer(modifier = Modifier.height(6.dp)) LinearProgressIndicator( - book.progress.coerceAtLeast(0.01f), + progress = { book.progress.coerceAtLeast(0.01f) }, modifier = Modifier .fillMaxWidth(), color = MaterialTheme.colorScheme.primary, - trackColor = MaterialTheme.colorScheme.onPrimaryContainer.copy(0.05f), + trackColor = MaterialTheme.colorScheme.secondaryContainer.copy(0.7f), strokeCap = StrokeCap.Round, ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt index 0f024e6c..84cdddf0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt @@ -31,8 +31,6 @@ import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel -import ua.acclorite.book_story.presentation.ui.ElevationDefaults -import ua.acclorite.book_story.presentation.ui.elevation /** * Change cover bottom sheet. Lets user select photo from the gallery and replaces old one. @@ -79,7 +77,7 @@ fun BookInfoChangeCoverBottomSheet( }, sheetState = rememberModalBottomSheetState(true), windowInsets = WindowInsets(0, 0, 0, 0), - containerColor = MaterialTheme.elevation(ElevationDefaults.BottomSheet) + containerColor = MaterialTheme.colorScheme.surfaceContainerLow ) { BookInfoChangeCoverBottomSheetItem( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt new file mode 100644 index 00000000..f347ffcc --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt @@ -0,0 +1,78 @@ +package ua.acclorite.book_story.presentation.screens.book_info.components.confirm_update_dialog + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Update +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn +import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent +import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel +import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent +import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel +import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent +import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel + +@Composable +fun BookInfoConfirmUpdateDialog( + libraryViewModel: LibraryViewModel, + historyViewModel: HistoryViewModel, + viewModel: BookInfoViewModel, + snackbarHostState: SnackbarHostState +) { + val context = LocalContext.current + val state by viewModel.state.collectAsState() + + CustomDialogWithLazyColumn( + title = stringResource(id = R.string.confirm_update), + imageVectorIcon = Icons.Default.Update, + description = stringResource( + id = R.string.confirm_update_description + ), + actionText = stringResource(id = R.string.confirm), + isActionEnabled = true, + onDismiss = { viewModel.onEvent(BookInfoEvent.OnDismissConfirmUpdateDialog) }, + onAction = { + viewModel.onEvent( + BookInfoEvent.OnConfirmUpdate( + snackbarState = snackbarHostState, + context = context, + refreshList = { + libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) + historyViewModel.onEvent(HistoryEvent.OnUpdateBook(it)) + } + ) + ) + }, + withDivider = false, + items = { + if (state.authorChanged) { + item { + BookInfoConfirmUpdateDialogItem(title = stringResource(id = R.string.author)) + } + } + if (state.descriptionChanged) { + item { + BookInfoConfirmUpdateDialogItem(title = stringResource(id = R.string.description)) + } + } + if (state.textChanged) { + item { + BookInfoConfirmUpdateDialogItem(title = stringResource(id = R.string.text)) + } + } + } + ) +} + + + + + + + + diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpdateDialogItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpdateDialogItem.kt new file mode 100644 index 00000000..68549d1b --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpdateDialogItem.kt @@ -0,0 +1,18 @@ +package ua.acclorite.book_story.presentation.screens.book_info.components.confirm_update_dialog + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun BookInfoConfirmUpdateDialogItem(title: String) { + Text( + text = "• $title", + color = MaterialTheme.colorScheme.onSurfaceVariant, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(horizontal = 24.dp, vertical = 4.dp) + ) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt index 256311e1..4acfa9c3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt @@ -22,8 +22,6 @@ import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel -import ua.acclorite.book_story.presentation.ui.ElevationDefaults -import ua.acclorite.book_story.presentation.ui.elevation import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -72,7 +70,7 @@ fun BookInfoDetailsBottomSheet( }, sheetState = rememberModalBottomSheetState(true), windowInsets = WindowInsets(0, 0, 0, 0), - containerColor = MaterialTheme.elevation(ElevationDefaults.BottomSheet) + containerColor = MaterialTheme.colorScheme.surfaceContainerLow ) { BookInfoDetailsBottomSheetItem( title = stringResource(id = R.string.file_name), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoEvent.kt index 0bc42428..485b0835 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoEvent.kt @@ -19,7 +19,6 @@ sealed class BookInfoEvent { data class OnRequestFocus(val focusRequester: FocusRequester) : BookInfoEvent() data class OnTitleValueChange(val value: String) : BookInfoEvent() data class OnUpdateTitle(val refreshList: (Book) -> Unit) : BookInfoEvent() - data object OnShowHideMoreDropDown : BookInfoEvent() data object OnShowHideDeleteDialog : BookInfoEvent() data object OnShowHideMoveDialog : BookInfoEvent() data class OnDeleteBook(val refreshList: () -> Unit, val navigator: Navigator) : BookInfoEvent() @@ -44,8 +43,7 @@ sealed class BookInfoEvent { val snackbarState: SnackbarHostState ) : BookInfoEvent() - data class OnUpdateBook( - val refreshList: (Book) -> Unit, + data class OnLoadUpdate( val snackbarState: SnackbarHostState, val context: Context ) : BookInfoEvent() @@ -53,4 +51,19 @@ sealed class BookInfoEvent { data class OnNavigateToReaderScreen( val navigator: Navigator ) : BookInfoEvent() + + data object OnDismissConfirmUpdateDialog : BookInfoEvent() + + data class OnShowConfirmUpdateDialog( + val updatedBook: Book, + val authorUpdated: Boolean, + val descriptionUpdated: Boolean, + val textUpdated: Boolean, + ) : BookInfoEvent() + + data class OnConfirmUpdate( + val snackbarState: SnackbarHostState, + val context: Context, + val refreshList: (Book) -> Unit + ) : BookInfoEvent() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoState.kt index 9b3667bd..3dfba788 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoState.kt @@ -8,7 +8,13 @@ import ua.acclorite.book_story.domain.util.Constants @Immutable data class BookInfoState( val book: Book = Constants.EMPTY_BOOK, + val isRefreshing: Boolean = false, + val showConfirmUpdateDialog: Boolean = false, + val updatedBook: Book? = null, + val authorChanged: Boolean = false, + val descriptionChanged: Boolean = false, + val textChanged: Boolean = false, val editTitle: Boolean = false, val hasFocused: Boolean = false, @@ -17,9 +23,7 @@ data class BookInfoState( val showChangeCoverBottomSheet: Boolean = false, val showDetailsBottomSheet: Boolean = false, - val showMoreDropDown: Boolean = false, val showDeleteDialog: Boolean = false, - val showMoveDialog: Boolean = false, val selectedCategory: Category = Category.READING, ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt index 24d4310e..9a11edb2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt @@ -16,14 +16,15 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.yield import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.model.History import ua.acclorite.book_story.domain.model.NullableBook import ua.acclorite.book_story.domain.use_case.DeleteBooks import ua.acclorite.book_story.domain.use_case.GetBookFromFile import ua.acclorite.book_story.domain.use_case.GetBooksById +import ua.acclorite.book_story.domain.use_case.GetText import ua.acclorite.book_story.domain.use_case.InsertHistory import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.use_case.UpdateBooksWithText @@ -43,7 +44,8 @@ class BookInfoViewModel @Inject constructor( private val insertHistory: InsertHistory, private val deleteBooks: DeleteBooks, private val getBookFromFile: GetBookFromFile, - private val getBookById: GetBooksById + private val getBookById: GetBooksById, + private val getText: GetText ) : ViewModel() { private val _state = MutableStateFlow(BookInfoState()) @@ -74,7 +76,7 @@ class BookInfoViewModel @Inject constructor( val newCoverImage = getBookById.execute( listOf( - _state.value.book.id ?: return@launch + _state.value.book.id ) ).first().coverImage @@ -174,14 +176,6 @@ class BookInfoViewModel @Inject constructor( } } - is BookInfoEvent.OnShowHideMoreDropDown -> { - _state.update { - it.copy( - showMoreDropDown = !it.showMoreDropDown - ) - } - } - is BookInfoEvent.OnShowHideDeleteDialog -> { _state.update { it.copy( @@ -274,7 +268,9 @@ class BookInfoViewModel @Inject constructor( if (event.durationMillis > 0) { job = viewModelScope.launch(Dispatchers.IO) { + yield() delay(event.durationMillis) + yield() event.snackbarState.currentSnackbarData?.dismiss() } } @@ -293,7 +289,7 @@ class BookInfoViewModel @Inject constructor( } } - is BookInfoEvent.OnUpdateBook -> { + is BookInfoEvent.OnLoadUpdate -> { viewModelScope.launch(Dispatchers.IO) { _state.update { it.copy( @@ -314,8 +310,7 @@ class BookInfoViewModel @Inject constructor( action = event.context.getString(R.string.retry), onAction = { onEvent( - BookInfoEvent.OnUpdateBook( - refreshList = event.refreshList, + BookInfoEvent.OnLoadUpdate( snackbarState = event.snackbarState, context = event.context ) @@ -335,17 +330,15 @@ class BookInfoViewModel @Inject constructor( } val nullableBook = getBookFromFile.execute(_state.value.book.file!!) - if (nullableBook is NullableBook.Null) { onEvent( BookInfoEvent.OnShowSnackbar( text = nullableBook.message?.asString(event.context) - ?: event.context.getString(R.string.error_something_went_wrong), + ?: event.context.getString(R.string.error_something_went_wrong_with_file), action = event.context.getString(R.string.retry), onAction = { onEvent( - BookInfoEvent.OnUpdateBook( - refreshList = event.refreshList, + BookInfoEvent.OnLoadUpdate( snackbarState = event.snackbarState, context = event.context ) @@ -366,24 +359,212 @@ class BookInfoViewModel @Inject constructor( } val updatedBook = nullableBook.book?.first ?: return@launch + val book = _state.value.book + + var authorUpdated = false + var descriptionUpdated = false + var textUpdated = false + + if ( + updatedBook.author.asString(event.context) != + book.author.asString(event.context) + ) { + authorUpdated = true + } + if (updatedBook.description != book.description) { + descriptionUpdated = true + } + if ( + updatedBook.text.map { it.line } != + book.text.ifEmpty { + getText.execute(book.textPath) + }.map { it.line } + ) { + textUpdated = true + } + + if (!authorUpdated && !descriptionUpdated && !textUpdated) { + onEvent( + BookInfoEvent.OnShowSnackbar( + event.context.getString(R.string.nothing_changed), + action = null, + durationMillis = 4000L, + snackbarState = event.snackbarState + ) + ) + delay(500) + _state.update { + it.copy( + isRefreshing = false + ) + } + return@launch + } + + onEvent( + BookInfoEvent.OnShowConfirmUpdateDialog( + updatedBook = updatedBook, + authorUpdated = authorUpdated, + descriptionUpdated = descriptionUpdated, + textUpdated = textUpdated + ) + ) + + _state.update { + it.copy( + isRefreshing = false + ) + } + } + } + + is BookInfoEvent.OnDismissConfirmUpdateDialog -> { + _state.update { + it.copy( + showConfirmUpdateDialog = false, + updatedBook = null, + authorChanged = false, + descriptionChanged = false, + textChanged = false + ) + } + } + + is BookInfoEvent.OnShowConfirmUpdateDialog -> { + _state.update { + it.copy( + showConfirmUpdateDialog = true, + updatedBook = event.updatedBook, + authorChanged = event.authorUpdated, + descriptionChanged = event.descriptionUpdated, + textChanged = event.textUpdated + ) + } + } + + is BookInfoEvent.OnConfirmUpdate -> { + viewModelScope.launch(Dispatchers.IO) { + _state.update { + it.copy( + isRefreshing = true, + showConfirmUpdateDialog = false + ) + } + + if (_state.value.updatedBook == null) { + onEvent( + BookInfoEvent.OnShowSnackbar( + text = event.context.getString( + R.string.error_something_went_wrong_with_file + ), + action = event.context.getString(R.string.retry), + onAction = { + onEvent( + BookInfoEvent.OnLoadUpdate( + snackbarState = event.snackbarState, + context = event.context + ) + ) + }, + durationMillis = 4000L, + snackbarState = event.snackbarState + ) + ) + delay(500) + _state.update { + it.copy( + isRefreshing = false + ) + } + return@launch + } + + val book = _state.value.book + val updatedBook = _state.value.updatedBook ?: return@launch + + val author = if (_state.value.authorChanged) { + updatedBook.author + } else { + book.author + } + val description = if (_state.value.descriptionChanged) { + updatedBook.description + } else { + book.description + } + val text = if (_state.value.textChanged) { + updatedBook.text + } else { + book.text + } _state.update { it.copy( book = it.book.copy( - author = updatedBook.author, - description = updatedBook.description + author = author, + description = description, + text = text ) ) } - updateBooksWithText.execute( - listOf( - _state.value.book.copy( - author = updatedBook.author, - description = updatedBook.description, - text = updatedBook.text + + if (_state.value.textChanged) { + val isSuccess = updateBooksWithText.execute( + listOf( + _state.value.book ) ) - ) + + if (!isSuccess) { + onEvent( + BookInfoEvent.OnShowSnackbar( + text = event.context.getString( + R.string.error_something_went_wrong_with_file + ), + action = event.context.getString(R.string.retry), + onAction = { + onEvent( + BookInfoEvent.OnLoadUpdate( + snackbarState = event.snackbarState, + context = event.context + ) + ) + }, + durationMillis = 4000L, + snackbarState = event.snackbarState + ) + ) + delay(500) + _state.update { + it.copy( + isRefreshing = false + ) + } + return@launch + } + } else { + updateBooks.execute( + listOf( + _state.value.book + ) + ) + } + + if (_state.value.textChanged) { + val newBook = getBookById.execute( + listOf(_state.value.book.id) + ).first() + + _state.update { + it.copy( + book = newBook, + authorChanged = false, + descriptionChanged = false, + textChanged = false, + updatedBook = null + ) + } + } event.refreshList(_state.value.book) onEvent( @@ -406,14 +587,13 @@ class BookInfoViewModel @Inject constructor( is BookInfoEvent.OnNavigateToReaderScreen -> { viewModelScope.launch { - _state.value.book.id?.let { + _state.value.book.id.let { insertHistory.execute( listOf( History( - null, - it, - null, - Date().time + bookId = it, + book = null, + time = Date().time ) ) ) @@ -422,7 +602,7 @@ class BookInfoViewModel @Inject constructor( Screen.READER, false, Argument( - "book", _state.value.book + "book", _state.value.book.id ) ) } @@ -432,15 +612,22 @@ class BookInfoViewModel @Inject constructor( fun init(navigator: Navigator) { viewModelScope.launch { - val book = navigator.retrieveArgument("book") as? Book + val bookId = navigator.retrieveArgument("book") as? Int - if (book == null) { + if (bookId == null) { + navigator.navigateBack() + return@launch + } + + val book = getBookById.execute(listOf(bookId)) + + if (book.isEmpty()) { navigator.navigateBack() return@launch } _state.update { - BookInfoState(book = book) + BookInfoState(book = book.first()) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt index ed9c5dec..62ca379d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt @@ -67,7 +67,6 @@ import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions -import ua.acclorite.book_story.presentation.ui.elevation @OptIn( ExperimentalMaterial3Api::class, @@ -96,6 +95,7 @@ fun BrowseScreen( var showErrorMessage by remember { mutableStateOf(false) } LaunchedEffect(Unit) { + viewModel.onEvent(BrowseEvent.OnUpdateScrollOffset) viewModel.onEvent( BrowseEvent.OnPermissionCheck( permissionState, @@ -124,9 +124,6 @@ fun BrowseScreen( containerColor = MaterialTheme.colorScheme.surface, topBar = { AnimatedTopAppBar( - containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation(), - scrollBehavior = null, isTopBarScrolled = state.hasSelectedItems || state.listState.canScrollBackward, @@ -138,7 +135,7 @@ fun BrowseScreen( content1Actions = { CustomIconButton( icon = Icons.Default.Search, - contentDescription = stringResource(id = R.string.search_content_desc), + contentDescription = R.string.search_content_desc, disableOnClick = true ) { viewModel.onEvent(BrowseEvent.OnSearchShowHide) @@ -150,8 +147,7 @@ fun BrowseScreen( content2NavigationIcon = { CustomIconButton( icon = Icons.Default.Clear, - contentDescription = - stringResource(id = R.string.clear_selected_items_content_desc), + contentDescription = R.string.clear_selected_items_content_desc, disableOnClick = true ) { viewModel.onEvent(BrowseEvent.OnClearSelectedFiles) @@ -170,8 +166,7 @@ fun BrowseScreen( content2Actions = { CustomIconButton( icon = Icons.Default.Check, - contentDescription = - stringResource(id = R.string.add_files_content_desc), + contentDescription = R.string.add_files_content_desc, disableOnClick = false, enabled = !state.showAddingDialog ) { @@ -183,9 +178,7 @@ fun BrowseScreen( content3NavigationIcon = { CustomIconButton( icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = stringResource( - id = R.string.exit_search_content_desc - ), + contentDescription = R.string.exit_search_content_desc, disableOnClick = true ) { viewModel.onEvent(BrowseEvent.OnSearchShowHide) @@ -256,8 +249,7 @@ fun BrowseScreen( ) { selectableFile -> BrowseFileItem( file = selectableFile, - modifier = Modifier - .animateItemPlacement(), + modifier = Modifier.animateItemPlacement(), hasSelectedFiles = state.selectableFiles.any { it.second }, onLongClick = { Toast.makeText( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseFIleItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseFIleItem.kt index 63a4b2df..254bd113 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseFIleItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseFIleItem.kt @@ -1,7 +1,5 @@ package ua.acclorite.book_story.presentation.screens.browse.components -import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -23,7 +21,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -71,24 +68,13 @@ fun BrowseFileItem( val backgroundColor = if (file.second) MaterialTheme.colorScheme.secondaryContainer else Color.Transparent - val animatedOutlineColor by animateColorAsState( - targetValue = outlineColor, - tween(300), - label = stringResource(id = R.string.outline_anim_content_desc) - ) - val animatedBackgroundColor by animateColorAsState( - targetValue = backgroundColor, - tween(300), - label = stringResource(id = R.string.background_anim_content_desc) - ) - Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 3.dp) .clip(RoundedCornerShape(10.dp)) - .background(animatedBackgroundColor) + .background(backgroundColor) .combinedClickable( onLongClick = { onLongClick() @@ -107,7 +93,7 @@ fun BrowseFileItem( modifier = Modifier .border( 1.dp, - animatedOutlineColor, + outlineColor, RoundedCornerShape(6.dp) ) .padding(14.dp), @@ -153,7 +139,11 @@ fun BrowseFileItem( DefaultTransition( visible = hasSelectedFiles ) { - CustomCheckbox(selected = file.second, size = 18.dp) + CustomCheckbox( + selected = file.second, + containerColor = MaterialTheme.colorScheme.surface, + size = 18.dp + ) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt index 4079d293..1526f145 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt @@ -6,9 +6,9 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.items -import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AddChart +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -55,14 +55,23 @@ fun BrowseAddingDialog( resetScroll = { libraryViewModel.onEvent(LibraryEvent.OnUpdateCurrentPage(0)) libraryViewModel.onEvent(LibraryEvent.OnLoadList) + }, + onFailed = { + Toast.makeText( + context, + context.getString(R.string.error_something_went_wrong), + Toast.LENGTH_LONG + ).show() + }, + onSuccess = { + Toast.makeText( + context, + context.getString(R.string.books_added), + Toast.LENGTH_LONG + ).show() } ) ) - Toast.makeText( - context, - context.getString(R.string.books_added), - Toast.LENGTH_LONG - ).show() }, withDivider = true, items = { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialogItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialogItem.kt index c1346e7a..e23d61ac 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialogItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialogItem.kt @@ -59,7 +59,10 @@ fun BrowseAddingDialogItem(result: Pair, onClick: (Boole ) } Box(modifier = Modifier.weight(0.15f), contentAlignment = Alignment.CenterEnd) { - CustomCheckbox(selected = result.second) + CustomCheckbox( + selected = result.second, + MaterialTheme.colorScheme.surfaceContainerHigh + ) } } } else { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseEvent.kt index c29a6708..f93016e4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseEvent.kt @@ -39,7 +39,13 @@ sealed class BrowseEvent { data object OnAddingDialogRequest : BrowseEvent() data object OnAddingDialogDismiss : BrowseEvent() data object OnGetBooksFromFiles : BrowseEvent() - data class OnAddBooks(val navigator: Navigator, val resetScroll: () -> Unit) : BrowseEvent() - data object OnLoadList : BrowseEvent() + data class OnAddBooks( + val navigator: Navigator, + val resetScroll: () -> Unit, + val onFailed: () -> Unit, + val onSuccess: () -> Unit + ) : BrowseEvent() + data object OnLoadList : BrowseEvent() + data object OnUpdateScrollOffset : BrowseEvent() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt index 2fe1b30d..a29cb9f8 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt @@ -18,13 +18,12 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.yield import ua.acclorite.book_story.domain.model.NullableBook -import ua.acclorite.book_story.domain.use_case.FastGetBooks import ua.acclorite.book_story.domain.use_case.GetBooksFromFiles import ua.acclorite.book_story.domain.use_case.GetFilesFromDevice import ua.acclorite.book_story.domain.use_case.InsertBooks import ua.acclorite.book_story.domain.util.Resource -import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject @@ -33,8 +32,7 @@ import javax.inject.Inject class BrowseViewModel @Inject constructor( private val getBooksFromFiles: GetBooksFromFiles, private val getFilesFromDevice: GetFilesFromDevice, - private val insertBooks: InsertBooks, - private val fastGetBooks: FastGetBooks + private val insertBooks: InsertBooks ) : ViewModel() { private val _state = MutableStateFlow(BrowseState()) @@ -42,6 +40,7 @@ class BrowseViewModel @Inject constructor( private var job: Job? = null private var job2: Job? = null + private var job3: Job? = null init { viewModelScope.launch(Dispatchers.IO) { @@ -138,7 +137,7 @@ class BrowseViewModel @Inject constructor( listState = LazyListState(0, 0) ) } - + yield() getFilesFromDownloads("") delay(500) _state.update { @@ -270,6 +269,7 @@ class BrowseViewModel @Inject constructor( job?.cancel() job = viewModelScope.launch(Dispatchers.IO) { delay(500) + yield() getFilesFromDownloads() } } @@ -280,6 +280,7 @@ class BrowseViewModel @Inject constructor( showAddingDialog = false ) } + job3?.cancel(null) } is BrowseEvent.OnAddingDialogRequest -> { @@ -293,18 +294,29 @@ class BrowseViewModel @Inject constructor( } is BrowseEvent.OnGetBooksFromFiles -> { - viewModelScope.launch(Dispatchers.IO) { + job3 = viewModelScope.launch(Dispatchers.IO) { _state.update { it.copy( isBooksLoading = true ) } - val books = getBooksFromFiles.execute( - _state.value.selectableFiles - .filter { it.second } - .map { it.first } - ) + yield() + + val books = mutableListOf() + _state.value.selectableFiles + .filter { it.second } + .map { it.first } + .forEach { + yield() + books.add( + getBooksFromFiles.execute( + listOf(it) + ).first() + ) + } + + yield() _state.update { it.copy( @@ -326,21 +338,21 @@ class BrowseViewModel @Inject constructor( return@launch } - insertBooks.execute(booksToInsert) - val books = fastGetBooks.execute("") + if (!insertBooks.execute(booksToInsert)) { + event.onFailed() + return@launch + } event.resetScroll() event.navigator.navigate( Screen.LIBRARY, - false, - Argument("added_books", books) + false ) + event.onSuccess() _state.update { it.copy( - showAddingDialog = false, - selectableFiles = emptyList(), - listState = LazyListState(0, 0) + showAddingDialog = false ) } onEvent(BrowseEvent.OnLoadList) @@ -360,6 +372,17 @@ class BrowseViewModel @Inject constructor( getFilesFromDownloads() } } + + is BrowseEvent.OnUpdateScrollOffset -> { + _state.update { + it.copy( + listState = LazyListState( + it.listState.firstVisibleItemIndex, + 0 + ) + ) + } + } } } @@ -378,8 +401,6 @@ class BrowseViewModel @Inject constructor( } } - is Resource.Loading -> Unit - is Resource.Error -> Unit } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt new file mode 100644 index 00000000..c8e40294 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt @@ -0,0 +1,85 @@ +package ua.acclorite.book_story.presentation.screens.help + +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.presentation.screens.help.components.HelpClickableNote +import ua.acclorite.book_story.presentation.screens.help.data.HelpViewModel + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun HelpScreen( + viewModel: HelpViewModel = hiltViewModel(), + navigator: Navigator +) { + val context = LocalContext.current + val listState = rememberLazyListState() + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( + canScroll = { + listState.canScrollForward || listState.canScrollBackward + } + ) + + Scaffold( + Modifier + .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection) + .windowInsetsPadding(WindowInsets.navigationBars), + containerColor = MaterialTheme.colorScheme.surface, + topBar = { + LargeTopAppBar( + title = { + Text(stringResource(id = R.string.help_screen)) + }, + navigationIcon = { + GoBackButton(navigator = navigator) + }, + scrollBehavior = scrollBehavior, + colors = TopAppBarDefaults.largeTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surface, + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer + ) + ) + } + ) { paddingValues -> + LazyColumn( + Modifier + .fillMaxSize() + .padding(top = paddingValues.calculateTopPadding()) + .padding(horizontal = 18.dp), + state = listState + ) { + item { Spacer(modifier = Modifier.height(16.dp)) } + + item { HelpClickableNote() } + + item { Spacer(modifier = Modifier.height(16.dp)) } + + /* TODO Help screen */ + + item { Spacer(modifier = Modifier.height(48.dp)) } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpClickableNote.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpClickableNote.kt new file mode 100644 index 00000000..fe12d508 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpClickableNote.kt @@ -0,0 +1,83 @@ +package ua.acclorite.book_story.presentation.screens.help.components + +import android.widget.Toast +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import ua.acclorite.book_story.R + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun HelpClickableNote() { + val context = LocalContext.current + + Column { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = stringResource(id = R.string.note_content_desc), + modifier = Modifier + .size(20.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(modifier = Modifier.height(8.dp)) + FlowRow(verticalArrangement = Arrangement.spacedBy(1.dp)) { + Text( + stringResource(id = R.string.clickable_note_1) + " ", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.align(Alignment.CenterVertically) + ) + Text( + stringResource(id = R.string.clickable_note_2) + " ", + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.tertiary, + modifier = Modifier + .align(Alignment.CenterVertically) + .clickable( + interactionSource = null, + indication = null, + onClick = { + Toast + .makeText( + context, + context.getString(R.string.clickable_note_action), + Toast.LENGTH_SHORT + ) + .show() + } + ) + ) + Text( + stringResource(id = R.string.clickable_note_3), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.align(Alignment.CenterVertically) + ) + } + } + +} + + + + + + diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt new file mode 100644 index 00000000..cca81a95 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt @@ -0,0 +1,11 @@ +package ua.acclorite.book_story.presentation.screens.help.data + +import android.content.Context + +sealed class HelpEvent { + data class OnNavigateToBrowserPage( + val page: String, + val context: Context, + val noAppsFound: () -> Unit + ) : HelpEvent() +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt new file mode 100644 index 00000000..4d02775d --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt @@ -0,0 +1,43 @@ +package ua.acclorite.book_story.presentation.screens.help.data + +import android.content.Intent +import android.net.Uri +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class HelpViewModel @Inject constructor( + +) : ViewModel() { + + fun onEvent(event: HelpEvent) { + when (event) { + is HelpEvent.OnNavigateToBrowserPage -> { + viewModelScope.launch { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse(event.page) + ) + + if (intent.resolveActivity(event.context.packageManager) != null) { + event.context.startActivity(intent) + return@launch + } + + event.noAppsFound() + } + } + } + } +} + + + + + + + + diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt index 48b67a3f..7b920b19 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -64,8 +65,6 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions -import ua.acclorite.book_story.presentation.ui.elevation -import java.util.UUID @OptIn( ExperimentalMaterial3Api::class, @@ -88,6 +87,10 @@ fun HistoryScreen( val focusRequester = remember { FocusRequester() } val snackbarState = remember { SnackbarHostState() } + LaunchedEffect(Unit) { + viewModel.onEvent(HistoryEvent.OnUpdateScrollOffset) + } + if (state.showDeleteWholeHistoryDialog) { HistoryDeleteWholeHistoryDialog(viewModel = viewModel, libraryViewModel = libraryViewModel) } @@ -99,7 +102,6 @@ fun HistoryScreen( containerColor = MaterialTheme.colorScheme.surface, topBar = { AnimatedTopAppBar( - scrolledContainerColor = MaterialTheme.elevation(), scrollBehavior = null, isTopBarScrolled = state.listState.canScrollBackward, @@ -113,16 +115,14 @@ fun HistoryScreen( content1Actions = { CustomIconButton( icon = Icons.Default.Search, - contentDescription = stringResource(id = R.string.search_content_desc), + contentDescription = R.string.search_content_desc, disableOnClick = true, ) { viewModel.onEvent(HistoryEvent.OnSearchShowHide) } CustomIconButton( icon = Icons.Outlined.DeleteSweep, - contentDescription = stringResource( - id = R.string.delete_whole_history_content_desc - ), + contentDescription = R.string.delete_whole_history_content_desc, disableOnClick = false, enabled = !state.isLoading && !state.isRefreshing @@ -138,9 +138,7 @@ fun HistoryScreen( content2NavigationIcon = { CustomIconButton( icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = stringResource( - id = R.string.exit_search_content_desc - ), + contentDescription = R.string.exit_search_content_desc, disableOnClick = true ) { viewModel.onEvent(HistoryEvent.OnSearchShowHide) @@ -229,7 +227,7 @@ fun HistoryScreen( } items( - groupedHistory.history, key = { it.id ?: UUID.randomUUID() } + groupedHistory.history, key = { it.id } ) { HistoryItem( modifier = Modifier.animateItemPlacement(), @@ -239,14 +237,14 @@ fun HistoryScreen( navigator.navigate( Screen.BOOK_INFO, false, - Argument("book", it.book) + Argument("book", it.bookId) ) }, onTitleClick = { viewModel.onEvent( HistoryEvent.OnNavigateToReaderScreen( navigator, - it.book + it.book!! ) ) }, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryItem.kt index 64ba65ff..8d766331 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryItem.kt @@ -19,7 +19,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Image import androidx.compose.material.icons.outlined.Delete import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -27,15 +26,14 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import coil.compose.AsyncImage import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.presentation.ui.elevation +import ua.acclorite.book_story.presentation.components.CustomCoverImage +import ua.acclorite.book_story.presentation.components.CustomIconButton import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -76,16 +74,14 @@ fun HistoryItem( .height(90.dp) .width(60.dp) .clip(RoundedCornerShape(10.dp)) - .background(MaterialTheme.elevation()) + .background(MaterialTheme.colorScheme.surfaceContainerLow) ) { if (history.book?.coverImage != null) { - AsyncImage( - model = history.book.coverImage, - contentDescription = stringResource(id = R.string.cover_image_content_desc), + CustomCoverImage( + uri = history.book.coverImage, modifier = Modifier .fillMaxSize() - .clip(RoundedCornerShape(10.dp)), - contentScale = ContentScale.Crop + .clip(RoundedCornerShape(10.dp)) ) } else { Icon( @@ -97,7 +93,7 @@ fun HistoryItem( .align(Alignment.Center) .fillMaxWidth(0.7f) .aspectRatio(1f), - tint = MaterialTheme.elevation(12.dp) + tint = MaterialTheme.colorScheme.surfaceContainerHigh ) } } @@ -137,17 +133,14 @@ fun HistoryItem( } } Box(modifier = Modifier.weight(0.11f), contentAlignment = Alignment.CenterEnd) { - IconButton( - enabled = isDeleteEnabled && isOnClickEnabled, - onClick = { - onDeleteClick() - } + CustomIconButton( + icon = Icons.Outlined.Delete, + contentDescription = R.string.delete_history_element_content_desc, + disableOnClick = true, + enabled = isDeleteEnabled, + color = MaterialTheme.colorScheme.onSurfaceVariant ) { - Icon( - imageVector = Icons.Outlined.Delete, - contentDescription = "Delete this history element", - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) + onDeleteClick() } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryEvent.kt index 2d51220e..fc6ded70 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryEvent.kt @@ -25,6 +25,8 @@ sealed class HistoryEvent { data class OnUpdateBook(val book: Book) : HistoryEvent() data class OnNavigateToReaderScreen( val navigator: Navigator, - val book: Book? + val book: Book ) : HistoryEvent() + + data object OnUpdateScrollOffset : HistoryEvent() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt index 031c40c3..081f868a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.yield import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.GroupedHistory import ua.acclorite.book_story.domain.model.History @@ -69,7 +70,9 @@ class HistoryViewModel @Inject constructor( ) } + yield() getHistoryFromDatabase("") + delay(500) _state.update { it.copy( @@ -121,14 +124,27 @@ class HistoryViewModel @Inject constructor( listOf(event.historyToDelete) ) - onEvent(HistoryEvent.OnRefreshList) + _state.update { + it.copy( + isRefreshing = true + ) + } + getHistoryFromDatabase() + _state.update { + it.copy( + isRefreshing = false + ) + } + event.refreshList() job2?.cancel() event.snackbarState.currentSnackbarData?.dismiss() job2 = viewModelScope.launch(Dispatchers.IO) { + yield() delay(10000) + yield() event.snackbarState.currentSnackbarData?.dismiss() } val snackbar = event.snackbarState.showSnackbar( @@ -143,7 +159,18 @@ class HistoryViewModel @Inject constructor( listOf(event.historyToDelete) ) event.refreshList() - onEvent(HistoryEvent.OnRefreshList) + _state.update { + it.copy( + isRefreshing = true + ) + } + getHistoryFromDatabase() + delay(500) + _state.update { + it.copy( + isRefreshing = false + ) + } } } } @@ -180,6 +207,7 @@ class HistoryViewModel @Inject constructor( job?.cancel() job = viewModelScope.launch(Dispatchers.IO) { delay(500) + yield() getHistoryFromDatabase() } } @@ -221,14 +249,13 @@ class HistoryViewModel @Inject constructor( is HistoryEvent.OnNavigateToReaderScreen -> { viewModelScope.launch { - event.book?.id?.let { + event.book.id.let { insertHistory.execute( listOf( History( - null, - it, - null, - Date().time + bookId = it, + book = null, + time = Date().time ) ) ) @@ -237,7 +264,18 @@ class HistoryViewModel @Inject constructor( Screen.READER, false, Argument( - "book", event.book + "book", event.book.id + ) + ) + } + } + + is HistoryEvent.OnUpdateScrollOffset -> { + _state.update { + it.copy( + listState = LazyListState( + it.listState.firstVisibleItemIndex, + 0 ) ) } @@ -343,8 +381,6 @@ class HistoryViewModel @Inject constructor( } } - is Resource.Loading -> Unit - is Resource.Error -> Unit } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt index e19d140b..dfd7eacb 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt @@ -21,8 +21,10 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.ExperimentalMaterialApi @@ -43,7 +45,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -86,8 +87,6 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions -import ua.acclorite.book_story.presentation.ui.elevation -import java.util.UUID @OptIn( ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class, @@ -105,6 +104,7 @@ fun LibraryScreen( initialPage = state.currentPage, pageCount = { Category.entries.size } ) + var isScrollInProgress by remember { mutableStateOf(false) } val refreshState = rememberPullRefreshState( refreshing = state.isRefreshing, onRefresh = { @@ -145,9 +145,6 @@ fun LibraryScreen( topBar = { Column(Modifier.fillMaxWidth()) { AnimatedTopAppBar( - containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation(), - scrollBehavior = null, isTopBarScrolled = state.hasSelectedItems, @@ -160,8 +157,8 @@ fun LibraryScreen( Text( text = state.books.size.toString(), modifier = Modifier - .clip(MaterialTheme.shapes.medium) - .background(MaterialTheme.elevation(elevation = 6.dp)) + .clip(RoundedCornerShape(14.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) .padding(horizontal = 8.dp, vertical = 3.dp), color = MaterialTheme.colorScheme.onSurfaceVariant, fontSize = 16.sp @@ -171,7 +168,7 @@ fun LibraryScreen( content1Actions = { CustomIconButton( icon = Icons.Default.Search, - contentDescription = stringResource(id = R.string.search_content_desc), + contentDescription = R.string.search_content_desc, disableOnClick = true, ) { viewModel.onEvent(LibraryEvent.OnSearchShowHide) @@ -183,8 +180,7 @@ fun LibraryScreen( content2NavigationIcon = { CustomIconButton( icon = Icons.Default.Clear, - contentDescription = - stringResource(id = R.string.clear_selected_items_content_desc), + contentDescription = R.string.clear_selected_items_content_desc, disableOnClick = true ) { viewModel.onEvent(LibraryEvent.OnClearSelectedBooks) @@ -203,9 +199,7 @@ fun LibraryScreen( content2Actions = { CustomIconButton( icon = Icons.AutoMirrored.Outlined.DriveFileMove, - contentDescription = stringResource( - id = R.string.move_books_content_desc - ), + contentDescription = R.string.move_books_content_desc, enabled = !state.isLoading && !state.isRefreshing && !state.showMoveDialog, @@ -216,9 +210,7 @@ fun LibraryScreen( } CustomIconButton( icon = Icons.Outlined.Delete, - contentDescription = stringResource( - id = R.string.delete_books_content_desc - ), + contentDescription = R.string.delete_books_content_desc, enabled = !state.isLoading && !state.isRefreshing && !state.showDeleteDialog, @@ -232,9 +224,7 @@ fun LibraryScreen( content3NavigationIcon = { CustomIconButton( icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = stringResource( - id = R.string.exit_search_content_desc - ), + contentDescription = R.string.exit_search_content_desc, disableOnClick = true ) { viewModel.onEvent( @@ -289,7 +279,7 @@ fun LibraryScreen( ) LibraryTabRow( viewModel = viewModel, - books = state.books.map { it.first }, + books = state.categorizedBooks, pagerState = pagerState ) } @@ -300,34 +290,40 @@ fun LibraryScreen( .fillMaxSize() .padding(top = paddingValues.calculateTopPadding()) ) { - HorizontalPager(state = pagerState, userScrollEnabled = !state.isRefreshing) { index -> - var categoryIsLoading by remember { mutableStateOf(true) } - val categorizedBooks = remember { mutableStateListOf>() } + HorizontalPager( + state = pagerState, + userScrollEnabled = !isScrollInProgress + ) { index -> val category = remember { Category.entries[index] } + val books = remember(state.categorizedBooks) { + state.categorizedBooks.find { + it.category == category + }?.books?.sortedWith( + compareByDescending> { it.first.lastOpened } + .thenBy { it.first.title } + ) ?: emptyList() + } + val listState = rememberLazyGridState() - LaunchedEffect(state.books) { - categorizedBooks.clear() - categorizedBooks.addAll( - state.books - .filter { it.first.category == category } - .sortedWith( - compareByDescending> { it.first.lastOpened } - .thenBy { it.first.title } - ) - ) - categoryIsLoading = false + LaunchedEffect(listState.isScrollInProgress, pagerState.currentPage) { + if (listState.isScrollInProgress != isScrollInProgress + && pagerState.currentPage == state.currentPage + ) { + isScrollInProgress = listState.isScrollInProgress + } } Box(modifier = Modifier.fillMaxSize()) { - DefaultTransition(visible = !state.isLoading && !categoryIsLoading) { + DefaultTransition(visible = !state.isLoading) { LazyVerticalGrid( columns = GridCells.Adaptive(120.dp), modifier = Modifier.fillMaxSize(), + state = listState, contentPadding = PaddingValues(8.dp) ) { items( - categorizedBooks, - key = { it.first.id ?: UUID.randomUUID() } + books, + key = { it.first.id } ) { LibraryBookItem( book = it, @@ -339,7 +335,7 @@ fun LibraryScreen( navigator.navigate( Screen.BOOK_INFO, false, - Argument("book", it.first) + Argument("book", it.first.id) ) } }, @@ -364,8 +360,7 @@ fun LibraryScreen( AnimatedVisibility( visible = !state.isLoading && !state.isRefreshing - && categorizedBooks.isEmpty() - && !categoryIsLoading, + && books.isEmpty(), modifier = Modifier.align(Alignment.Center), enter = Transitions.DefaultTransitionIn, exit = fadeOut(tween(0)) @@ -379,16 +374,16 @@ fun LibraryScreen( navigator.navigate(Screen.BROWSE, false) } } - - PullRefreshIndicator( - state.isRefreshing, - refreshState, - Modifier.align(Alignment.TopCenter), - backgroundColor = MaterialTheme.colorScheme.inverseSurface, - contentColor = MaterialTheme.colorScheme.inverseOnSurface - ) } } + + PullRefreshIndicator( + state.isRefreshing, + refreshState, + Modifier.align(Alignment.TopCenter), + backgroundColor = MaterialTheme.colorScheme.inverseSurface, + contentColor = MaterialTheme.colorScheme.inverseOnSurface + ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryBookItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryBookItem.kt index 17e1e5c0..b519556b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryBookItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryBookItem.kt @@ -1,7 +1,5 @@ package ua.acclorite.book_story.presentation.screens.library.components -import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable @@ -23,24 +21,21 @@ import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.util.Selected +import ua.acclorite.book_story.presentation.components.CustomCoverImage import ua.acclorite.book_story.presentation.data.removeDigits import ua.acclorite.book_story.presentation.data.removeTrailingZero -import ua.acclorite.book_story.presentation.ui.elevation /** * Library list element item. @@ -54,10 +49,18 @@ fun LibraryBookItem( onLongClick: () -> Unit, onButtonClick: () -> Unit ) { - val backgroundColor = if (book.second) MaterialTheme.colorScheme.primary - else Color.Transparent - val fontColor = if (book.second) MaterialTheme.colorScheme.onPrimary - else MaterialTheme.colorScheme.onSurface + val primaryColor = MaterialTheme.colorScheme.primary + val onPrimaryColor = MaterialTheme.colorScheme.onPrimary + val onSurfaceColor = MaterialTheme.colorScheme.onSurface + + val backgroundColor = remember(book.second) { + if (book.second) primaryColor + else Color.Transparent + } + val fontColor = remember(book.second) { + if (book.second) onPrimaryColor + else onSurfaceColor + } val progress = remember(book.first) { "${ @@ -68,22 +71,11 @@ fun LibraryBookItem( }%" } - val animatedBackgroundColor by animateColorAsState( - targetValue = backgroundColor, - tween(300), - label = "Background animation" - ) - val animatedFontColor by animateColorAsState( - targetValue = fontColor, - tween(300), - label = "Font color animation" - ) - Column( modifier .padding(3.dp) .background( - animatedBackgroundColor, + backgroundColor, MaterialTheme.shapes.large ) .padding(3.dp) @@ -94,7 +86,7 @@ fun LibraryBookItem( .aspectRatio(1f / 1.5f) .fillMaxWidth() .clip(MaterialTheme.shapes.medium) - .background(MaterialTheme.elevation()) + .background(MaterialTheme.colorScheme.surfaceContainerLow) .combinedClickable( onClick = { onCoverImageClick() @@ -105,13 +97,11 @@ fun LibraryBookItem( ) ) { if (book.first.coverImage != null) { - AsyncImage( - model = book.first.coverImage, - contentDescription = stringResource(id = R.string.cover_image_content_desc), + CustomCoverImage( + uri = book.first.coverImage!!, modifier = Modifier .fillMaxSize() - .clip(MaterialTheme.shapes.medium), - contentScale = ContentScale.Crop + .clip(MaterialTheme.shapes.medium) ) } else { Icon( @@ -123,7 +113,7 @@ fun LibraryBookItem( .align(Alignment.Center) .fillMaxWidth(0.7f) .aspectRatio(1f), - tint = MaterialTheme.elevation(12.dp) + tint = MaterialTheme.colorScheme.surfaceContainerHigh ) } @@ -155,7 +145,7 @@ fun LibraryBookItem( ) { Icon( imageVector = Icons.Filled.PlayArrow, - contentDescription = "Continue reading", + contentDescription = stringResource(id = R.string.continue_reading_content_desc), Modifier.size(20.dp) ) } @@ -163,7 +153,7 @@ fun LibraryBookItem( Spacer(modifier = Modifier.height(6.dp)) Text( book.first.title, - color = animatedFontColor, + color = fontColor, style = MaterialTheme.typography.bodyMedium, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTabRow.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTabRow.kt index 3390d941..6fe5677f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTabRow.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTabRow.kt @@ -1,6 +1,6 @@ package ua.acclorite.book_story.presentation.screens.library.components -import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.animation.core.animateDpAsState import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -9,15 +9,16 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ScrollableTabRow +import androidx.compose.material3.PrimaryScrollableTabRow import androidx.compose.material3.Tab import androidx.compose.material3.TabRowDefaults import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -26,48 +27,51 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.Book +import ua.acclorite.book_story.domain.model.CategorizedBooks import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel -import ua.acclorite.book_story.presentation.ui.elevation /** * Tab row, either scrollable or static, depends on screen width. */ -@OptIn(ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun LibraryTabRow(viewModel: LibraryViewModel, books: List, pagerState: PagerState) { +fun LibraryTabRow( + viewModel: LibraryViewModel, + books: List, + pagerState: PagerState +) { val context = LocalContext.current val tabItems = remember(books) { listOf( Pair( context.getString(R.string.reading_tab), - books.filter { it.category == Category.READING }.size + books.find { it.category == Category.READING }?.books?.size ?: 0 ), Pair( context.getString(R.string.already_read_tab), - books.filter { it.category == Category.ALREADY_READ }.size + books.find { it.category == Category.ALREADY_READ }?.books?.size ?: 0 ), Pair( context.getString(R.string.planning_tab), - books.filter { it.category == Category.PLANNING }.size + books.find { it.category == Category.PLANNING }?.books?.size ?: 0 ), Pair( context.getString(R.string.dropped_tab), - books.filter { it.category == Category.DROPPED }.size + books.find { it.category == Category.DROPPED }?.books?.size ?: 0 ) ) } Box(Modifier.fillMaxWidth()) { - Divider( + HorizontalDivider( modifier = Modifier .align(Alignment.BottomCenter) .fillMaxWidth(), - color = MaterialTheme.colorScheme.surfaceVariant + color = MaterialTheme.colorScheme.surfaceContainerHighest ) - ScrollableTabRow( + PrimaryScrollableTabRow( modifier = Modifier .fillMaxWidth() .padding(bottom = 0.5.dp), @@ -76,19 +80,18 @@ fun LibraryTabRow(viewModel: LibraryViewModel, books: List, pagerState: Pa edgePadding = 0.dp, divider = {}, indicator = { tabPositions -> - TabRowDefaults.Indicator( - Modifier - .tabIndicatorOffset(tabPositions[pagerState.currentPage]) - .padding(horizontal = 16.dp) - .padding(end = 5.5.dp) - .clip( - RoundedCornerShape( - 100 - ) - ), - color = MaterialTheme.colorScheme.primary, - height = 3.dp - ) + if (pagerState.currentPage < tabPositions.size) { + val width by animateDpAsState( + targetValue = tabPositions[pagerState.currentPage].contentWidth, + label = "" + ) + + TabRowDefaults.PrimaryIndicator( + Modifier + .tabIndicatorOffset(tabPositions[pagerState.currentPage]), + width = width + ) + } } ) { tabItems.forEachIndexed { index, tabItem -> @@ -112,7 +115,7 @@ fun LibraryTabRow(viewModel: LibraryViewModel, books: List, pagerState: Pa text = tabItem.second.toString(), modifier = Modifier .clip(MaterialTheme.shapes.medium) - .background(MaterialTheme.elevation(6.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) .padding(horizontal = 8.dp, vertical = 4.dp), color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt index 398b1d86..0dc7b9be 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt @@ -1,7 +1,6 @@ package ua.acclorite.book_story.presentation.screens.library.components.dialog import android.widget.Toast -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.lazy.items import androidx.compose.foundation.pager.PagerState import androidx.compose.material.icons.Icons @@ -23,7 +22,6 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewMode /** * Move dialog. Moves all selected books to the selected category. */ -@OptIn(ExperimentalFoundationApi::class) @Composable fun LibraryMoveDialog( viewModel: LibraryViewModel, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryEvent.kt index d6f8b374..5c7669db 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryEvent.kt @@ -1,8 +1,5 @@ -@file:OptIn(ExperimentalFoundationApi::class) - package ua.acclorite.book_story.presentation.screens.library.data -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.pager.PagerState import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.domain.model.Book @@ -13,6 +10,7 @@ import ua.acclorite.book_story.presentation.data.Navigator sealed class LibraryEvent { data object OnRefreshList : LibraryEvent() data object OnLoadList : LibraryEvent() + data class OnRecalculateCategories(val books: List>) : LibraryEvent() data class OnScrollToPage(val index: Int, val pagerState: PagerState) : LibraryEvent() data class OnUpdateCurrentPage(val page: Int) : LibraryEvent() data object OnSearchShowHide : LibraryEvent() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryState.kt index 402fc0d1..e28a76ef 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryState.kt @@ -2,12 +2,15 @@ package ua.acclorite.book_story.presentation.screens.library.data import androidx.compose.runtime.Immutable import ua.acclorite.book_story.domain.model.Book +import ua.acclorite.book_story.domain.model.CategorizedBooks import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.util.Selected @Immutable data class LibraryState( val books: List> = emptyList(), + val categorizedBooks: List = emptyList(), + val isLoading: Boolean = true, val isRefreshing: Boolean = false, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt index eabc42d5..32daf7d8 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt @@ -1,6 +1,5 @@ package ua.acclorite.book_story.presentation.screens.library.data -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -11,19 +10,19 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.yield +import ua.acclorite.book_story.domain.model.CategorizedBooks import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.model.History import ua.acclorite.book_story.domain.use_case.DeleteBooks import ua.acclorite.book_story.domain.use_case.GetBooks import ua.acclorite.book_story.domain.use_case.InsertHistory import ua.acclorite.book_story.domain.use_case.UpdateBooks -import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Screen import java.util.Date import javax.inject.Inject -@OptIn(ExperimentalFoundationApi::class) @HiltViewModel class LibraryViewModel @Inject constructor( private val getBooks: GetBooks, @@ -87,7 +86,9 @@ class LibraryViewModel @Inject constructor( ) } + yield() getBooksFromDatabase("") + delay(500) _state.update { it.copy( @@ -152,6 +153,7 @@ class LibraryViewModel @Inject constructor( job?.cancel() job = viewModelScope.launch(Dispatchers.IO) { delay(500) + yield() getBooksFromDatabase() } } @@ -168,6 +170,7 @@ class LibraryViewModel @Inject constructor( } } + onEvent(LibraryEvent.OnRecalculateCategories(editedList)) _state.update { it.copy( books = editedList, @@ -186,6 +189,7 @@ class LibraryViewModel @Inject constructor( hasSelectedItems = false ) } + onEvent(LibraryEvent.OnRecalculateCategories(_state.value.books)) } } @@ -289,6 +293,7 @@ class LibraryViewModel @Inject constructor( } } + onEvent(LibraryEvent.OnRecalculateCategories(books)) _state.update { it.copy( books = books @@ -299,14 +304,13 @@ class LibraryViewModel @Inject constructor( is LibraryEvent.OnNavigateToReaderScreen -> { viewModelScope.launch { - event.book.id?.let { + event.book.id.let { insertHistory.execute( listOf( History( - null, - it, - null, - Date().time + bookId = it, + book = null, + time = Date().time ) ) ) @@ -315,35 +319,51 @@ class LibraryViewModel @Inject constructor( Screen.READER, false, Argument( - "book", event.book + "book", event.book.id ) ) } } + + is LibraryEvent.OnRecalculateCategories -> { + val categorizedBooks = event.books.groupBy { + it.first.category + }.toList().map { + CategorizedBooks( + it.first, + it.second + ) + } + _state.update { + it.copy( + categorizedBooks = categorizedBooks + ) + } + } } } private suspend fun getBooksFromDatabase( query: String = if (_state.value.showSearch) _state.value.searchQuery else "" ) { - getBooks.execute(query).collect { result -> - when (result) { - is Resource.Success -> { - _state.update { - it.copy( - books = result.data?.map { book -> Pair(book, false) } - ?: emptyList(), - isLoading = false - ) - } - } + val books = getBooks.execute(query).map { book -> Pair(book, false) } + val categorizedBooks = books.groupBy { + it.first.category + }.toList().map { + CategorizedBooks( + it.first, + it.second + ) + } - is Resource.Loading -> Unit - is Resource.Error -> Unit - } + _state.update { + it.copy( + books = books, + categorizedBooks = categorizedBooks, + isLoading = false + ) } } - } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt index 466d6b0b..1a5d42f5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt @@ -21,7 +21,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.selection.DisableSelection -import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -71,7 +71,6 @@ import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.Re import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(FlowPreview::class) @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @@ -84,7 +83,7 @@ fun ReaderScreen( navigator: Navigator ) { val context = LocalContext.current as ComponentActivity - val systemBarsColor = MaterialTheme.elevation(20.dp).copy(0.85f) + val systemBarsColor = MaterialTheme.colorScheme.surfaceContainerHighest.copy(0.85f) var loading by remember { mutableStateOf(true) } val listState = rememberLazyListState() @@ -100,7 +99,7 @@ fun ReaderScreen( ): Offset { val velocity = consumed.y - if ((velocity > 70 || velocity < -70) && state.showMenu) { + if ((velocity > 70 || velocity < -70) && state.showMenu && !state.lockMenu) { viewModel.onEvent(ReaderEvent.OnShowHideMenu(context = context)) } @@ -140,7 +139,7 @@ fun ReaderScreen( snapshotFlow { listState.firstVisibleItemIndex to listState.firstVisibleItemScrollOffset }.debounce(500).collectLatest { items -> - if (!loading) { + if (!loading && state.book.text.isNotEmpty() && listState.layoutInfo.totalItemsCount > 0) { val lastVisibleItemIndex = listState.layoutInfo.visibleItemsInfo.last().index val progress = if (items.first > 0) { @@ -386,8 +385,7 @@ fun ReaderScreen( LinearProgressIndicator( modifier = Modifier.fillMaxWidth(0.55f), strokeCap = StrokeCap.Round, - color = MaterialTheme.colorScheme.primary, - backgroundColor = MaterialTheme.elevation(2.dp) + trackColor = MaterialTheme.colorScheme.secondaryContainer.copy(0.7f) ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt index 9ff45a5d..b930042a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt @@ -21,6 +21,7 @@ import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -55,6 +56,13 @@ fun ReaderEndItem( val state by viewModel.state.collectAsState() val context = LocalContext.current as ComponentActivity + val buttonText = remember { + context.getString( + if (state.book.category != Category.ALREADY_READ) R.string.move_to_read + else R.string.back_to_library + ) + } + Column( modifier = Modifier .fillMaxWidth() @@ -133,10 +141,7 @@ fun ReaderEndItem( ) ) { Text( - stringResource( - if (state.book.category != Category.ALREADY_READ) R.string.move_to_read - else R.string.back_to_library - ), + buttonText, style = MaterialTheme.typography.bodyMedium, maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderStartItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderStartItem.kt index 0539f8ec..a4d3862b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderStartItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderStartItem.kt @@ -28,14 +28,12 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.CustomCoverImage import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel -import ua.acclorite.book_story.presentation.ui.elevation /** * Reader start item. Displays at the beginning of the book. @@ -61,16 +59,14 @@ fun ReaderStartItem(viewModel: ReaderViewModel) { .height(135.dp) .width(90.dp) .clip(RoundedCornerShape(10.dp)) - .background(MaterialTheme.elevation()) + .background(MaterialTheme.colorScheme.surfaceContainerLow) ) { if (state.book.coverImage != null) { - AsyncImage( - model = state.book.coverImage!!, - contentDescription = stringResource(id = R.string.cover_image_content_desc), + CustomCoverImage( + uri = state.book.coverImage!!, modifier = Modifier .fillMaxSize() - .clip(RoundedCornerShape(10.dp)), - contentScale = ContentScale.Crop + .clip(RoundedCornerShape(10.dp)) ) } else { Icon( @@ -80,7 +76,7 @@ fun ReaderStartItem(viewModel: ReaderViewModel) { .align(Alignment.Center) .fillMaxWidth(0.7f) .aspectRatio(1f), - tint = MaterialTheme.elevation(12.dp) + tint = MaterialTheme.colorScheme.surfaceContainerHigh ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt index 0babba89..71d75518 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt @@ -4,7 +4,9 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListState @@ -74,35 +76,34 @@ fun ReaderBottomBar( color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.titleLarge ) + Spacer(modifier = Modifier.height(3.dp)) Slider( value = state.book.progress, + enabled = !state.lockMenu, onValueChange = { - viewModel.onEvent(ReaderEvent.OnScroll(listState, it)) - viewModel.onEvent( - ReaderEvent.OnChangeProgress( - progress = it, - navigator = navigator, - firstVisibleItemIndex = listState.firstVisibleItemIndex, - firstVisibleItemOffset = 0, - refreshList = { book -> - libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(book)) - historyViewModel.onEvent(HistoryEvent.OnUpdateBook(book)) - } + if (listState.layoutInfo.totalItemsCount > 0) { + viewModel.onEvent(ReaderEvent.OnScroll(listState, it)) + viewModel.onEvent( + ReaderEvent.OnChangeProgress( + progress = it, + navigator = navigator, + firstVisibleItemIndex = listState.firstVisibleItemIndex, + firstVisibleItemOffset = 0, + refreshList = { book -> + libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(book)) + historyViewModel.onEvent(HistoryEvent.OnUpdateBook(book)) + } + ) ) - ) + } }, colors = SliderDefaults.colors( - activeTrackColor = MaterialTheme.colorScheme.primary, - thumbColor = MaterialTheme.colorScheme.primary, - inactiveTrackColor = MaterialTheme.colorScheme.onPrimaryContainer.copy(0.15f), - disabledActiveTickColor = Color.Transparent, - disabledActiveTrackColor = Color.Transparent, - disabledInactiveTickColor = Color.Transparent, - disabledInactiveTrackColor = Color.Transparent, - disabledThumbColor = Color.Transparent, - activeTickColor = Color.Transparent, - inactiveTickColor = Color.Transparent + inactiveTrackColor = MaterialTheme.colorScheme.secondary.copy(0.15f), + disabledActiveTrackColor = MaterialTheme.colorScheme.primary, + disabledThumbColor = MaterialTheme.colorScheme.primary, + disabledInactiveTrackColor = MaterialTheme.colorScheme.secondary.copy(0.15f), ) ) + Spacer(modifier = Modifier.height(5.dp)) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt index 15c581c6..1a8e6ee8 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt @@ -69,7 +69,7 @@ fun ReaderTopBar( navigationIcon = { CustomIconButton( icon = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = stringResource(id = R.string.go_back_content_desc), + contentDescription = R.string.go_back_content_desc, disableOnClick = true ) { viewModel.onEvent( @@ -99,6 +99,7 @@ fun ReaderTopBar( maxLines = 1, modifier = Modifier .clickable( + enabled = !state.lockMenu, interactionSource = null, indication = null, onClick = { @@ -138,8 +139,9 @@ fun ReaderTopBar( actions = { CustomIconButton( icon = Icons.Default.Settings, - contentDescription = stringResource(id = R.string.open_reader_settings_content_desc), - disableOnClick = false + contentDescription = R.string.open_reader_settings_content_desc, + disableOnClick = false, + enabled = !state.lockMenu ) { viewModel.onEvent(ReaderEvent.OnShowHideSettingsBottomSheet) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt index b4b1d6e1..d76d68c7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt @@ -4,7 +4,7 @@ import androidx.activity.ComponentActivity import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween -import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues @@ -27,6 +27,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext @@ -34,7 +35,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.ChipItem +import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.data.MainEvent @@ -45,14 +46,12 @@ import ua.acclorite.book_story.presentation.screens.settings.components.Checkbox import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle -import ua.acclorite.book_story.presentation.ui.ElevationDefaults -import ua.acclorite.book_story.presentation.ui.elevation /** * Settings bottom sheet. Has General and Colors categories. */ @OptIn( - ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class + ExperimentalMaterial3Api::class ) @Composable fun ReaderSettingsBottomSheet(mainViewModel: MainViewModel, viewModel: ReaderViewModel) { @@ -98,195 +97,199 @@ fun ReaderSettingsBottomSheet(mainViewModel: MainViewModel, viewModel: ReaderVie ) } - ModalBottomSheet( - scrimColor = animatedScrimColor, - dragHandle = {}, - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight(animatedHeight), - onDismissRequest = { - viewModel.onEvent(ReaderEvent.OnShowHideSettingsBottomSheet) - }, - sheetState = rememberModalBottomSheetState(true), - windowInsets = WindowInsets(0, 0, 0, 0), - containerColor = MaterialTheme.elevation(ElevationDefaults.BottomSheet) - ) { - ReaderSettingsBottomSheetTabRow(viewModel = viewModel, pagerState = pagerState) + Box(modifier = Modifier.fillMaxSize()) { + ModalBottomSheet( + scrimColor = animatedScrimColor, + dragHandle = {}, + modifier = Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .fillMaxHeight(animatedHeight), + onDismissRequest = { + viewModel.onEvent(ReaderEvent.OnShowHideSettingsBottomSheet) + }, + sheetState = rememberModalBottomSheetState(true), + windowInsets = WindowInsets(0, 0, 0, 0), + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ) { + ReaderSettingsBottomSheetTabRow(viewModel = viewModel, pagerState = pagerState) - HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize()) { page -> - LazyColumn(Modifier.fillMaxSize()) { - if (page == 0) { - item { - Spacer(modifier = Modifier.height(22.dp)) - } - item { - CategoryTitle( - title = stringResource(id = R.string.font_reader_settings), - color = MaterialTheme.colorScheme.onSurface - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) - } - item { - ChipsWithTitle( - title = stringResource(id = R.string.font_family_option), - chips = Constants.FONTS - .map { - ChipItem( - it.id, - it.fontName.asString(), + HorizontalPager(state = pagerState) { page -> + LazyColumn { + if (page == 0) { + item { + Spacer(modifier = Modifier.height(22.dp)) + } + item { + CategoryTitle( + title = stringResource(id = R.string.font_reader_settings), + color = MaterialTheme.colorScheme.onSurface + ) + } + item { + Spacer(modifier = Modifier.height(8.dp)) + } + item { + ChipsWithTitle( + title = stringResource(id = R.string.font_family_option), + chips = Constants.FONTS + .map { + ButtonItem( + it.id, + it.fontName.asString(), + MaterialTheme.typography.labelLarge.copy( + fontFamily = it.font + ), + it.id == fontFamily.id + ) + }, + onClick = { + mainViewModel.onEvent(MainEvent.OnChangeFontFamily(it.id)) + } + ) + } + item { + ChipsWithTitle( + title = stringResource(id = R.string.font_style_option), + chips = listOf( + ButtonItem( + "normal", + stringResource(id = R.string.font_style_normal), MaterialTheme.typography.labelLarge.copy( - fontFamily = it.font + fontFamily = fontFamily.font, + fontStyle = FontStyle.Normal ), - it.id == fontFamily.id - ) - }, - onClick = { - mainViewModel.onEvent(MainEvent.OnChangeFontFamily(it.id)) - } - ) - } - item { - ChipsWithTitle( - title = stringResource(id = R.string.font_style_option), - chips = listOf( - ChipItem( - "normal", - stringResource(id = R.string.font_style_normal), - MaterialTheme.typography.labelLarge.copy( - fontFamily = fontFamily.font, - fontStyle = FontStyle.Normal + !state.isItalic!! ), - !state.isItalic!! - ), - ChipItem( - "italic", - stringResource(id = R.string.font_style_italic), - MaterialTheme.typography.labelLarge.copy( - fontFamily = fontFamily.font, - fontStyle = FontStyle.Italic + ButtonItem( + "italic", + stringResource(id = R.string.font_style_italic), + MaterialTheme.typography.labelLarge.copy( + fontFamily = fontFamily.font, + fontStyle = FontStyle.Italic + ), + state.isItalic!! ), - state.isItalic!! ), - ), - onClick = { - mainViewModel.onEvent( - MainEvent.OnChangeFontStyle( - when (it.id) { - "italic" -> true - else -> false - } + onClick = { + mainViewModel.onEvent( + MainEvent.OnChangeFontStyle( + when (it.id) { + "italic" -> true + else -> false + } + ) ) - ) - } - ) - } - item { - SliderWithTitle( - value = state.fontSize!! to "pt", - fromValue = 10, - toValue = 35, - title = stringResource(id = R.string.font_size_option), - onValueChange = { + } + ) + } + item { + SliderWithTitle( + value = state.fontSize!! to "pt", + fromValue = 10, + toValue = 35, + title = stringResource(id = R.string.font_size_option), + onValueChange = { + mainViewModel.onEvent( + MainEvent.OnChangeFontSize(it) + ) + } + ) + } + item { + Spacer(modifier = Modifier.height(22.dp)) + } + item { + CategoryTitle( + title = stringResource(id = R.string.text_reader_settings), + color = MaterialTheme.colorScheme.onSurface + ) + } + item { + Spacer(modifier = Modifier.height(8.dp)) + } + item { + SliderWithTitle( + value = state.lineHeight!! to "pt", + fromValue = 1, + toValue = 16, + title = stringResource(id = R.string.line_height_option), + onValueChange = { + mainViewModel.onEvent( + MainEvent.OnChangeLineHeight(it) + ) + } + ) + } + item { + SliderWithTitle( + value = state.paragraphHeight!! to "pt", + fromValue = 0, + toValue = 24, + title = stringResource(id = R.string.paragraph_height_option), + onValueChange = { + mainViewModel.onEvent( + MainEvent.OnChangeParagraphHeight(it) + ) + } + ) + } + item { + CheckboxWithTitle( + selected = state.paragraphIndentation!!, + title = stringResource(id = R.string.paragraph_indentation_option) + ) { mainViewModel.onEvent( - MainEvent.OnChangeFontSize(it) + MainEvent.OnChangeParagraphIndentation(!state.paragraphIndentation!!) ) } - ) + } } - item { - Spacer(modifier = Modifier.height(22.dp)) - } - item { - CategoryTitle( - title = stringResource(id = R.string.text_reader_settings), - color = MaterialTheme.colorScheme.onSurface - ) - } - item { - Spacer(modifier = Modifier.height(8.dp)) - } - item { - SliderWithTitle( - value = state.lineHeight!! to "pt", - fromValue = 1, - toValue = 16, - title = stringResource(id = R.string.line_height_option), - onValueChange = { - mainViewModel.onEvent( - MainEvent.OnChangeLineHeight(it) - ) - } - ) - } - item { - SliderWithTitle( - value = state.paragraphHeight!! to "pt", - fromValue = 0, - toValue = 24, - title = stringResource(id = R.string.paragraph_height_option), - onValueChange = { - mainViewModel.onEvent( - MainEvent.OnChangeParagraphHeight(it) - ) - } - ) - } - item { - CheckboxWithTitle( - selected = state.paragraphIndentation!!, - title = stringResource(id = R.string.paragraph_indentation_option) - ) { - mainViewModel.onEvent( - MainEvent.OnChangeParagraphIndentation(!state.paragraphIndentation!!) + + if (page == 1) { + item { + Spacer(modifier = Modifier.height(14.dp)) + } + item { + ColorPickerWithTitle( + value = Color(state.backgroundColor!!.toULong()), + title = stringResource(id = R.string.background_color_option), + onValueChange = { + mainViewModel.onEvent( + MainEvent.OnChangeBackgroundColor( + it.value.toLong() + ) + ) + } + ) + } + item { + ColorPickerWithTitle( + value = Color(state.fontColor!!.toULong()), + title = stringResource(id = R.string.font_color_option), + onValueChange = { + mainViewModel.onEvent( + MainEvent.OnChangeFontColor( + it.value.toLong() + ) + ) + } ) } } - } - if (page == 1) { item { - Spacer(modifier = Modifier.height(14.dp)) - } - item { - ColorPickerWithTitle( - value = Color(state.backgroundColor!!.toULong()), - title = stringResource(id = R.string.background_color_option), - onValueChange = { - mainViewModel.onEvent( - MainEvent.OnChangeBackgroundColor( - it.value.toLong() - ) - ) - } + Spacer( + modifier = Modifier.height( + 8.dp + navigationBarPadding + ) ) } - item { - ColorPickerWithTitle( - value = Color(state.fontColor!!.toULong()), - title = stringResource(id = R.string.font_color_option), - onValueChange = { - mainViewModel.onEvent( - MainEvent.OnChangeFontColor( - it.value.toLong() - ) - ) - } - ) - } - } - - item { - Spacer( - modifier = Modifier.height( - 8.dp + navigationBarPadding - ) - ) } } } } + } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt index 71818fc6..45a4e7bd 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt @@ -1,22 +1,16 @@ package ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.PrimaryTabRow import androidx.compose.material3.Tab -import androidx.compose.material3.TabRow -import androidx.compose.material3.TabRowDefaults -import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel @@ -24,7 +18,7 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel /** * Settings bottom sheet tab row. It is used to switch between categories. */ -@OptIn(ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun ReaderSettingsBottomSheetTabRow(viewModel: ReaderViewModel, pagerState: PagerState) { val tabItems = listOf( @@ -32,27 +26,11 @@ fun ReaderSettingsBottomSheetTabRow(viewModel: ReaderViewModel, pagerState: Page stringResource(id = R.string.color_tab) ) - TabRow( + PrimaryTabRow( modifier = Modifier .fillMaxWidth(), selectedTabIndex = pagerState.currentPage, - divider = { - Divider(color = MaterialTheme.colorScheme.surfaceVariant) - }, - indicator = { tabPositions -> - TabRowDefaults.Indicator( - Modifier - .tabIndicatorOffset(tabPositions[pagerState.currentPage]) - .padding(horizontal = 64.dp) - .clip( - RoundedCornerShape( - topStartPercent = 100, - topEndPercent = 100 - ) - ), - color = MaterialTheme.colorScheme.primary - ) - } + containerColor = Color.Transparent ) { tabItems.forEachIndexed { index, tabItem -> Tab( @@ -62,7 +40,7 @@ fun ReaderSettingsBottomSheetTabRow(viewModel: ReaderViewModel, pagerState: Page viewModel.onEvent(ReaderEvent.OnScrollToSettingsPage(index, pagerState)) }, selectedContentColor = MaterialTheme.colorScheme.primary, - unselectedContentColor = MaterialTheme.colorScheme.onSurface, + unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant, text = { Text( tabItem, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt index 3fa17f9a..c006f49f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt @@ -1,9 +1,6 @@ -@file:OptIn(ExperimentalFoundationApi::class) - package ua.acclorite.book_story.presentation.screens.reader.data import androidx.activity.ComponentActivity -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.pager.PagerState import ua.acclorite.book_story.domain.model.Book diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderState.kt index 5614fb99..2d86f0b5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderState.kt @@ -9,7 +9,10 @@ import ua.acclorite.book_story.domain.util.UIText data class ReaderState( val book: Book = Constants.EMPTY_BOOK, val errorMessage: UIText? = null, + val showMenu: Boolean = false, + val lockMenu: Boolean = false, + val showSettingsBottomSheet: Boolean = false, val currentPage: Int = 0, ) \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt index 53de02bf..31f1cbda 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt @@ -2,8 +2,8 @@ package ua.acclorite.book_story.presentation.screens.reader.data import android.app.SearchManager import android.content.Intent +import android.util.Log import androidx.activity.ComponentActivity -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.snapshotFlow import androidx.core.view.WindowCompat @@ -22,7 +22,7 @@ import kotlinx.coroutines.launch import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Category -import ua.acclorite.book_story.domain.model.StringWithId +import ua.acclorite.book_story.domain.use_case.GetBooksById import ua.acclorite.book_story.domain.use_case.GetLatestHistory import ua.acclorite.book_story.domain.use_case.GetText import ua.acclorite.book_story.domain.use_case.UpdateBooks @@ -33,12 +33,12 @@ import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject import kotlin.math.roundToInt -@OptIn(ExperimentalFoundationApi::class) @HiltViewModel class ReaderViewModel @Inject constructor( private val updateBooks: UpdateBooks, private val getText: GetText, - private val getLatestHistory: GetLatestHistory + private val getLatestHistory: GetLatestHistory, + private val getBooksById: GetBooksById ) : ViewModel() { private val _state = MutableStateFlow(ReaderState()) @@ -57,21 +57,44 @@ class ReaderViewModel @Inject constructor( is ReaderEvent.OnLoadText -> { viewModelScope.launch(Dispatchers.IO) { - val text = getText.execute(_state.value.book.id!!) + if ( + _state.value.book.text.isEmpty() || + _state.value.book.letters < 1 || + _state.value.book.words < 1 + ) { + val text = getText.execute(_state.value.book.textPath) - if (text.isBlank()) { - event.onTextIsEmpty() + if (text.isEmpty()) { + event.onTextIsEmpty() + } + + val textAsLine = text.joinToString( + separator = "\n", + transform = { + it.line + } + ) + + val letters = textAsLine + .replace("\n", "") + .length + val words = textAsLine + .replace("\n", " ") + .split("\\s+".toRegex()) + .size + + _state.update { + it.copy( + book = it.book.copy( + text = text, + letters = letters, + words = words + ) + ) + } } - val letters = text - .replace("\n", "") - .length - val words = text - .replace("\n", " ") - .split("\\s+".toRegex()) - .size - - val history = _state.value.book.id?.let { + val history = _state.value.book.id.let { getLatestHistory.execute( it ) @@ -80,12 +103,7 @@ class ReaderViewModel @Inject constructor( _state.update { it.copy( book = it.book.copy( - text = text - .split("\n") - .map { line -> StringWithId(line.trim()) }, lastOpened = history?.time, - letters = letters, - words = words ) ) } @@ -114,6 +132,10 @@ class ReaderViewModel @Inject constructor( loaded = true break } catch (e: Exception) { + Log.w( + "READER", + "Couldn't scroll to desired index and offset" + ) delay(100) } } @@ -133,6 +155,10 @@ class ReaderViewModel @Inject constructor( } is ReaderEvent.OnShowHideMenu -> { + if (_state.value.lockMenu) { + return + } + val shouldShow = event.show ?: !_state.value.showMenu val insetsController = WindowCompat.getInsetsController( @@ -160,42 +186,50 @@ class ReaderViewModel @Inject constructor( is ReaderEvent.OnGoBack -> { viewModelScope.launch { + _state.update { + it.copy( + lockMenu = true + ) + } + val insetsController = WindowCompat.getInsetsController( event.context.window, event.context.window.decorView ) - val firstVisibleItemIndex = event.listState.firstVisibleItemIndex - val firstVisibleItemOffset = event.listState.firstVisibleItemScrollOffset - val lastVisibleItemIndex = event.listState.layoutInfo - .visibleItemsInfo.last().index + if (event.listState.layoutInfo.totalItemsCount > 0) { + val firstVisibleItemIndex = event.listState.firstVisibleItemIndex + val firstVisibleItemOffset = event.listState.firstVisibleItemScrollOffset + val lastVisibleItemIndex = event.listState.layoutInfo + .visibleItemsInfo.last().index - val progress = if (firstVisibleItemIndex > 0) { - if (lastVisibleItemIndex >= (event.listState.layoutInfo.totalItemsCount - 1)) { - 1f + val progress = if (firstVisibleItemIndex > 0) { + if (lastVisibleItemIndex >= (event.listState.layoutInfo.totalItemsCount - 1)) { + 1f + } else { + (firstVisibleItemIndex.toFloat() / (_state.value.book.text.lastIndex) + .toFloat()) + } } else { - (firstVisibleItemIndex.toFloat() / (_state.value.book.text.lastIndex) - .toFloat()) + 0f } - } else { - 0f - } - _state.update { - it.copy( - book = it.book.copy( - progress = progress, - scrollIndex = firstVisibleItemIndex, - scrollOffset = firstVisibleItemOffset + _state.update { + it.copy( + book = it.book.copy( + progress = progress, + scrollIndex = firstVisibleItemIndex, + scrollOffset = firstVisibleItemOffset + ) ) - ) + } } updateBooks.execute( listOf(_state.value.book) ) event.navigator.putArgument( - Argument("book", _state.value.book) + Argument("book", _state.value.book.id) ) event.refreshList(_state.value.book) @@ -232,7 +266,7 @@ class ReaderViewModel @Inject constructor( event.navigator.putArgument( Argument( "book", - _state.value.book + _state.value.book.id ) ) event.refreshList(_state.value.book) @@ -355,9 +389,16 @@ class ReaderViewModel @Inject constructor( onLoaded: () -> Unit ) { viewModelScope.launch(Dispatchers.IO) { - val book = navigator.retrieveArgument("book") as? Book + val bookId = navigator.retrieveArgument("book") as? Int - if (book == null) { + if (bookId == null) { + navigator.navigateBack() + return@launch + } + + val book = getBooksById.execute(listOf(bookId)) + + if (book.isEmpty()) { navigator.navigateBack() return@launch } @@ -367,7 +408,7 @@ class ReaderViewModel @Inject constructor( } _state.update { - ReaderState(book = book) + ReaderState(book = book.first()) } onEvent( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt index 5fbb86a7..671eed99 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt @@ -29,7 +29,6 @@ import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryItem -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -60,7 +59,7 @@ fun SettingsScreen( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation() + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer ) ) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ChipsWithTitle.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ChipsWithTitle.kt index 76516e72..26bda740 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ChipsWithTitle.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ChipsWithTitle.kt @@ -1,6 +1,5 @@ package ua.acclorite.book_story.presentation.screens.settings.components -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -9,30 +8,26 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.ChipDefaults -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.FilterChip -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.FilterChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import ua.acclorite.book_story.domain.model.ChipItem +import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.presentation.components.CategoryTitle /** - * Chips with title. Use list of [ChipItem]s to display chips. + * Chips with title. Use list of [ButtonItem]s to display chips. */ -@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class) @Composable fun ChipsWithTitle( title: String, - chips: List, + chips: List, horizontalPadding: Dp = 18.dp, verticalPadding: Dp = 8.dp, - onClick: (ChipItem) -> Unit + onClick: (ButtonItem) -> Unit ) { Column( Modifier @@ -50,29 +45,15 @@ fun ChipsWithTitle( FilterChip( modifier = Modifier.height(36.dp), selected = item.selected, - enabled = !item.selected, - shape = MaterialTheme.shapes.small, - border = if (!item.selected) BorderStroke( - 1.dp, - MaterialTheme.colorScheme.outline - ) else null, - colors = ChipDefaults.filterChipColors( - backgroundColor = Color.Transparent, - disabledBackgroundColor = MaterialTheme.colorScheme.secondaryContainer - ), + label = { + Text( + item.title, + style = item.textStyle, + maxLines = 1 + ) + }, onClick = { onClick(item) }, - ) { - Text( - item.title, - style = item.textStyle, - color = if (item.selected) { - MaterialTheme.colorScheme.onSecondaryContainer - } else { - MaterialTheme.colorScheme.onSurfaceVariant - }, - maxLines = 1 - ) - } + ) } }, ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ColorPickerWithTitle.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ColorPickerWithTitle.kt index c48b675d..720d009e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ColorPickerWithTitle.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/ColorPickerWithTitle.kt @@ -9,8 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material.Icon -import androidx.compose.material.IconButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History import androidx.compose.material3.MaterialTheme @@ -27,6 +25,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.components.CategoryTitle +import ua.acclorite.book_story.presentation.components.CustomIconButton /** * Color picker with title. @@ -49,8 +48,7 @@ fun ColorPickerWithTitle( ) { CategoryTitle( title = title, - padding = 0.dp, -// color = MaterialTheme.colorScheme.onSurface + padding = 0.dp ) Spacer(modifier = Modifier.height(8.dp)) RevertibleSlider( @@ -111,22 +109,18 @@ private fun RevertibleSlider( horizontalPadding = 0.dp, verticalPadding = 0.dp ) - Box(modifier = Modifier.weight(0.15f)) { - IconButton( - modifier = Modifier.align(Alignment.CenterEnd), + Box(modifier = Modifier.weight(0.15f), contentAlignment = Alignment.CenterEnd) { + CustomIconButton( + modifier = Modifier.size(28.dp), + icon = Icons.Default.History, + contentDescription = R.string.revert_content_desc, + disableOnClick = false, enabled = initialValue != value.first, - onClick = { onValueChange(initialValue) } + color = if (initialValue == value.first) MaterialTheme.colorScheme.onSurfaceVariant + else MaterialTheme.colorScheme.onSurface ) { - Icon( - imageVector = Icons.Default.History, - contentDescription = stringResource(id = R.string.revert_content_desc), - modifier = Modifier - .size(28.dp), - tint = if (initialValue == value.first) MaterialTheme.colorScheme.onSurfaceVariant - else MaterialTheme.colorScheme.onSurface - ) + onValueChange(initialValue) } - } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SegmentedButtonWithTitle.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SegmentedButtonWithTitle.kt new file mode 100644 index 00000000..e89ae291 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SegmentedButtonWithTitle.kt @@ -0,0 +1,86 @@ +package ua.acclorite.book_story.presentation.screens.settings.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.CategoryTitle + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SegmentedButtonWithTitle( + title: String, + buttons: List, + enabled: Boolean, + horizontalPadding: Dp = 18.dp, + verticalPadding: Dp = 8.dp, + onClick: (ButtonItem) -> Unit +) { + val colors = SegmentedButtonDefaults.colors() + + Column( + Modifier + .fillMaxWidth() + .padding(horizontal = horizontalPadding, vertical = verticalPadding) + ) { + CategoryTitle(title = title, padding = 0.dp) + + Spacer(modifier = Modifier.height(8.dp)) + + SingleChoiceSegmentedButtonRow { + buttons.forEachIndexed { index, buttonItem -> + SegmentedButton( + enabled = enabled, + selected = buttonItem.selected, + onClick = { onClick(buttonItem) }, + shape = when (index) { + buttons.lastIndex -> RoundedCornerShape( + topEndPercent = 100, + bottomEndPercent = 100 + ) + + 0 -> RoundedCornerShape( + topStartPercent = 100, + bottomStartPercent = 100 + ) + + else -> RoundedCornerShape(0) + }, + colors = SegmentedButtonDefaults.colors( + disabledInactiveBorderColor = colors.disabledActiveBorderColor, + disabledInactiveContentColor = colors.disabledActiveContentColor, + disabledActiveContainerColor = colors.activeContainerColor.copy(0.12f), + ), + label = { + Text( + text = buttonItem.title, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + ) + } + } + } +} + + + + + + + + diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SliderWithTitle.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SliderWithTitle.kt index 63515b35..665ad0bd 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SliderWithTitle.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/components/SliderWithTitle.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider +import androidx.compose.material3.SliderDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -54,7 +55,11 @@ fun SliderWithTitle( onValueChange = { onValueChange(it.roundToInt()) }, - steps = toValue - fromValue + steps = toValue - fromValue, + colors = SliderDefaults.colors( + activeTickColor = MaterialTheme.colorScheme.onPrimary, + inactiveTickColor = MaterialTheme.colorScheme.onSurfaceVariant, + ) ) } } @@ -90,7 +95,11 @@ fun SliderWithTitle( value = value.first, onValueChange = { onValueChange(it) - } + }, + colors = SliderDefaults.colors( + activeTickColor = MaterialTheme.colorScheme.onPrimary, + inactiveTickColor = MaterialTheme.colorScheme.onSurfaceVariant, + ) ) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt index 105b2d8e..fffba2d1 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt @@ -24,17 +24,18 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.ChipItem +import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.Navigator -import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle +import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher.AppearanceSettingsThemeSwitcher import ua.acclorite.book_story.presentation.ui.DarkTheme -import ua.acclorite.book_story.presentation.ui.elevation +import ua.acclorite.book_story.presentation.ui.Theme +import ua.acclorite.book_story.presentation.ui.ThemeContrast @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -68,7 +69,7 @@ fun AppearanceSettings( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation() + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer ) ) } @@ -93,10 +94,11 @@ fun AppearanceSettings( } item { - ChipsWithTitle( + SegmentedButtonWithTitle( title = stringResource(id = R.string.dark_theme_option), - chips = DarkTheme.entries.map { - ChipItem( + enabled = true, + buttons = DarkTheme.entries.map { + ButtonItem( it.toString(), when (it) { DarkTheme.OFF -> stringResource(id = R.string.dark_theme_off) @@ -106,7 +108,7 @@ fun AppearanceSettings( MaterialTheme.typography.labelLarge, it == state.darkTheme ) - }, + } ) { mainViewModel.onEvent( MainEvent.OnChangeDarkTheme( @@ -116,6 +118,31 @@ fun AppearanceSettings( } } + item { + SegmentedButtonWithTitle( + title = stringResource(id = R.string.theme_contrast_option), + enabled = state.theme != Theme.DYNAMIC, + buttons = ThemeContrast.entries.map { + ButtonItem( + it.toString(), + when (it) { + ThemeContrast.STANDARD -> stringResource(id = R.string.theme_contrast_standard) + ThemeContrast.MEDIUM -> stringResource(id = R.string.theme_contrast_medium) + ThemeContrast.HIGH -> stringResource(id = R.string.theme_contrast_high) + }, + MaterialTheme.typography.labelLarge, + it == state.themeContrast + ) + } + ) { + mainViewModel.onEvent( + MainEvent.OnChangeThemeContrast( + it.id + ) + ) + } + } + item { AppearanceSettingsThemeSwitcher(mainViewModel = mainViewModel) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcher.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcher.kt index 5ee744bf..2deba751 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcher.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcher.kt @@ -31,7 +31,6 @@ fun AppearanceSettingsThemeSwitcher( mainViewModel: MainViewModel ) { val state by mainViewModel.state.collectAsState() - val themes = remember { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC } @@ -48,23 +47,25 @@ fun AppearanceSettingsThemeSwitcher( Spacer(modifier = Modifier.height(10.dp)) LazyRow( Modifier - .fillMaxWidth() + .fillMaxWidth(), ) { itemsIndexed(themes) { index, themeEntry -> - if (index == 0) + if (index == 0) { Spacer(modifier = Modifier.width(18.dp)) + } else { + Spacer(modifier = Modifier.width(8.dp)) + } AppearanceSettingsThemeSwitcherItem( theme = themeEntry, darkTheme = state.darkTheme!!.isDark(), + themeContrast = state.themeContrast!!, selected = state.theme == themeEntry.first ) { mainViewModel.onEvent(MainEvent.OnChangeTheme(themeEntry.first.toString())) } - if (index != Theme.entries.lastIndex) { - Spacer(modifier = Modifier.width(8.dp)) - } else { + if (index == themes.lastIndex) { Spacer(modifier = Modifier.width(18.dp)) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcherItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcherItem.kt index 686ce1ab..52cea293 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcherItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/theme_switcher/AppearanceSettingsThemeSwitcherItem.kt @@ -1,5 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -19,21 +24,19 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Text -import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.presentation.ui.Theme -import ua.acclorite.book_story.presentation.ui.colorScheme +import ua.acclorite.book_story.presentation.ui.ThemeContrast +import ua.acclorite.book_story.presentation.ui.animatedColorScheme /** * Theme switcher item. @@ -42,10 +45,11 @@ import ua.acclorite.book_story.presentation.ui.colorScheme fun AppearanceSettingsThemeSwitcherItem( theme: Pair, darkTheme: Boolean, + themeContrast: ThemeContrast, selected: Boolean, onClick: () -> Unit ) { - val colorScheme = colorScheme(theme.first, darkTheme) + val colorScheme = animatedColorScheme(theme.first, darkTheme, themeContrast) Column( modifier = Modifier.fillMaxWidth(), @@ -83,15 +87,23 @@ fun AppearanceSettingsThemeSwitcherItem( .background(colorScheme.onSurface) ) Spacer(modifier = Modifier.width(8.dp)) - Icon( - imageVector = Icons.Default.CheckCircle, - contentDescription = stringResource(id = R.string.selected_content_desc), - modifier = Modifier - .size(26.dp), - tint = - if (selected) colorScheme.primary - else Color.Transparent - ) + + AnimatedVisibility( + visible = selected, + enter = scaleIn(tween(300), initialScale = 0.5f) + + fadeIn(tween(300)), + exit = fadeOut(tween(100)) + ) { + Icon( + imageVector = Icons.Default.CheckCircle, + contentDescription = stringResource(id = R.string.selected_content_desc), + modifier = Modifier + .size(26.dp), + tint = colorScheme.primary + ) + } + + Box(modifier = Modifier.height(26.dp)) } Spacer(modifier = Modifier.height(8.dp)) Box( @@ -101,9 +113,7 @@ fun AppearanceSettingsThemeSwitcherItem( .width(70.dp) .clip(RoundedCornerShape(14.dp)) .background( - colorScheme.surfaceColorAtElevation( - NavigationBarDefaults.Elevation - ) + colorScheme.surfaceContainer ) ) Spacer(modifier = Modifier.height(40.dp)) @@ -112,9 +122,7 @@ fun AppearanceSettingsThemeSwitcherItem( .width(130.dp) .height(40.dp) .background( - colorScheme.surfaceColorAtElevation( - NavigationBarDefaults.Elevation - ) + colorScheme.surfaceContainer ), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically @@ -141,7 +149,7 @@ fun AppearanceSettingsThemeSwitcherItem( color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.labelLarge, overflow = TextOverflow.Ellipsis, - maxLines = 1 + maxLines = 2 ) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt index 743cc998..f91724e4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt @@ -23,14 +23,13 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.ChipItem +import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -64,7 +63,7 @@ fun GeneralSettings( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation() + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer ) ) } @@ -82,7 +81,7 @@ fun GeneralSettings( ChipsWithTitle( title = stringResource(id = R.string.language_option), chips = Constants.LANGUAGES.sortedBy { it.second }.map { - ChipItem( + ButtonItem( it.first, it.second, MaterialTheme.typography.labelLarge, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt index ee379b6e..937e3116 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.ChipItem +import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.GoBackButton @@ -35,7 +35,6 @@ import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.screens.settings.components.CheckboxWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle -import ua.acclorite.book_story.presentation.ui.elevation @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -74,7 +73,7 @@ fun ReaderSettings( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.elevation() + scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer ) ) } @@ -102,7 +101,7 @@ fun ReaderSettings( title = stringResource(id = R.string.font_family_option), chips = Constants.FONTS .map { - ChipItem( + ButtonItem( it.id, it.fontName.asString(), MaterialTheme.typography.labelLarge.copy( @@ -120,7 +119,7 @@ fun ReaderSettings( ChipsWithTitle( title = stringResource(id = R.string.font_style_option), chips = listOf( - ChipItem( + ButtonItem( "normal", stringResource(id = R.string.font_style_normal), MaterialTheme.typography.labelLarge.copy( @@ -129,7 +128,7 @@ fun ReaderSettings( ), !state.isItalic!! ), - ChipItem( + ButtonItem( "italic", stringResource(id = R.string.font_style_italic), MaterialTheme.typography.labelLarge.copy( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Color.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/Color.kt index a6624616..b2030d0e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Color.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/Color.kt @@ -5,6 +5,7 @@ import androidx.compose.material3.ColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.ui.platform.LocalContext import ua.acclorite.book_story.presentation.ui.theme.aquaTheme import ua.acclorite.book_story.presentation.ui.theme.blueTheme @@ -14,6 +15,7 @@ import ua.acclorite.book_story.presentation.ui.theme.purpleTheme import ua.acclorite.book_story.presentation.ui.theme.redTheme import ua.acclorite.book_story.presentation.ui.theme.yellowTheme +@Immutable enum class Theme { DYNAMIC, BLUE, @@ -41,7 +43,7 @@ fun String.toTheme(): Theme { */ @SuppressLint("NewApi") @Composable -fun colorScheme(theme: Theme, darkTheme: Boolean): ColorScheme { +fun colorScheme(theme: Theme, darkTheme: Boolean, themeContrast: ThemeContrast): ColorScheme { when (theme) { Theme.DYNAMIC -> { /* Dynamic Theme */ @@ -53,37 +55,37 @@ fun colorScheme(theme: Theme, darkTheme: Boolean): ColorScheme { Theme.BLUE -> { /* Blue Theme */ - return blueTheme(isDark = darkTheme) + return blueTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.PURPLE -> { /* Purple Theme */ - return purpleTheme(isDark = darkTheme) + return purpleTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.GREEN -> { /* Green Theme */ - return greenTheme(isDark = darkTheme) + return greenTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.PINK -> { /* Pink Theme */ - return pinkTheme(isDark = darkTheme) + return pinkTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.YELLOW -> { /* Yellow Theme */ - return yellowTheme(isDark = darkTheme) + return yellowTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.RED -> { /* Red Theme */ - return redTheme(isDark = darkTheme) + return redTheme(isDark = darkTheme, themeContrast = themeContrast) } Theme.AQUA -> { /* Aqua Theme */ - return aquaTheme(isDark = darkTheme) + return aquaTheme(isDark = darkTheme, themeContrast = themeContrast) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Elevation.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/Elevation.kt deleted file mode 100644 index beca6587..00000000 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Elevation.kt +++ /dev/null @@ -1,8 +0,0 @@ -package ua.acclorite.book_story.presentation.ui - -import androidx.compose.ui.unit.dp - -object ElevationDefaults { - val Dialog = 6.dp - val BottomSheet = 1.dp -} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Theme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/Theme.kt index 3f7075ff..5997f87d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/Theme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/Theme.kt @@ -2,19 +2,28 @@ package ua.acclorite.book_story.presentation.ui import android.app.Activity import android.os.Build +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.tween import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Shapes -import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.unit.Dp import androidx.core.view.WindowCompat +@Immutable +enum class ThemeContrast { + STANDARD, + MEDIUM, + HIGH +} + +@Immutable enum class DarkTheme { FOLLOW_SYSTEM, OFF, @@ -25,6 +34,10 @@ fun String.toDarkTheme(): DarkTheme { return DarkTheme.valueOf(this) } +fun String.toThemeContrast(): ThemeContrast { + return ThemeContrast.valueOf(this) +} + @Composable fun DarkTheme.isDark(): Boolean { return when (this) { @@ -38,6 +51,7 @@ fun DarkTheme.isDark(): Boolean { fun BooksHistoryResurrectionTheme( theme: Theme, isDark: Boolean, + themeContrast: ThemeContrast, content: @Composable () -> Unit ) { val view = LocalView.current @@ -58,12 +72,16 @@ fun BooksHistoryResurrectionTheme( } } + val colorScheme = colorScheme( + theme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) theme + else if (theme != Theme.DYNAMIC) theme else Theme.BLUE, + darkTheme = isDark, + themeContrast = themeContrast + ) + val animatedColorScheme = animateColorScheme(targetColorScheme = colorScheme) + MaterialTheme( - colorScheme = colorScheme( - theme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) theme - else if (theme != Theme.DYNAMIC) theme else Theme.BLUE, - darkTheme = isDark - ), + colorScheme = animatedColorScheme, shapes = Shapes(), typography = Typography, content = content @@ -71,5 +89,71 @@ fun BooksHistoryResurrectionTheme( } @Composable -fun MaterialTheme.elevation(elevation: Dp = NavigationBarDefaults.Elevation): Color = - colorScheme.surfaceColorAtElevation(elevation) \ No newline at end of file +private fun animateColor(targetColor: Color): Color { + return animateColorAsState( + targetValue = targetColor, + animationSpec = tween(300), + label = "" + ).value +} + +@Composable +private fun animateColorScheme(targetColorScheme: ColorScheme): ColorScheme { + return ColorScheme( + primary = animateColor(targetColor = targetColorScheme.primary), + onPrimary = animateColor(targetColor = targetColorScheme.onPrimary), + primaryContainer = animateColor(targetColor = targetColorScheme.primaryContainer), + onPrimaryContainer = animateColor(targetColor = targetColorScheme.onPrimaryContainer), + secondary = animateColor(targetColor = targetColorScheme.secondary), + onSecondary = animateColor(targetColor = targetColorScheme.onSecondary), + secondaryContainer = animateColor(targetColor = targetColorScheme.secondaryContainer), + onSecondaryContainer = animateColor(targetColor = targetColorScheme.onSecondaryContainer), + tertiary = animateColor(targetColor = targetColorScheme.tertiary), + onTertiary = animateColor(targetColor = targetColorScheme.onTertiary), + tertiaryContainer = animateColor(targetColor = targetColorScheme.tertiaryContainer), + onTertiaryContainer = animateColor(targetColor = targetColorScheme.onTertiaryContainer), + error = animateColor(targetColor = targetColorScheme.error), + errorContainer = animateColor(targetColor = targetColorScheme.errorContainer), + onError = animateColor(targetColor = targetColorScheme.onError), + onErrorContainer = animateColor(targetColor = targetColorScheme.onErrorContainer), + background = animateColor(targetColor = targetColorScheme.background), + onBackground = animateColor(targetColor = targetColorScheme.onBackground), + surface = animateColor(targetColor = targetColorScheme.surface), + onSurface = animateColor(targetColor = targetColorScheme.onSurface), + surfaceVariant = animateColor(targetColor = targetColorScheme.surfaceVariant), + onSurfaceVariant = animateColor(targetColor = targetColorScheme.onSurfaceVariant), + outline = animateColor(targetColor = targetColorScheme.outline), + inverseOnSurface = animateColor(targetColor = targetColorScheme.inverseOnSurface), + inverseSurface = animateColor(targetColor = targetColorScheme.inverseSurface), + inversePrimary = animateColor(targetColor = targetColorScheme.inversePrimary), + surfaceTint = animateColor(targetColor = targetColorScheme.surfaceTint), + outlineVariant = animateColor(targetColor = targetColorScheme.outlineVariant), + scrim = animateColor(targetColor = targetColorScheme.scrim), + surfaceBright = animateColor(targetColor = targetColorScheme.surfaceBright), + surfaceDim = animateColor(targetColor = targetColorScheme.surfaceDim), + surfaceContainer = animateColor(targetColor = targetColorScheme.surfaceContainer), + surfaceContainerHigh = animateColor(targetColor = targetColorScheme.surfaceContainerHigh), + surfaceContainerHighest = animateColor(targetColor = targetColorScheme.surfaceContainerHighest), + surfaceContainerLow = animateColor(targetColor = targetColorScheme.surfaceContainerLow), + surfaceContainerLowest = animateColor(targetColor = targetColorScheme.surfaceContainerLowest), + ) +} + +@Composable +fun animatedColorScheme( + theme: Theme, + isDark: Boolean, + themeContrast: ThemeContrast +): ColorScheme { + val colorScheme = colorScheme( + theme = theme, + darkTheme = isDark, + themeContrast = themeContrast + ) + + return animateColorScheme(targetColorScheme = colorScheme) +} + + + + diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/AquaTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/AquaTheme.kt index 290a8fcc..f4506a68 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/AquaTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/AquaTheme.kt @@ -5,132 +5,472 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF006876) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFA1EFFF) -private val md_theme_light_onPrimaryContainer = Color(0xFF001F25) -private val md_theme_light_secondary = Color(0xFF4A6268) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFCDE7ED) -private val md_theme_light_onSecondaryContainer = Color(0xFF051F23) -private val md_theme_light_tertiary = Color(0xFF545D7E) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFDBE1FF) -private val md_theme_light_onTertiaryContainer = Color(0xFF101A37) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFBFCFD) -private val md_theme_light_onBackground = Color(0xFF191C1D) -private val md_theme_light_surface = Color(0xFFFBFCFD) -private val md_theme_light_onSurface = Color(0xFF191C1D) -private val md_theme_light_surfaceVariant = Color(0xFFDBE4E6) -private val md_theme_light_onSurfaceVariant = Color(0xFF3F484A) -private val md_theme_light_outline = Color(0xFF6F797B) -private val md_theme_light_inverseOnSurface = Color(0xFFEFF1F2) -private val md_theme_light_inverseSurface = Color(0xFF2E3132) -private val md_theme_light_inversePrimary = Color(0xFF51D7EF) -private val md_theme_light_surfaceTint = Color(0xFF006876) -private val md_theme_light_outlineVariant = Color(0xFFBFC8CA) -private val md_theme_light_scrim = Color(0xFF000000) -private val md_theme_dark_primary = Color(0xFF51D7EF) -private val md_theme_dark_onPrimary = Color(0xFF00363E) -private val md_theme_dark_primaryContainer = Color(0xFF004E59) -private val md_theme_dark_onPrimaryContainer = Color(0xFFA1EFFF) -private val md_theme_dark_secondary = Color(0xFFB1CBD1) -private val md_theme_dark_onSecondary = Color(0xFF1C3439) -private val md_theme_dark_secondaryContainer = Color(0xFF334A50) -private val md_theme_dark_onSecondaryContainer = Color(0xFFCDE7ED) -private val md_theme_dark_tertiary = Color(0xFFBCC5EB) -private val md_theme_dark_onTertiary = Color(0xFF262F4D) -private val md_theme_dark_tertiaryContainer = Color(0xFF3C4665) -private val md_theme_dark_onTertiaryContainer = Color(0xFFDBE1FF) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF191C1D) -private val md_theme_dark_onBackground = Color(0xFFE1E3E3) -private val md_theme_dark_surface = Color(0xFF191C1D) -private val md_theme_dark_onSurface = Color(0xFFE1E3E3) -private val md_theme_dark_surfaceVariant = Color(0xFF3F484A) -private val md_theme_dark_onSurfaceVariant = Color(0xFFBFC8CA) -private val md_theme_dark_outline = Color(0xFF899295) -private val md_theme_dark_inverseOnSurface = Color(0xFF191C1D) -private val md_theme_dark_inverseSurface = Color(0xFFE1E3E3) -private val md_theme_dark_inversePrimary = Color(0xFF006876) -private val md_theme_dark_surfaceTint = Color(0xFF51D7EF) -private val md_theme_dark_outlineVariant = Color(0xFF3F484A) -private val md_theme_dark_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF116682) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFBDE9FF) +private val onPrimaryContainerLight = Color(0xFF001F2A) +private val secondaryLight = Color(0xFF4D616C) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFD0E6F2) +private val onSecondaryContainerLight = Color(0xFF081E27) +private val tertiaryLight = Color(0xFF5D5B7D) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFE3DFFF) +private val onTertiaryContainerLight = Color(0xFF191836) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFF6FAFD) +private val onBackgroundLight = Color(0xFF171C1F) +private val surfaceLight = Color(0xFFF6FAFD) +private val onSurfaceLight = Color(0xFF171C1F) +private val surfaceVariantLight = Color(0xFFDCE4E9) +private val onSurfaceVariantLight = Color(0xFF40484C) +private val outlineLight = Color(0xFF70787D) +private val outlineVariantLight = Color(0xFFC0C8CD) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF2C3134) +private val inverseOnSurfaceLight = Color(0xFFEDF1F5) +private val inversePrimaryLight = Color(0xFF8BD0EF) +private val surfaceDimLight = Color(0xFFD6DBDE) +private val surfaceBrightLight = Color(0xFFF6FAFD) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFF0F4F8) +private val surfaceContainerLight = Color(0xFFEAEEF2) +private val surfaceContainerHighLight = Color(0xFFE4E9EC) +private val surfaceContainerHighestLight = Color(0xFFDFE3E7) + +private val primaryLightMediumContrast = Color(0xFF00495F) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFF337D99) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF31464F) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF637882) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF413F60) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF737195) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFF6FAFD) +private val onBackgroundLightMediumContrast = Color(0xFF171C1F) +private val surfaceLightMediumContrast = Color(0xFFF6FAFD) +private val onSurfaceLightMediumContrast = Color(0xFF171C1F) +private val surfaceVariantLightMediumContrast = Color(0xFFDCE4E9) +private val onSurfaceVariantLightMediumContrast = Color(0xFF3C4448) +private val outlineLightMediumContrast = Color(0xFF586065) +private val outlineVariantLightMediumContrast = Color(0xFF747C80) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF2C3134) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFEDF1F5) +private val inversePrimaryLightMediumContrast = Color(0xFF8BD0EF) +private val surfaceDimLightMediumContrast = Color(0xFFD6DBDE) +private val surfaceBrightLightMediumContrast = Color(0xFFF6FAFD) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFF0F4F8) +private val surfaceContainerLightMediumContrast = Color(0xFFEAEEF2) +private val surfaceContainerHighLightMediumContrast = Color(0xFFE4E9EC) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFDFE3E7) + +private val primaryLightHighContrast = Color(0xFF002633) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF00495F) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF10252E) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF31464F) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF201F3D) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF413F60) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFF6FAFD) +private val onBackgroundLightHighContrast = Color(0xFF171C1F) +private val surfaceLightHighContrast = Color(0xFFF6FAFD) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFDCE4E9) +private val onSurfaceVariantLightHighContrast = Color(0xFF1D2529) +private val outlineLightHighContrast = Color(0xFF3C4448) +private val outlineVariantLightHighContrast = Color(0xFF3C4448) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF2C3134) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFD5F0FF) +private val surfaceDimLightHighContrast = Color(0xFFD6DBDE) +private val surfaceBrightLightHighContrast = Color(0xFFF6FAFD) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFF0F4F8) +private val surfaceContainerLightHighContrast = Color(0xFFEAEEF2) +private val surfaceContainerHighLightHighContrast = Color(0xFFE4E9EC) +private val surfaceContainerHighestLightHighContrast = Color(0xFFDFE3E7) + + +private val primaryDark = Color(0xFF8BD0EF) +private val onPrimaryDark = Color(0xFF003546) +private val primaryContainerDark = Color(0xFF004D64) +private val onPrimaryContainerDark = Color(0xFFBDE9FF) +private val secondaryDark = Color(0xFFB4CAD6) +private val onSecondaryDark = Color(0xFF1F333C) +private val secondaryContainerDark = Color(0xFF354A53) +private val onSecondaryContainerDark = Color(0xFFD0E6F2) +private val tertiaryDark = Color(0xFFC6C2EA) +private val onTertiaryDark = Color(0xFF2E2D4D) +private val tertiaryContainerDark = Color(0xFF454364) +private val onTertiaryContainerDark = Color(0xFFE3DFFF) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF0F1417) +private val onBackgroundDark = Color(0xFFDFE3E7) +private val surfaceDark = Color(0xFF0F1417) +private val onSurfaceDark = Color(0xFFDFE3E7) +private val surfaceVariantDark = Color(0xFF40484C) +private val onSurfaceVariantDark = Color(0xFFC0C8CD) +private val outlineDark = Color(0xFF8A9297) +private val outlineVariantDark = Color(0xFF40484C) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFDFE3E7) +private val inverseOnSurfaceDark = Color(0xFF2C3134) +private val inversePrimaryDark = Color(0xFF116682) +private val surfaceDimDark = Color(0xFF0F1417) +private val surfaceBrightDark = Color(0xFF353A3D) +private val surfaceContainerLowestDark = Color(0xFF0A0F11) +private val surfaceContainerLowDark = Color(0xFF171C1F) +private val surfaceContainerDark = Color(0xFF1B2023) +private val surfaceContainerHighDark = Color(0xFF262B2D) +private val surfaceContainerHighestDark = Color(0xFF303538) + +private val primaryDarkMediumContrast = Color(0xFF8FD4F4) +private val onPrimaryDarkMediumContrast = Color(0xFF001923) +private val primaryContainerDarkMediumContrast = Color(0xFF5399B7) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFB8CEDA) +private val onSecondaryDarkMediumContrast = Color(0xFF031921) +private val secondaryContainerDarkMediumContrast = Color(0xFF7F949F) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFCAC7EF) +private val onTertiaryDarkMediumContrast = Color(0xFF141231) +private val tertiaryContainerDarkMediumContrast = Color(0xFF908DB2) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF0F1417) +private val onBackgroundDarkMediumContrast = Color(0xFFDFE3E7) +private val surfaceDarkMediumContrast = Color(0xFF0F1417) +private val onSurfaceDarkMediumContrast = Color(0xFFF7FBFF) +private val surfaceVariantDarkMediumContrast = Color(0xFF40484C) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFC4CCD1) +private val outlineDarkMediumContrast = Color(0xFF9CA4A9) +private val outlineVariantDarkMediumContrast = Color(0xFF7C8489) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFDFE3E7) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF262B2E) +private val inversePrimaryDarkMediumContrast = Color(0xFF004E66) +private val surfaceDimDarkMediumContrast = Color(0xFF0F1417) +private val surfaceBrightDarkMediumContrast = Color(0xFF353A3D) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF0A0F11) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF171C1F) +private val surfaceContainerDarkMediumContrast = Color(0xFF1B2023) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF262B2D) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF303538) + +private val primaryDarkHighContrast = Color(0xFFF7FBFF) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFF8FD4F4) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFF7FBFF) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFB8CEDA) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFFEF9FF) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFCAC7EF) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF0F1417) +private val onBackgroundDarkHighContrast = Color(0xFFDFE3E7) +private val surfaceDarkHighContrast = Color(0xFF0F1417) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF40484C) +private val onSurfaceVariantDarkHighContrast = Color(0xFFF7FBFF) +private val outlineDarkHighContrast = Color(0xFFC4CCD1) +private val outlineVariantDarkHighContrast = Color(0xFFC4CCD1) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFDFE3E7) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF002E3D) +private val surfaceDimDarkHighContrast = Color(0xFF0F1417) +private val surfaceBrightDarkHighContrast = Color(0xFF353A3D) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF0A0F11) +private val surfaceContainerLowDarkHighContrast = Color(0xFF171C1F) +private val surfaceContainerDarkHighContrast = Color(0xFF1B2023) +private val surfaceContainerHighDarkHighContrast = Color(0xFF262B2D) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF303538) + @Composable -fun aquaTheme(isDark: Boolean): ColorScheme { +fun aquaTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlueTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlueTheme.kt index f1966ac3..21b4ff42 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlueTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/BlueTheme.kt @@ -5,133 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF005DB8) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFD6E3FF) -private val md_theme_light_onPrimaryContainer = Color(0xFF001B3E) -private val md_theme_light_secondary = Color(0xFF565F71) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFDAE2F9) -private val md_theme_light_onSecondaryContainer = Color(0xFF131C2B) -private val md_theme_light_tertiary = Color(0xFF6F5575) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFF9D8FD) -private val md_theme_light_onTertiaryContainer = Color(0xFF28132E) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFDFBFF) -private val md_theme_light_onBackground = Color(0xFF1A1B1E) -private val md_theme_light_surface = Color(0xFFFDFBFF) -private val md_theme_light_onSurface = Color(0xFF1A1B1E) -private val md_theme_light_surfaceVariant = Color(0xFFE0E2EC) -private val md_theme_light_onSurfaceVariant = Color(0xFF44474E) -private val md_theme_light_outline = Color(0xFF74777F) -private val md_theme_light_inverseOnSurface = Color(0xFFF1F0F4) -private val md_theme_light_inverseSurface = Color(0xFF2F3033) -private val md_theme_light_inversePrimary = Color(0xFFAAC7FF) -private val md_theme_light_surfaceTint = Color(0xFF005DB8) -private val md_theme_light_outlineVariant = Color(0xFFC4C6D0) -private val md_theme_light_scrim = Color(0xFF000000) -private val md_theme_dark_primary = Color(0xFFAAC7FF) -private val md_theme_dark_onPrimary = Color(0xFF002F64) -private val md_theme_dark_primaryContainer = Color(0xFF00458D) -private val md_theme_dark_onPrimaryContainer = Color(0xFFD6E3FF) -private val md_theme_dark_secondary = Color(0xFFBEC6DC) -private val md_theme_dark_onSecondary = Color(0xFF283141) -private val md_theme_dark_secondaryContainer = Color(0xFF3E4759) -private val md_theme_dark_onSecondaryContainer = Color(0xFFDAE2F9) -private val md_theme_dark_tertiary = Color(0xFFDCBCE0) -private val md_theme_dark_onTertiary = Color(0xFF3F2844) -private val md_theme_dark_tertiaryContainer = Color(0xFF573E5C) -private val md_theme_dark_onTertiaryContainer = Color(0xFFF9D8FD) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF1A1B1E) -private val md_theme_dark_onBackground = Color(0xFFE3E2E6) -private val md_theme_dark_surface = Color(0xFF1A1B1E) -private val md_theme_dark_onSurface = Color(0xFFE3E2E6) -private val md_theme_dark_surfaceVariant = Color(0xFF44474E) -private val md_theme_dark_onSurfaceVariant = Color(0xFFC4C6D0) -private val md_theme_dark_outline = Color(0xFF8E9099) -private val md_theme_dark_inverseOnSurface = Color(0xFF1A1B1E) -private val md_theme_dark_inverseSurface = Color(0xFFE3E2E6) -private val md_theme_dark_inversePrimary = Color(0xFF005DB8) -private val md_theme_dark_surfaceTint = Color(0xFFAAC7FF) -private val md_theme_dark_outlineVariant = Color(0xFF44474E) -private val md_theme_dark_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF485D92) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFDAE2FF) +private val onPrimaryContainerLight = Color(0xFF001847) +private val secondaryLight = Color(0xFF585E71) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFDCE2F9) +private val onSecondaryContainerLight = Color(0xFF151B2C) +private val tertiaryLight = Color(0xFF735572) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFFED7F9) +private val onTertiaryContainerLight = Color(0xFF2A122C) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFFAF8FF) +private val onBackgroundLight = Color(0xFF1A1B21) +private val surfaceLight = Color(0xFFFAF8FF) +private val onSurfaceLight = Color(0xFF1A1B21) +private val surfaceVariantLight = Color(0xFFE1E2EC) +private val onSurfaceVariantLight = Color(0xFF44464F) +private val outlineLight = Color(0xFF757780) +private val outlineVariantLight = Color(0xFFC5C6D0) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF2F3036) +private val inverseOnSurfaceLight = Color(0xFFF1F0F7) +private val inversePrimaryLight = Color(0xFFB1C5FF) +private val surfaceDimLight = Color(0xFFDAD9E0) +private val surfaceBrightLight = Color(0xFFFAF8FF) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFF4F3FA) +private val surfaceContainerLight = Color(0xFFEEEDF4) +private val surfaceContainerHighLight = Color(0xFFE8E7EF) +private val surfaceContainerHighestLight = Color(0xFFE2E2E9) +private val primaryLightMediumContrast = Color(0xFF2C4174) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFF5F73AA) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF3C4255) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF6E7488) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF553955) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF8A6A88) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFFAF8FF) +private val onBackgroundLightMediumContrast = Color(0xFF1A1B21) +private val surfaceLightMediumContrast = Color(0xFFFAF8FF) +private val onSurfaceLightMediumContrast = Color(0xFF1A1B21) +private val surfaceVariantLightMediumContrast = Color(0xFFE1E2EC) +private val onSurfaceVariantLightMediumContrast = Color(0xFF41424B) +private val outlineLightMediumContrast = Color(0xFF5D5F67) +private val outlineVariantLightMediumContrast = Color(0xFF797A83) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF2F3036) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFF1F0F7) +private val inversePrimaryLightMediumContrast = Color(0xFFB1C5FF) +private val surfaceDimLightMediumContrast = Color(0xFFDAD9E0) +private val surfaceBrightLightMediumContrast = Color(0xFFFAF8FF) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFF4F3FA) +private val surfaceContainerLightMediumContrast = Color(0xFFEEEDF4) +private val surfaceContainerHighLightMediumContrast = Color(0xFFE8E7EF) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFE2E2E9) + +private val primaryLightHighContrast = Color(0xFF041F51) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF2C4174) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF1C2233) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF3C4255) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF321933) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF553955) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFFAF8FF) +private val onBackgroundLightHighContrast = Color(0xFF1A1B21) +private val surfaceLightHighContrast = Color(0xFFFAF8FF) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFE1E2EC) +private val onSurfaceVariantLightHighContrast = Color(0xFF21242B) +private val outlineLightHighContrast = Color(0xFF41424B) +private val outlineVariantLightHighContrast = Color(0xFF41424B) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF2F3036) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFE7EBFF) +private val surfaceDimLightHighContrast = Color(0xFFDAD9E0) +private val surfaceBrightLightHighContrast = Color(0xFFFAF8FF) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFF4F3FA) +private val surfaceContainerLightHighContrast = Color(0xFFEEEDF4) +private val surfaceContainerHighLightHighContrast = Color(0xFFE8E7EF) +private val surfaceContainerHighestLightHighContrast = Color(0xFFE2E2E9) + + +private val primaryDark = Color(0xFFB1C5FF) +private val onPrimaryDark = Color(0xFF172E60) +private val primaryContainerDark = Color(0xFF304578) +private val onPrimaryContainerDark = Color(0xFFDAE2FF) +private val secondaryDark = Color(0xFFC0C6DD) +private val onSecondaryDark = Color(0xFF2A3042) +private val secondaryContainerDark = Color(0xFF404659) +private val onSecondaryContainerDark = Color(0xFFDCE2F9) +private val tertiaryDark = Color(0xFFE1BBDD) +private val onTertiaryDark = Color(0xFF412742) +private val tertiaryContainerDark = Color(0xFF5A3D59) +private val onTertiaryContainerDark = Color(0xFFFED7F9) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF121318) +private val onBackgroundDark = Color(0xFFE2E2E9) +private val surfaceDark = Color(0xFF121318) +private val onSurfaceDark = Color(0xFFE2E2E9) +private val surfaceVariantDark = Color(0xFF44464F) +private val onSurfaceVariantDark = Color(0xFFC5C6D0) +private val outlineDark = Color(0xFF8F9099) +private val outlineVariantDark = Color(0xFF44464F) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFE2E2E9) +private val inverseOnSurfaceDark = Color(0xFF2F3036) +private val inversePrimaryDark = Color(0xFF485D92) +private val surfaceDimDark = Color(0xFF121318) +private val surfaceBrightDark = Color(0xFF38393F) +private val surfaceContainerLowestDark = Color(0xFF0D0E13) +private val surfaceContainerLowDark = Color(0xFF1A1B21) +private val surfaceContainerDark = Color(0xFF1E1F25) +private val surfaceContainerHighDark = Color(0xFF282A2F) +private val surfaceContainerHighestDark = Color(0xFF33343A) + +private val primaryDarkMediumContrast = Color(0xFFB8CAFF) +private val onPrimaryDarkMediumContrast = Color(0xFF00143C) +private val primaryContainerDarkMediumContrast = Color(0xFF7B8FC8) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFC4CAE1) +private val onSecondaryDarkMediumContrast = Color(0xFF0F1626) +private val secondaryContainerDarkMediumContrast = Color(0xFF8A90A5) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFE5BFE1) +private val onTertiaryDarkMediumContrast = Color(0xFF250D26) +private val tertiaryContainerDarkMediumContrast = Color(0xFFA886A6) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF121318) +private val onBackgroundDarkMediumContrast = Color(0xFFE2E2E9) +private val surfaceDarkMediumContrast = Color(0xFF121318) +private val onSurfaceDarkMediumContrast = Color(0xFFFCFAFF) +private val surfaceVariantDarkMediumContrast = Color(0xFF44464F) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFC9CAD4) +private val outlineDarkMediumContrast = Color(0xFFA1A2AC) +private val outlineVariantDarkMediumContrast = Color(0xFF81838C) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFE2E2E9) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF282A2F) +private val inversePrimaryDarkMediumContrast = Color(0xFF31467A) +private val surfaceDimDarkMediumContrast = Color(0xFF121318) +private val surfaceBrightDarkMediumContrast = Color(0xFF38393F) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF0D0E13) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF1A1B21) +private val surfaceContainerDarkMediumContrast = Color(0xFF1E1F25) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF282A2F) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF33343A) + +private val primaryDarkHighContrast = Color(0xFFFCFAFF) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFFB8CAFF) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFFCFAFF) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFC4CAE1) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFFFF9FA) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFE5BFE1) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF121318) +private val onBackgroundDarkHighContrast = Color(0xFFE2E2E9) +private val surfaceDarkHighContrast = Color(0xFF121318) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF44464F) +private val onSurfaceVariantDarkHighContrast = Color(0xFFFCFAFF) +private val outlineDarkHighContrast = Color(0xFFC9CAD4) +private val outlineVariantDarkHighContrast = Color(0xFFC9CAD4) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFE2E2E9) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF0F275A) +private val surfaceDimDarkHighContrast = Color(0xFF121318) +private val surfaceBrightDarkHighContrast = Color(0xFF38393F) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF0D0E13) +private val surfaceContainerLowDarkHighContrast = Color(0xFF1A1B21) +private val surfaceContainerDarkHighContrast = Color(0xFF1E1F25) +private val surfaceContainerHighDarkHighContrast = Color(0xFF282A2F) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF33343A) @Composable -fun blueTheme(isDark: Boolean): ColorScheme { +fun blueTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/GreenTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/GreenTheme.kt index 308bba5a..daad0f1e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/GreenTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/GreenTheme.kt @@ -5,132 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF006C50) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFF85F8CC) -private val md_theme_light_onPrimaryContainer = Color(0xFF002116) -private val md_theme_light_secondary = Color(0xFF4C6359) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFCEE9DB) -private val md_theme_light_onSecondaryContainer = Color(0xFF092017) -private val md_theme_light_tertiary = Color(0xFF3F6374) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFC2E8FD) -private val md_theme_light_onTertiaryContainer = Color(0xFF001F2A) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFBFDF9) -private val md_theme_light_onBackground = Color(0xFF191C1A) -private val md_theme_light_surface = Color(0xFFFBFDF9) -private val md_theme_light_onSurface = Color(0xFF191C1A) -private val md_theme_light_surfaceVariant = Color(0xFFDBE5DE) -private val md_theme_light_onSurfaceVariant = Color(0xFF404944) -private val md_theme_light_outline = Color(0xFF707974) -private val md_theme_light_inverseOnSurface = Color(0xFFEFF1EE) -private val md_theme_light_inverseSurface = Color(0xFF2E312F) -private val md_theme_light_inversePrimary = Color(0xFF67DBB1) -private val md_theme_light_surfaceTint = Color(0xFF006C50) -private val md_theme_light_outlineVariant = Color(0xFFBFC9C2) -private val md_theme_light_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF306A42) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFB3F1BF) +private val onPrimaryContainerLight = Color(0xFF00210D) +private val secondaryLight = Color(0xFF506353) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFD2E8D3) +private val onSecondaryContainerLight = Color(0xFF0D1F12) +private val tertiaryLight = Color(0xFF3A656F) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFBEEAF6) +private val onTertiaryContainerLight = Color(0xFF001F25) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFF6FBF3) +private val onBackgroundLight = Color(0xFF181D18) +private val surfaceLight = Color(0xFFF6FBF3) +private val onSurfaceLight = Color(0xFF181D18) +private val surfaceVariantLight = Color(0xFFDDE5DA) +private val onSurfaceVariantLight = Color(0xFF414941) +private val outlineLight = Color(0xFF717971) +private val outlineVariantLight = Color(0xFFC1C9BF) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF2D322D) +private val inverseOnSurfaceLight = Color(0xFFEEF2EA) +private val inversePrimaryLight = Color(0xFF97D5A5) +private val surfaceDimLight = Color(0xFFD7DBD4) +private val surfaceBrightLight = Color(0xFFF6FBF3) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFF0F5ED) +private val surfaceContainerLight = Color(0xFFEBEFE7) +private val surfaceContainerHighLight = Color(0xFFE5EAE2) +private val surfaceContainerHighestLight = Color(0xFFDFE4DC) + +private val primaryLightMediumContrast = Color(0xFF0F4D29) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFF478157) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF344738) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF657A68) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF1C4952) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF517B85) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFF6FBF3) +private val onBackgroundLightMediumContrast = Color(0xFF181D18) +private val surfaceLightMediumContrast = Color(0xFFF6FBF3) +private val onSurfaceLightMediumContrast = Color(0xFF181D18) +private val surfaceVariantLightMediumContrast = Color(0xFFDDE5DA) +private val onSurfaceVariantLightMediumContrast = Color(0xFF3D453D) +private val outlineLightMediumContrast = Color(0xFF596159) +private val outlineVariantLightMediumContrast = Color(0xFF757D74) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF2D322D) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFEEF2EA) +private val inversePrimaryLightMediumContrast = Color(0xFF97D5A5) +private val surfaceDimLightMediumContrast = Color(0xFFD7DBD4) +private val surfaceBrightLightMediumContrast = Color(0xFFF6FBF3) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFF0F5ED) +private val surfaceContainerLightMediumContrast = Color(0xFFEBEFE7) +private val surfaceContainerHighLightMediumContrast = Color(0xFFE5EAE2) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFDFE4DC) + +private val primaryLightHighContrast = Color(0xFF002911) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF0F4D29) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF142619) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF344738) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF00262E) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF1C4952) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFF6FBF3) +private val onBackgroundLightHighContrast = Color(0xFF181D18) +private val surfaceLightHighContrast = Color(0xFFF6FBF3) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFDDE5DA) +private val onSurfaceVariantLightHighContrast = Color(0xFF1E261F) +private val outlineLightHighContrast = Color(0xFF3D453D) +private val outlineVariantLightHighContrast = Color(0xFF3D453D) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF2D322D) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFBCFBC8) +private val surfaceDimLightHighContrast = Color(0xFFD7DBD4) +private val surfaceBrightLightHighContrast = Color(0xFFF6FBF3) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFF0F5ED) +private val surfaceContainerLightHighContrast = Color(0xFFEBEFE7) +private val surfaceContainerHighLightHighContrast = Color(0xFFE5EAE2) +private val surfaceContainerHighestLightHighContrast = Color(0xFFDFE4DC) + + +private val primaryDark = Color(0xFF97D5A5) +private val onPrimaryDark = Color(0xFF00391A) +private val primaryContainerDark = Color(0xFF15512D) +private val onPrimaryContainerDark = Color(0xFFB3F1BF) +private val secondaryDark = Color(0xFFB6CCB8) +private val onSecondaryDark = Color(0xFF223526) +private val secondaryContainerDark = Color(0xFF384B3C) +private val onSecondaryContainerDark = Color(0xFFD2E8D3) +private val tertiaryDark = Color(0xFFA2CED9) +private val onTertiaryDark = Color(0xFF01363F) +private val tertiaryContainerDark = Color(0xFF204D56) +private val onTertiaryContainerDark = Color(0xFFBEEAF6) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF101510) +private val onBackgroundDark = Color(0xFFDFE4DC) +private val surfaceDark = Color(0xFF101510) +private val onSurfaceDark = Color(0xFFDFE4DC) +private val surfaceVariantDark = Color(0xFF414941) +private val onSurfaceVariantDark = Color(0xFFC1C9BF) +private val outlineDark = Color(0xFF8B938A) +private val outlineVariantDark = Color(0xFF414941) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFDFE4DC) +private val inverseOnSurfaceDark = Color(0xFF2D322D) +private val inversePrimaryDark = Color(0xFF306A42) +private val surfaceDimDark = Color(0xFF101510) +private val surfaceBrightDark = Color(0xFF353A35) +private val surfaceContainerLowestDark = Color(0xFF0A0F0B) +private val surfaceContainerLowDark = Color(0xFF181D18) +private val surfaceContainerDark = Color(0xFF1C211C) +private val surfaceContainerHighDark = Color(0xFF262B26) +private val surfaceContainerHighestDark = Color(0xFF313631) + +private val primaryDarkMediumContrast = Color(0xFF9BD9A9) +private val onPrimaryDarkMediumContrast = Color(0xFF001B09) +private val primaryContainerDarkMediumContrast = Color(0xFF639E72) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFBBD0BC) +private val onSecondaryDarkMediumContrast = Color(0xFF081A0D) +private val secondaryContainerDarkMediumContrast = Color(0xFF819683) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFA6D2DD) +private val onTertiaryDarkMediumContrast = Color(0xFF00191F) +private val tertiaryContainerDarkMediumContrast = Color(0xFF6D97A2) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF101510) +private val onBackgroundDarkMediumContrast = Color(0xFFDFE4DC) +private val surfaceDarkMediumContrast = Color(0xFF101510) +private val onSurfaceDarkMediumContrast = Color(0xFFF8FCF4) +private val surfaceVariantDarkMediumContrast = Color(0xFF414941) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFC5CDC3) +private val outlineDarkMediumContrast = Color(0xFF9DA59C) +private val outlineVariantDarkMediumContrast = Color(0xFF7D857D) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFDFE4DC) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF262B26) +private val inversePrimaryDarkMediumContrast = Color(0xFF16522E) +private val surfaceDimDarkMediumContrast = Color(0xFF101510) +private val surfaceBrightDarkMediumContrast = Color(0xFF353A35) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF0A0F0B) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF181D18) +private val surfaceContainerDarkMediumContrast = Color(0xFF1C211C) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF262B26) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF313631) + +private val primaryDarkHighContrast = Color(0xFFEFFFEE) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFF9BD9A9) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFEFFFEE) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFBBD0BC) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFF3FCFF) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFA6D2DD) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF101510) +private val onBackgroundDarkHighContrast = Color(0xFFDFE4DC) +private val surfaceDarkHighContrast = Color(0xFF101510) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF414941) +private val onSurfaceVariantDarkHighContrast = Color(0xFFF5FDF2) +private val outlineDarkHighContrast = Color(0xFFC5CDC3) +private val outlineVariantDarkHighContrast = Color(0xFFC5CDC3) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFDFE4DC) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF003216) +private val surfaceDimDarkHighContrast = Color(0xFF101510) +private val surfaceBrightDarkHighContrast = Color(0xFF353A35) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF0A0F0B) +private val surfaceContainerLowDarkHighContrast = Color(0xFF181D18) +private val surfaceContainerDarkHighContrast = Color(0xFF1C211C) +private val surfaceContainerHighDarkHighContrast = Color(0xFF262B26) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF313631) -private val md_theme_dark_primary = Color(0xFF67DBB1) -private val md_theme_dark_onPrimary = Color(0xFF003828) -private val md_theme_dark_primaryContainer = Color(0xFF00513B) -private val md_theme_dark_onPrimaryContainer = Color(0xFF85F8CC) -private val md_theme_dark_secondary = Color(0xFFB3CCBF) -private val md_theme_dark_onSecondary = Color(0xFF1E352C) -private val md_theme_dark_secondaryContainer = Color(0xFF354B41) -private val md_theme_dark_onSecondaryContainer = Color(0xFFCEE9DB) -private val md_theme_dark_tertiary = Color(0xFFA6CCE0) -private val md_theme_dark_onTertiary = Color(0xFF093544) -private val md_theme_dark_tertiaryContainer = Color(0xFF264B5C) -private val md_theme_dark_onTertiaryContainer = Color(0xFFC2E8FD) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF191C1A) -private val md_theme_dark_onBackground = Color(0xFFE1E3DF) -private val md_theme_dark_surface = Color(0xFF191C1A) -private val md_theme_dark_onSurface = Color(0xFFE1E3DF) -private val md_theme_dark_surfaceVariant = Color(0xFF404944) -private val md_theme_dark_onSurfaceVariant = Color(0xFFBFC9C2) -private val md_theme_dark_outline = Color(0xFF89938D) -private val md_theme_dark_inverseOnSurface = Color(0xFF191C1A) -private val md_theme_dark_inverseSurface = Color(0xFFE1E3DF) -private val md_theme_dark_inversePrimary = Color(0xFF006C50) -private val md_theme_dark_surfaceTint = Color(0xFF67DBB1) -private val md_theme_dark_outlineVariant = Color(0xFF404944) -private val md_theme_dark_scrim = Color(0xFF000000) @Composable -fun greenTheme(isDark: Boolean): ColorScheme { +fun greenTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PinkTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PinkTheme.kt index fca9320f..2e013447 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PinkTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PinkTheme.kt @@ -5,132 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF914084) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFFFD7F2) -private val md_theme_light_onPrimaryContainer = Color(0xFF390034) -private val md_theme_light_secondary = Color(0xFF6F5868) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFF8DAED) -private val md_theme_light_onSecondaryContainer = Color(0xFF271623) -private val md_theme_light_tertiary = Color(0xFF815342) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFFFDBCF) -private val md_theme_light_onTertiaryContainer = Color(0xFF321206) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFFFBFF) -private val md_theme_light_onBackground = Color(0xFF1F1A1D) -private val md_theme_light_surface = Color(0xFFFFFBFF) -private val md_theme_light_onSurface = Color(0xFF1F1A1D) -private val md_theme_light_surfaceVariant = Color(0xFFEEDEE7) -private val md_theme_light_onSurfaceVariant = Color(0xFF4E444A) -private val md_theme_light_outline = Color(0xFF80747B) -private val md_theme_light_inverseOnSurface = Color(0xFFF8EEF2) -private val md_theme_light_inverseSurface = Color(0xFF342F32) -private val md_theme_light_inversePrimary = Color(0xFFFFACEB) -private val md_theme_light_surfaceTint = Color(0xFF914084) -private val md_theme_light_outlineVariant = Color(0xFFD2C2CB) -private val md_theme_light_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF8C4A60) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFFFD9E2) +private val onPrimaryContainerLight = Color(0xFF3A071D) +private val secondaryLight = Color(0xFF74565F) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFFFD9E2) +private val onSecondaryContainerLight = Color(0xFF2B151C) +private val tertiaryLight = Color(0xFF7C5635) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFFFDCC2) +private val onTertiaryContainerLight = Color(0xFF2E1500) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFFFF8F8) +private val onBackgroundLight = Color(0xFF22191C) +private val surfaceLight = Color(0xFFFFF8F8) +private val onSurfaceLight = Color(0xFF22191C) +private val surfaceVariantLight = Color(0xFFF2DDE2) +private val onSurfaceVariantLight = Color(0xFF514347) +private val outlineLight = Color(0xFF837377) +private val outlineVariantLight = Color(0xFFD5C2C6) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF372E30) +private val inverseOnSurfaceLight = Color(0xFFFDEDEF) +private val inversePrimaryLight = Color(0xFFFFB0C8) +private val surfaceDimLight = Color(0xFFE6D6D9) +private val surfaceBrightLight = Color(0xFFFFF8F8) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFFFF0F2) +private val surfaceContainerLight = Color(0xFFFAEAED) +private val surfaceContainerHighLight = Color(0xFFF5E4E7) +private val surfaceContainerHighestLight = Color(0xFFEFDFE1) + +private val primaryLightMediumContrast = Color(0xFF6B2F45) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFFA55F77) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF563B43) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF8C6C75) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF5D3B1C) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF956C49) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFFFF8F8) +private val onBackgroundLightMediumContrast = Color(0xFF22191C) +private val surfaceLightMediumContrast = Color(0xFFFFF8F8) +private val onSurfaceLightMediumContrast = Color(0xFF22191C) +private val surfaceVariantLightMediumContrast = Color(0xFFF2DDE2) +private val onSurfaceVariantLightMediumContrast = Color(0xFF4D3F43) +private val outlineLightMediumContrast = Color(0xFF6A5B5F) +private val outlineVariantLightMediumContrast = Color(0xFF87777A) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF372E30) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFFDEDEF) +private val inversePrimaryLightMediumContrast = Color(0xFFFFB0C8) +private val surfaceDimLightMediumContrast = Color(0xFFE6D6D9) +private val surfaceBrightLightMediumContrast = Color(0xFFFFF8F8) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFFFF0F2) +private val surfaceContainerLightMediumContrast = Color(0xFFFAEAED) +private val surfaceContainerHighLightMediumContrast = Color(0xFFF5E4E7) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFEFDFE1) + +private val primaryLightHighContrast = Color(0xFF420E24) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF6B2F45) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF321B23) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF563B43) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF371B01) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF5D3B1C) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFFFF8F8) +private val onBackgroundLightHighContrast = Color(0xFF22191C) +private val surfaceLightHighContrast = Color(0xFFFFF8F8) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFF2DDE2) +private val onSurfaceVariantLightHighContrast = Color(0xFF2C2124) +private val outlineLightHighContrast = Color(0xFF4D3F43) +private val outlineVariantLightHighContrast = Color(0xFF4D3F43) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF372E30) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFFFE6EB) +private val surfaceDimLightHighContrast = Color(0xFFE6D6D9) +private val surfaceBrightLightHighContrast = Color(0xFFFFF8F8) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFFFF0F2) +private val surfaceContainerLightHighContrast = Color(0xFFFAEAED) +private val surfaceContainerHighLightHighContrast = Color(0xFFF5E4E7) +private val surfaceContainerHighestLightHighContrast = Color(0xFFEFDFE1) + + +private val primaryDark = Color(0xFFFFB0C8) +private val onPrimaryDark = Color(0xFF541D32) +private val primaryContainerDark = Color(0xFF703349) +private val onPrimaryContainerDark = Color(0xFFFFD9E2) +private val secondaryDark = Color(0xFFE2BDC6) +private val onSecondaryDark = Color(0xFF422931) +private val secondaryContainerDark = Color(0xFF5A3F47) +private val onSecondaryContainerDark = Color(0xFFFFD9E2) +private val tertiaryDark = Color(0xFFEFBD94) +private val onTertiaryDark = Color(0xFF48290C) +private val tertiaryContainerDark = Color(0xFF623F20) +private val onTertiaryContainerDark = Color(0xFFFFDCC2) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF191113) +private val onBackgroundDark = Color(0xFFEFDFE1) +private val surfaceDark = Color(0xFF191113) +private val onSurfaceDark = Color(0xFFEFDFE1) +private val surfaceVariantDark = Color(0xFF514347) +private val onSurfaceVariantDark = Color(0xFFD5C2C6) +private val outlineDark = Color(0xFF9E8C90) +private val outlineVariantDark = Color(0xFF514347) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFEFDFE1) +private val inverseOnSurfaceDark = Color(0xFF372E30) +private val inversePrimaryDark = Color(0xFF8C4A60) +private val surfaceDimDark = Color(0xFF191113) +private val surfaceBrightDark = Color(0xFF413739) +private val surfaceContainerLowestDark = Color(0xFF140C0E) +private val surfaceContainerLowDark = Color(0xFF22191C) +private val surfaceContainerDark = Color(0xFF261D20) +private val surfaceContainerHighDark = Color(0xFF31282A) +private val surfaceContainerHighestDark = Color(0xFF3C3235) + +private val primaryDarkMediumContrast = Color(0xFFFFB7CC) +private val onPrimaryDarkMediumContrast = Color(0xFF330218) +private val primaryContainerDarkMediumContrast = Color(0xFFC67B93) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFE7C1CB) +private val onSecondaryDarkMediumContrast = Color(0xFF251017) +private val secondaryContainerDarkMediumContrast = Color(0xFFAA8891) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFF3C198) +private val onTertiaryDarkMediumContrast = Color(0xFF261100) +private val tertiaryContainerDarkMediumContrast = Color(0xFFB48862) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF191113) +private val onBackgroundDarkMediumContrast = Color(0xFFEFDFE1) +private val surfaceDarkMediumContrast = Color(0xFF191113) +private val onSurfaceDarkMediumContrast = Color(0xFFFFF9F9) +private val surfaceVariantDarkMediumContrast = Color(0xFF514347) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFDAC6CA) +private val outlineDarkMediumContrast = Color(0xFFB19EA2) +private val outlineVariantDarkMediumContrast = Color(0xFF907F83) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFEFDFE1) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF31282A) +private val inversePrimaryDarkMediumContrast = Color(0xFF71344A) +private val surfaceDimDarkMediumContrast = Color(0xFF191113) +private val surfaceBrightDarkMediumContrast = Color(0xFF413739) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF140C0E) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF22191C) +private val surfaceContainerDarkMediumContrast = Color(0xFF261D20) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF31282A) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF3C3235) + +private val primaryDarkHighContrast = Color(0xFFFFF9F9) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFFFFB7CC) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFFFF9F9) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFE7C1CB) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFFFFAF8) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFF3C198) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF191113) +private val onBackgroundDarkHighContrast = Color(0xFFEFDFE1) +private val surfaceDarkHighContrast = Color(0xFF191113) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF514347) +private val onSurfaceVariantDarkHighContrast = Color(0xFFFFF9F9) +private val outlineDarkHighContrast = Color(0xFFDAC6CA) +private val outlineVariantDarkHighContrast = Color(0xFFDAC6CA) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFEFDFE1) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF4C162C) +private val surfaceDimDarkHighContrast = Color(0xFF191113) +private val surfaceBrightDarkHighContrast = Color(0xFF413739) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF140C0E) +private val surfaceContainerLowDarkHighContrast = Color(0xFF22191C) +private val surfaceContainerDarkHighContrast = Color(0xFF261D20) +private val surfaceContainerHighDarkHighContrast = Color(0xFF31282A) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF3C3235) -private val md_theme_dark_primary = Color(0xFFFFACEB) -private val md_theme_dark_onPrimary = Color(0xFF590B52) -private val md_theme_dark_primaryContainer = Color(0xFF75276A) -private val md_theme_dark_onPrimaryContainer = Color(0xFFFFD7F2) -private val md_theme_dark_secondary = Color(0xFFDBBED1) -private val md_theme_dark_onSecondary = Color(0xFF3E2A39) -private val md_theme_dark_secondaryContainer = Color(0xFF564050) -private val md_theme_dark_onSecondaryContainer = Color(0xFFF8DAED) -private val md_theme_dark_tertiary = Color(0xFFF5B9A4) -private val md_theme_dark_onTertiary = Color(0xFF4C2618) -private val md_theme_dark_tertiaryContainer = Color(0xFF663C2D) -private val md_theme_dark_onTertiaryContainer = Color(0xFFFFDBCF) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF1F1A1D) -private val md_theme_dark_onBackground = Color(0xFFEAE0E3) -private val md_theme_dark_surface = Color(0xFF1F1A1D) -private val md_theme_dark_onSurface = Color(0xFFEAE0E3) -private val md_theme_dark_surfaceVariant = Color(0xFF4E444A) -private val md_theme_dark_onSurfaceVariant = Color(0xFFD2C2CB) -private val md_theme_dark_outline = Color(0xFF9B8D95) -private val md_theme_dark_inverseOnSurface = Color(0xFF1F1A1D) -private val md_theme_dark_inverseSurface = Color(0xFFEAE0E3) -private val md_theme_dark_inversePrimary = Color(0xFF914084) -private val md_theme_dark_surfaceTint = Color(0xFFFFACEB) -private val md_theme_dark_outlineVariant = Color(0xFF4E444A) -private val md_theme_dark_scrim = Color(0xFF000000) @Composable -fun pinkTheme(isDark: Boolean): ColorScheme { +fun pinkTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PurpleTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PurpleTheme.kt index 0767a954..f747f3a2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PurpleTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/PurpleTheme.kt @@ -5,133 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast + +private val primaryLight = Color(0xFF725188) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFF3DAFF) +private val onPrimaryContainerLight = Color(0xFF2B0C40) +private val secondaryLight = Color(0xFF675A6E) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFEFDCF5) +private val onSecondaryContainerLight = Color(0xFF221729) +private val tertiaryLight = Color(0xFF815154) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFFFDADA) +private val onTertiaryContainerLight = Color(0xFF331014) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFFFF7FD) +private val onBackgroundLight = Color(0xFF1E1A20) +private val surfaceLight = Color(0xFFFFF7FD) +private val onSurfaceLight = Color(0xFF1E1A20) +private val surfaceVariantLight = Color(0xFFEADFEA) +private val onSurfaceVariantLight = Color(0xFF4B454D) +private val outlineLight = Color(0xFF7C747E) +private val outlineVariantLight = Color(0xFFCDC3CE) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF332F35) +private val inverseOnSurfaceLight = Color(0xFFF7EEF6) +private val inversePrimaryLight = Color(0xFFDFB8F6) +private val surfaceDimLight = Color(0xFFE0D7DF) +private val surfaceBrightLight = Color(0xFFFFF7FD) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFFAF1F9) +private val surfaceContainerLight = Color(0xFFF4EBF3) +private val surfaceContainerHighLight = Color(0xFFEEE6ED) +private val surfaceContainerHighestLight = Color(0xFFE9E0E8) + +private val primaryLightMediumContrast = Color(0xFF55366A) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFF89679F) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF4B3E52) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF7E6F85) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF613739) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF9A676A) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFFFF7FD) +private val onBackgroundLightMediumContrast = Color(0xFF1E1A20) +private val surfaceLightMediumContrast = Color(0xFFFFF7FD) +private val onSurfaceLightMediumContrast = Color(0xFF1E1A20) +private val surfaceVariantLightMediumContrast = Color(0xFFEADFEA) +private val onSurfaceVariantLightMediumContrast = Color(0xFF474149) +private val outlineLightMediumContrast = Color(0xFF645D66) +private val outlineVariantLightMediumContrast = Color(0xFF807882) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF332F35) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFF7EEF6) +private val inversePrimaryLightMediumContrast = Color(0xFFDFB8F6) +private val surfaceDimLightMediumContrast = Color(0xFFE0D7DF) +private val surfaceBrightLightMediumContrast = Color(0xFFFFF7FD) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFFAF1F9) +private val surfaceContainerLightMediumContrast = Color(0xFFF4EBF3) +private val surfaceContainerHighLightMediumContrast = Color(0xFFEEE6ED) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFE9E0E8) + +private val primaryLightHighContrast = Color(0xFF321347) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF55366A) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF291E30) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF4B3E52) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF3B171A) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF613739) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFFFF7FD) +private val onBackgroundLightHighContrast = Color(0xFF1E1A20) +private val surfaceLightHighContrast = Color(0xFFFFF7FD) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFEADFEA) +private val onSurfaceVariantLightHighContrast = Color(0xFF27222A) +private val outlineLightHighContrast = Color(0xFF474149) +private val outlineVariantLightHighContrast = Color(0xFF474149) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF332F35) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFF9E6FF) +private val surfaceDimLightHighContrast = Color(0xFFE0D7DF) +private val surfaceBrightLightHighContrast = Color(0xFFFFF7FD) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFFAF1F9) +private val surfaceContainerLightHighContrast = Color(0xFFF4EBF3) +private val surfaceContainerHighLightHighContrast = Color(0xFFEEE6ED) +private val surfaceContainerHighestLightHighContrast = Color(0xFFE9E0E8) -private val md_theme_light_primary = Color(0xFF7A4A98) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFF4D9FF) -private val md_theme_light_onPrimaryContainer = Color(0xFF2F004B) -private val md_theme_light_secondary = Color(0xFF68596E) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFEFDCF5) -private val md_theme_light_onSecondaryContainer = Color(0xFF221729) -private val md_theme_light_tertiary = Color(0xFF815153) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFFFDADA) -private val md_theme_light_onTertiaryContainer = Color(0xFF331113) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFFFBFF) -private val md_theme_light_onBackground = Color(0xFF1D1B1E) -private val md_theme_light_surface = Color(0xFFFFFBFF) -private val md_theme_light_onSurface = Color(0xFF1D1B1E) -private val md_theme_light_surfaceVariant = Color(0xFFEADFEA) -private val md_theme_light_onSurfaceVariant = Color(0xFF4B454D) -private val md_theme_light_outline = Color(0xFF7D747E) -private val md_theme_light_inverseOnSurface = Color(0xFFF6EFF3) -private val md_theme_light_inverseSurface = Color(0xFF332F33) -private val md_theme_light_inversePrimary = Color(0xFFE4B5FF) -private val md_theme_light_surfaceTint = Color(0xFF7A4A98) -private val md_theme_light_outlineVariant = Color(0xFFCDC3CE) -private val md_theme_light_scrim = Color(0xFF000000) +private val primaryDark = Color(0xFFDFB8F6) +private val onPrimaryDark = Color(0xFF412356) +private val primaryContainerDark = Color(0xFF593A6E) +private val onPrimaryContainerDark = Color(0xFFF3DAFF) +private val secondaryDark = Color(0xFFD2C1D9) +private val onSecondaryDark = Color(0xFF382C3E) +private val secondaryContainerDark = Color(0xFF4F4256) +private val onSecondaryContainerDark = Color(0xFFEFDCF5) +private val tertiaryDark = Color(0xFFF4B7B9) +private val onTertiaryDark = Color(0xFF4C2528) +private val tertiaryContainerDark = Color(0xFF663B3D) +private val onTertiaryContainerDark = Color(0xFFFFDADA) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF161217) +private val onBackgroundDark = Color(0xFFE9E0E8) +private val surfaceDark = Color(0xFF161217) +private val onSurfaceDark = Color(0xFFE9E0E8) +private val surfaceVariantDark = Color(0xFF4B454D) +private val onSurfaceVariantDark = Color(0xFFCDC3CE) +private val outlineDark = Color(0xFF968E98) +private val outlineVariantDark = Color(0xFF4B454D) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFE9E0E8) +private val inverseOnSurfaceDark = Color(0xFF332F35) +private val inversePrimaryDark = Color(0xFF725188) +private val surfaceDimDark = Color(0xFF161217) +private val surfaceBrightDark = Color(0xFF3C383E) +private val surfaceContainerLowestDark = Color(0xFF100D12) +private val surfaceContainerLowDark = Color(0xFF1E1A20) +private val surfaceContainerDark = Color(0xFF221E24) +private val surfaceContainerHighDark = Color(0xFF2D282E) +private val surfaceContainerHighestDark = Color(0xFF383339) + +private val primaryDarkMediumContrast = Color(0xFFE4BCFB) +private val onPrimaryDarkMediumContrast = Color(0xFF25053A) +private val primaryContainerDarkMediumContrast = Color(0xFFA783BD) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFD6C5DD) +private val onSecondaryDarkMediumContrast = Color(0xFF1D1223) +private val secondaryContainerDarkMediumContrast = Color(0xFF9B8BA2) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFF9BBBE) +private val onTertiaryDarkMediumContrast = Color(0xFF2C0B0F) +private val tertiaryContainerDarkMediumContrast = Color(0xFFB98385) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF161217) +private val onBackgroundDarkMediumContrast = Color(0xFFE9E0E8) +private val surfaceDarkMediumContrast = Color(0xFF161217) +private val onSurfaceDarkMediumContrast = Color(0xFFFFF9FB) +private val surfaceVariantDarkMediumContrast = Color(0xFF4B454D) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFD2C8D2) +private val outlineDarkMediumContrast = Color(0xFFA9A0AA) +private val outlineVariantDarkMediumContrast = Color(0xFF89808A) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFE9E0E8) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF2D292E) +private val inversePrimaryDarkMediumContrast = Color(0xFF5A3B70) +private val surfaceDimDarkMediumContrast = Color(0xFF161217) +private val surfaceBrightDarkMediumContrast = Color(0xFF3C383E) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF100D12) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF1E1A20) +private val surfaceContainerDarkMediumContrast = Color(0xFF221E24) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF2D282E) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF383339) + +private val primaryDarkHighContrast = Color(0xFFFFF9FB) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFFE4BCFB) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFFFF9FB) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFD6C5DD) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFFFF9F9) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFF9BBBE) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF161217) +private val onBackgroundDarkHighContrast = Color(0xFFE9E0E8) +private val surfaceDarkHighContrast = Color(0xFF161217) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF4B454D) +private val onSurfaceVariantDarkHighContrast = Color(0xFFFFF9FB) +private val outlineDarkHighContrast = Color(0xFFD2C8D2) +private val outlineVariantDarkHighContrast = Color(0xFFD2C8D2) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFE9E0E8) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF3A1C4F) +private val surfaceDimDarkHighContrast = Color(0xFF161217) +private val surfaceBrightDarkHighContrast = Color(0xFF3C383E) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF100D12) +private val surfaceContainerLowDarkHighContrast = Color(0xFF1E1A20) +private val surfaceContainerDarkHighContrast = Color(0xFF221E24) +private val surfaceContainerHighDarkHighContrast = Color(0xFF2D282E) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF383339) -private val md_theme_dark_primary = Color(0xFFE4B5FF) -private val md_theme_dark_onPrimary = Color(0xFF481866) -private val md_theme_dark_primaryContainer = Color(0xFF61317F) -private val md_theme_dark_onPrimaryContainer = Color(0xFFF4D9FF) -private val md_theme_dark_secondary = Color(0xFFD3C1D8) -private val md_theme_dark_onSecondary = Color(0xFF382C3E) -private val md_theme_dark_secondaryContainer = Color(0xFF4F4255) -private val md_theme_dark_onSecondaryContainer = Color(0xFFEFDCF5) -private val md_theme_dark_tertiary = Color(0xFFF4B7B9) -private val md_theme_dark_onTertiary = Color(0xFF4C2527) -private val md_theme_dark_tertiaryContainer = Color(0xFF663B3C) -private val md_theme_dark_onTertiaryContainer = Color(0xFFFFDADA) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF1D1B1E) -private val md_theme_dark_onBackground = Color(0xFFE8E0E5) -private val md_theme_dark_surface = Color(0xFF1D1B1E) -private val md_theme_dark_onSurface = Color(0xFFE8E0E5) -private val md_theme_dark_surfaceVariant = Color(0xFF4B454D) -private val md_theme_dark_onSurfaceVariant = Color(0xFFCDC3CE) -private val md_theme_dark_outline = Color(0xFF978E98) -private val md_theme_dark_inverseOnSurface = Color(0xFF1D1B1E) -private val md_theme_dark_inverseSurface = Color(0xFFE8E0E5) -private val md_theme_dark_inversePrimary = Color(0xFF7A4A98) -private val md_theme_dark_surfaceTint = Color(0xFFE4B5FF) -private val md_theme_dark_outlineVariant = Color(0xFF4B454D) -private val md_theme_dark_scrim = Color(0xFF000000) @Composable -fun purpleTheme(isDark: Boolean): ColorScheme { +fun purpleTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/RedTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/RedTheme.kt index 76bc92ae..c73a7954 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/RedTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/RedTheme.kt @@ -5,132 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF9C4143) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFFFDAD8) -private val md_theme_light_onPrimaryContainer = Color(0xFF410007) -private val md_theme_light_secondary = Color(0xFF775655) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFFFDAD8) -private val md_theme_light_onSecondaryContainer = Color(0xFF2C1515) -private val md_theme_light_tertiary = Color(0xFF745A2F) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFFFDEAC) -private val md_theme_light_onTertiaryContainer = Color(0xFF281900) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFFFBFF) -private val md_theme_light_onBackground = Color(0xFF201A1A) -private val md_theme_light_surface = Color(0xFFFFFBFF) -private val md_theme_light_onSurface = Color(0xFF201A1A) -private val md_theme_light_surfaceVariant = Color(0xFFF4DDDC) -private val md_theme_light_onSurfaceVariant = Color(0xFF524343) -private val md_theme_light_outline = Color(0xFF857372) -private val md_theme_light_inverseOnSurface = Color(0xFFFBEEED) -private val md_theme_light_inverseSurface = Color(0xFF362F2E) -private val md_theme_light_inversePrimary = Color(0xFFFFB3B1) -private val md_theme_light_surfaceTint = Color(0xFF9C4143) -private val md_theme_light_outlineVariant = Color(0xFFD7C1C0) -private val md_theme_light_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF904A42) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFFFDAD5) +private val onPrimaryContainerLight = Color(0xFF3B0906) +private val secondaryLight = Color(0xFF775652) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFFFDAD5) +private val onSecondaryContainerLight = Color(0xFF2C1512) +private val tertiaryLight = Color(0xFF715B2E) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFFDDFA6) +private val onTertiaryContainerLight = Color(0xFF261A00) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFFFF8F7) +private val onBackgroundLight = Color(0xFF231918) +private val surfaceLight = Color(0xFFFFF8F7) +private val onSurfaceLight = Color(0xFF231918) +private val surfaceVariantLight = Color(0xFFF5DDDA) +private val onSurfaceVariantLight = Color(0xFF534341) +private val outlineLight = Color(0xFF857370) +private val outlineVariantLight = Color(0xFFD8C2BF) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF392E2D) +private val inverseOnSurfaceLight = Color(0xFFFFEDEA) +private val inversePrimaryLight = Color(0xFFFFB4AA) +private val surfaceDimLight = Color(0xFFE8D6D4) +private val surfaceBrightLight = Color(0xFFFFF8F7) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFFFF0EE) +private val surfaceContainerLight = Color(0xFFFCEAE7) +private val surfaceContainerHighLight = Color(0xFFF6E4E2) +private val surfaceContainerHighestLight = Color(0xFFF1DEDC) + +private val primaryLightMediumContrast = Color(0xFF6E3029) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFFAA6057) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF593B38) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF8F6C68) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF534015) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF897142) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFFFF8F7) +private val onBackgroundLightMediumContrast = Color(0xFF231918) +private val surfaceLightMediumContrast = Color(0xFFFFF8F7) +private val onSurfaceLightMediumContrast = Color(0xFF231918) +private val surfaceVariantLightMediumContrast = Color(0xFFF5DDDA) +private val onSurfaceVariantLightMediumContrast = Color(0xFF4F3F3D) +private val outlineLightMediumContrast = Color(0xFF6C5B59) +private val outlineVariantLightMediumContrast = Color(0xFF897674) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF392E2D) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFFFEDEA) +private val inversePrimaryLightMediumContrast = Color(0xFFFFB4AA) +private val surfaceDimLightMediumContrast = Color(0xFFE8D6D4) +private val surfaceBrightLightMediumContrast = Color(0xFFFFF8F7) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFFFF0EE) +private val surfaceContainerLightMediumContrast = Color(0xFFFCEAE7) +private val surfaceContainerHighLightMediumContrast = Color(0xFFF6E4E2) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFF1DEDC) + +private val primaryLightHighContrast = Color(0xFF44100C) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF6E3029) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF341C19) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF593B38) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF2E2000) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF534015) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFFFF8F7) +private val onBackgroundLightHighContrast = Color(0xFF231918) +private val surfaceLightHighContrast = Color(0xFFFFF8F7) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFF5DDDA) +private val onSurfaceVariantLightHighContrast = Color(0xFF2E211F) +private val outlineLightHighContrast = Color(0xFF4F3F3D) +private val outlineVariantLightHighContrast = Color(0xFF4F3F3D) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF392E2D) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFFFE7E3) +private val surfaceDimLightHighContrast = Color(0xFFE8D6D4) +private val surfaceBrightLightHighContrast = Color(0xFFFFF8F7) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFFFF0EE) +private val surfaceContainerLightHighContrast = Color(0xFFFCEAE7) +private val surfaceContainerHighLightHighContrast = Color(0xFFF6E4E2) +private val surfaceContainerHighestLightHighContrast = Color(0xFFF1DEDC) + + +private val primaryDark = Color(0xFFFFB4AA) +private val onPrimaryDark = Color(0xFF561E19) +private val primaryContainerDark = Color(0xFF73342D) +private val onPrimaryContainerDark = Color(0xFFFFDAD5) +private val secondaryDark = Color(0xFFE7BDB7) +private val onSecondaryDark = Color(0xFF442926) +private val secondaryContainerDark = Color(0xFF5D3F3B) +private val onSecondaryContainerDark = Color(0xFFFFDAD5) +private val tertiaryDark = Color(0xFFDFC38C) +private val onTertiaryDark = Color(0xFF3F2E04) +private val tertiaryContainerDark = Color(0xFF574419) +private val onTertiaryContainerDark = Color(0xFFFDDFA6) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF1A1110) +private val onBackgroundDark = Color(0xFFF1DEDC) +private val surfaceDark = Color(0xFF1A1110) +private val onSurfaceDark = Color(0xFFF1DEDC) +private val surfaceVariantDark = Color(0xFF534341) +private val onSurfaceVariantDark = Color(0xFFD8C2BF) +private val outlineDark = Color(0xFFA08C8A) +private val outlineVariantDark = Color(0xFF534341) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFF1DEDC) +private val inverseOnSurfaceDark = Color(0xFF392E2D) +private val inversePrimaryDark = Color(0xFF904A42) +private val surfaceDimDark = Color(0xFF1A1110) +private val surfaceBrightDark = Color(0xFF423735) +private val surfaceContainerLowestDark = Color(0xFF140C0B) +private val surfaceContainerLowDark = Color(0xFF231918) +private val surfaceContainerDark = Color(0xFF271D1C) +private val surfaceContainerHighDark = Color(0xFF322826) +private val surfaceContainerHighestDark = Color(0xFF3D3231) + +private val primaryDarkMediumContrast = Color(0xFFFFBAB1) +private val onPrimaryDarkMediumContrast = Color(0xFF330403) +private val primaryContainerDarkMediumContrast = Color(0xFFCC7B71) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFEBC1BB) +private val onSecondaryDarkMediumContrast = Color(0xFF26100D) +private val secondaryContainerDarkMediumContrast = Color(0xFFAE8883) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFE4C790) +private val onTertiaryDarkMediumContrast = Color(0xFF1F1500) +private val tertiaryContainerDarkMediumContrast = Color(0xFFA78E5B) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF1A1110) +private val onBackgroundDarkMediumContrast = Color(0xFFF1DEDC) +private val surfaceDarkMediumContrast = Color(0xFF1A1110) +private val onSurfaceDarkMediumContrast = Color(0xFFFFF9F9) +private val surfaceVariantDarkMediumContrast = Color(0xFF534341) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFDCC6C3) +private val outlineDarkMediumContrast = Color(0xFFB39E9C) +private val outlineVariantDarkMediumContrast = Color(0xFF927F7C) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFF1DEDC) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF322826) +private val inversePrimaryDarkMediumContrast = Color(0xFF74352E) +private val surfaceDimDarkMediumContrast = Color(0xFF1A1110) +private val surfaceBrightDarkMediumContrast = Color(0xFF423735) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF140C0B) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF231918) +private val surfaceContainerDarkMediumContrast = Color(0xFF271D1C) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF322826) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF3D3231) + +private val primaryDarkHighContrast = Color(0xFFFFF9F9) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFFFF9F9) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFEBC1BB) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFFFFAF7) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFE4C790) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF1A1110) +private val onBackgroundDarkHighContrast = Color(0xFFF1DEDC) +private val surfaceDarkHighContrast = Color(0xFF1A1110) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF534341) +private val onSurfaceVariantDarkHighContrast = Color(0xFFFFF9F9) +private val outlineDarkHighContrast = Color(0xFFDCC6C3) +private val outlineVariantDarkHighContrast = Color(0xFFDCC6C3) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFF1DEDC) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF4E1813) +private val surfaceDimDarkHighContrast = Color(0xFF1A1110) +private val surfaceBrightDarkHighContrast = Color(0xFF423735) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF140C0B) +private val surfaceContainerLowDarkHighContrast = Color(0xFF231918) +private val surfaceContainerDarkHighContrast = Color(0xFF271D1C) +private val surfaceContainerHighDarkHighContrast = Color(0xFF322826) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF3D3231) -private val md_theme_dark_primary = Color(0xFFFFB3B1) -private val md_theme_dark_onPrimary = Color(0xFF5F1319) -private val md_theme_dark_primaryContainer = Color(0xFF7E2A2D) -private val md_theme_dark_onPrimaryContainer = Color(0xFFFFDAD8) -private val md_theme_dark_secondary = Color(0xFFE6BDBB) -private val md_theme_dark_onSecondary = Color(0xFF442929) -private val md_theme_dark_secondaryContainer = Color(0xFF5D3F3E) -private val md_theme_dark_onSecondaryContainer = Color(0xFFFFDAD8) -private val md_theme_dark_tertiary = Color(0xFFE4C18D) -private val md_theme_dark_onTertiary = Color(0xFF412D05) -private val md_theme_dark_tertiaryContainer = Color(0xFF5A4319) -private val md_theme_dark_onTertiaryContainer = Color(0xFFFFDEAC) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF201A1A) -private val md_theme_dark_onBackground = Color(0xFFEDE0DF) -private val md_theme_dark_surface = Color(0xFF201A1A) -private val md_theme_dark_onSurface = Color(0xFFEDE0DF) -private val md_theme_dark_surfaceVariant = Color(0xFF524343) -private val md_theme_dark_onSurfaceVariant = Color(0xFFD7C1C0) -private val md_theme_dark_outline = Color(0xFFA08C8B) -private val md_theme_dark_inverseOnSurface = Color(0xFF201A1A) -private val md_theme_dark_inverseSurface = Color(0xFFEDE0DF) -private val md_theme_dark_inversePrimary = Color(0xFF9C4143) -private val md_theme_dark_surfaceTint = Color(0xFFFFB3B1) -private val md_theme_dark_outlineVariant = Color(0xFF524343) -private val md_theme_dark_scrim = Color(0xFF000000) @Composable -fun redTheme(isDark: Boolean): ColorScheme { +fun redTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/YellowTheme.kt b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/YellowTheme.kt index 03a8e281..2545aa01 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/YellowTheme.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/ui/theme/YellowTheme.kt @@ -5,132 +5,471 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +import ua.acclorite.book_story.presentation.ui.ThemeContrast -private val md_theme_light_primary = Color(0xFF8F4E00) -private val md_theme_light_onPrimary = Color(0xFFFFFFFF) -private val md_theme_light_primaryContainer = Color(0xFFFFDCC2) -private val md_theme_light_onPrimaryContainer = Color(0xFF2E1500) -private val md_theme_light_secondary = Color(0xFF745943) -private val md_theme_light_onSecondary = Color(0xFFFFFFFF) -private val md_theme_light_secondaryContainer = Color(0xFFFFDCC2) -private val md_theme_light_onSecondaryContainer = Color(0xFF2A1707) -private val md_theme_light_tertiary = Color(0xFF5B6237) -private val md_theme_light_onTertiary = Color(0xFFFFFFFF) -private val md_theme_light_tertiaryContainer = Color(0xFFE0E7B1) -private val md_theme_light_onTertiaryContainer = Color(0xFF191E00) -private val md_theme_light_error = Color(0xFFBA1A1A) -private val md_theme_light_errorContainer = Color(0xFFFFDAD6) -private val md_theme_light_onError = Color(0xFFFFFFFF) -private val md_theme_light_onErrorContainer = Color(0xFF410002) -private val md_theme_light_background = Color(0xFFFFFBFF) -private val md_theme_light_onBackground = Color(0xFF201B17) -private val md_theme_light_surface = Color(0xFFFFFBFF) -private val md_theme_light_onSurface = Color(0xFF201B17) -private val md_theme_light_surfaceVariant = Color(0xFFF3DFD1) -private val md_theme_light_onSurfaceVariant = Color(0xFF51443B) -private val md_theme_light_outline = Color(0xFF847469) -private val md_theme_light_inverseOnSurface = Color(0xFFFAEEE8) -private val md_theme_light_inverseSurface = Color(0xFF352F2B) -private val md_theme_light_inversePrimary = Color(0xFFFFB77A) -private val md_theme_light_surfaceTint = Color(0xFF8F4E00) -private val md_theme_light_outlineVariant = Color(0xFFD6C3B6) -private val md_theme_light_scrim = Color(0xFF000000) +private val primaryLight = Color(0xFF845415) +private val onPrimaryLight = Color(0xFFFFFFFF) +private val primaryContainerLight = Color(0xFFFFDDBB) +private val onPrimaryContainerLight = Color(0xFF2B1700) +private val secondaryLight = Color(0xFF725A41) +private val onSecondaryLight = Color(0xFFFFFFFF) +private val secondaryContainerLight = Color(0xFFFDDDBD) +private val onSecondaryContainerLight = Color(0xFF281805) +private val tertiaryLight = Color(0xFF56633B) +private val onTertiaryLight = Color(0xFFFFFFFF) +private val tertiaryContainerLight = Color(0xFFD9E9B6) +private val onTertiaryContainerLight = Color(0xFF141F01) +private val errorLight = Color(0xFFBA1A1A) +private val onErrorLight = Color(0xFFFFFFFF) +private val errorContainerLight = Color(0xFFFFDAD6) +private val onErrorContainerLight = Color(0xFF410002) +private val backgroundLight = Color(0xFFFFF8F4) +private val onBackgroundLight = Color(0xFF211A14) +private val surfaceLight = Color(0xFFFFF8F4) +private val onSurfaceLight = Color(0xFF211A14) +private val surfaceVariantLight = Color(0xFFF1DFD0) +private val onSurfaceVariantLight = Color(0xFF50453A) +private val outlineLight = Color(0xFF827568) +private val outlineVariantLight = Color(0xFFD4C4B5) +private val scrimLight = Color(0xFF000000) +private val inverseSurfaceLight = Color(0xFF372F27) +private val inverseOnSurfaceLight = Color(0xFFFDEEE3) +private val inversePrimaryLight = Color(0xFFFABA73) +private val surfaceDimLight = Color(0xFFE5D8CC) +private val surfaceBrightLight = Color(0xFFFFF8F4) +private val surfaceContainerLowestLight = Color(0xFFFFFFFF) +private val surfaceContainerLowLight = Color(0xFFFFF1E6) +private val surfaceContainerLight = Color(0xFFFAEBE0) +private val surfaceContainerHighLight = Color(0xFFF4E6DA) +private val surfaceContainerHighestLight = Color(0xFFEEE0D5) + +private val primaryLightMediumContrast = Color(0xFF623A00) +private val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +private val primaryContainerLightMediumContrast = Color(0xFF9D6A2A) +private val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryLightMediumContrast = Color(0xFF543F28) +private val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightMediumContrast = Color(0xFF897056) +private val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryLightMediumContrast = Color(0xFF3B4722) +private val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightMediumContrast = Color(0xFF6C7A50) +private val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +private val errorLightMediumContrast = Color(0xFF8C0009) +private val onErrorLightMediumContrast = Color(0xFFFFFFFF) +private val errorContainerLightMediumContrast = Color(0xFFDA342E) +private val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +private val backgroundLightMediumContrast = Color(0xFFFFF8F4) +private val onBackgroundLightMediumContrast = Color(0xFF211A14) +private val surfaceLightMediumContrast = Color(0xFFFFF8F4) +private val onSurfaceLightMediumContrast = Color(0xFF211A14) +private val surfaceVariantLightMediumContrast = Color(0xFFF1DFD0) +private val onSurfaceVariantLightMediumContrast = Color(0xFF4C4136) +private val outlineLightMediumContrast = Color(0xFF695D51) +private val outlineVariantLightMediumContrast = Color(0xFF86786C) +private val scrimLightMediumContrast = Color(0xFF000000) +private val inverseSurfaceLightMediumContrast = Color(0xFF372F27) +private val inverseOnSurfaceLightMediumContrast = Color(0xFFFDEEE3) +private val inversePrimaryLightMediumContrast = Color(0xFFFABA73) +private val surfaceDimLightMediumContrast = Color(0xFFE5D8CC) +private val surfaceBrightLightMediumContrast = Color(0xFFFFF8F4) +private val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightMediumContrast = Color(0xFFFFF1E6) +private val surfaceContainerLightMediumContrast = Color(0xFFFAEBE0) +private val surfaceContainerHighLightMediumContrast = Color(0xFFF4E6DA) +private val surfaceContainerHighestLightMediumContrast = Color(0xFFEEE0D5) + +private val primaryLightHighContrast = Color(0xFF351D00) +private val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +private val primaryContainerLightHighContrast = Color(0xFF623A00) +private val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val secondaryLightHighContrast = Color(0xFF301F0A) +private val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +private val secondaryContainerLightHighContrast = Color(0xFF543F28) +private val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryLightHighContrast = Color(0xFF1B2605) +private val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +private val tertiaryContainerLightHighContrast = Color(0xFF3B4722) +private val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +private val errorLightHighContrast = Color(0xFF4E0002) +private val onErrorLightHighContrast = Color(0xFFFFFFFF) +private val errorContainerLightHighContrast = Color(0xFF8C0009) +private val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +private val backgroundLightHighContrast = Color(0xFFFFF8F4) +private val onBackgroundLightHighContrast = Color(0xFF211A14) +private val surfaceLightHighContrast = Color(0xFFFFF8F4) +private val onSurfaceLightHighContrast = Color(0xFF000000) +private val surfaceVariantLightHighContrast = Color(0xFFF1DFD0) +private val onSurfaceVariantLightHighContrast = Color(0xFF2C2219) +private val outlineLightHighContrast = Color(0xFF4C4136) +private val outlineVariantLightHighContrast = Color(0xFF4C4136) +private val scrimLightHighContrast = Color(0xFF000000) +private val inverseSurfaceLightHighContrast = Color(0xFF372F27) +private val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +private val inversePrimaryLightHighContrast = Color(0xFFFFE8D4) +private val surfaceDimLightHighContrast = Color(0xFFE5D8CC) +private val surfaceBrightLightHighContrast = Color(0xFFFFF8F4) +private val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +private val surfaceContainerLowLightHighContrast = Color(0xFFFFF1E6) +private val surfaceContainerLightHighContrast = Color(0xFFFAEBE0) +private val surfaceContainerHighLightHighContrast = Color(0xFFF4E6DA) +private val surfaceContainerHighestLightHighContrast = Color(0xFFEEE0D5) + + +private val primaryDark = Color(0xFFFABA73) +private val onPrimaryDark = Color(0xFF482900) +private val primaryContainerDark = Color(0xFF673D00) +private val onPrimaryContainerDark = Color(0xFFFFDDBB) +private val secondaryDark = Color(0xFFE0C1A3) +private val onSecondaryDark = Color(0xFF402D17) +private val secondaryContainerDark = Color(0xFF58432C) +private val onSecondaryContainerDark = Color(0xFFFDDDBD) +private val tertiaryDark = Color(0xFFBDCC9C) +private val onTertiaryDark = Color(0xFF293412) +private val tertiaryContainerDark = Color(0xFF3F4B26) +private val onTertiaryContainerDark = Color(0xFFD9E9B6) +private val errorDark = Color(0xFFFFB4AB) +private val onErrorDark = Color(0xFF690005) +private val errorContainerDark = Color(0xFF93000A) +private val onErrorContainerDark = Color(0xFFFFDAD6) +private val backgroundDark = Color(0xFF18120C) +private val onBackgroundDark = Color(0xFFEEE0D5) +private val surfaceDark = Color(0xFF18120C) +private val onSurfaceDark = Color(0xFFEEE0D5) +private val surfaceVariantDark = Color(0xFF50453A) +private val onSurfaceVariantDark = Color(0xFFD4C4B5) +private val outlineDark = Color(0xFF9D8E81) +private val outlineVariantDark = Color(0xFF50453A) +private val scrimDark = Color(0xFF000000) +private val inverseSurfaceDark = Color(0xFFEEE0D5) +private val inverseOnSurfaceDark = Color(0xFF372F27) +private val inversePrimaryDark = Color(0xFF845415) +private val surfaceDimDark = Color(0xFF18120C) +private val surfaceBrightDark = Color(0xFF403830) +private val surfaceContainerLowestDark = Color(0xFF130D07) +private val surfaceContainerLowDark = Color(0xFF211A14) +private val surfaceContainerDark = Color(0xFF251E17) +private val surfaceContainerHighDark = Color(0xFF302921) +private val surfaceContainerHighestDark = Color(0xFF3B332C) + +private val primaryDarkMediumContrast = Color(0xFFFFBE76) +private val onPrimaryDarkMediumContrast = Color(0xFF241200) +private val primaryContainerDarkMediumContrast = Color(0xFFBE8543) +private val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +private val secondaryDarkMediumContrast = Color(0xFFE4C5A7) +private val onSecondaryDarkMediumContrast = Color(0xFF221302) +private val secondaryContainerDarkMediumContrast = Color(0xFFA78C70) +private val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +private val tertiaryDarkMediumContrast = Color(0xFFC2D1A0) +private val onTertiaryDarkMediumContrast = Color(0xFF0F1900) +private val tertiaryContainerDarkMediumContrast = Color(0xFF88966A) +private val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +private val errorDarkMediumContrast = Color(0xFFFFBAB1) +private val onErrorDarkMediumContrast = Color(0xFF370001) +private val errorContainerDarkMediumContrast = Color(0xFFFF5449) +private val onErrorContainerDarkMediumContrast = Color(0xFF000000) +private val backgroundDarkMediumContrast = Color(0xFF18120C) +private val onBackgroundDarkMediumContrast = Color(0xFFEEE0D5) +private val surfaceDarkMediumContrast = Color(0xFF18120C) +private val onSurfaceDarkMediumContrast = Color(0xFFFFFAF8) +private val surfaceVariantDarkMediumContrast = Color(0xFF50453A) +private val onSurfaceVariantDarkMediumContrast = Color(0xFFD9C8B9) +private val outlineDarkMediumContrast = Color(0xFFB0A092) +private val outlineVariantDarkMediumContrast = Color(0xFF8F8174) +private val scrimDarkMediumContrast = Color(0xFF000000) +private val inverseSurfaceDarkMediumContrast = Color(0xFFEEE0D5) +private val inverseOnSurfaceDarkMediumContrast = Color(0xFF302921) +private val inversePrimaryDarkMediumContrast = Color(0xFF693E00) +private val surfaceDimDarkMediumContrast = Color(0xFF18120C) +private val surfaceBrightDarkMediumContrast = Color(0xFF403830) +private val surfaceContainerLowestDarkMediumContrast = Color(0xFF130D07) +private val surfaceContainerLowDarkMediumContrast = Color(0xFF211A14) +private val surfaceContainerDarkMediumContrast = Color(0xFF251E17) +private val surfaceContainerHighDarkMediumContrast = Color(0xFF302921) +private val surfaceContainerHighestDarkMediumContrast = Color(0xFF3B332C) + +private val primaryDarkHighContrast = Color(0xFFFFFAF8) +private val onPrimaryDarkHighContrast = Color(0xFF000000) +private val primaryContainerDarkHighContrast = Color(0xFFFFBE76) +private val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +private val secondaryDarkHighContrast = Color(0xFFFFFAF8) +private val onSecondaryDarkHighContrast = Color(0xFF000000) +private val secondaryContainerDarkHighContrast = Color(0xFFE4C5A7) +private val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +private val tertiaryDarkHighContrast = Color(0xFFF5FFDB) +private val onTertiaryDarkHighContrast = Color(0xFF000000) +private val tertiaryContainerDarkHighContrast = Color(0xFFC2D1A0) +private val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +private val errorDarkHighContrast = Color(0xFFFFF9F9) +private val onErrorDarkHighContrast = Color(0xFF000000) +private val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +private val onErrorContainerDarkHighContrast = Color(0xFF000000) +private val backgroundDarkHighContrast = Color(0xFF18120C) +private val onBackgroundDarkHighContrast = Color(0xFFEEE0D5) +private val surfaceDarkHighContrast = Color(0xFF18120C) +private val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +private val surfaceVariantDarkHighContrast = Color(0xFF50453A) +private val onSurfaceVariantDarkHighContrast = Color(0xFFFFFAF8) +private val outlineDarkHighContrast = Color(0xFFD9C8B9) +private val outlineVariantDarkHighContrast = Color(0xFFD9C8B9) +private val scrimDarkHighContrast = Color(0xFF000000) +private val inverseSurfaceDarkHighContrast = Color(0xFFEEE0D5) +private val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +private val inversePrimaryDarkHighContrast = Color(0xFF3F2400) +private val surfaceDimDarkHighContrast = Color(0xFF18120C) +private val surfaceBrightDarkHighContrast = Color(0xFF403830) +private val surfaceContainerLowestDarkHighContrast = Color(0xFF130D07) +private val surfaceContainerLowDarkHighContrast = Color(0xFF211A14) +private val surfaceContainerDarkHighContrast = Color(0xFF251E17) +private val surfaceContainerHighDarkHighContrast = Color(0xFF302921) +private val surfaceContainerHighestDarkHighContrast = Color(0xFF3B332C) -private val md_theme_dark_primary = Color(0xFFFFB77A) -private val md_theme_dark_onPrimary = Color(0xFF4C2700) -private val md_theme_dark_primaryContainer = Color(0xFF6D3A00) -private val md_theme_dark_onPrimaryContainer = Color(0xFFFFDCC2) -private val md_theme_dark_secondary = Color(0xFFE3C0A5) -private val md_theme_dark_onSecondary = Color(0xFF412C19) -private val md_theme_dark_secondaryContainer = Color(0xFF5A422E) -private val md_theme_dark_onSecondaryContainer = Color(0xFFFFDCC2) -private val md_theme_dark_tertiary = Color(0xFFC4CB97) -private val md_theme_dark_onTertiary = Color(0xFF2D330E) -private val md_theme_dark_tertiaryContainer = Color(0xFF434A22) -private val md_theme_dark_onTertiaryContainer = Color(0xFFE0E7B1) -private val md_theme_dark_error = Color(0xFFFFB4AB) -private val md_theme_dark_errorContainer = Color(0xFF93000A) -private val md_theme_dark_onError = Color(0xFF690005) -private val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) -private val md_theme_dark_background = Color(0xFF201B17) -private val md_theme_dark_onBackground = Color(0xFFECE0DA) -private val md_theme_dark_surface = Color(0xFF201B17) -private val md_theme_dark_onSurface = Color(0xFFECE0DA) -private val md_theme_dark_surfaceVariant = Color(0xFF51443B) -private val md_theme_dark_onSurfaceVariant = Color(0xFFD6C3B6) -private val md_theme_dark_outline = Color(0xFF9E8E82) -private val md_theme_dark_inverseOnSurface = Color(0xFF201B17) -private val md_theme_dark_inverseSurface = Color(0xFFECE0DA) -private val md_theme_dark_inversePrimary = Color(0xFF8F4E00) -private val md_theme_dark_surfaceTint = Color(0xFFFFB77A) -private val md_theme_dark_outlineVariant = Color(0xFF51443B) -private val md_theme_dark_scrim = Color(0xFF000000) @Composable -fun yellowTheme(isDark: Boolean): ColorScheme { +fun yellowTheme(isDark: Boolean, themeContrast: ThemeContrast): ColorScheme { return if (isDark) { - darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, + ) + } + + ThemeContrast.MEDIUM -> { + darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, + ) + } + } } else { - lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim - ) + when (themeContrast) { + ThemeContrast.STANDARD -> { + lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, + ) + } + + ThemeContrast.MEDIUM -> { + lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, + ) + } + + ThemeContrast.HIGH -> { + lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index d774d0bc..e1475871 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -18,6 +18,7 @@ Видалити книгу? Перемістити книгу? Видалити історію читання? + Підтвердити оновлення? @@ -48,6 +49,11 @@ Це видалить всю історію з бази даних. + + При підтвердженні ця книга буде оновлена. + Будь ласка, запам\'ятайте де ви зупинилися перед оновленням тексту. + Наступне буде оновлено: + @@ -57,6 +63,9 @@ Немає опису. + Щось пішло не так. + + Щось пішло не так. Будь ласка, перевірте чи файл цієї книги не пошкоджений. Хибний формат файлу. @@ -106,6 +115,7 @@ Перекласти Словник Ще раз + Підтвердити файли @@ -121,6 +131,9 @@ Виберіть нову обкладинку з ваших фото Видалити обкладинку Видаліть нинішню обкладинку книги + Автор + Опис + Текст Читаю @@ -147,6 +160,7 @@ Мова застосунка Темна тема + Контрастність теми Тема застосунка Сімейство шрифтів Стиль шрифта @@ -163,9 +177,14 @@ Синій - Вимкнено - Ввімкнено - Тема системи + Вимкнена + Ввімкнена + Системна + + + Типова + Середня + Висока Похилий @@ -198,6 +217,7 @@ Елемент історії був успішно видалений. Файл \"%1$s\" не знайдено. Текст, автор та опис книги були успішно оновлені. + Книга актуальна. Перемістити @@ -236,6 +256,12 @@ Слава Україні! 🇺🇦 Героям Слава! 🐉 + + Будь ласка, зверніть увагу, що на + такий виділений текст + можна натиснути. + На мене можна натиснути! + За замовчуванням @@ -244,29 +270,30 @@ Вчора - Оновити текст, автора та опис книги + Оновити книгу Продовжити читання Назад Обкладинка - Відкрити налаштування читача - Анімація фону - Анімація контуру + Налаштування читача Анімація верхньої панелі Файл Галочка - Показати випадаючий список + Випадаючий список Обкладенка не знайдена Застосувати зміни Помилка Пошук - Очистити вибрані предмети + Очистити обрані предмети Додати файли Вийти з пошуку Видалити всю історію - Перемістити книгу в іншу категорію + Перемістити обрані книги Видалити обрані книги Повернути Вибрано Іконка застосунку + Примітка + Видалити елемент історії + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a84c2cb..39401e85 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - 0.9.3 + 0.9.6 Book\'s Story https://github.com/Acclorite/book-story/releases/latest @@ -34,6 +34,7 @@ Delete book? Move book? Delete reading history? + Confirm update? @@ -64,6 +65,11 @@ It will delete the whole history from the database. + + By confirming this book will be updated. + Please remember where you left before updating text. + Following will be updated: + @@ -73,6 +79,9 @@ No description. + Something went wrong. + + Something went wrong. Please check whether this book\'s file is not corrupted. Wrong file format. @@ -121,6 +130,7 @@ Translate Dictionary Retry + Confirm files @@ -136,6 +146,9 @@ Choose new cover from your photos Delete cover image Delete current cover image of the book + Author + Description + Text Reading @@ -162,6 +175,7 @@ App language Dark theme + Theme contrast App theme Font family Font style @@ -180,7 +194,12 @@ Disabled Enabled - Follow system + System + + + Standard + Medium + High Italic @@ -213,6 +232,7 @@ History element was successfully deleted. File \"%1$s\" was not found. Book text, author and description were successfully updated. + Book is up to date. Move @@ -251,6 +271,12 @@ Slava Ukraini! 🇺🇦 Heroyam Slava! 🐉 + + Please note, that + such highlighted text + can be clicked. + I\'m clickable! + Default @@ -259,17 +285,15 @@ Yesterday - Refresh text, author and description of the book + Refresh book Continue reading Go back Cover image - Open reader settings - Background animation - Outline animation + Reader settings Top app bar animation File Checkbox - Show dropdown + Dropdown Cover image not found Apply changes Error @@ -278,10 +302,12 @@ Add files Exit search Delete whole history - Move books to another category + Move selected books Delete selected books Revert Selected App icon + Note + Delete history element \ No newline at end of file