Navigation.kt: Type-safety, non-null parameters for Screens, improved navigation + Included generated Room Database schemas to be able to build the project.

This commit is contained in:
acclorite 2024-06-19 18:54:17 +03:00
parent be9630ca24
commit 667a91f950
53 changed files with 922 additions and 465 deletions

View file

@ -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')"
]
}
}

View file

@ -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')"
]
}
}

View file

@ -112,11 +112,15 @@ class Activity : AppCompatActivity() {
themeContrast = state.value.themeContrast!! themeContrast = state.value.themeContrast!!
) { ) {
NavigationHost( NavigationHost(
startScreen = if (state.value.showStartScreen!!) Screen.START startScreen = if (state.value.showStartScreen!!) Screen.Start
else Screen.LIBRARY else Screen.Library
) { ) {
navigation( navigation(
screens = arrayOf(Screen.LIBRARY, Screen.HISTORY, Screen.BROWSE), screens = arrayOf(
Screen.Library.getRoute(),
Screen.History.getRoute(),
Screen.Browse.getRoute()
),
bottomBar = { bottomBar = {
BottomNavigationBar() BottomNavigationBar()
}, },
@ -125,8 +129,7 @@ class Activity : AppCompatActivity() {
} }
) { ) {
// Library // Library
composable( composable<Screen.Library>(
screen = Screen.LIBRARY,
enterAnim = Transitions.FadeTransitionIn, enterAnim = Transitions.FadeTransitionIn,
exitAnim = Transitions.FadeTransitionOut exitAnim = Transitions.FadeTransitionOut
) { ) {
@ -134,8 +137,7 @@ class Activity : AppCompatActivity() {
} }
// History // History
composable( composable<Screen.History>(
screen = Screen.HISTORY,
enterAnim = Transitions.FadeTransitionIn, enterAnim = Transitions.FadeTransitionIn,
exitAnim = Transitions.FadeTransitionOut exitAnim = Transitions.FadeTransitionOut
) { ) {
@ -143,8 +145,7 @@ class Activity : AppCompatActivity() {
} }
// Browse // Browse
composable( composable<Screen.Browse>(
screen = Screen.BROWSE,
enterAnim = Transitions.FadeTransitionIn, enterAnim = Transitions.FadeTransitionIn,
exitAnim = Transitions.FadeTransitionOut exitAnim = Transitions.FadeTransitionOut
) { ) {
@ -153,57 +154,54 @@ class Activity : AppCompatActivity() {
} }
// Book Info // Book Info
composable(screen = Screen.BOOK_INFO) { composable<Screen.BookInfo> {
BookInfoScreenRoot() BookInfoScreenRoot(it)
} }
// Reader // Reader
composable(screen = Screen.READER) { composable<Screen.Reader> {
ReaderScreenRoot() ReaderScreenRoot(it)
} }
// Settings // Settings
composable(screen = Screen.SETTINGS) { composable<Screen.Settings> {
SettingsScreenRoot() SettingsScreenRoot()
} }
// Nested settings categories // Nested settings categories
composable(screen = Screen.GENERAL_SETTINGS) { composable<Screen.Settings.General> {
GeneralSettingsRoot() GeneralSettingsRoot()
} }
composable(screen = Screen.APPEARANCE_SETTINGS) { composable<Screen.Settings.Appearance> {
AppearanceSettingsRoot() AppearanceSettingsRoot()
} }
composable(screen = Screen.READER_SETTINGS) { composable<Screen.Settings.ReaderSettings> {
ReaderSettingsRoot() ReaderSettingsRoot()
} }
// About screen // About screen
composable(screen = Screen.ABOUT) { composable<Screen.About> {
AboutScreenRoot() AboutScreenRoot()
} }
// Nested about categories // Nested about categories
composable(screen = Screen.LICENSES) { composable<Screen.About.Licenses> {
LicensesScreenRoot() LicensesScreenRoot()
} }
composable(screen = Screen.LICENSES_INFO) { composable<Screen.About.LicenseInfo> {
LicenseInfoScreenRoot() LicenseInfoScreenRoot(it)
} }
composable(screen = Screen.CREDITS) { composable<Screen.About.Credits> {
CreditsScreenRoot() CreditsScreenRoot()
} }
// Help screen // Help screen
composable(screen = Screen.HELP) { composable<Screen.Help> {
HelpScreenRoot() HelpScreenRoot(it)
} }
// Start screen // Start screen
composable( composable<Screen.Start>(enterAnim = Transitions.FadeTransitionIn) {
screen = Screen.START,
enterAnim = Transitions.FadeTransitionIn
) {
StartScreenRoot() StartScreenRoot()
} }
} }

View file

@ -30,21 +30,21 @@ object Constants {
// Navigation items for NavigationBars. // Navigation items for NavigationBars.
val NAVIGATION_ITEMS = listOf( val NAVIGATION_ITEMS = listOf(
NavigationItem( NavigationItem(
screen = Screen.LIBRARY, screen = Screen.Library,
title = R.string.library_screen, title = R.string.library_screen,
tooltip = R.string.library_content_desc, tooltip = R.string.library_content_desc,
selectedIcon = R.drawable.library_screen_filled, selectedIcon = R.drawable.library_screen_filled,
unselectedIcon = R.drawable.library_screen_outlined unselectedIcon = R.drawable.library_screen_outlined
), ),
NavigationItem( NavigationItem(
screen = Screen.HISTORY, screen = Screen.History,
title = R.string.history_screen, title = R.string.history_screen,
tooltip = R.string.history_content_desc, tooltip = R.string.history_content_desc,
selectedIcon = R.drawable.history_screen_filled, selectedIcon = R.drawable.history_screen_filled,
unselectedIcon = R.drawable.history_screen_outlined unselectedIcon = R.drawable.history_screen_outlined
), ),
NavigationItem( NavigationItem(
screen = Screen.BROWSE, screen = Screen.Browse,
title = R.string.browse_screen, title = R.string.browse_screen,
tooltip = R.string.browse_content_desc, tooltip = R.string.browse_content_desc,
selectedIcon = R.drawable.browse_screen_filled, selectedIcon = R.drawable.browse_screen_filled,

View file

@ -1,8 +1,11 @@
package ua.acclorite.book_story.domain.util package ua.acclorite.book_story.domain.util
import android.graphics.Bitmap import android.graphics.Bitmap
import ua.acclorite.book_story.presentation.data.Navigator
typealias CoverImage = Bitmap typealias CoverImage = Bitmap
typealias Selected = Boolean typealias Selected = Boolean
typealias ID = Int typealias ID = Int
typealias LanguageCode = String typealias LanguageCode = String
typealias Route = String
typealias OnNavigate = (Navigator.() -> Unit) -> Unit

View file

@ -4,13 +4,18 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import ua.acclorite.book_story.R 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 @Composable
fun GoBackButton(navigator: Navigator, enabled: Boolean = true, customOnClick: () -> Unit = {}) { fun GoBackButton(onNavigate: OnNavigate, enabled: Boolean = true, customOnClick: () -> Unit = {}) {
CustomIconButton( CustomIconButton(
icon = Icons.AutoMirrored.Filled.ArrowBack, icon = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = R.string.go_back_content_desc, contentDescription = R.string.go_back_content_desc,
@ -18,6 +23,8 @@ fun GoBackButton(navigator: Navigator, enabled: Boolean = true, customOnClick: (
enabled = enabled enabled = enabled
) { ) {
customOnClick() customOnClick()
navigator.navigateBack() onNavigate {
navigateBack()
}
} }
} }

View file

@ -21,7 +21,8 @@ import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.Screen 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 @Composable
fun MoreDropDown() { fun MoreDropDown() {
@ -55,7 +56,7 @@ fun MoreDropDown() {
) )
}, },
onClick = { onClick = {
navigator.navigate(Screen.SETTINGS, false) navigator.navigate(Screen.Settings)
}, },
contentPadding = PaddingValues(start = startPadding, end = endPadding) contentPadding = PaddingValues(start = startPadding, end = endPadding)
) )
@ -68,7 +69,7 @@ fun MoreDropDown() {
) )
}, },
onClick = { onClick = {
navigator.navigate(Screen.HELP, false) navigator.navigate(Screen.Help(false))
}, },
contentPadding = PaddingValues(start = startPadding, end = endPadding) contentPadding = PaddingValues(start = startPadding, end = endPadding)
) )
@ -81,7 +82,7 @@ fun MoreDropDown() {
) )
}, },
onClick = { onClick = {
navigator.navigate(Screen.ABOUT, false) navigator.navigate(Screen.About)
}, },
contentPadding = PaddingValues(start = startPadding, end = endPadding) contentPadding = PaddingValues(start = startPadding, end = endPadding)
) )

View file

@ -8,21 +8,25 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import ua.acclorite.book_story.domain.util.Constants 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.LocalNavigator
import ua.acclorite.book_story.presentation.data.Screen
/** /**
* Bottom navigation bar, uses default [NavigationBar]. * Bottom navigation bar, uses default [NavigationBar].
*/ */
@Composable @Composable
fun BottomNavigationBar() { fun BottomNavigationBar() {
var currentScreen: Screen? by remember { mutableStateOf(null) } var currentScreen: Route? by remember { mutableStateOf(null) }
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
navigator.getCurrentScreen().collect { navigator.currentScreen.collect { route ->
if (it == Screen.LIBRARY || it == Screen.HISTORY || it == Screen.BROWSE) { if (
currentScreen = it Constants.NAVIGATION_ITEMS.any {
navigator.run { it.screen.getRoute() } == route
}
) {
currentScreen = route
} }
} }
} }
@ -31,7 +35,7 @@ fun BottomNavigationBar() {
Constants.NAVIGATION_ITEMS.forEach { Constants.NAVIGATION_ITEMS.forEach {
BottomNavigationBarItem( BottomNavigationBarItem(
item = it, item = it,
isSelected = currentScreen == it.screen isSelected = currentScreen == navigator.run { it.screen.getRoute() }
) { ) {
navigator.navigate(it.screen, false) navigator.navigate(it.screen, false)
} }

View file

@ -24,22 +24,26 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.util.Constants 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.LocalNavigator
import ua.acclorite.book_story.presentation.data.Screen
/** /**
* Custom Navigation Rail. It is used to be shown on Tablets. * Custom Navigation Rail. It is used to be shown on Tablets.
*/ */
@Composable @Composable
fun BoxScope.CustomNavigationRail() { fun BoxScope.CustomNavigationRail() {
var currentScreen: Screen? by remember { mutableStateOf(null) } var currentScreen: Route? by remember { mutableStateOf(null) }
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val layoutDirection = LocalLayoutDirection.current val layoutDirection = LocalLayoutDirection.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
navigator.getCurrentScreen().collect { navigator.currentScreen.collect { route ->
if (it == Screen.LIBRARY || it == Screen.HISTORY || it == Screen.BROWSE) { if (
currentScreen = it Constants.NAVIGATION_ITEMS.any {
navigator.run { it.screen.getRoute() } == route
}
) {
currentScreen = route
} }
} }
} }
@ -69,7 +73,7 @@ fun BoxScope.CustomNavigationRail() {
Constants.NAVIGATION_ITEMS.forEach { Constants.NAVIGATION_ITEMS.forEach {
CustomNavigationRailItem( CustomNavigationRailItem(
item = it, item = it,
isSelected = currentScreen == it.screen isSelected = currentScreen == navigator.run { it.screen.getRoute() }
) { ) {
navigator.navigate(it.screen, false) navigator.navigate(it.screen, false)
} }

View file

@ -43,60 +43,87 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.lifecycle.withCreationCallback import dagger.hilt.android.lifecycle.withCreationCallback
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize 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.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.ui.Transitions import ua.acclorite.book_story.presentation.ui.Transitions
import java.io.Serializable
private const val CURRENT_SCREEN = "current_screen" private const val CURRENT_SCREEN = "current_screen"
private const val BACKSTACK = "back_stack" private const val BACKSTACK = "back_stack"
private const val USE_BACK_ANIM = "use_back_animation" 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<Navigator> { val LocalNavigator = compositionLocalOf<Navigator> {
error("Cannot initialize Navigator.") error("Cannot initialize Navigator.")
} }
/** /**
* All screens are listed here, later each screen will be passed as a param for [Navigator.composable] function. * Screens. Should be [Serializable] to be able to pass them inside [SavedStateHandle].
*/ * Each screen should have unique name.
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.
*/ */
@Immutable @Immutable
@Parcelize @Parcelize
data class Argument<out T : Serializable>( sealed class Screen : Parcelable {
val key: String,
val value: T @Parcelize
) : Parcelable 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.currentScreen] param represents current [Screen].
* [Navigator.navigate] navigates to [Screen] passed as param. * [Navigator.navigate] navigates to [Screen] passed as param.
@ -104,139 +131,186 @@ data class Argument<out T : Serializable>(
@HiltViewModel(assistedFactory = Navigator.Factory::class) @HiltViewModel(assistedFactory = Navigator.Factory::class)
class Navigator @AssistedInject constructor( class Navigator @AssistedInject constructor(
private val savedStateHandle: SavedStateHandle, private val savedStateHandle: SavedStateHandle,
@Assisted startScreen: Screen @Assisted private val startScreen: Screen
) : ViewModel() { ) : ViewModel() {
private val currentScreen = savedStateHandle.getStateFlow(CURRENT_SCREEN, startScreen) val currentScreen = savedStateHandle.getStateFlow(CURRENT_SCREEN, startScreen.getRoute())
private val useBackAnimation = savedStateHandle.getStateFlow(USE_BACK_ANIM, false) val useBackAnimation = savedStateHandle.getStateFlow(USE_BACK_ANIM, false)
private val backStack = savedStateHandle.getStateFlow(BACKSTACK, mutableListOf<Screen>()) private val backStack = savedStateHandle.getStateFlow(BACKSTACK, mutableListOf<Route>())
private val arguments = savedStateHandle val screens = savedStateHandle.getStateFlow(SCREENS, mutableListOf<Screen>())
.getStateFlow(ARGUMENTS, mutableListOf<Argument<Serializable>>())
fun putArgument(argument: Argument<Serializable>) { init {
putScreen(startScreen)
}
/**
* Saves screen into [screens]. Later can be retrieved via [retrieveScreen].
*
* @param screen [Screen].
*/
fun putScreen(screen: Screen) {
var found = false var found = false
for ((index, arg) in arguments.value.withIndex()) { for ((index, arg) in screens.value.withIndex()) {
if (arg.key == argument.key) { if (arg.getRoute() == screen.getRoute()) {
arguments.value[index] = argument screens.value[index] = screen
found = true found = true
break break
} }
} }
if (!found) { if (!found) {
arguments.value.add(argument) screens.value.add(screen)
} }
} }
fun retrieveArgument(key: String): Serializable? { /**
for (arg in arguments.value) { * Retrieves screen that was put via [putScreen].
if (arg.key == key) { *
return arg.value * @exception Exception if there is no such screen saved that specified in [S], throws an [Exception].
*/
inline fun <reified S : Screen> retrieveScreen(): S {
for (arg in screens.value) {
if (arg.getRoute() == getRoute<S>()) {
return arg as S
} }
} }
return null
}
fun clearArgument(key: String) { throw Exception("Screen was not found.")
arguments.value.removeIf { it.key == key }
} }
fun navigate(screen: Screen, useBackAnimation: Boolean, vararg args: Argument<Serializable>) = /**
viewModelScope.launch(Dispatchers.Default) { * Navigates to the desired screen. Ignored if [currentScreen] is already [screen].
backStack.value.add(currentScreen.value) *
* @param screen [Screen] to navigate to.
args.forEach { * @param useBackAnimation Whether back animation should be used(as when user goes back).
putArgument(it) * @param saveInBackStack Whether this screen should be saved in [backStack] (basically history of all opened screens).
} */
fun navigate(
savedStateHandle[USE_BACK_ANIM] = useBackAnimation
savedStateHandle[CURRENT_SCREEN] = screen
}
fun navigateWithoutBackStack(
screen: Screen, screen: Screen,
useBackAnimation: Boolean, useBackAnimation: Boolean = false,
vararg args: Argument<Serializable> saveInBackStack: Boolean = true
) = viewModelScope.launch(Dispatchers.Default) { ) = viewModelScope.launch(Dispatchers.Default) {
if (backStack.value.lastOrNull() == screen) { if (screen.getRoute() == currentScreen.value) {
backStack.value.removeLast() return@launch
} }
args.forEach { if (saveInBackStack) {
putArgument(it) backStack.value.add(currentScreen.value)
} }
putScreen(screen)
savedStateHandle[USE_BACK_ANIM] = useBackAnimation savedStateHandle[USE_BACK_ANIM] = useBackAnimation
savedStateHandle[CURRENT_SCREEN] = screen savedStateHandle[CURRENT_SCREEN] = screen.getRoute()
} }
fun navigateBack(useBackAnimation: Boolean = true) = /**
viewModelScope.launch(Dispatchers.Default) { * 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()) { if (canGoBack()) {
savedStateHandle[USE_BACK_ANIM] = useBackAnimation savedStateHandle[USE_BACK_ANIM] = useBackAnimation
savedStateHandle[CURRENT_SCREEN] = backStack.value.last() savedStateHandle[CURRENT_SCREEN] = backStack.value.last()
backStack.value.removeLast() backStack.value.removeLast()
} }
} }
/**
* Clears the whole [backStack].
*/
fun clearBackStack() { fun clearBackStack() {
backStack.value.clear() backStack.value.clear()
} }
/**
* Whether there is screen to go back.
*/
fun canGoBack(): Boolean { fun canGoBack(): Boolean {
return backStack.value.isNotEmpty() return backStack.value.isNotEmpty()
} }
fun getCurrentScreen(): StateFlow<Screen> { /**
return currentScreen * Gets route of specified [S].
} */
inline fun <reified S : Screen> getRoute(): Route {
fun getUseBackAnim(): StateFlow<Boolean> { return S::class.simpleName!!
return useBackAnimation
} }
/** /**
* 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 enterAnim Enter Animation.
* @param backEnterAnim Enter Animation for navigating back. * @param backEnterAnim Enter Animation for navigating back.
* @param exitAnim Exit Animation. * @param exitAnim Exit Animation.
* @param backExitAnim Exit Animation for navigating back. * @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") @SuppressLint("ComposableNaming")
@Composable @Composable
fun composable( inline fun <reified S : Screen> composable(
screen: Screen,
enterAnim: EnterTransition = Transitions.SlidingTransitionIn, enterAnim: EnterTransition = Transitions.SlidingTransitionIn,
backEnterAnim: EnterTransition = Transitions.BackSlidingTransitionIn, backEnterAnim: EnterTransition = Transitions.BackSlidingTransitionIn,
exitAnim: ExitTransition = Transitions.SlidingTransitionOut, exitAnim: ExitTransition = Transitions.SlidingTransitionOut,
backExitAnim: ExitTransition = Transitions.BackSlidingTransitionOut, backExitAnim: ExitTransition = Transitions.BackSlidingTransitionOut,
content: @Composable () -> Unit noinline content: @Composable (screen: S) -> Unit
) { ) {
val currentRoute by currentScreen.collectAsState()
val useBackAnimation by useBackAnimation.collectAsState()
CustomAnimatedVisibility( CustomAnimatedVisibility(
visible = getCurrentScreen().collectAsState().value == screen, visible = currentRoute == getRoute<S>(),
enter = if (!useBackAnimation.collectAsState().value) enterAnim else backEnterAnim, enter = if (!useBackAnimation) enterAnim else backEnterAnim,
exit = if (!useBackAnimation.collectAsState().value) exitAnim else backExitAnim exit = if (!useBackAnimation) exitAnim else backExitAnim
) { ) {
content() val screen = remember { retrieveScreen<S>() }
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) @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@SuppressLint("ComposableNaming") @SuppressLint("ComposableNaming")
@Composable @Composable
fun navigation( 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, bottomBar: @Composable () -> Unit,
navigationRail: @Composable BoxScope.() -> Unit, navigationRail: @Composable BoxScope.() -> Unit,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val activity = LocalContext.current as ComponentActivity val activity = LocalContext.current as ComponentActivity
val currentScreen by getCurrentScreen().collectAsState() val currentScreen by currentScreen.collectAsState()
val useBackAnimation by getUseBackAnim().collectAsState() val useBackAnimation by useBackAnimation.collectAsState()
val shouldShow by remember(currentScreen) { val shouldShow by remember(currentScreen) {
derivedStateOf { derivedStateOf {
screens.any { it == currentScreen } screens.any { it == currentScreen }
@ -251,10 +325,10 @@ class Navigator @AssistedInject constructor(
CustomAnimatedVisibility( CustomAnimatedVisibility(
visible = shouldShow, visible = shouldShow,
enter = if (useBackAnimation) Transitions.BackSlidingTransitionIn enter = if (useBackAnimation) backEnterBarAnim
else Transitions.SlidingTransitionIn, else enterBarAnim,
exit = if (useBackAnimation) Transitions.BackSlidingTransitionOut exit = if (useBackAnimation) backExitBarAnim
else Transitions.SlidingTransitionOut else exitBarAnim
) { ) {
Scaffold( Scaffold(
bottomBar = { 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 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 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]. * @param content Content of the [NavigationHost]. Highly recommended to use [Navigator.composable].
*/ */
@Composable @Composable
fun NavigationHost( fun NavigationHost(
startScreen: Screen, startScreen: Screen,

View file

@ -33,10 +33,10 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.data.Screen
import ua.acclorite.book_story.presentation.screens.about.components.AboutItem import ua.acclorite.book_story.presentation.screens.about.components.AboutItem
import ua.acclorite.book_story.presentation.screens.about.components.AboutUpdateDialog import ua.acclorite.book_story.presentation.screens.about.components.AboutUpdateDialog
@ -53,7 +53,7 @@ fun AboutScreenRoot() {
AboutScreen( AboutScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = aboutViewModel::onEvent onEvent = aboutViewModel::onEvent
) )
} }
@ -62,7 +62,7 @@ fun AboutScreenRoot() {
@Composable @Composable
private fun AboutScreen( private fun AboutScreen(
state: State<AboutState>, state: State<AboutState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (AboutEvent) -> Unit onEvent: (AboutEvent) -> Unit
) { ) {
val context = LocalContext.current val context = LocalContext.current
@ -87,7 +87,7 @@ private fun AboutScreen(
Text(stringResource(id = R.string.about_screen)) Text(stringResource(id = R.string.about_screen))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
@ -213,7 +213,9 @@ private fun AboutScreen(
title = stringResource(id = R.string.licenses_option), title = stringResource(id = R.string.licenses_option),
description = null 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), title = stringResource(id = R.string.credits_option),
description = null description = null
) { ) {
navigator.navigate(Screen.CREDITS, false) onNavigate {
navigate(Screen.About.Credits)
}
} }
} }

View file

@ -21,11 +21,11 @@ import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.Constants 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.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.AboutEvent
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
import ua.acclorite.book_story.presentation.screens.about.nested.credits.components.CreditItem import ua.acclorite.book_story.presentation.screens.about.nested.credits.components.CreditItem
@ -36,7 +36,7 @@ fun CreditsScreenRoot() {
val aboutViewModel: AboutViewModel = hiltViewModel() val aboutViewModel: AboutViewModel = hiltViewModel()
CreditsScreen( CreditsScreen(
navigator = navigator, onNavigate = { navigator.it() },
onAboutNavigateEvent = aboutViewModel::onEvent onAboutNavigateEvent = aboutViewModel::onEvent
) )
} }
@ -44,7 +44,7 @@ fun CreditsScreenRoot() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun CreditsScreen( private fun CreditsScreen(
navigator: Navigator, onNavigate: OnNavigate,
onAboutNavigateEvent: (AboutEvent.OnNavigateToBrowserPage) -> Unit onAboutNavigateEvent: (AboutEvent.OnNavigateToBrowserPage) -> Unit
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
@ -62,7 +62,7 @@ private fun CreditsScreen(
Text(stringResource(id = R.string.credits_option)) Text(stringResource(id = R.string.credits_option))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(

View file

@ -42,19 +42,20 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.CustomIconButton
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.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.LicenseInfoState
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel
import ua.acclorite.book_story.presentation.ui.SlidingTransition import ua.acclorite.book_story.presentation.ui.SlidingTransition
@Composable @Composable
fun LicenseInfoScreenRoot() { fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
val licenseInfoViewModel: LicenseInfoViewModel = hiltViewModel() val licenseInfoViewModel: LicenseInfoViewModel = hiltViewModel()
@ -63,15 +64,16 @@ fun LicenseInfoScreenRoot() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
licenseInfoViewModel.init( licenseInfoViewModel.init(
navigator, screen = screen,
context onNavigate = { navigator.it() },
context = context
) )
} }
LicenseInfoScreen( LicenseInfoScreen(
state = state, state = state,
onEvent = licenseInfoViewModel::onEvent, onNavigate = { navigator.it() },
navigator = navigator onEvent = licenseInfoViewModel::onEvent
) )
} }
@ -79,8 +81,8 @@ fun LicenseInfoScreenRoot() {
@Composable @Composable
private fun LicenseInfoScreen( private fun LicenseInfoScreen(
state: State<LicenseInfoState>, state: State<LicenseInfoState>,
onEvent: (LicenseInfoEvent) -> Unit, onNavigate: OnNavigate,
navigator: Navigator onEvent: (LicenseInfoEvent) -> Unit
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
val context = LocalContext.current val context = LocalContext.current
@ -106,7 +108,7 @@ private fun LicenseInfoScreen(
) )
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
actions = { actions = {
if (state.value.license?.website?.isNotBlank() == true) { if (state.value.license?.website?.isNotBlank() == true) {

View file

@ -13,7 +13,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch 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 import javax.inject.Inject
@HiltViewModel @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) { viewModelScope.launch(Dispatchers.IO) {
_state.update { _state.update {
it.copy(license = null) 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 { val license = Libs.Builder().withContext(context).build().libraries.find {
it.uniqueId == licenseId it.uniqueId == screen.licenseId
} }
if (license == null) { if (license == null) {
navigator.navigateBack() onNavigate {
navigateBack()
}
return@launch return@launch
} }

View file

@ -28,13 +28,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.components.customItems 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.LocalNavigator
import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.data.Screen 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.components.LicenseItem
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState
@ -54,7 +53,7 @@ fun LicensesScreenRoot() {
LicensesScreen( LicensesScreen(
state = state, state = state,
navigator = navigator onNavigate = { navigator.it() }
) )
} }
@ -62,7 +61,7 @@ fun LicensesScreenRoot() {
@Composable @Composable
private fun LicensesScreen( private fun LicensesScreen(
state: State<LicensesState>, state: State<LicensesState>,
navigator: Navigator onNavigate: OnNavigate
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
@ -78,7 +77,7 @@ private fun LicensesScreen(
Text(stringResource(id = R.string.licenses_option)) Text(stringResource(id = R.string.licenses_option))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
@ -105,11 +104,9 @@ private fun LicensesScreen(
customItems(state.value.licenses, key = { it.uniqueId }) { customItems(state.value.licenses, key = { it.uniqueId }) {
LicenseItem(library = it) { LicenseItem(library = it) {
navigator.navigate( onNavigate {
Screen.LICENSES_INFO, navigate(Screen.About.LicenseInfo(it.uniqueId))
false, }
Argument("license", it.uniqueId)
)
} }
} }

View file

@ -57,13 +57,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomIconButton
import ua.acclorite.book_story.presentation.components.CustomSnackbar import ua.acclorite.book_story.presentation.components.CustomSnackbar
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.BookInfoBackground
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDescriptionSection import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDescriptionSection
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoInfoSection 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 import ua.acclorite.book_story.presentation.ui.Transitions
@Composable @Composable
fun BookInfoScreenRoot() { fun BookInfoScreenRoot(screen: Screen.BookInfo) {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val viewModel: BookInfoViewModel = hiltViewModel() val viewModel: BookInfoViewModel = hiltViewModel()
@ -99,13 +100,14 @@ fun BookInfoScreenRoot() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init( viewModel.init(
navigator screen = screen,
onNavigate = { navigator.it() }
) )
} }
BookInfoScreen( BookInfoScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = viewModel::onEvent, onEvent = viewModel::onEvent,
onLibraryEvent = libraryViewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent,
onBrowseEvent = browseViewModel::onEvent, onBrowseEvent = browseViewModel::onEvent,
@ -117,7 +119,7 @@ fun BookInfoScreenRoot() {
@Composable @Composable
private fun BookInfoScreen( private fun BookInfoScreen(
state: State<BookInfoState>, state: State<BookInfoState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (BookInfoEvent) -> Unit, onEvent: (BookInfoEvent) -> Unit,
onLibraryEvent: (LibraryEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit,
onBrowseEvent: (BrowseEvent) -> Unit, onBrowseEvent: (BrowseEvent) -> Unit,
@ -203,7 +205,7 @@ private fun BookInfoScreen(
onEvent(BookInfoEvent.OnShowHideEditTitle) onEvent(BookInfoEvent.OnShowHideEditTitle)
} }
} else { } else {
GoBackButton(navigator = navigator, enabled = !state.value.isRefreshing) { GoBackButton(onNavigate = onNavigate, enabled = !state.value.isRefreshing) {
onEvent(BookInfoEvent.OnCancelUpdate) onEvent(BookInfoEvent.OnCancelUpdate)
} }
} }
@ -329,7 +331,7 @@ private fun BookInfoScreen(
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
if (!state.value.isRefreshing) { if (!state.value.isRefreshing) {
onEvent(BookInfoEvent.OnNavigateToReaderScreen(navigator)) onEvent(BookInfoEvent.OnNavigateToReaderScreen(onNavigate = onNavigate))
} }
}, },
shape = MaterialTheme.shapes.large, shape = MaterialTheme.shapes.large,
@ -387,7 +389,9 @@ private fun BookInfoScreen(
if (!state.value.isRefreshing) { if (!state.value.isRefreshing) {
onEvent(BookInfoEvent.OnCancelUpdate) onEvent(BookInfoEvent.OnCancelUpdate)
navigator.navigateBack() onNavigate {
navigateBack()
}
} }
} }
} }

View file

@ -16,6 +16,11 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
/** /**
* Delete dialog. Deletes current book. * Delete dialog. Deletes current book.
*
* @param onEvent [BookInfoEvent] callback.
* @param onLibraryLoadEvent [LibraryEvent] callback.
* @param onHistoryLoadEvent [HistoryEvent] callback.
* @param onBrowseLoadEvent [BrowseEvent] callback.
*/ */
@Composable @Composable
fun BookInfoDeleteDialog( fun BookInfoDeleteDialog(
@ -40,7 +45,7 @@ fun BookInfoDeleteDialog(
onAction = { onAction = {
onEvent( onEvent(
BookInfoEvent.OnDeleteBook( BookInfoEvent.OnDeleteBook(
navigator = navigator, onNavigate = { navigator.it() },
refreshList = { refreshList = {
onLibraryLoadEvent(LibraryEvent.OnLoadList) onLibraryLoadEvent(LibraryEvent.OnLoadList)
onBrowseLoadEvent(BrowseEvent.OnLoadList) onBrowseLoadEvent(BrowseEvent.OnLoadList)

View file

@ -21,7 +21,13 @@ import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent 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 @Composable
fun BookInfoMoveDialog( fun BookInfoMoveDialog(
@ -60,7 +66,7 @@ fun BookInfoMoveDialog(
updatePage = { updatePage = {
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
}, },
navigator = navigator onNavigate = { navigator.it() }
) )
) )
Toast.makeText( Toast.makeText(

View file

@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category 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 @Immutable
sealed class BookInfoEvent { sealed class BookInfoEvent {
@ -23,11 +23,13 @@ sealed class BookInfoEvent {
data class OnUpdateTitle(val refreshList: (Book) -> Unit) : BookInfoEvent() data class OnUpdateTitle(val refreshList: (Book) -> Unit) : BookInfoEvent()
data object OnShowHideDeleteDialog : BookInfoEvent() data object OnShowHideDeleteDialog : BookInfoEvent()
data object OnShowHideMoveDialog : 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( data class OnMoveBook(
val refreshList: (Book) -> Unit, val refreshList: (Book) -> Unit,
val updatePage: (Int) -> Unit, val updatePage: (Int) -> Unit,
val navigator: Navigator val onNavigate: OnNavigate
) : BookInfoEvent() ) : BookInfoEvent()
data class OnSelectCategory(val category: Category) : BookInfoEvent() data class OnSelectCategory(val category: Category) : BookInfoEvent()
@ -51,7 +53,7 @@ sealed class BookInfoEvent {
) : BookInfoEvent() ) : BookInfoEvent()
data class OnNavigateToReaderScreen( data class OnNavigateToReaderScreen(
val navigator: Navigator val onNavigate: OnNavigate
) : BookInfoEvent() ) : BookInfoEvent()
data object OnDismissConfirmUpdateDialog : BookInfoEvent() data object OnDismissConfirmUpdateDialog : BookInfoEvent()

View file

@ -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.History
import ua.acclorite.book_story.domain.model.NullableBook 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.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.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.GetText
import ua.acclorite.book_story.domain.use_case.InsertHistory 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.UpdateBookWithText
import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.use_case.UpdateBooks
import ua.acclorite.book_story.domain.use_case.UpdateCoverImageOfBook import ua.acclorite.book_story.domain.use_case.UpdateCoverImageOfBook
import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.domain.util.OnNavigate
import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.Screen
import java.io.File import java.io.File
import java.util.Date import java.util.Date
@ -45,7 +44,7 @@ class BookInfoViewModel @Inject constructor(
private val insertHistory: InsertHistory, private val insertHistory: InsertHistory,
private val deleteBooks: DeleteBooks, private val deleteBooks: DeleteBooks,
private val getBookFromFile: GetBookFromFile, private val getBookFromFile: GetBookFromFile,
private val getBookById: GetBooksById, private val getBookById: GetBookById,
private val getText: GetText private val getText: GetText
) : ViewModel() { ) : ViewModel() {
@ -76,11 +75,8 @@ class BookInfoViewModel @Inject constructor(
image image
) )
val newCoverImage = getBookById.execute( val newCoverImage =
listOf( getBookById.execute(_state.value.book.id)?.coverImage ?: return@launch
_state.value.book.id
)
).first().coverImage
_state.update { _state.update {
it.copy( it.copy(
@ -197,7 +193,9 @@ class BookInfoViewModel @Inject constructor(
deleteBooks.execute(listOf(_state.value.book)) deleteBooks.execute(listOf(_state.value.book))
event.refreshList() event.refreshList()
event.navigator.navigateBack() event.onNavigate {
navigateBack()
}
} }
} }
@ -240,7 +238,12 @@ class BookInfoViewModel @Inject constructor(
it != _state.value.selectedCategory it != _state.value.selectedCategory
}.size - 1 }.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) { if (_state.value.textChanged) {
val newBook = getBookById.execute( val newBook = getBookById.execute(_state.value.book.id)
listOf(_state.value.book.id)
).first() 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 { _state.update {
it.copy( it.copy(
@ -611,36 +640,29 @@ class BookInfoViewModel @Inject constructor(
) )
) )
} }
event.navigator.navigate( event.onNavigate {
Screen.READER, navigate(
false, Screen.Reader(_state.value.book.id)
Argument(
"book", _state.value.book.id
)
) )
} }
} }
} }
} }
}
fun init(navigator: Navigator) { fun init(screen: Screen.BookInfo, onNavigate: OnNavigate) {
viewModelScope.launch { viewModelScope.launch {
val bookId = navigator.retrieveArgument("book") as? Int val book = getBookById.execute(screen.bookId)
if (bookId == null) { if (book == null) {
navigator.navigateBack() onNavigate {
return@launch navigateBack()
} }
val book = getBookById.execute(listOf(bookId))
if (book.isEmpty()) {
navigator.navigateBack()
return@launch return@launch
} }
_state.update { _state.update {
BookInfoState(book = book.first()) BookInfoState(book = book)
} }
} }
} }

View file

@ -46,6 +46,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.permissions.rememberPermissionState
import ua.acclorite.book_story.R 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.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomIconButton 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.IsEmpty
import ua.acclorite.book_story.presentation.components.is_messages.IsError 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.LocalNavigator
import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.data.Screen 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.BrowseFileItem
import ua.acclorite.book_story.presentation.screens.browse.components.BrowseStoragePermissionDialog import ua.acclorite.book_story.presentation.screens.browse.components.BrowseStoragePermissionDialog
@ -78,7 +78,7 @@ fun BrowseScreenRoot() {
BrowseScreen( BrowseScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = viewModel::onEvent, onEvent = viewModel::onEvent,
onLibraryEvent = libraryViewModel::onEvent onLibraryEvent = libraryViewModel::onEvent
) )
@ -92,7 +92,7 @@ fun BrowseScreenRoot() {
@Composable @Composable
private fun BrowseScreen( private fun BrowseScreen(
state: State<BrowseState>, state: State<BrowseState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (BrowseEvent) -> Unit, onEvent: (BrowseEvent) -> Unit,
onLibraryEvent: (LibraryEvent) -> Unit onLibraryEvent: (LibraryEvent) -> Unit
) { ) {
@ -303,7 +303,11 @@ private fun BrowseScreen(
message = stringResource(id = R.string.browse_empty), message = stringResource(id = R.string.browse_empty),
icon = painterResource(id = R.drawable.empty_browse), icon = painterResource(id = R.drawable.empty_browse),
actionTitle = stringResource(id = R.string.get_help), 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 return@BackHandler
} }
navigator.navigate(Screen.LIBRARY, false) onNavigate {
navigate(Screen.Library)
}
} }
} }

View file

@ -27,7 +27,12 @@ import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent 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 @Composable
fun BrowseAddingDialog( fun BrowseAddingDialog(
@ -49,7 +54,7 @@ fun BrowseAddingDialog(
onAction = { onAction = {
onEvent( onEvent(
BrowseEvent.OnAddBooks( BrowseEvent.OnAddBooks(
navigator, onNavigate = { navigator.it() },
resetScroll = { resetScroll = {
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0)) onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0))
onLibraryEvent(LibraryEvent.OnLoadList) onLibraryEvent(LibraryEvent.OnLoadList)

View file

@ -8,8 +8,8 @@ import androidx.compose.ui.focus.FocusRequester
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.domain.model.NullableBook 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.domain.util.Selected
import ua.acclorite.book_story.presentation.data.Navigator
import java.io.File import java.io.File
@Immutable @Immutable
@ -21,7 +21,8 @@ sealed class BrowseEvent {
) : BrowseEvent() ) : BrowseEvent()
data class OnStoragePermissionDismiss( data class OnStoragePermissionDismiss(
val permissionState: PermissionState, val showErrorMessage: () -> Unit val permissionState: PermissionState,
val showErrorMessage: () -> Unit
) : BrowseEvent() ) : BrowseEvent()
data object OnRefreshList : BrowseEvent() data object OnRefreshList : BrowseEvent()
@ -41,7 +42,7 @@ sealed class BrowseEvent {
data object OnAddingDialogDismiss : BrowseEvent() data object OnAddingDialogDismiss : BrowseEvent()
data object OnGetBooksFromFiles : BrowseEvent() data object OnGetBooksFromFiles : BrowseEvent()
data class OnAddBooks( data class OnAddBooks(
val navigator: Navigator, val onNavigate: OnNavigate,
val resetScroll: () -> Unit, val resetScroll: () -> Unit,
val onFailed: () -> Unit, val onFailed: () -> Unit,
val onSuccess: () -> Unit val onSuccess: () -> Unit

View file

@ -396,10 +396,9 @@ class BrowseViewModel @Inject constructor(
} }
event.resetScroll() event.resetScroll()
event.navigator.navigate( event.onNavigate {
Screen.LIBRARY, navigate(Screen.Library)
false }
)
event.onSuccess() event.onSuccess()
_state.update { _state.update {

View file

@ -33,13 +33,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.CustomIconButton
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel 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.data.Screen
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel 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 import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel
@Composable @Composable
fun HelpScreenRoot() { fun HelpScreenRoot(screen: Screen.Help) {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val helpViewModel: HelpViewModel = hiltViewModel() val helpViewModel: HelpViewModel = hiltViewModel()
val browseViewModel: BrowseViewModel = hiltViewModel() val browseViewModel: BrowseViewModel = hiltViewModel()
@ -73,12 +73,12 @@ fun HelpScreenRoot() {
val state = helpViewModel.state.collectAsState() val state = helpViewModel.state.collectAsState()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
helpViewModel.init(navigator) helpViewModel.init(screen = screen)
} }
HelpScreen( HelpScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = helpViewModel::onEvent, onEvent = helpViewModel::onEvent,
onMainEvent = mainViewModel::onEvent, onMainEvent = mainViewModel::onEvent,
onBrowseEvent = browseViewModel::onEvent, onBrowseEvent = browseViewModel::onEvent,
@ -92,7 +92,7 @@ fun HelpScreenRoot() {
@Composable @Composable
private fun HelpScreen( private fun HelpScreen(
state: State<HelpState>, state: State<HelpState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit, onEvent: (HelpEvent) -> Unit,
onMainEvent: (MainEvent) -> Unit, onMainEvent: (MainEvent) -> Unit,
onBrowseEvent: (BrowseEvent) -> Unit, onBrowseEvent: (BrowseEvent) -> Unit,
@ -113,7 +113,7 @@ private fun HelpScreen(
}, },
navigationIcon = { navigationIcon = {
if (!state.value.fromStart) { if (!state.value.fromStart) {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
} }
}, },
actions = { actions = {
@ -125,8 +125,10 @@ private fun HelpScreen(
) { ) {
onStartEvent(StartEvent.OnResetStartScreen) onStartEvent(StartEvent.OnResetStartScreen)
onMainEvent(MainEvent.OnChangeShowStartScreen(true)) onMainEvent(MainEvent.OnChangeShowStartScreen(true))
navigator.navigateWithoutBackStack(Screen.START, false) onNavigate {
navigator.clearBackStack() navigate(Screen.Start, saveInBackStack = false)
clearBackStack()
}
} }
} }
}, },
@ -149,11 +151,11 @@ private fun HelpScreen(
.fillMaxWidth(), .fillMaxWidth(),
shape = RoundedCornerShape(100), shape = RoundedCornerShape(100),
onClick = { onClick = {
navigator.clearArgument("from_start")
onBrowseEvent(BrowseEvent.OnLoadList) onBrowseEvent(BrowseEvent.OnLoadList)
onMainEvent(MainEvent.OnChangeShowStartScreen(false)) onMainEvent(MainEvent.OnChangeShowStartScreen(false))
navigator.navigateWithoutBackStack(Screen.BROWSE, false) onNavigate {
navigate(Screen.Browse, saveInBackStack = false)
}
} }
) { ) {
Text(text = stringResource(id = R.string.done)) Text(text = stringResource(id = R.string.done))
@ -203,6 +205,7 @@ private fun HelpScreen(
item { item {
HelpAddBooksItem( HelpAddBooksItem(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -210,6 +213,7 @@ private fun HelpScreen(
item { item {
HelpCustomizeApp( HelpCustomizeApp(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -217,6 +221,7 @@ private fun HelpScreen(
item { item {
HelpMoveOrDeleteBooks( HelpMoveOrDeleteBooks(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -224,6 +229,7 @@ private fun HelpScreen(
item { item {
HelpEditBook( HelpEditBook(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -231,6 +237,7 @@ private fun HelpScreen(
item { item {
HelpReadBook( HelpReadBook(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -238,6 +245,7 @@ private fun HelpScreen(
item { item {
HelpCustomizeReader( HelpCustomizeReader(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -245,6 +253,7 @@ private fun HelpScreen(
item { item {
HelpUpdateBook( HelpUpdateBook(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -252,6 +261,7 @@ private fun HelpScreen(
item { item {
HelpManageHistory( HelpManageHistory(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }
@ -266,6 +276,7 @@ private fun HelpScreen(
item { item {
HelpSetUpTranslator( HelpSetUpTranslator(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent onEvent = onEvent
) )
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpAddBooksItem( fun LazyItemScope.HelpAddBooksItem(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_add_books), title = stringResource(id = R.string.help_title_how_to_add_books),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -49,16 +48,18 @@ fun LazyItemScope.HelpAddBooksItem(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"browse" -> { "browse" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.BROWSE, true) navigate(Screen.Browse, useBackAnimation = true)
} }
} }
"library" -> { "library" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true) navigate(Screen.Library, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpCustomizeApp( fun LazyItemScope.HelpCustomizeApp(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_customize_app), title = stringResource(id = R.string.help_title_how_to_customize_app),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpCustomizeApp(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"settings" -> { "settings" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.SETTINGS, true) navigate(Screen.Settings, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpCustomizeReader( fun LazyItemScope.HelpCustomizeReader(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_customize_reader), title = stringResource(id = R.string.help_title_how_to_customize_reader),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpCustomizeReader(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"settings" -> { "settings" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.SETTINGS, true) navigate(Screen.Settings, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpEditBook( fun LazyItemScope.HelpEditBook(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_edit_book), title = stringResource(id = R.string.help_title_how_to_edit_book),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpEditBook(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"library" -> { "library" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true) navigate(Screen.Library, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpManageHistory( fun LazyItemScope.HelpManageHistory(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_manage_history), title = stringResource(id = R.string.help_title_how_to_manage_history),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpManageHistory(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"history" -> { "history" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.HISTORY, true) navigate(Screen.History, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpMoveOrDeleteBooks( fun LazyItemScope.HelpMoveOrDeleteBooks(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_move_or_delete_books), title = stringResource(id = R.string.help_title_how_to_move_or_delete_books),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpMoveOrDeleteBooks(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"library" -> { "library" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true) navigate(Screen.Library, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpReadBook( fun LazyItemScope.HelpReadBook(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_read_book), title = stringResource(id = R.string.help_title_how_to_read_book),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpReadBook(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"library" -> { "library" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true) navigate(Screen.Library, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpSetUpTranslator( fun LazyItemScope.HelpSetUpTranslator(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_set_up_translator), title = stringResource(id = R.string.help_title_how_to_set_up_translator),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpSetUpTranslator(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"reader_settings" -> { "reader_settings" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.READER_SETTINGS, true) navigate(Screen.Settings.ReaderSettings, useBackAnimation = true)
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.State
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import ua.acclorite.book_story.R 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.data.Screen
import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation import ua.acclorite.book_story.presentation.screens.help.components.HelpAnnotation
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem 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 @Composable
fun LazyItemScope.HelpUpdateBook( fun LazyItemScope.HelpUpdateBook(
state: State<HelpState>, state: State<HelpState>,
onNavigate: OnNavigate,
onEvent: (HelpEvent) -> Unit onEvent: (HelpEvent) -> Unit
) { ) {
val navigator = LocalNavigator.current
HelpItem( HelpItem(
title = stringResource(id = R.string.help_title_how_to_update_book), title = stringResource(id = R.string.help_title_how_to_update_book),
description = buildAnnotatedString { description = buildAnnotatedString {
@ -44,10 +43,12 @@ fun LazyItemScope.HelpUpdateBook(
) )
}, },
onTagClick = { tag -> onTagClick = { tag ->
onNavigate {
when (tag) { when (tag) {
"library" -> { "library" -> {
if (!state.value.fromStart) { if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true) navigate(Screen.Library, useBackAnimation = true)
}
} }
} }
} }

View file

@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Screen
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@ -75,13 +75,11 @@ class HelpViewModel @Inject constructor(
} }
} }
fun init(navigator: Navigator) { fun init(screen: Screen.Help) {
viewModelScope.launch { viewModelScope.launch {
val isFromStart = navigator.retrieveArgument("from_start") as? Boolean ?: false
_state.update { _state.update {
it.copy( it.copy(
fromStart = isFromStart fromStart = screen.fromStart
) )
} }
} }

View file

@ -38,6 +38,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R 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.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CategoryTitle
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility 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.MoreDropDown
import ua.acclorite.book_story.presentation.components.customItems 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.IsEmpty
import ua.acclorite.book_story.presentation.data.Argument
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.data.Screen
import ua.acclorite.book_story.presentation.screens.history.components.HistoryDeleteWholeHistoryDialog import ua.acclorite.book_story.presentation.screens.history.components.HistoryDeleteWholeHistoryDialog
import ua.acclorite.book_story.presentation.screens.history.components.HistoryItem import ua.acclorite.book_story.presentation.screens.history.components.HistoryItem
@ -71,7 +70,7 @@ fun HistoryScreenRoot() {
HistoryScreen( HistoryScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = viewModel::onEvent, onEvent = viewModel::onEvent,
onLibraryEvent = libraryViewModel::onEvent onLibraryEvent = libraryViewModel::onEvent
) )
@ -84,7 +83,7 @@ fun HistoryScreenRoot() {
@Composable @Composable
private fun HistoryScreen( private fun HistoryScreen(
state: State<HistoryState>, state: State<HistoryState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (HistoryEvent) -> Unit, onEvent: (HistoryEvent) -> Unit,
onLibraryEvent: (LibraryEvent) -> Unit onLibraryEvent: (LibraryEvent) -> Unit
) { ) {
@ -230,17 +229,17 @@ private fun HistoryScreen(
history = it, history = it,
isOnClickEnabled = !state.value.isRefreshing, isOnClickEnabled = !state.value.isRefreshing,
onBodyClick = { onBodyClick = {
navigator.navigate( onNavigate {
Screen.BOOK_INFO, navigate(
false, Screen.BookInfo(it.bookId)
Argument("book", it.bookId)
) )
}
}, },
onTitleClick = { onTitleClick = {
onEvent( onEvent(
HistoryEvent.OnNavigateToReaderScreen( HistoryEvent.OnNavigateToReaderScreen(
navigator, onNavigate = onNavigate,
it.book!! book = it.book!!
) )
) )
}, },
@ -300,7 +299,9 @@ private fun HistoryScreen(
return@BackHandler return@BackHandler
} }
navigator.navigate(Screen.LIBRARY, false) onNavigate {
navigate(Screen.Library)
}
} }
} }

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.History 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 @Immutable
sealed class HistoryEvent { sealed class HistoryEvent {
@ -27,7 +27,7 @@ sealed class HistoryEvent {
data class OnRequestFocus(val focusRequester: FocusRequester) : HistoryEvent() data class OnRequestFocus(val focusRequester: FocusRequester) : HistoryEvent()
data class OnUpdateBook(val book: Book) : HistoryEvent() data class OnUpdateBook(val book: Book) : HistoryEvent()
data class OnNavigateToReaderScreen( data class OnNavigateToReaderScreen(
val navigator: Navigator, val onNavigate: OnNavigate,
val book: Book val book: Book
) : HistoryEvent() ) : HistoryEvent()

View file

@ -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.GetHistory
import ua.acclorite.book_story.domain.use_case.InsertHistory import ua.acclorite.book_story.domain.use_case.InsertHistory
import ua.acclorite.book_story.domain.util.Resource 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 ua.acclorite.book_story.presentation.data.Screen
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
@ -266,13 +265,9 @@ class HistoryViewModel @Inject constructor(
) )
) )
} }
event.navigator.navigate( event.onNavigate {
Screen.READER, navigate(Screen.Reader(event.book.id))
false, }
Argument(
"book", event.book.id
)
)
} }
} }

View file

@ -62,6 +62,7 @@ import kotlinx.coroutines.launch
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category 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.domain.util.Selected
import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility 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.customItems
import ua.acclorite.book_story.presentation.components.header import ua.acclorite.book_story.presentation.components.header
import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty 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.LocalNavigator
import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.data.Screen 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.BrowseEvent
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
@ -100,7 +99,7 @@ fun LibraryScreenRoot() {
LibraryScreen( LibraryScreen(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onEvent = viewModel::onEvent, onEvent = viewModel::onEvent,
onBrowseEvent = browseViewModel::onEvent, onBrowseEvent = browseViewModel::onEvent,
onHistoryEvent = historyViewModel::onEvent onHistoryEvent = historyViewModel::onEvent
@ -114,7 +113,7 @@ fun LibraryScreenRoot() {
@Composable @Composable
private fun LibraryScreen( private fun LibraryScreen(
state: State<LibraryState>, state: State<LibraryState>,
navigator: Navigator, onNavigate: OnNavigate,
onEvent: (LibraryEvent) -> Unit, onEvent: (LibraryEvent) -> Unit,
onHistoryEvent: (HistoryEvent) -> Unit, onHistoryEvent: (HistoryEvent) -> Unit,
onBrowseEvent: (BrowseEvent) -> Unit onBrowseEvent: (BrowseEvent) -> Unit
@ -338,11 +337,9 @@ private fun LibraryScreen(
if (state.value.hasSelectedItems) { if (state.value.hasSelectedItems) {
onEvent(LibraryEvent.OnSelectBook(it)) onEvent(LibraryEvent.OnSelectBook(it))
} else { } else {
navigator.navigate( onNavigate {
Screen.BOOK_INFO, navigate(Screen.BookInfo(it.first.id))
false, }
Argument("book", it.first.id)
)
} }
}, },
onLongClick = { onLongClick = {
@ -353,8 +350,8 @@ private fun LibraryScreen(
onButtonClick = { onButtonClick = {
onEvent( onEvent(
LibraryEvent.OnNavigateToReaderScreen( LibraryEvent.OnNavigateToReaderScreen(
navigator, onNavigate = onNavigate,
it.first book = it.first
) )
) )
} }
@ -381,7 +378,9 @@ private fun LibraryScreen(
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
actionTitle = stringResource(id = R.string.add_book) actionTitle = stringResource(id = R.string.add_book)
) { ) {
navigator.navigate(Screen.BROWSE, false) onNavigate {
navigate(Screen.Browse)
}
} }
} }
} }

View file

@ -5,8 +5,8 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category 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.domain.util.Selected
import ua.acclorite.book_story.presentation.data.Navigator
@Immutable @Immutable
sealed class LibraryEvent { sealed class LibraryEvent {
@ -30,7 +30,7 @@ sealed class LibraryEvent {
data class OnDeleteBooks(val refreshList: () -> Unit) : LibraryEvent() data class OnDeleteBooks(val refreshList: () -> Unit) : LibraryEvent()
data class OnUpdateBook(val book: Book) : LibraryEvent() data class OnUpdateBook(val book: Book) : LibraryEvent()
data class OnNavigateToReaderScreen( data class OnNavigateToReaderScreen(
val navigator: Navigator, val onNavigate: OnNavigate,
val book: Book val book: Book
) : LibraryEvent() ) : LibraryEvent()
} }

View file

@ -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.GetBooks
import ua.acclorite.book_story.domain.use_case.InsertHistory import ua.acclorite.book_story.domain.use_case.InsertHistory
import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.use_case.UpdateBooks
import ua.acclorite.book_story.presentation.data.Argument
import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.Screen
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
@ -338,13 +337,9 @@ class LibraryViewModel @Inject constructor(
) )
) )
} }
event.navigator.navigate( event.onNavigate {
Screen.READER, navigate(Screen.Reader(event.book.id))
false, }
Argument(
"book", event.book.id
)
)
} }
} }

View file

@ -50,6 +50,7 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.Constants 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.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomSelectionContainer import ua.acclorite.book_story.presentation.components.CustomSelectionContainer
import ua.acclorite.book_story.presentation.components.customItems 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.MainEvent
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.data.MainViewModel 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.HistoryEvent
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.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 import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
@Composable @Composable
fun ReaderScreenRoot() { fun ReaderScreenRoot(screen: Screen.Reader) {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
@ -103,8 +104,9 @@ fun ReaderScreenRoot() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init( viewModel.init(
navigator, screen = screen,
context, onNavigate = { navigator.it() },
context = context,
refreshList = { refreshList = {
libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it))
historyViewModel.onEvent(HistoryEvent.OnLoadList) historyViewModel.onEvent(HistoryEvent.OnLoadList)
@ -139,8 +141,8 @@ fun ReaderScreenRoot() {
ReaderScreen( ReaderScreen(
state = state, state = state,
mainState = mainState, mainState = mainState,
navigator = navigator,
lazyListState = lazyListState, lazyListState = lazyListState,
onNavigate = { navigator.it() },
onEvent = viewModel::onEvent, onEvent = viewModel::onEvent,
onMainEvent = mainViewModel::onEvent, onMainEvent = mainViewModel::onEvent,
onLibraryEvent = libraryViewModel::onEvent, onLibraryEvent = libraryViewModel::onEvent,
@ -153,8 +155,8 @@ fun ReaderScreenRoot() {
private fun ReaderScreen( private fun ReaderScreen(
state: State<ReaderState>, state: State<ReaderState>,
mainState: State<MainState>, mainState: State<MainState>,
navigator: Navigator,
lazyListState: LazyListState, lazyListState: LazyListState,
onNavigate: OnNavigate,
onEvent: (ReaderEvent) -> Unit, onEvent: (ReaderEvent) -> Unit,
onMainEvent: (MainEvent) -> Unit, onMainEvent: (MainEvent) -> Unit,
onLibraryEvent: (LibraryEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit,
@ -278,6 +280,7 @@ private fun ReaderScreen(
) { ) {
ReaderTopBar( ReaderTopBar(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent, onEvent = onEvent,
onLibraryUpdateEvent = onLibraryEvent, onLibraryUpdateEvent = onLibraryEvent,
onHistoryUpdateEvent = onHistoryEvent onHistoryUpdateEvent = onHistoryEvent
@ -399,6 +402,7 @@ private fun ReaderScreen(
DisableSelection { DisableSelection {
ReaderEndItem( ReaderEndItem(
state = state, state = state,
onNavigate = onNavigate,
onEvent = onEvent, onEvent = onEvent,
onLibraryEvent = onLibraryEvent, onLibraryEvent = onLibraryEvent,
onHistoryUpdateEvent = onHistoryEvent, onHistoryUpdateEvent = onHistoryEvent,
@ -427,13 +431,14 @@ private fun ReaderScreen(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
context, context,
navigator,
refreshList = { refreshList = {
onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onLibraryEvent(LibraryEvent.OnUpdateBook(it))
onHistoryEvent(HistoryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it))
}, },
navigate = { navigate = {
it.navigateBack() onNavigate {
navigateBack()
}
} }
) )
) )
@ -461,13 +466,14 @@ private fun ReaderScreen(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
context, context,
navigator,
refreshList = { refreshList = {
onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onLibraryEvent(LibraryEvent.OnUpdateBook(it))
onHistoryEvent(HistoryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it))
}, },
navigate = { navigate = {
it.navigateBack() onNavigate {
navigateBack()
}
} }
) )
) )

View file

@ -30,7 +30,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Category 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.data.Screen
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent 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. * Reader end item. Displays at the end of the book.
* *
* @param state [ReaderState]. * @param state [ReaderState].
* @param onNavigate Navigator callback.
* @param onEvent [ReaderEvent] callback. * @param onEvent [ReaderEvent] callback.
* @param onLibraryEvent [LibraryEvent] callback. * @param onLibraryEvent [LibraryEvent] callback.
* @param onHistoryUpdateEvent [HistoryEvent] callback. * @param onHistoryUpdateEvent [HistoryEvent] callback.
@ -49,13 +50,12 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
@Composable @Composable
fun ReaderEndItem( fun ReaderEndItem(
state: State<ReaderState>, state: State<ReaderState>,
onNavigate: OnNavigate,
onEvent: (ReaderEvent) -> Unit, onEvent: (ReaderEvent) -> Unit,
onLibraryEvent: (LibraryEvent) -> Unit, onLibraryEvent: (LibraryEvent) -> Unit,
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit, onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit,
) { ) {
val navigator = LocalNavigator.current
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
val buttonText = remember { val buttonText = remember {
context.getString( context.getString(
if (state.value.book.category != Category.ALREADY_READ) R.string.move_to_read if (state.value.book.category != Category.ALREADY_READ) R.string.move_to_read
@ -106,7 +106,7 @@ fun ReaderEndItem(
updatePage = { updatePage = {
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
}, },
navigator = navigator, onNavigate = onNavigate,
context = context context = context
) )
) )
@ -120,13 +120,14 @@ fun ReaderEndItem(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
context, context,
navigator,
refreshList = { refreshList = {
onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onLibraryEvent(LibraryEvent.OnUpdateBook(it))
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
}, },
navigate = { navigate = {
it.navigate(Screen.LIBRARY, true) onNavigate {
navigate(Screen.Library, useBackAnimation = true)
}
} }
) )
) )

View file

@ -27,8 +27,8 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R 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.CustomIconButton
import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.Screen
import ua.acclorite.book_story.presentation.data.removeDigits import ua.acclorite.book_story.presentation.data.removeDigits
import ua.acclorite.book_story.presentation.data.removeTrailingZero 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. * Reader top bar. Displays title of the book.
* *
* @param state [ReaderState]. * @param state [ReaderState].
* @param onNavigate Navigator callback.
* @param onEvent [ReaderEvent] callback. * @param onEvent [ReaderEvent] callback.
* @param onLibraryUpdateEvent [LibraryEvent] callback. * @param onLibraryUpdateEvent [LibraryEvent] callback.
* @param onHistoryUpdateEvent [HistoryEvent] callback. * @param onHistoryUpdateEvent [HistoryEvent] callback.
@ -50,13 +51,12 @@ import ua.acclorite.book_story.presentation.ui.Colors
@Composable @Composable
fun ReaderTopBar( fun ReaderTopBar(
state: State<ReaderState>, state: State<ReaderState>,
onNavigate: OnNavigate,
onEvent: (ReaderEvent) -> Unit, onEvent: (ReaderEvent) -> Unit,
onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit,
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit
) { ) {
val navigator = LocalNavigator.current
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
val progress by remember(state.value.book.progress) { val progress by remember(state.value.book.progress) {
derivedStateOf { derivedStateOf {
(state.value.book.progress * 100) (state.value.book.progress * 100)
@ -77,13 +77,14 @@ fun ReaderTopBar(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
context, context,
navigator,
refreshList = { refreshList = {
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
}, },
navigate = { navigate = {
it.navigateBack() onNavigate {
navigateBack()
}
} }
) )
) )
@ -108,17 +109,19 @@ fun ReaderTopBar(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
context, context,
navigator,
refreshList = { refreshList = {
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
}, },
navigate = { navigate = {
it.navigateWithoutBackStack( onNavigate {
Screen.BOOK_INFO, navigate(
true Screen.BookInfo(state.value.book.id),
useBackAnimation = true,
saveInBackStack = false
) )
} }
}
) )
) )
} }

View file

@ -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.model.SelectableLanguage
import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.ID
import ua.acclorite.book_story.domain.util.LanguageCode 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.domain.util.UIText
import ua.acclorite.book_story.presentation.data.Navigator
@Immutable @Immutable
sealed class ReaderEvent { sealed class ReaderEvent {
@ -20,8 +20,10 @@ sealed class ReaderEvent {
val onTextIsEmpty: () -> Unit val onTextIsEmpty: () -> Unit
) : ReaderEvent() ) : ReaderEvent()
data class OnShowHideMenu(val show: Boolean? = null, val context: ComponentActivity) : data class OnShowHideMenu(
ReaderEvent() val show: Boolean? = null,
val context: ComponentActivity
) : ReaderEvent()
data class OnShowHideTranslatorBottomSheet(val show: Boolean? = null) : ReaderEvent() data class OnShowHideTranslatorBottomSheet(val show: Boolean? = null) : ReaderEvent()
@ -63,9 +65,8 @@ sealed class ReaderEvent {
data class OnGoBack( data class OnGoBack(
val context: ComponentActivity, val context: ComponentActivity,
val navigator: Navigator, val navigate: () -> Unit,
val refreshList: (Book) -> Unit, val refreshList: (Book) -> Unit
val navigate: (Navigator) -> Unit
) : ReaderEvent() ) : ReaderEvent()
data class OnChangeProgress( data class OnChangeProgress(
@ -82,7 +83,7 @@ sealed class ReaderEvent {
val context: ComponentActivity, val context: ComponentActivity,
val onUpdateCategories: (Book) -> Unit, val onUpdateCategories: (Book) -> Unit,
val updatePage: (Int) -> Unit, val updatePage: (Int) -> Unit,
val navigator: Navigator val onNavigate: OnNavigate
) : ReaderEvent() ) : ReaderEvent()
data class OnOpenTranslator( data class OnOpenTranslator(

View file

@ -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.use_case.UpdateBooks
import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.ID
import ua.acclorite.book_story.domain.util.LanguageCode 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.Resource
import ua.acclorite.book_story.domain.util.UIText 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.Screen
import ua.acclorite.book_story.presentation.data.removeKey import ua.acclorite.book_story.presentation.data.removeKey
import ua.acclorite.book_story.presentation.data.removeKeys import ua.acclorite.book_story.presentation.data.removeKeys
@ -912,7 +912,7 @@ class ReaderViewModel @Inject constructor(
} }
insetsController.show(WindowInsetsCompat.Type.systemBars()) insetsController.show(WindowInsetsCompat.Type.systemBars())
event.navigate(event.navigator) event.navigate()
} }
} }
@ -967,7 +967,6 @@ class ReaderViewModel @Inject constructor(
onEvent( onEvent(
ReaderEvent.OnGoBack( ReaderEvent.OnGoBack(
event.context, event.context,
event.navigator,
refreshList = {}, refreshList = {},
navigate = {} navigate = {}
) )
@ -995,7 +994,12 @@ class ReaderViewModel @Inject constructor(
}.size - 1 }.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( fun init(
navigator: Navigator, screen: Screen.Reader,
onNavigate: OnNavigate,
context: ComponentActivity, context: ComponentActivity,
refreshList: (Book) -> Unit, refreshList: (Book) -> Unit,
onError: (UIText) -> Unit onError: (UIText) -> Unit
) { ) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val bookId = navigator.retrieveArgument("book") as? Int val book = getBookById.execute(screen.bookId)
if (bookId == null) {
navigator.navigateBack()
return@launch
}
val book = getBookById.execute(bookId)
if (book == null) { if (book == null) {
navigator.navigateBack() onNavigate {
navigateBack()
}
return@launch return@launch
} }

View file

@ -24,10 +24,10 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R 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.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.data.LocalNavigator 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.data.Screen
import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryItem 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() { fun SettingsScreenRoot() {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
SettingsScreen(navigator = navigator) SettingsScreen(onNavigate = { navigator.it() })
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun SettingsScreen( private fun SettingsScreen(
navigator: Navigator onNavigate: OnNavigate
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
@ -57,7 +57,7 @@ private fun SettingsScreen(
Text(stringResource(id = R.string.settings_screen)) Text(stringResource(id = R.string.settings_screen))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
@ -83,7 +83,9 @@ private fun SettingsScreen(
text = stringResource(id = R.string.general_settings), text = stringResource(id = R.string.general_settings),
description = stringResource(id = R.string.general_settings_desc) 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), text = stringResource(id = R.string.appearance_settings),
description = stringResource(id = R.string.appearance_settings_desc) 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), text = stringResource(id = R.string.reader_settings),
description = stringResource(id = R.string.reader_settings_desc) description = stringResource(id = R.string.reader_settings_desc)
) { ) {
navigator.navigate(Screen.READER_SETTINGS, false) onNavigate {
navigate(Screen.Settings.ReaderSettings)
}
} }
} }

View file

@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem 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.CategoryTitle
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState 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.MainEvent
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.data.MainViewModel 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.ColorPickerWithTitle
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher.AppearanceSettingsThemeSwitcher import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.theme_switcher.AppearanceSettingsThemeSwitcher
@ -58,7 +58,7 @@ fun AppearanceSettingsRoot() {
AppearanceSettings( AppearanceSettings(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onMainEvent = mainViewModel::onEvent onMainEvent = mainViewModel::onEvent
) )
} }
@ -67,7 +67,7 @@ fun AppearanceSettingsRoot() {
@Composable @Composable
private fun AppearanceSettings( private fun AppearanceSettings(
state: State<MainState>, state: State<MainState>,
navigator: Navigator, onNavigate: OnNavigate,
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
@ -91,7 +91,7 @@ private fun AppearanceSettings(
Text(stringResource(id = R.string.appearance_settings)) Text(stringResource(id = R.string.appearance_settings))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(

View file

@ -31,13 +31,13 @@ import com.google.accompanist.permissions.rememberPermissionState
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.domain.util.Constants 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.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.data.MainViewModel 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.ChipsWithTitle
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
@ -53,7 +53,7 @@ fun GeneralSettingsRoot() {
GeneralSettings( GeneralSettings(
state = state, state = state,
navigator = navigator, onNavigate = { navigator.it() },
onSettingsEvent = settingsViewModel::onEvent, onSettingsEvent = settingsViewModel::onEvent,
onMainEvent = mainViewModel::onEvent onMainEvent = mainViewModel::onEvent
) )
@ -64,7 +64,7 @@ fun GeneralSettingsRoot() {
@Composable @Composable
private fun GeneralSettings( private fun GeneralSettings(
state: State<MainState>, state: State<MainState>,
navigator: Navigator, onNavigate: OnNavigate,
onSettingsEvent: (SettingsEvent) -> Unit, onSettingsEvent: (SettingsEvent) -> Unit,
onMainEvent: (MainEvent) -> Unit onMainEvent: (MainEvent) -> Unit
) { ) {
@ -87,7 +87,7 @@ private fun GeneralSettings(
Text(stringResource(id = R.string.general_settings)) Text(stringResource(id = R.string.general_settings))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(

View file

@ -28,6 +28,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.domain.util.Constants 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.CategoryTitle
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState 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.MainEvent
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.data.MainViewModel 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.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.ChipsWithTitle
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
@ -58,7 +58,7 @@ fun ReaderSettingsRoot() {
ReaderSettings( ReaderSettings(
state = state, state = state,
settingsState = settingsState, settingsState = settingsState,
navigator = navigator, onNavigate = { navigator.it() },
onMainEvent = mainViewModel::onEvent, onMainEvent = mainViewModel::onEvent,
onEvent = settingsViewModel::onEvent onEvent = settingsViewModel::onEvent
) )
@ -69,7 +69,7 @@ fun ReaderSettingsRoot() {
private fun ReaderSettings( private fun ReaderSettings(
state: State<MainState>, state: State<MainState>,
settingsState: State<SettingsState>, settingsState: State<SettingsState>,
navigator: Navigator, onNavigate: OnNavigate,
onMainEvent: (MainEvent) -> Unit, onMainEvent: (MainEvent) -> Unit,
onEvent: (SettingsEvent) -> Unit onEvent: (SettingsEvent) -> Unit
) { ) {
@ -145,7 +145,7 @@ private fun ReaderSettings(
Text(stringResource(id = R.string.reader_settings)) Text(stringResource(id = R.string.reader_settings))
}, },
navigationIcon = { navigationIcon = {
GoBackButton(navigator = navigator) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollState.first,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(

View file

@ -35,7 +35,12 @@ import ua.acclorite.book_story.presentation.screens.start.data.StartEvent
import ua.acclorite.book_story.presentation.screens.start.data.StartState 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 @Composable
fun StartDone( fun StartDone(
@ -72,7 +77,7 @@ fun StartDone(
onClick = { onClick = {
onEvent( onEvent(
StartEvent.OnGoToBrowse( StartEvent.OnGoToBrowse(
navigator, onNavigate = { navigator.it() },
onCompletedStartGuide = { onCompletedStartGuide = {
onBrowseEvent(BrowseEvent.OnLoadList) onBrowseEvent(BrowseEvent.OnLoadList)
onMainEvent( onMainEvent(
@ -91,9 +96,7 @@ fun StartDone(
shape = RoundedCornerShape(100), shape = RoundedCornerShape(100),
onClick = { onClick = {
onEvent( onEvent(
StartEvent.OnGoToHelp( StartEvent.OnGoToHelp { navigator.it() }
navigator
)
) )
} }
) { ) {

View file

@ -6,7 +6,7 @@ import androidx.activity.ComponentActivity
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.domain.util.OnNavigate
@Immutable @Immutable
sealed class StartEvent { sealed class StartEvent {
@ -23,10 +23,10 @@ sealed class StartEvent {
val onEnableUpdates: () -> Unit val onEnableUpdates: () -> Unit
) : StartEvent() ) : StartEvent()
data class OnGoToBrowse(val navigator: Navigator, val onCompletedStartGuide: () -> Unit) : data class OnGoToBrowse(val onNavigate: OnNavigate, val onCompletedStartGuide: () -> Unit) :
StartEvent() StartEvent()
data class OnGoToHelp(val navigator: Navigator) : StartEvent() data class OnGoToHelp(val onNavigate: OnNavigate) : StartEvent()
data object OnResetStartScreen : StartEvent() data object OnResetStartScreen : StartEvent()
} }

View file

@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import ua.acclorite.book_story.domain.use_case.CheckForUpdates 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 ua.acclorite.book_story.presentation.data.Screen
import javax.inject.Inject import javax.inject.Inject
@ -239,13 +238,16 @@ class StartViewModel @Inject constructor(
} }
is StartEvent.OnGoToBrowse -> { is StartEvent.OnGoToBrowse -> {
event.navigator.navigateWithoutBackStack(Screen.BROWSE, false) event.onNavigate {
navigate(Screen.Browse, saveInBackStack = false)
}
event.onCompletedStartGuide() event.onCompletedStartGuide()
} }
is StartEvent.OnGoToHelp -> { is StartEvent.OnGoToHelp -> {
event.navigator.putArgument(Argument("from_start", true)) event.onNavigate {
event.navigator.navigateWithoutBackStack(Screen.HELP, false) navigate(Screen.Help(true), saveInBackStack = false)
}
} }
is StartEvent.OnResetStartScreen -> { is StartEvent.OnResetStartScreen -> {