From 667a91f950238349edbfad1c99d843dfdc51b39b Mon Sep 17 00:00:00 2001 From: acclorite Date: Wed, 19 Jun 2024 18:54:17 +0300 Subject: [PATCH] Navigation.kt: Type-safety, non-null parameters for Screens, improved navigation + Included generated Room Database schemas to be able to build the project. --- .../1.json | 126 ++++++++ .../2.json | 161 ++++++++++ .../java/ua/acclorite/book_story/Activity.kt | 54 ++-- .../book_story/domain/util/Constants.kt | 6 +- .../book_story/domain/util/Typealias.kt | 3 + .../presentation/components/GoBackButton.kt | 15 +- .../presentation/components/MoreDropDown.kt | 9 +- .../BottomNavigationBar.kt | 16 +- .../CustomNavigationRail.kt | 16 +- .../presentation/data/Navigation.kt | 290 +++++++++++------- .../presentation/screens/about/AboutScreen.kt | 16 +- .../about/nested/credits/CreditsScreen.kt | 8 +- .../nested/license_info/LicenseInfoScreen.kt | 20 +- .../license_info/data/LicenseInfoViewModel.kt | 18 +- .../about/nested/licenses/LicensesScreen.kt | 17 +- .../screens/book_info/BookInfoScreen.kt | 20 +- .../components/dialog/BookInfoDeleteDialog.kt | 7 +- .../components/dialog/BookInfoMoveDialog.kt | 10 +- .../screens/book_info/data/BookInfoEvent.kt | 10 +- .../book_info/data/BookInfoViewModel.kt | 86 ++++-- .../screens/browse/BrowseScreen.kt | 16 +- .../adding_dialog/BrowseAddingDialog.kt | 9 +- .../screens/browse/data/BrowseEvent.kt | 7 +- .../screens/browse/data/BrowseViewModel.kt | 7 +- .../presentation/screens/help/HelpScreen.kt | 33 +- .../help/components/items/HelpAddBooksItem.kt | 23 +- .../help/components/items/HelpCustomizeApp.kt | 15 +- .../components/items/HelpCustomizeReader.kt | 15 +- .../help/components/items/HelpEditBook.kt | 15 +- .../components/items/HelpManageHistory.kt | 15 +- .../components/items/HelpMoveOrDeleteBooks.kt | 15 +- .../help/components/items/HelpReadBook.kt | 15 +- .../components/items/HelpSetUpTranslator.kt | 15 +- .../help/components/items/HelpUpdateBook.kt | 15 +- .../screens/help/data/HelpViewModel.kt | 8 +- .../screens/history/HistoryScreen.kt | 25 +- .../screens/history/data/HistoryEvent.kt | 4 +- .../screens/history/data/HistoryViewModel.kt | 11 +- .../screens/library/LibraryScreen.kt | 23 +- .../screens/library/data/LibraryEvent.kt | 4 +- .../screens/library/data/LibraryViewModel.kt | 11 +- .../screens/reader/ReaderScreen.kt | 26 +- .../reader/components/ReaderEndItem.kt | 13 +- .../reader/components/app_bar/ReaderTopBar.kt | 23 +- .../screens/reader/data/ReaderEvent.kt | 15 +- .../screens/reader/data/ReaderViewModel.kt | 28 +- .../screens/settings/SettingsScreen.kt | 20 +- .../nested/appearance/AppearanceSettings.kt | 8 +- .../nested/general/GeneralSettings.kt | 8 +- .../settings/nested/reader/ReaderSettings.kt | 8 +- .../screens/start/components/StartDone.kt | 13 +- .../screens/start/data/StartEvent.kt | 6 +- .../screens/start/data/StartViewModel.kt | 10 +- 53 files changed, 922 insertions(+), 465 deletions(-) create mode 100644 app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/1.json create mode 100644 app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/2.json diff --git a/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/1.json b/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/1.json new file mode 100644 index 00000000..16d81a83 --- /dev/null +++ b/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/1.json @@ -0,0 +1,126 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "c8a3497d25808dec49816f26182b61d6", + "entities": [ + { + "tableName": "BookEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `author` TEXT, `description` TEXT, `textPath` TEXT NOT NULL, `filePath` TEXT NOT NULL, `scrollIndex` INTEGER NOT NULL, `scrollOffset` INTEGER NOT NULL, `progress` REAL NOT NULL, `image` TEXT, `category` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "textPath", + "columnName": "textPath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "filePath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "scrollIndex", + "columnName": "scrollIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scrollOffset", + "columnName": "scrollOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "progress", + "columnName": "progress", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "HistoryEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bookId` INTEGER NOT NULL, `time` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookId", + "columnName": "bookId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c8a3497d25808dec49816f26182b61d6')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/2.json b/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/2.json new file mode 100644 index 00000000..fe0e55ba --- /dev/null +++ b/app/schemas/ua.acclorite.book_story.data.local.room.BookDatabase/2.json @@ -0,0 +1,161 @@ +{ + "formatVersion": 1, + "database": { + "version": 2, + "identityHash": "6c2faed7c7730847a4e20e2eadd73a55", + "entities": [ + { + "tableName": "BookEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `author` TEXT, `description` TEXT, `textPath` TEXT NOT NULL, `filePath` TEXT NOT NULL, `scrollIndex` INTEGER NOT NULL, `scrollOffset` INTEGER NOT NULL, `progress` REAL NOT NULL, `image` TEXT, `category` TEXT NOT NULL, `enableTranslator` INTEGER NOT NULL DEFAULT false, `translateFrom` TEXT NOT NULL DEFAULT 'auto', `translateTo` TEXT NOT NULL DEFAULT 'en', `doubleClickTranslation` INTEGER NOT NULL DEFAULT true, `translateWhenOpen` INTEGER NOT NULL DEFAULT false)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "textPath", + "columnName": "textPath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "filePath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "scrollIndex", + "columnName": "scrollIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scrollOffset", + "columnName": "scrollOffset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "progress", + "columnName": "progress", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "enableTranslator", + "columnName": "enableTranslator", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "translateFrom", + "columnName": "translateFrom", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'auto'" + }, + { + "fieldPath": "translateTo", + "columnName": "translateTo", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'en'" + }, + { + "fieldPath": "doubleClickTranslation", + "columnName": "doubleClickTranslation", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "true" + }, + { + "fieldPath": "translateWhenOpen", + "columnName": "translateWhenOpen", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "HistoryEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bookId` INTEGER NOT NULL, `time` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookId", + "columnName": "bookId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6c2faed7c7730847a4e20e2eadd73a55')" + ] + } +} \ No newline at end of file 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 c0b89360..e52a08aa 100644 --- a/app/src/main/java/ua/acclorite/book_story/Activity.kt +++ b/app/src/main/java/ua/acclorite/book_story/Activity.kt @@ -112,11 +112,15 @@ class Activity : AppCompatActivity() { themeContrast = state.value.themeContrast!! ) { NavigationHost( - startScreen = if (state.value.showStartScreen!!) Screen.START - else Screen.LIBRARY + startScreen = if (state.value.showStartScreen!!) Screen.Start + else Screen.Library ) { navigation( - screens = arrayOf(Screen.LIBRARY, Screen.HISTORY, Screen.BROWSE), + screens = arrayOf( + Screen.Library.getRoute(), + Screen.History.getRoute(), + Screen.Browse.getRoute() + ), bottomBar = { BottomNavigationBar() }, @@ -125,8 +129,7 @@ class Activity : AppCompatActivity() { } ) { // Library - composable( - screen = Screen.LIBRARY, + composable( enterAnim = Transitions.FadeTransitionIn, exitAnim = Transitions.FadeTransitionOut ) { @@ -134,8 +137,7 @@ class Activity : AppCompatActivity() { } // History - composable( - screen = Screen.HISTORY, + composable( enterAnim = Transitions.FadeTransitionIn, exitAnim = Transitions.FadeTransitionOut ) { @@ -143,8 +145,7 @@ class Activity : AppCompatActivity() { } // Browse - composable( - screen = Screen.BROWSE, + composable( enterAnim = Transitions.FadeTransitionIn, exitAnim = Transitions.FadeTransitionOut ) { @@ -153,57 +154,54 @@ class Activity : AppCompatActivity() { } // Book Info - composable(screen = Screen.BOOK_INFO) { - BookInfoScreenRoot() + composable { + BookInfoScreenRoot(it) } // Reader - composable(screen = Screen.READER) { - ReaderScreenRoot() + composable { + ReaderScreenRoot(it) } // Settings - composable(screen = Screen.SETTINGS) { + composable { SettingsScreenRoot() } // Nested settings categories - composable(screen = Screen.GENERAL_SETTINGS) { + composable { GeneralSettingsRoot() } - composable(screen = Screen.APPEARANCE_SETTINGS) { + composable { AppearanceSettingsRoot() } - composable(screen = Screen.READER_SETTINGS) { + composable { ReaderSettingsRoot() } // About screen - composable(screen = Screen.ABOUT) { + composable { AboutScreenRoot() } // Nested about categories - composable(screen = Screen.LICENSES) { + composable { LicensesScreenRoot() } - composable(screen = Screen.LICENSES_INFO) { - LicenseInfoScreenRoot() + composable { + LicenseInfoScreenRoot(it) } - composable(screen = Screen.CREDITS) { + composable { CreditsScreenRoot() } // Help screen - composable(screen = Screen.HELP) { - HelpScreenRoot() + composable { + HelpScreenRoot(it) } // Start screen - composable( - screen = Screen.START, - enterAnim = Transitions.FadeTransitionIn - ) { + composable(enterAnim = Transitions.FadeTransitionIn) { StartScreenRoot() } } 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 a69115b2..c78fb11a 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 @@ -30,21 +30,21 @@ object Constants { // Navigation items for NavigationBars. val NAVIGATION_ITEMS = listOf( NavigationItem( - screen = Screen.LIBRARY, + screen = Screen.Library, title = R.string.library_screen, tooltip = R.string.library_content_desc, selectedIcon = R.drawable.library_screen_filled, unselectedIcon = R.drawable.library_screen_outlined ), NavigationItem( - screen = Screen.HISTORY, + screen = Screen.History, title = R.string.history_screen, tooltip = R.string.history_content_desc, selectedIcon = R.drawable.history_screen_filled, unselectedIcon = R.drawable.history_screen_outlined ), NavigationItem( - screen = Screen.BROWSE, + screen = Screen.Browse, title = R.string.browse_screen, tooltip = R.string.browse_content_desc, selectedIcon = R.drawable.browse_screen_filled, diff --git a/app/src/main/java/ua/acclorite/book_story/domain/util/Typealias.kt b/app/src/main/java/ua/acclorite/book_story/domain/util/Typealias.kt index 2cd826ec..a88b6e2d 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/util/Typealias.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/util/Typealias.kt @@ -1,8 +1,11 @@ package ua.acclorite.book_story.domain.util import android.graphics.Bitmap +import ua.acclorite.book_story.presentation.data.Navigator typealias CoverImage = Bitmap typealias Selected = Boolean typealias ID = Int typealias LanguageCode = String +typealias Route = String +typealias OnNavigate = (Navigator.() -> Unit) -> Unit 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 6a5b5075..aa5d2ff0 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 @@ -4,13 +4,18 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.runtime.Composable import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate /** - * Go back arrow button. Prevents double or triple clicking on it while going back action is performed. + * Go back arrow button. + * Prevents double or triple clicking on it while going back action is performed. + * + * @param onNavigate [OnNavigate]. + * @param enabled Whether this button is enabled. + * @param customOnClick Call before going back. */ @Composable -fun GoBackButton(navigator: Navigator, enabled: Boolean = true, customOnClick: () -> Unit = {}) { +fun GoBackButton(onNavigate: OnNavigate, enabled: Boolean = true, customOnClick: () -> Unit = {}) { CustomIconButton( icon = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = R.string.go_back_content_desc, @@ -18,6 +23,8 @@ fun GoBackButton(navigator: Navigator, enabled: Boolean = true, customOnClick: ( enabled = enabled ) { customOnClick() - navigator.navigateBack() + onNavigate { + navigateBack() + } } } \ No newline at end of file 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 c41d7af2..71972dde 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 @@ -21,7 +21,8 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.Screen /** - * More drop down. Navigates to Settings, About and Help screens. + * More drop down. + * Navigates to Settings, About and Help screens. */ @Composable fun MoreDropDown() { @@ -55,7 +56,7 @@ fun MoreDropDown() { ) }, onClick = { - navigator.navigate(Screen.SETTINGS, false) + navigator.navigate(Screen.Settings) }, contentPadding = PaddingValues(start = startPadding, end = endPadding) ) @@ -68,7 +69,7 @@ fun MoreDropDown() { ) }, onClick = { - navigator.navigate(Screen.HELP, false) + navigator.navigate(Screen.Help(false)) }, contentPadding = PaddingValues(start = startPadding, end = endPadding) ) @@ -81,7 +82,7 @@ fun MoreDropDown() { ) }, onClick = { - navigator.navigate(Screen.ABOUT, false) + navigator.navigate(Screen.About) }, 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 45d02e0f..0761654d 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 @@ -8,21 +8,25 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.Route import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Screen /** * Bottom navigation bar, uses default [NavigationBar]. */ @Composable fun BottomNavigationBar() { - var currentScreen: Screen? by remember { mutableStateOf(null) } + var currentScreen: Route? by remember { mutableStateOf(null) } val navigator = LocalNavigator.current LaunchedEffect(Unit) { - navigator.getCurrentScreen().collect { - if (it == Screen.LIBRARY || it == Screen.HISTORY || it == Screen.BROWSE) { - currentScreen = it + navigator.currentScreen.collect { route -> + if ( + Constants.NAVIGATION_ITEMS.any { + navigator.run { it.screen.getRoute() } == route + } + ) { + currentScreen = route } } } @@ -31,7 +35,7 @@ fun BottomNavigationBar() { Constants.NAVIGATION_ITEMS.forEach { BottomNavigationBarItem( item = it, - isSelected = currentScreen == it.screen + isSelected = currentScreen == navigator.run { it.screen.getRoute() } ) { navigator.navigate(it.screen, false) } 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 81eb2e0f..04d55f5b 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 @@ -24,22 +24,26 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.Route import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Screen /** * Custom Navigation Rail. It is used to be shown on Tablets. */ @Composable fun BoxScope.CustomNavigationRail() { - var currentScreen: Screen? by remember { mutableStateOf(null) } + var currentScreen: Route? by remember { mutableStateOf(null) } val navigator = LocalNavigator.current val layoutDirection = LocalLayoutDirection.current LaunchedEffect(Unit) { - navigator.getCurrentScreen().collect { - if (it == Screen.LIBRARY || it == Screen.HISTORY || it == Screen.BROWSE) { - currentScreen = it + navigator.currentScreen.collect { route -> + if ( + Constants.NAVIGATION_ITEMS.any { + navigator.run { it.screen.getRoute() } == route + } + ) { + currentScreen = route } } } @@ -69,7 +73,7 @@ fun BoxScope.CustomNavigationRail() { Constants.NAVIGATION_ITEMS.forEach { CustomNavigationRailItem( item = it, - isSelected = currentScreen == it.screen + isSelected = currentScreen == navigator.run { it.screen.getRoute() } ) { navigator.navigate(it.screen, false) } 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 2c7afc11..68c6ae8f 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 @@ -43,60 +43,87 @@ import dagger.assisted.AssistedInject import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.withCreationCallback import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize +import kotlinx.serialization.Serializable +import ua.acclorite.book_story.domain.util.Route import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility 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" +private const val SCREENS = "screens" +/** + * Passed in [CompositionLocalProvider] and can be accessed through [LocalNavigator].current. + */ val LocalNavigator = compositionLocalOf { error("Cannot initialize Navigator.") } /** - * All screens are listed here, later each screen will be passed as a param for [Navigator.composable] function. - */ -enum class Screen { - LIBRARY, - HISTORY, - BROWSE, - - BOOK_INFO, - READER, - - SETTINGS, - GENERAL_SETTINGS, - APPEARANCE_SETTINGS, - READER_SETTINGS, - - ABOUT, - LICENSES, - LICENSES_INFO, - CREDITS, - - HELP, - START -} - -/** - * Navigation Argument. + * Screens. Should be [Serializable] to be able to pass them inside [SavedStateHandle]. + * Each screen should have unique name. */ @Immutable @Parcelize -data class Argument( - val key: String, - val value: T -) : Parcelable +sealed class Screen : Parcelable { + + @Parcelize + data object Library : Screen() + + @Parcelize + data object History : Screen() + + @Parcelize + data object Browse : Screen() + + @Parcelize + data class BookInfo( + val bookId: Int + ) : Screen() + + @Parcelize + data class Reader( + val bookId: Int + ) : Screen() + + @Parcelize + data object Settings : Screen() { + @Parcelize + data object General : Screen() + + @Parcelize + data object Appearance : Screen() + + @Parcelize + data object ReaderSettings : Screen() + } + + @Parcelize + data object About : Screen() { + @Parcelize + data object Licenses : Screen() + + @Parcelize + data class LicenseInfo(val licenseId: String) : Screen() + + @Parcelize + data object Credits : Screen() + } + + @Parcelize + data class Help( + val fromStart: Boolean + ) : Screen() + + @Parcelize + data object Start : Screen() +} /** - * Navigator. Using to navigate between screens. + * Navigator. Used to navigate between screens. * * [Navigator.currentScreen] param represents current [Screen]. * [Navigator.navigate] navigates to [Screen] passed as param. @@ -104,139 +131,186 @@ data class Argument( @HiltViewModel(assistedFactory = Navigator.Factory::class) class Navigator @AssistedInject constructor( private val savedStateHandle: SavedStateHandle, - @Assisted startScreen: Screen + @Assisted private val startScreen: Screen ) : ViewModel() { - 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 = savedStateHandle - .getStateFlow(ARGUMENTS, mutableListOf>()) + val currentScreen = savedStateHandle.getStateFlow(CURRENT_SCREEN, startScreen.getRoute()) + val useBackAnimation = savedStateHandle.getStateFlow(USE_BACK_ANIM, false) + private val backStack = savedStateHandle.getStateFlow(BACKSTACK, mutableListOf()) + val screens = savedStateHandle.getStateFlow(SCREENS, mutableListOf()) - fun putArgument(argument: Argument) { + init { + putScreen(startScreen) + } + + /** + * Saves screen into [screens]. Later can be retrieved via [retrieveScreen]. + * + * @param screen [Screen]. + */ + fun putScreen(screen: Screen) { var found = false - for ((index, arg) in arguments.value.withIndex()) { - if (arg.key == argument.key) { - arguments.value[index] = argument + for ((index, arg) in screens.value.withIndex()) { + if (arg.getRoute() == screen.getRoute()) { + screens.value[index] = screen found = true break } } if (!found) { - arguments.value.add(argument) + screens.value.add(screen) } } - fun retrieveArgument(key: String): Serializable? { - for (arg in arguments.value) { - if (arg.key == key) { - return arg.value + /** + * Retrieves screen that was put via [putScreen]. + * + * @exception Exception if there is no such screen saved that specified in [S], throws an [Exception]. + */ + inline fun retrieveScreen(): S { + for (arg in screens.value) { + if (arg.getRoute() == getRoute()) { + return arg as S } } - return null + + throw Exception("Screen was not found.") } - fun clearArgument(key: String) { - arguments.value.removeIf { it.key == key } - } - - fun navigate(screen: Screen, useBackAnimation: Boolean, vararg args: Argument) = - viewModelScope.launch(Dispatchers.Default) { - backStack.value.add(currentScreen.value) - - args.forEach { - putArgument(it) - } - - savedStateHandle[USE_BACK_ANIM] = useBackAnimation - savedStateHandle[CURRENT_SCREEN] = screen - } - - fun navigateWithoutBackStack( + /** + * Navigates to the desired screen. Ignored if [currentScreen] is already [screen]. + * + * @param screen [Screen] to navigate to. + * @param useBackAnimation Whether back animation should be used(as when user goes back). + * @param saveInBackStack Whether this screen should be saved in [backStack] (basically history of all opened screens). + */ + fun navigate( screen: Screen, - useBackAnimation: Boolean, - vararg args: Argument + useBackAnimation: Boolean = false, + saveInBackStack: Boolean = true ) = viewModelScope.launch(Dispatchers.Default) { - if (backStack.value.lastOrNull() == screen) { - backStack.value.removeLast() + if (screen.getRoute() == currentScreen.value) { + return@launch } - args.forEach { - putArgument(it) + if (saveInBackStack) { + backStack.value.add(currentScreen.value) } + putScreen(screen) + savedStateHandle[USE_BACK_ANIM] = useBackAnimation - savedStateHandle[CURRENT_SCREEN] = screen + savedStateHandle[CURRENT_SCREEN] = screen.getRoute() } - fun navigateBack(useBackAnimation: Boolean = true) = - viewModelScope.launch(Dispatchers.Default) { - if (canGoBack()) { - savedStateHandle[USE_BACK_ANIM] = useBackAnimation - savedStateHandle[CURRENT_SCREEN] = backStack.value.last() - backStack.value.removeLast() - } - } + /** + * Navigates user to the previous screen, if there is. + * If there is nowhere to go, this call is ignored. + * + * @param useBackAnimation Whether user should see back animation when he goes to the previous screen. + */ + fun navigateBack( + useBackAnimation: Boolean = true + ) = viewModelScope.launch(Dispatchers.Default) { + if (canGoBack()) { + savedStateHandle[USE_BACK_ANIM] = useBackAnimation + savedStateHandle[CURRENT_SCREEN] = backStack.value.last() + backStack.value.removeLast() + } + } + + /** + * Clears the whole [backStack]. + */ fun clearBackStack() { backStack.value.clear() } + /** + * Whether there is screen to go back. + */ fun canGoBack(): Boolean { return backStack.value.isNotEmpty() } - fun getCurrentScreen(): StateFlow { - return currentScreen - } - - fun getUseBackAnim(): StateFlow { - return useBackAnimation + /** + * Gets route of specified [S]. + */ + inline fun getRoute(): Route { + return S::class.simpleName!! } /** - * Animated Screen. Used in [NavigationHost]. Be sure to not use the same [screen] parameter twice, it'll override the highest one in your code. + * Gets route of this screen. + */ + fun Screen.getRoute(): Route { + return this::class.simpleName!! + } + + /** + * Animated Screen. Used in [NavigationHost]. + * Each [composable] should have unique [Screen]. * - * @param screen The [Screen] that represents [content]. * @param enterAnim Enter Animation. * @param backEnterAnim Enter Animation for navigating back. * @param exitAnim Exit Animation. * @param backExitAnim Exit Animation for navigating back. - * @param content The Screen content to show when [Navigator.currentScreen] equals [screen]. + * @param content The Screen content to show when [Navigator.currentScreen] equals [S]. */ @SuppressLint("ComposableNaming") @Composable - fun composable( - screen: Screen, + inline fun composable( enterAnim: EnterTransition = Transitions.SlidingTransitionIn, backEnterAnim: EnterTransition = Transitions.BackSlidingTransitionIn, exitAnim: ExitTransition = Transitions.SlidingTransitionOut, backExitAnim: ExitTransition = Transitions.BackSlidingTransitionOut, - content: @Composable () -> Unit + noinline content: @Composable (screen: S) -> Unit ) { + val currentRoute by currentScreen.collectAsState() + val useBackAnimation by useBackAnimation.collectAsState() + CustomAnimatedVisibility( - visible = getCurrentScreen().collectAsState().value == screen, - enter = if (!useBackAnimation.collectAsState().value) enterAnim else backEnterAnim, - exit = if (!useBackAnimation.collectAsState().value) exitAnim else backExitAnim + visible = currentRoute == getRoute(), + enter = if (!useBackAnimation) enterAnim else backEnterAnim, + exit = if (!useBackAnimation) exitAnim else backExitAnim ) { - content() + val screen = remember { retrieveScreen() } + content(screen) } } + /** + * Navigator's navigation. + * Shows BottomBar or Navigation Rail when any of the [screens] are currently showing. + * + * @param screens [Screen]s where navigation shows. + * @param enterBarAnim Enter animation for navigation. + * @param backEnterBarAnim Back enter animation for navigation. + * @param exitBarAnim Exit animation for navigation. + * @param backExitBarAnim Back exit animation for navigation. + * @param bottomBar Bottom bar, sticks to the bottom. + * @param navigationRail Navigation rail, sticks to the sides. + * @param content Content, all [screens] should be inside as [composable]. + */ @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @SuppressLint("ComposableNaming") @Composable fun navigation( - vararg screens: Screen, + vararg screens: Route, + enterBarAnim: EnterTransition = Transitions.SlidingTransitionIn, + backEnterBarAnim: EnterTransition = Transitions.BackSlidingTransitionIn, + exitBarAnim: ExitTransition = Transitions.SlidingTransitionOut, + backExitBarAnim: ExitTransition = Transitions.BackSlidingTransitionOut, bottomBar: @Composable () -> Unit, navigationRail: @Composable BoxScope.() -> Unit, content: @Composable () -> Unit ) { val activity = LocalContext.current as ComponentActivity - val currentScreen by getCurrentScreen().collectAsState() - val useBackAnimation by getUseBackAnim().collectAsState() + val currentScreen by currentScreen.collectAsState() + val useBackAnimation by useBackAnimation.collectAsState() val shouldShow by remember(currentScreen) { derivedStateOf { screens.any { it == currentScreen } @@ -251,10 +325,10 @@ class Navigator @AssistedInject constructor( CustomAnimatedVisibility( visible = shouldShow, - enter = if (useBackAnimation) Transitions.BackSlidingTransitionIn - else Transitions.SlidingTransitionIn, - exit = if (useBackAnimation) Transitions.BackSlidingTransitionOut - else Transitions.SlidingTransitionOut + enter = if (useBackAnimation) backEnterBarAnim + else enterBarAnim, + exit = if (useBackAnimation) backExitBarAnim + else exitBarAnim ) { Scaffold( bottomBar = { @@ -305,13 +379,13 @@ class Navigator @AssistedInject constructor( } /** - * Navigation Host. Contains [Navigator.composable]s in [content]. + * Custom Navigation Host. Contains [Navigator.composable]s in [content]. + * Based on [CustomAnimatedVisibility]. * * @param startScreen Start Screen. Be sure to pass [Screen] that uses in one of your [Navigator.composable]s. * @param colorBetweenAnimations The color, that using between animations, recommended to set this to background or navigation bar color. * @param content Content of the [NavigationHost]. Highly recommended to use [Navigator.composable]. */ - @Composable fun NavigationHost( startScreen: Screen, 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 07997b5b..22b33883 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 @@ -33,10 +33,10 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.about.components.AboutItem import ua.acclorite.book_story.presentation.screens.about.components.AboutUpdateDialog @@ -53,7 +53,7 @@ fun AboutScreenRoot() { AboutScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = aboutViewModel::onEvent ) } @@ -62,7 +62,7 @@ fun AboutScreenRoot() { @Composable private fun AboutScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (AboutEvent) -> Unit ) { val context = LocalContext.current @@ -87,7 +87,7 @@ private fun AboutScreen( Text(stringResource(id = R.string.about_screen)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( @@ -213,7 +213,9 @@ private fun AboutScreen( title = stringResource(id = R.string.licenses_option), description = null ) { - navigator.navigate(Screen.LICENSES, false) + onNavigate { + navigate(Screen.About.Licenses) + } } } @@ -222,7 +224,9 @@ private fun AboutScreen( title = stringResource(id = R.string.credits_option), description = null ) { - navigator.navigate(Screen.CREDITS, false) + onNavigate { + navigate(Screen.About.Credits) + } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt index 030fcd00..a45ac87e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt @@ -21,11 +21,11 @@ import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator 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.screens.about.nested.credits.components.CreditItem @@ -36,7 +36,7 @@ fun CreditsScreenRoot() { val aboutViewModel: AboutViewModel = hiltViewModel() CreditsScreen( - navigator = navigator, + onNavigate = { navigator.it() }, onAboutNavigateEvent = aboutViewModel::onEvent ) } @@ -44,7 +44,7 @@ fun CreditsScreenRoot() { @OptIn(ExperimentalMaterial3Api::class) @Composable private fun CreditsScreen( - navigator: Navigator, + onNavigate: OnNavigate, onAboutNavigateEvent: (AboutEvent.OnNavigateToBrowserPage) -> Unit ) { val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() @@ -62,7 +62,7 @@ private fun CreditsScreen( Text(stringResource(id = R.string.credits_option)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt index fc98ec28..c7a1633c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt @@ -42,19 +42,20 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoEvent import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoState import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel import ua.acclorite.book_story.presentation.ui.SlidingTransition @Composable -fun LicenseInfoScreenRoot() { +fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) { val navigator = LocalNavigator.current val context = LocalContext.current val licenseInfoViewModel: LicenseInfoViewModel = hiltViewModel() @@ -63,15 +64,16 @@ fun LicenseInfoScreenRoot() { LaunchedEffect(Unit) { licenseInfoViewModel.init( - navigator, - context + screen = screen, + onNavigate = { navigator.it() }, + context = context ) } LicenseInfoScreen( state = state, - onEvent = licenseInfoViewModel::onEvent, - navigator = navigator + onNavigate = { navigator.it() }, + onEvent = licenseInfoViewModel::onEvent ) } @@ -79,8 +81,8 @@ fun LicenseInfoScreenRoot() { @Composable private fun LicenseInfoScreen( state: State, - onEvent: (LicenseInfoEvent) -> Unit, - navigator: Navigator + onNavigate: OnNavigate, + onEvent: (LicenseInfoEvent) -> Unit ) { val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val context = LocalContext.current @@ -106,7 +108,7 @@ private fun LicenseInfoScreen( ) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, actions = { if (state.value.license?.website?.isNotBlank() == true) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt index 423f94be..4d5f82fa 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt @@ -13,7 +13,8 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate +import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject @HiltViewModel @@ -42,25 +43,20 @@ class LicenseInfoViewModel @Inject constructor() : ViewModel() { } } - fun init(navigator: Navigator, context: Context) { + fun init(screen: Screen.About.LicenseInfo, onNavigate: OnNavigate, context: Context) { viewModelScope.launch(Dispatchers.IO) { _state.update { it.copy(license = null) } - val licenseId = navigator.retrieveArgument("license") as? String - - if (licenseId == null) { - navigator.navigateBack() - return@launch - } - val license = Libs.Builder().withContext(context).build().libraries.find { - it.uniqueId == licenseId + it.uniqueId == screen.licenseId } if (license == null) { - navigator.navigateBack() + onNavigate { + navigateBack() + } return@launch } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt index 2e644eae..c0c936d7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt @@ -28,13 +28,12 @@ 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.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems -import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.about.nested.licenses.components.LicenseItem import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState @@ -54,7 +53,7 @@ fun LicensesScreenRoot() { LicensesScreen( state = state, - navigator = navigator + onNavigate = { navigator.it() } ) } @@ -62,7 +61,7 @@ fun LicensesScreenRoot() { @Composable private fun LicensesScreen( state: State, - navigator: Navigator + onNavigate: OnNavigate ) { val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() @@ -78,7 +77,7 @@ private fun LicensesScreen( Text(stringResource(id = R.string.licenses_option)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( @@ -105,11 +104,9 @@ private fun LicensesScreen( customItems(state.value.licenses, key = { it.uniqueId }) { LicenseItem(library = it) { - navigator.navigate( - Screen.LICENSES_INFO, - false, - Argument("license", it.uniqueId) - ) + onNavigate { + navigate(Screen.About.LicenseInfo(it.uniqueId)) + } } } 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 51591384..44fcfb51 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 @@ -57,13 +57,14 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomSnackbar import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDescriptionSection import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoInfoSection @@ -87,7 +88,7 @@ import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions @Composable -fun BookInfoScreenRoot() { +fun BookInfoScreenRoot(screen: Screen.BookInfo) { val navigator = LocalNavigator.current val viewModel: BookInfoViewModel = hiltViewModel() @@ -99,13 +100,14 @@ fun BookInfoScreenRoot() { LaunchedEffect(Unit) { viewModel.init( - navigator + screen = screen, + onNavigate = { navigator.it() } ) } BookInfoScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = viewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent, onBrowseEvent = browseViewModel::onEvent, @@ -117,7 +119,7 @@ fun BookInfoScreenRoot() { @Composable private fun BookInfoScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (BookInfoEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit, onBrowseEvent: (BrowseEvent) -> Unit, @@ -203,7 +205,7 @@ private fun BookInfoScreen( onEvent(BookInfoEvent.OnShowHideEditTitle) } } else { - GoBackButton(navigator = navigator, enabled = !state.value.isRefreshing) { + GoBackButton(onNavigate = onNavigate, enabled = !state.value.isRefreshing) { onEvent(BookInfoEvent.OnCancelUpdate) } } @@ -329,7 +331,7 @@ private fun BookInfoScreen( FloatingActionButton( onClick = { if (!state.value.isRefreshing) { - onEvent(BookInfoEvent.OnNavigateToReaderScreen(navigator)) + onEvent(BookInfoEvent.OnNavigateToReaderScreen(onNavigate = onNavigate)) } }, shape = MaterialTheme.shapes.large, @@ -387,7 +389,9 @@ private fun BookInfoScreen( if (!state.value.isRefreshing) { onEvent(BookInfoEvent.OnCancelUpdate) - navigator.navigateBack() + onNavigate { + navigateBack() + } } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt index 1b65d5af..369c9051 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt @@ -16,6 +16,11 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** * Delete dialog. Deletes current book. + * + * @param onEvent [BookInfoEvent] callback. + * @param onLibraryLoadEvent [LibraryEvent] callback. + * @param onHistoryLoadEvent [HistoryEvent] callback. + * @param onBrowseLoadEvent [BrowseEvent] callback. */ @Composable fun BookInfoDeleteDialog( @@ -40,7 +45,7 @@ fun BookInfoDeleteDialog( onAction = { onEvent( BookInfoEvent.OnDeleteBook( - navigator = navigator, + onNavigate = { navigator.it() }, refreshList = { onLibraryLoadEvent(LibraryEvent.OnLoadList) onBrowseLoadEvent(BrowseEvent.OnLoadList) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt index 87fecad5..7559045e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt @@ -21,7 +21,13 @@ import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** - * Move dialog. Moves current book to the selected category. + * Move dialog. + * Moves current book to the selected category. + * + * @param state [BookInfoState]. + * @param onEvent [BookInfoEvent] callback. + * @param onLibraryEvent [LibraryEvent] callback. + * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @Composable fun BookInfoMoveDialog( @@ -60,7 +66,7 @@ fun BookInfoMoveDialog( updatePage = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) }, - navigator = navigator + onNavigate = { navigator.it() } ) ) Toast.makeText( 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 31017070..a6d06d00 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 @@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Category -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate @Immutable sealed class BookInfoEvent { @@ -23,11 +23,13 @@ sealed class BookInfoEvent { data class OnUpdateTitle(val refreshList: (Book) -> Unit) : BookInfoEvent() data object OnShowHideDeleteDialog : BookInfoEvent() data object OnShowHideMoveDialog : BookInfoEvent() - data class OnDeleteBook(val refreshList: () -> Unit, val navigator: Navigator) : BookInfoEvent() + data class OnDeleteBook(val refreshList: () -> Unit, val onNavigate: OnNavigate) : + BookInfoEvent() + data class OnMoveBook( val refreshList: (Book) -> Unit, val updatePage: (Int) -> Unit, - val navigator: Navigator + val onNavigate: OnNavigate ) : BookInfoEvent() data class OnSelectCategory(val category: Category) : BookInfoEvent() @@ -51,7 +53,7 @@ sealed class BookInfoEvent { ) : BookInfoEvent() data class OnNavigateToReaderScreen( - val navigator: Navigator + val onNavigate: OnNavigate ) : BookInfoEvent() data object OnDismissConfirmUpdateDialog : BookInfoEvent() 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 11de879a..72a52b92 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 @@ -22,15 +22,14 @@ 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.GetBookById 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.UpdateBookWithText import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.use_case.UpdateCoverImageOfBook -import ua.acclorite.book_story.presentation.data.Argument -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import java.io.File import java.util.Date @@ -45,7 +44,7 @@ class BookInfoViewModel @Inject constructor( private val insertHistory: InsertHistory, private val deleteBooks: DeleteBooks, private val getBookFromFile: GetBookFromFile, - private val getBookById: GetBooksById, + private val getBookById: GetBookById, private val getText: GetText ) : ViewModel() { @@ -76,11 +75,8 @@ class BookInfoViewModel @Inject constructor( image ) - val newCoverImage = getBookById.execute( - listOf( - _state.value.book.id - ) - ).first().coverImage + val newCoverImage = + getBookById.execute(_state.value.book.id)?.coverImage ?: return@launch _state.update { it.copy( @@ -197,7 +193,9 @@ class BookInfoViewModel @Inject constructor( deleteBooks.execute(listOf(_state.value.book)) event.refreshList() - event.navigator.navigateBack() + event.onNavigate { + navigateBack() + } } } @@ -240,7 +238,12 @@ class BookInfoViewModel @Inject constructor( it != _state.value.selectedCategory }.size - 1 ) - event.navigator.navigate(Screen.LIBRARY, true) + event.onNavigate { + navigate( + Screen.Library, + useBackAnimation = true + ) + } } } @@ -553,9 +556,35 @@ class BookInfoViewModel @Inject constructor( } if (_state.value.textChanged) { - val newBook = getBookById.execute( - listOf(_state.value.book.id) - ).first() + val newBook = getBookById.execute(_state.value.book.id) + + if (newBook == 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 + } _state.update { it.copy( @@ -611,36 +640,29 @@ class BookInfoViewModel @Inject constructor( ) ) } - event.navigator.navigate( - Screen.READER, - false, - Argument( - "book", _state.value.book.id + event.onNavigate { + navigate( + Screen.Reader(_state.value.book.id) ) - ) + } } } } } - fun init(navigator: Navigator) { + fun init(screen: Screen.BookInfo, onNavigate: OnNavigate) { viewModelScope.launch { - val bookId = navigator.retrieveArgument("book") as? Int + val book = getBookById.execute(screen.bookId) - if (bookId == null) { - navigator.navigateBack() - return@launch - } - - val book = getBookById.execute(listOf(bookId)) - - if (book.isEmpty()) { - navigator.navigateBack() + if (book == null) { + onNavigate { + navigateBack() + } return@launch } _state.update { - BookInfoState(book = book.first()) + BookInfoState(book = book) } } } 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 8f9ea355..fbeba8ba 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 @@ -46,6 +46,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberPermissionState import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton @@ -55,7 +56,6 @@ import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.components.is_messages.IsError import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.browse.components.BrowseFileItem import ua.acclorite.book_story.presentation.screens.browse.components.BrowseStoragePermissionDialog @@ -78,7 +78,7 @@ fun BrowseScreenRoot() { BrowseScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = viewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent ) @@ -92,7 +92,7 @@ fun BrowseScreenRoot() { @Composable private fun BrowseScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (BrowseEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit ) { @@ -303,7 +303,11 @@ private fun BrowseScreen( message = stringResource(id = R.string.browse_empty), icon = painterResource(id = R.drawable.empty_browse), actionTitle = stringResource(id = R.string.get_help), - action = { navigator.navigate(Screen.HELP, false) } + action = { + onNavigate { + navigate(Screen.Help(false)) + } + } ) } @@ -328,7 +332,9 @@ private fun BrowseScreen( return@BackHandler } - navigator.navigate(Screen.LIBRARY, false) + onNavigate { + navigate(Screen.Library) + } } } 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 8b53d5ea..c1ce8dba 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 @@ -27,7 +27,12 @@ import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** - * Adding dialog. Adds all selected books to the Library. + * Adding dialog. + * Adds all selected books to the Library. + * + * @param state [BrowseState]. + * @param onEvent [BrowseEvent] callback. + * @param onLibraryEvent [LibraryEvent] callback. */ @Composable fun BrowseAddingDialog( @@ -49,7 +54,7 @@ fun BrowseAddingDialog( onAction = { onEvent( BrowseEvent.OnAddBooks( - navigator, + onNavigate = { navigator.it() }, resetScroll = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0)) onLibraryEvent(LibraryEvent.OnLoadList) 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 267326be..c75f657e 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 @@ -8,8 +8,8 @@ import androidx.compose.ui.focus.FocusRequester import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import ua.acclorite.book_story.domain.model.NullableBook +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.Selected -import ua.acclorite.book_story.presentation.data.Navigator import java.io.File @Immutable @@ -21,7 +21,8 @@ sealed class BrowseEvent { ) : BrowseEvent() data class OnStoragePermissionDismiss( - val permissionState: PermissionState, val showErrorMessage: () -> Unit + val permissionState: PermissionState, + val showErrorMessage: () -> Unit ) : BrowseEvent() data object OnRefreshList : BrowseEvent() @@ -41,7 +42,7 @@ sealed class BrowseEvent { data object OnAddingDialogDismiss : BrowseEvent() data object OnGetBooksFromFiles : BrowseEvent() data class OnAddBooks( - val navigator: Navigator, + val onNavigate: OnNavigate, val resetScroll: () -> Unit, val onFailed: () -> Unit, val onSuccess: () -> Unit 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 b326e925..9b6adfe9 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 @@ -396,10 +396,9 @@ class BrowseViewModel @Inject constructor( } event.resetScroll() - event.navigator.navigate( - Screen.LIBRARY, - false - ) + event.onNavigate { + navigate(Screen.Library) + } event.onSuccess() _state.update { 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 index cfc4c664..24afffb4 100644 --- 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 @@ -33,13 +33,13 @@ 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.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.data.LocalNavigator 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.data.Screen import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel @@ -63,7 +63,7 @@ import ua.acclorite.book_story.presentation.screens.start.data.StartEvent import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel @Composable -fun HelpScreenRoot() { +fun HelpScreenRoot(screen: Screen.Help) { val navigator = LocalNavigator.current val helpViewModel: HelpViewModel = hiltViewModel() val browseViewModel: BrowseViewModel = hiltViewModel() @@ -73,12 +73,12 @@ fun HelpScreenRoot() { val state = helpViewModel.state.collectAsState() LaunchedEffect(Unit) { - helpViewModel.init(navigator) + helpViewModel.init(screen = screen) } HelpScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = helpViewModel::onEvent, onMainEvent = mainViewModel::onEvent, onBrowseEvent = browseViewModel::onEvent, @@ -92,7 +92,7 @@ fun HelpScreenRoot() { @Composable private fun HelpScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit, onMainEvent: (MainEvent) -> Unit, onBrowseEvent: (BrowseEvent) -> Unit, @@ -113,7 +113,7 @@ private fun HelpScreen( }, navigationIcon = { if (!state.value.fromStart) { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) } }, actions = { @@ -125,8 +125,10 @@ private fun HelpScreen( ) { onStartEvent(StartEvent.OnResetStartScreen) onMainEvent(MainEvent.OnChangeShowStartScreen(true)) - navigator.navigateWithoutBackStack(Screen.START, false) - navigator.clearBackStack() + onNavigate { + navigate(Screen.Start, saveInBackStack = false) + clearBackStack() + } } } }, @@ -149,11 +151,11 @@ private fun HelpScreen( .fillMaxWidth(), shape = RoundedCornerShape(100), onClick = { - navigator.clearArgument("from_start") - onBrowseEvent(BrowseEvent.OnLoadList) onMainEvent(MainEvent.OnChangeShowStartScreen(false)) - navigator.navigateWithoutBackStack(Screen.BROWSE, false) + onNavigate { + navigate(Screen.Browse, saveInBackStack = false) + } } ) { Text(text = stringResource(id = R.string.done)) @@ -203,6 +205,7 @@ private fun HelpScreen( item { HelpAddBooksItem( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -210,6 +213,7 @@ private fun HelpScreen( item { HelpCustomizeApp( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -217,6 +221,7 @@ private fun HelpScreen( item { HelpMoveOrDeleteBooks( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -224,6 +229,7 @@ private fun HelpScreen( item { HelpEditBook( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -231,6 +237,7 @@ private fun HelpScreen( item { HelpReadBook( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -238,6 +245,7 @@ private fun HelpScreen( item { HelpCustomizeReader( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -245,6 +253,7 @@ private fun HelpScreen( item { HelpUpdateBook( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -252,6 +261,7 @@ private fun HelpScreen( item { HelpManageHistory( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } @@ -266,6 +276,7 @@ private fun HelpScreen( item { HelpSetUpTranslator( state = state, + onNavigate = onNavigate, onEvent = onEvent ) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpAddBooksItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpAddBooksItem.kt index 2cbe4bb3..10ec9874 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpAddBooksItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpAddBooksItem.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpAddBooksItem( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_add_books), description = buildAnnotatedString { @@ -49,16 +48,18 @@ fun LazyItemScope.HelpAddBooksItem( ) }, onTagClick = { tag -> - when (tag) { - "browse" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.BROWSE, true) + onNavigate { + when (tag) { + "browse" -> { + if (!state.value.fromStart) { + navigate(Screen.Browse, useBackAnimation = true) + } } - } - "library" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.LIBRARY, true) + "library" -> { + if (!state.value.fromStart) { + navigate(Screen.Library, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeApp.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeApp.kt index 6c84103e..6923652f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeApp.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeApp.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpCustomizeApp( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_customize_app), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpCustomizeApp( ) }, onTagClick = { tag -> - when (tag) { - "settings" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.SETTINGS, true) + onNavigate { + when (tag) { + "settings" -> { + if (!state.value.fromStart) { + navigate(Screen.Settings, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeReader.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeReader.kt index 009411bc..3da91297 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeReader.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpCustomizeReader.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpCustomizeReader( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_customize_reader), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpCustomizeReader( ) }, onTagClick = { tag -> - when (tag) { - "settings" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.SETTINGS, true) + onNavigate { + when (tag) { + "settings" -> { + if (!state.value.fromStart) { + navigate(Screen.Settings, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpEditBook.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpEditBook.kt index f9116e8a..45803dca 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpEditBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpEditBook.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpEditBook( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_edit_book), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpEditBook( ) }, onTagClick = { tag -> - when (tag) { - "library" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.LIBRARY, true) + onNavigate { + when (tag) { + "library" -> { + if (!state.value.fromStart) { + navigate(Screen.Library, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpManageHistory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpManageHistory.kt index 297e57f5..1c0408ef 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpManageHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpManageHistory.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpManageHistory( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_manage_history), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpManageHistory( ) }, onTagClick = { tag -> - when (tag) { - "history" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.HISTORY, true) + onNavigate { + when (tag) { + "history" -> { + if (!state.value.fromStart) { + navigate(Screen.History, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpMoveOrDeleteBooks.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpMoveOrDeleteBooks.kt index 30119a3a..246ba171 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpMoveOrDeleteBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpMoveOrDeleteBooks.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpMoveOrDeleteBooks( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_move_or_delete_books), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpMoveOrDeleteBooks( ) }, onTagClick = { tag -> - when (tag) { - "library" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.LIBRARY, true) + onNavigate { + when (tag) { + "library" -> { + if (!state.value.fromStart) { + navigate(Screen.Library, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpReadBook.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpReadBook.kt index 89932576..2e3122bc 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpReadBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpReadBook.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpReadBook( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_read_book), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpReadBook( ) }, onTagClick = { tag -> - when (tag) { - "library" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.LIBRARY, true) + onNavigate { + when (tag) { + "library" -> { + if (!state.value.fromStart) { + navigate(Screen.Library, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpSetUpTranslator.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpSetUpTranslator.kt index 6058036c..11956f2d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpSetUpTranslator.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpSetUpTranslator.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpSetUpTranslator( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_set_up_translator), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpSetUpTranslator( ) }, onTagClick = { tag -> - when (tag) { - "reader_settings" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.READER_SETTINGS, true) + onNavigate { + when (tag) { + "reader_settings" -> { + if (!state.value.fromStart) { + navigate(Screen.Settings.ReaderSettings, useBackAnimation = true) + } } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpUpdateBook.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpUpdateBook.kt index ea6ea104..5ba24209 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpUpdateBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/items/HelpUpdateBook.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpItem @@ -16,10 +16,9 @@ import ua.acclorite.book_story.presentation.screens.help.data.HelpState @Composable fun LazyItemScope.HelpUpdateBook( state: State, + onNavigate: OnNavigate, onEvent: (HelpEvent) -> Unit ) { - val navigator = LocalNavigator.current - HelpItem( title = stringResource(id = R.string.help_title_how_to_update_book), description = buildAnnotatedString { @@ -44,10 +43,12 @@ fun LazyItemScope.HelpUpdateBook( ) }, onTagClick = { tag -> - when (tag) { - "library" -> { - if (!state.value.fromStart) { - navigator.navigate(Screen.LIBRARY, true) + onNavigate { + when (tag) { + "library" -> { + if (!state.value.fromStart) { + navigate(Screen.Library, useBackAnimation = true) + } } } } 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 index 8236eebd..46210b50 100644 --- 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 @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject @HiltViewModel @@ -75,13 +75,11 @@ class HelpViewModel @Inject constructor( } } - fun init(navigator: Navigator) { + fun init(screen: Screen.Help) { viewModelScope.launch { - val isFromStart = navigator.retrieveArgument("from_start") as? Boolean ?: false - _state.update { it.copy( - fromStart = isFromStart + fromStart = screen.fromStart ) } } 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 d6602fa9..dd86b041 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 @@ -38,6 +38,7 @@ 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.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility @@ -47,9 +48,7 @@ import ua.acclorite.book_story.presentation.components.CustomSnackbar import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty -import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.history.components.HistoryDeleteWholeHistoryDialog import ua.acclorite.book_story.presentation.screens.history.components.HistoryItem @@ -71,7 +70,7 @@ fun HistoryScreenRoot() { HistoryScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = viewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent ) @@ -84,7 +83,7 @@ fun HistoryScreenRoot() { @Composable private fun HistoryScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (HistoryEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit ) { @@ -230,17 +229,17 @@ private fun HistoryScreen( history = it, isOnClickEnabled = !state.value.isRefreshing, onBodyClick = { - navigator.navigate( - Screen.BOOK_INFO, - false, - Argument("book", it.bookId) - ) + onNavigate { + navigate( + Screen.BookInfo(it.bookId) + ) + } }, onTitleClick = { onEvent( HistoryEvent.OnNavigateToReaderScreen( - navigator, - it.book!! + onNavigate = onNavigate, + book = it.book!! ) ) }, @@ -300,7 +299,9 @@ private fun HistoryScreen( return@BackHandler } - navigator.navigate(Screen.LIBRARY, false) + onNavigate { + navigate(Screen.Library) + } } } 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 382fb2f9..83ea5a3c 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 @@ -6,7 +6,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate @Immutable sealed class HistoryEvent { @@ -27,7 +27,7 @@ sealed class HistoryEvent { data class OnRequestFocus(val focusRequester: FocusRequester) : HistoryEvent() data class OnUpdateBook(val book: Book) : HistoryEvent() data class OnNavigateToReaderScreen( - val navigator: Navigator, + val onNavigate: OnNavigate, val book: Book ) : HistoryEvent() 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 0e1a05fa..d15807f2 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 @@ -22,7 +22,6 @@ import ua.acclorite.book_story.domain.use_case.GetBooksById import ua.acclorite.book_story.domain.use_case.GetHistory import ua.acclorite.book_story.domain.use_case.InsertHistory 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.text.SimpleDateFormat import java.util.Calendar @@ -266,13 +265,9 @@ class HistoryViewModel @Inject constructor( ) ) } - event.navigator.navigate( - Screen.READER, - false, - Argument( - "book", event.book.id - ) - ) + event.onNavigate { + navigate(Screen.Reader(event.book.id)) + } } } 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 412eba05..3f2f4982 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 @@ -62,6 +62,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.util.OnNavigate import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility @@ -71,9 +72,7 @@ import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.header import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty -import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel @@ -100,7 +99,7 @@ fun LibraryScreenRoot() { LibraryScreen( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onEvent = viewModel::onEvent, onBrowseEvent = browseViewModel::onEvent, onHistoryEvent = historyViewModel::onEvent @@ -114,7 +113,7 @@ fun LibraryScreenRoot() { @Composable private fun LibraryScreen( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onEvent: (LibraryEvent) -> Unit, onHistoryEvent: (HistoryEvent) -> Unit, onBrowseEvent: (BrowseEvent) -> Unit @@ -338,11 +337,9 @@ private fun LibraryScreen( if (state.value.hasSelectedItems) { onEvent(LibraryEvent.OnSelectBook(it)) } else { - navigator.navigate( - Screen.BOOK_INFO, - false, - Argument("book", it.first.id) - ) + onNavigate { + navigate(Screen.BookInfo(it.first.id)) + } } }, onLongClick = { @@ -353,8 +350,8 @@ private fun LibraryScreen( onButtonClick = { onEvent( LibraryEvent.OnNavigateToReaderScreen( - navigator, - it.first + onNavigate = onNavigate, + book = it.first ) ) } @@ -381,7 +378,9 @@ private fun LibraryScreen( modifier = Modifier.align(Alignment.Center), actionTitle = stringResource(id = R.string.add_book) ) { - navigator.navigate(Screen.BROWSE, false) + onNavigate { + navigate(Screen.Browse) + } } } } 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 a08e046b..cbfb5571 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 @@ -5,8 +5,8 @@ import androidx.compose.runtime.Immutable import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Category +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.Selected -import ua.acclorite.book_story.presentation.data.Navigator @Immutable sealed class LibraryEvent { @@ -30,7 +30,7 @@ sealed class LibraryEvent { data class OnDeleteBooks(val refreshList: () -> Unit) : LibraryEvent() data class OnUpdateBook(val book: Book) : LibraryEvent() data class OnNavigateToReaderScreen( - val navigator: Navigator, + val onNavigate: OnNavigate, val book: Book ) : LibraryEvent() } \ No newline at end of file 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 252f0d26..eb58b2fb 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 @@ -18,7 +18,6 @@ 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.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Screen import java.util.Date import javax.inject.Inject @@ -338,13 +337,9 @@ class LibraryViewModel @Inject constructor( ) ) } - event.navigator.navigate( - Screen.READER, - false, - Argument( - "book", event.book.id - ) - ) + event.onNavigate { + navigate(Screen.Reader(event.book.id)) + } } } 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 1ac19562..3a1c1eb9 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 @@ -50,6 +50,7 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomSelectionContainer import ua.acclorite.book_story.presentation.components.customItems @@ -59,7 +60,7 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainViewModel -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.presentation.data.Screen 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 @@ -77,7 +78,7 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel @Composable -fun ReaderScreenRoot() { +fun ReaderScreenRoot(screen: Screen.Reader) { val navigator = LocalNavigator.current val context = LocalContext.current as ComponentActivity @@ -103,8 +104,9 @@ fun ReaderScreenRoot() { LaunchedEffect(Unit) { viewModel.init( - navigator, - context, + screen = screen, + onNavigate = { navigator.it() }, + context = context, refreshList = { libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) historyViewModel.onEvent(HistoryEvent.OnLoadList) @@ -139,8 +141,8 @@ fun ReaderScreenRoot() { ReaderScreen( state = state, mainState = mainState, - navigator = navigator, lazyListState = lazyListState, + onNavigate = { navigator.it() }, onEvent = viewModel::onEvent, onMainEvent = mainViewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent, @@ -153,8 +155,8 @@ fun ReaderScreenRoot() { private fun ReaderScreen( state: State, mainState: State, - navigator: Navigator, lazyListState: LazyListState, + onNavigate: OnNavigate, onEvent: (ReaderEvent) -> Unit, onMainEvent: (MainEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit, @@ -278,6 +280,7 @@ private fun ReaderScreen( ) { ReaderTopBar( state = state, + onNavigate = onNavigate, onEvent = onEvent, onLibraryUpdateEvent = onLibraryEvent, onHistoryUpdateEvent = onHistoryEvent @@ -399,6 +402,7 @@ private fun ReaderScreen( DisableSelection { ReaderEndItem( state = state, + onNavigate = onNavigate, onEvent = onEvent, onLibraryEvent = onLibraryEvent, onHistoryUpdateEvent = onHistoryEvent, @@ -427,13 +431,14 @@ private fun ReaderScreen( onEvent( ReaderEvent.OnGoBack( context, - navigator, refreshList = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { - it.navigateBack() + onNavigate { + navigateBack() + } } ) ) @@ -461,13 +466,14 @@ private fun ReaderScreen( onEvent( ReaderEvent.OnGoBack( context, - navigator, refreshList = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { - it.navigateBack() + onNavigate { + navigateBack() + } } ) ) 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 649ebb30..b3633f20 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 @@ -30,7 +30,7 @@ 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.model.Category -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent @@ -41,6 +41,7 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState * Reader end item. Displays at the end of the book. * * @param state [ReaderState]. + * @param onNavigate Navigator callback. * @param onEvent [ReaderEvent] callback. * @param onLibraryEvent [LibraryEvent] callback. * @param onHistoryUpdateEvent [HistoryEvent] callback. @@ -49,13 +50,12 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState @Composable fun ReaderEndItem( state: State, + onNavigate: OnNavigate, onEvent: (ReaderEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit, onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit, ) { - val navigator = LocalNavigator.current val context = LocalContext.current as ComponentActivity - val buttonText = remember { context.getString( if (state.value.book.category != Category.ALREADY_READ) R.string.move_to_read @@ -106,7 +106,7 @@ fun ReaderEndItem( updatePage = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) }, - navigator = navigator, + onNavigate = onNavigate, context = context ) ) @@ -120,13 +120,14 @@ fun ReaderEndItem( onEvent( ReaderEvent.OnGoBack( context, - navigator, refreshList = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { - it.navigate(Screen.LIBRARY, true) + onNavigate { + navigate(Screen.Library, useBackAnimation = true) + } } ) ) 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 58274490..df8a8f2b 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 @@ -27,8 +27,8 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton -import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.removeDigits import ua.acclorite.book_story.presentation.data.removeTrailingZero @@ -42,6 +42,7 @@ import ua.acclorite.book_story.presentation.ui.Colors * Reader top bar. Displays title of the book. * * @param state [ReaderState]. + * @param onNavigate Navigator callback. * @param onEvent [ReaderEvent] callback. * @param onLibraryUpdateEvent [LibraryEvent] callback. * @param onHistoryUpdateEvent [HistoryEvent] callback. @@ -50,13 +51,12 @@ import ua.acclorite.book_story.presentation.ui.Colors @Composable fun ReaderTopBar( state: State, + onNavigate: OnNavigate, onEvent: (ReaderEvent) -> Unit, onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit ) { - val navigator = LocalNavigator.current val context = LocalContext.current as ComponentActivity - val progress by remember(state.value.book.progress) { derivedStateOf { (state.value.book.progress * 100) @@ -77,13 +77,14 @@ fun ReaderTopBar( onEvent( ReaderEvent.OnGoBack( context, - navigator, refreshList = { onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { - it.navigateBack() + onNavigate { + navigateBack() + } } ) ) @@ -108,16 +109,18 @@ fun ReaderTopBar( onEvent( ReaderEvent.OnGoBack( context, - navigator, refreshList = { onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { - it.navigateWithoutBackStack( - Screen.BOOK_INFO, - true - ) + onNavigate { + navigate( + Screen.BookInfo(state.value.book.id), + useBackAnimation = true, + saveInBackStack = false + ) + } } ) ) 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 92cd0d41..e57586b7 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 @@ -8,8 +8,8 @@ import ua.acclorite.book_story.domain.model.LineWithTranslation import ua.acclorite.book_story.domain.model.SelectableLanguage import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.LanguageCode +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.UIText -import ua.acclorite.book_story.presentation.data.Navigator @Immutable sealed class ReaderEvent { @@ -20,8 +20,10 @@ sealed class ReaderEvent { val onTextIsEmpty: () -> Unit ) : ReaderEvent() - data class OnShowHideMenu(val show: Boolean? = null, val context: ComponentActivity) : - ReaderEvent() + data class OnShowHideMenu( + val show: Boolean? = null, + val context: ComponentActivity + ) : ReaderEvent() data class OnShowHideTranslatorBottomSheet(val show: Boolean? = null) : ReaderEvent() @@ -63,9 +65,8 @@ sealed class ReaderEvent { data class OnGoBack( val context: ComponentActivity, - val navigator: Navigator, - val refreshList: (Book) -> Unit, - val navigate: (Navigator) -> Unit + val navigate: () -> Unit, + val refreshList: (Book) -> Unit ) : ReaderEvent() data class OnChangeProgress( @@ -82,7 +83,7 @@ sealed class ReaderEvent { val context: ComponentActivity, val onUpdateCategories: (Book) -> Unit, val updatePage: (Int) -> Unit, - val navigator: Navigator + val onNavigate: OnNavigate ) : ReaderEvent() data class OnOpenTranslator( 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 2114cc88..5ac93746 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 @@ -42,9 +42,9 @@ import ua.acclorite.book_story.domain.use_case.TranslateText import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.LanguageCode +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.UIText -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.removeKey import ua.acclorite.book_story.presentation.data.removeKeys @@ -912,7 +912,7 @@ class ReaderViewModel @Inject constructor( } insetsController.show(WindowInsetsCompat.Type.systemBars()) - event.navigate(event.navigator) + event.navigate() } } @@ -967,7 +967,6 @@ class ReaderViewModel @Inject constructor( onEvent( ReaderEvent.OnGoBack( event.context, - event.navigator, refreshList = {}, navigate = {} ) @@ -995,7 +994,12 @@ class ReaderViewModel @Inject constructor( }.size - 1 ) - event.navigator.navigate(Screen.LIBRARY, true) + event.onNavigate { + navigate( + Screen.Library, + useBackAnimation = true + ) + } } } @@ -1226,23 +1230,19 @@ class ReaderViewModel @Inject constructor( } fun init( - navigator: Navigator, + screen: Screen.Reader, + onNavigate: OnNavigate, context: ComponentActivity, refreshList: (Book) -> Unit, onError: (UIText) -> Unit ) { viewModelScope.launch(Dispatchers.IO) { - val bookId = navigator.retrieveArgument("book") as? Int - - if (bookId == null) { - navigator.navigateBack() - return@launch - } - - val book = getBookById.execute(bookId) + val book = getBookById.execute(screen.bookId) if (book == null) { - navigator.navigateBack() + onNavigate { + navigateBack() + } return@launch } 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 8cc8e6e3..1d5799f4 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 @@ -24,10 +24,10 @@ 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.util.OnNavigate import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.data.LocalNavigator -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 @@ -35,13 +35,13 @@ import ua.acclorite.book_story.presentation.screens.settings.components.Settings fun SettingsScreenRoot() { val navigator = LocalNavigator.current - SettingsScreen(navigator = navigator) + SettingsScreen(onNavigate = { navigator.it() }) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun SettingsScreen( - navigator: Navigator + onNavigate: OnNavigate ) { val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() @@ -57,7 +57,7 @@ private fun SettingsScreen( Text(stringResource(id = R.string.settings_screen)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( @@ -83,7 +83,9 @@ private fun SettingsScreen( text = stringResource(id = R.string.general_settings), description = stringResource(id = R.string.general_settings_desc) ) { - navigator.navigate(Screen.GENERAL_SETTINGS, false) + onNavigate { + navigate(Screen.Settings.General) + } } } @@ -93,7 +95,9 @@ private fun SettingsScreen( text = stringResource(id = R.string.appearance_settings), description = stringResource(id = R.string.appearance_settings_desc) ) { - navigator.navigate(Screen.APPEARANCE_SETTINGS, false) + onNavigate { + navigate(Screen.Settings.Appearance) + } } } @@ -103,7 +107,9 @@ private fun SettingsScreen( text = stringResource(id = R.string.reader_settings), description = stringResource(id = R.string.reader_settings_desc) ) { - navigator.navigate(Screen.READER_SETTINGS, false) + onNavigate { + navigate(Screen.Settings.ReaderSettings) + } } } 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 be774a6e..56375762 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 @@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState @@ -36,7 +37,6 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainState 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.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 @@ -58,7 +58,7 @@ fun AppearanceSettingsRoot() { AppearanceSettings( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onMainEvent = mainViewModel::onEvent ) } @@ -67,7 +67,7 @@ fun AppearanceSettingsRoot() { @Composable private fun AppearanceSettings( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onMainEvent: (MainEvent) -> Unit ) { val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() @@ -91,7 +91,7 @@ private fun AppearanceSettings( Text(stringResource(id = R.string.appearance_settings)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( 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 3e1c7236..e0e2d4db 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 @@ -31,13 +31,13 @@ import com.google.accompanist.permissions.rememberPermissionState import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainState 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.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent @@ -53,7 +53,7 @@ fun GeneralSettingsRoot() { GeneralSettings( state = state, - navigator = navigator, + onNavigate = { navigator.it() }, onSettingsEvent = settingsViewModel::onEvent, onMainEvent = mainViewModel::onEvent ) @@ -64,7 +64,7 @@ fun GeneralSettingsRoot() { @Composable private fun GeneralSettings( state: State, - navigator: Navigator, + onNavigate: OnNavigate, onSettingsEvent: (SettingsEvent) -> Unit, onMainEvent: (MainEvent) -> Unit ) { @@ -87,7 +87,7 @@ private fun GeneralSettings( Text(stringResource(id = R.string.general_settings)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( 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 29d9f441..28a1e068 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 @@ -28,6 +28,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState @@ -36,7 +37,6 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainViewModel -import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.screens.reader.components.translator_bottom_sheet.ReaderTranslatorBottomSheetLanguageChooser import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle @@ -58,7 +58,7 @@ fun ReaderSettingsRoot() { ReaderSettings( state = state, settingsState = settingsState, - navigator = navigator, + onNavigate = { navigator.it() }, onMainEvent = mainViewModel::onEvent, onEvent = settingsViewModel::onEvent ) @@ -69,7 +69,7 @@ fun ReaderSettingsRoot() { private fun ReaderSettings( state: State, settingsState: State, - navigator: Navigator, + onNavigate: OnNavigate, onMainEvent: (MainEvent) -> Unit, onEvent: (SettingsEvent) -> Unit ) { @@ -145,7 +145,7 @@ private fun ReaderSettings( Text(stringResource(id = R.string.reader_settings)) }, navigationIcon = { - GoBackButton(navigator = navigator) + GoBackButton(onNavigate = onNavigate) }, scrollBehavior = scrollState.first, colors = TopAppBarDefaults.largeTopAppBarColors( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt index 1ec4d65c..5d6a162c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt @@ -35,7 +35,12 @@ import ua.acclorite.book_story.presentation.screens.start.data.StartEvent import ua.acclorite.book_story.presentation.screens.start.data.StartState /** - * Done screen. + * Start Done screen. + * + * @param state [StartState]. + * @param onEvent [StartEvent] callback. + * @param onMainEvent [MainEvent] callback. + * @param onBrowseEvent [BrowseEvent] callback. */ @Composable fun StartDone( @@ -72,7 +77,7 @@ fun StartDone( onClick = { onEvent( StartEvent.OnGoToBrowse( - navigator, + onNavigate = { navigator.it() }, onCompletedStartGuide = { onBrowseEvent(BrowseEvent.OnLoadList) onMainEvent( @@ -91,9 +96,7 @@ fun StartDone( shape = RoundedCornerShape(100), onClick = { onEvent( - StartEvent.OnGoToHelp( - navigator - ) + StartEvent.OnGoToHelp { navigator.it() } ) } ) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartEvent.kt index 852ba1e5..2a5352e9 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartEvent.kt @@ -6,7 +6,7 @@ import androidx.activity.ComponentActivity import androidx.compose.runtime.Immutable import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState -import ua.acclorite.book_story.presentation.data.Navigator +import ua.acclorite.book_story.domain.util.OnNavigate @Immutable sealed class StartEvent { @@ -23,10 +23,10 @@ sealed class StartEvent { val onEnableUpdates: () -> Unit ) : StartEvent() - data class OnGoToBrowse(val navigator: Navigator, val onCompletedStartGuide: () -> Unit) : + data class OnGoToBrowse(val onNavigate: OnNavigate, val onCompletedStartGuide: () -> Unit) : StartEvent() - data class OnGoToHelp(val navigator: Navigator) : StartEvent() + data class OnGoToHelp(val onNavigate: OnNavigate) : StartEvent() data object OnResetStartScreen : StartEvent() } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt index 6cbbbe0f..4db29800 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.yield import ua.acclorite.book_story.domain.use_case.CheckForUpdates -import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject @@ -239,13 +238,16 @@ class StartViewModel @Inject constructor( } is StartEvent.OnGoToBrowse -> { - event.navigator.navigateWithoutBackStack(Screen.BROWSE, false) + event.onNavigate { + navigate(Screen.Browse, saveInBackStack = false) + } event.onCompletedStartGuide() } is StartEvent.OnGoToHelp -> { - event.navigator.putArgument(Argument("from_start", true)) - event.navigator.navigateWithoutBackStack(Screen.HELP, false) + event.onNavigate { + navigate(Screen.Help(true), saveInBackStack = false) + } } is StartEvent.OnResetStartScreen -> {