🛠️ ViewModel passing code reformat
* Provided all viewModels through LocalComposition * Removed passing viewModels as parameters
This commit is contained in:
parent
3b287ff1a0
commit
b135ed301c
112 changed files with 802 additions and 1451 deletions
|
|
@ -19,6 +19,7 @@ import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.bottom_navigation_bar.BottomNavigationBar
|
import ua.acclorite.book_story.presentation.components.bottom_navigation_bar.BottomNavigationBar
|
||||||
import ua.acclorite.book_story.presentation.components.custom_navigation_rail.CustomNavigationRail
|
import ua.acclorite.book_story.presentation.components.custom_navigation_rail.CustomNavigationRail
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||||
|
|
@ -89,8 +90,8 @@ class Activity : AppCompatActivity() {
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
val isLoaded = mainViewModel.isReady.collectAsState()
|
val isLoaded = mainViewModel.isReady.collectAsState()
|
||||||
val state = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val imeInsets = WindowInsets.ime
|
val imeInsets = WindowInsets.ime
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ua.acclorite.book_story.domain.util
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
abstract class BaseViewModel<S, E> : ViewModel() {
|
||||||
|
abstract val state: StateFlow<S>
|
||||||
|
abstract fun onEvent(event: E)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.ProvidableCompositionLocal
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainState
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.data.AboutState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.help.data.HelpEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.help.data.HelpState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.help.data.HelpViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryState
|
||||||
|
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.LibraryState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
|
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.settings.data.SettingsEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
||||||
|
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.StartViewModel
|
||||||
|
|
||||||
|
data class ViewModelComposition<S, E, V>(
|
||||||
|
val state: State<S>,
|
||||||
|
val onEvent: (E) -> Unit,
|
||||||
|
val viewModel: V
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
inline fun <reified V : BaseViewModel<S, E>, S, E> viewModelComposition(
|
||||||
|
): ProvidableCompositionLocal<ViewModelComposition<S, E, V>> {
|
||||||
|
val viewModel: V = hiltViewModel()
|
||||||
|
val state = viewModel.state.collectAsState()
|
||||||
|
|
||||||
|
return compositionLocalOf {
|
||||||
|
ViewModelComposition(
|
||||||
|
state = state,
|
||||||
|
onEvent = viewModel::onEvent,
|
||||||
|
viewModel = viewModel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val LocalMainViewModel
|
||||||
|
@Composable get() = viewModelComposition<MainViewModel, MainState, MainEvent>()
|
||||||
|
val LocalLibraryViewModel
|
||||||
|
@Composable get() = viewModelComposition<LibraryViewModel, LibraryState, LibraryEvent>()
|
||||||
|
val LocalHistoryViewModel
|
||||||
|
@Composable get() = viewModelComposition<HistoryViewModel, HistoryState, HistoryEvent>()
|
||||||
|
val LocalBrowseViewModel
|
||||||
|
@Composable get() = viewModelComposition<BrowseViewModel, BrowseState, BrowseEvent>()
|
||||||
|
val LocalBookInfoViewModel
|
||||||
|
@Composable get() = viewModelComposition<BookInfoViewModel, BookInfoState, BookInfoEvent>()
|
||||||
|
val LocalReaderViewModel
|
||||||
|
@Composable get() = viewModelComposition<ReaderViewModel, ReaderState, ReaderEvent>()
|
||||||
|
val LocalSettingsViewModel
|
||||||
|
@Composable get() = viewModelComposition<SettingsViewModel, SettingsState, SettingsEvent>()
|
||||||
|
val LocalAboutViewModel
|
||||||
|
@Composable get() = viewModelComposition<AboutViewModel, AboutState, AboutEvent>()
|
||||||
|
val LocalLicensesViewModel
|
||||||
|
@Composable get() = viewModelComposition<LicensesViewModel, LicensesState, LicensesEvent>()
|
||||||
|
val LocalLicenseInfoViewModel
|
||||||
|
@Composable get() = viewModelComposition<LicenseInfoViewModel, LicenseInfoState, LicenseInfoEvent>()
|
||||||
|
val LocalHelpViewModel
|
||||||
|
@Composable get() = viewModelComposition<HelpViewModel, HelpState, HelpEvent>()
|
||||||
|
val LocalStartViewModel
|
||||||
|
@Composable get() = viewModelComposition<StartViewModel, StartState, StartEvent>()
|
||||||
|
|
@ -82,6 +82,10 @@ data class MainState(
|
||||||
val browseIncludedFilterItems: List<String> = provideDefaultValue { emptyList() },
|
val browseIncludedFilterItems: List<String> = provideDefaultValue { emptyList() },
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
companion object {
|
companion object {
|
||||||
|
private fun <D> provideDefaultValue(calculation: () -> D): D {
|
||||||
|
return calculation()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes [MainState] by given [Map].
|
* Initializes [MainState] by given [Map].
|
||||||
* If no value provided in [data], assigns default value.
|
* If no value provided in [data], assigns default value.
|
||||||
|
|
@ -210,7 +214,3 @@ data class MainState(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D> provideDefaultValue(calculation: () -> D): D {
|
|
||||||
return calculation()
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package ua.acclorite.book_story.presentation.data
|
package ua.acclorite.book_story.presentation.data
|
||||||
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -16,6 +15,7 @@ import ua.acclorite.book_story.domain.use_case.ChangeLanguage
|
||||||
import ua.acclorite.book_story.domain.use_case.CheckForUpdates
|
import ua.acclorite.book_story.domain.use_case.CheckForUpdates
|
||||||
import ua.acclorite.book_story.domain.use_case.GetAllSettings
|
import ua.acclorite.book_story.domain.use_case.GetAllSettings
|
||||||
import ua.acclorite.book_story.domain.use_case.SetDatastore
|
import ua.acclorite.book_story.domain.use_case.SetDatastore
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.Constants
|
import ua.acclorite.book_story.domain.util.Constants
|
||||||
import ua.acclorite.book_story.domain.util.DataStoreConstants
|
import ua.acclorite.book_story.domain.util.DataStoreConstants
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
|
@ -41,7 +41,7 @@ class MainViewModel @Inject constructor(
|
||||||
private val changeLanguage: ChangeLanguage,
|
private val changeLanguage: ChangeLanguage,
|
||||||
private val checkForUpdates: CheckForUpdates,
|
private val checkForUpdates: CheckForUpdates,
|
||||||
private val getAllSettings: GetAllSettings
|
private val getAllSettings: GetAllSettings
|
||||||
) : ViewModel() {
|
) : BaseViewModel<MainState, MainEvent>() {
|
||||||
|
|
||||||
private val _isReady = MutableStateFlow(false)
|
private val _isReady = MutableStateFlow(false)
|
||||||
val isReady = _isReady.asStateFlow()
|
val isReady = _isReady.asStateFlow()
|
||||||
|
|
@ -52,9 +52,9 @@ class MainViewModel @Inject constructor(
|
||||||
private val _state: MutableStateFlow<MainState> = MutableStateFlow(
|
private val _state: MutableStateFlow<MainState> = MutableStateFlow(
|
||||||
stateHandle[Constants.MAIN_STATE] ?: MainState()
|
stateHandle[Constants.MAIN_STATE] ?: MainState()
|
||||||
)
|
)
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
fun onEvent(event: MainEvent) {
|
override fun onEvent(event: MainEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is MainEvent.OnChangeLanguage -> {
|
is MainEvent.OnChangeLanguage -> {
|
||||||
viewModelScope.launch(Dispatchers.Main) {
|
viewModelScope.launch(Dispatchers.Main) {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import ua.acclorite.book_story.domain.util.OnNavigate
|
||||||
import ua.acclorite.book_story.domain.util.Route
|
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
|
||||||
|
|
@ -54,11 +55,14 @@ private const val USE_BACK_ANIM = "use_back_animation"
|
||||||
private const val SCREENS = "screens"
|
private const val SCREENS = "screens"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passed in [CompositionLocalProvider] and can be accessed through [LocalNavigator].current.
|
* Passed in [CompositionLocalProvider].
|
||||||
*/
|
*/
|
||||||
val LocalNavigator = compositionLocalOf<Navigator> {
|
val LocalNavigator = compositionLocalOf<Navigator> {
|
||||||
error("Cannot initialize Navigator.")
|
error("Cannot initialize Navigator.")
|
||||||
}
|
}
|
||||||
|
val LocalOnNavigate = compositionLocalOf<OnNavigate> {
|
||||||
|
error("Cannot initialize Navigator.")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Screens. Should be [Serializable] to be able to pass them inside [SavedStateHandle].
|
* Screens. Should be [Serializable] to be able to pass them inside [SavedStateHandle].
|
||||||
|
|
@ -434,7 +438,10 @@ fun NavigationHost(
|
||||||
.background(colorBetweenAnimations)
|
.background(colorBetweenAnimations)
|
||||||
)
|
)
|
||||||
|
|
||||||
CompositionLocalProvider(LocalNavigator provides navigator) {
|
CompositionLocalProvider(
|
||||||
|
LocalNavigator provides navigator,
|
||||||
|
LocalOnNavigate provides { navigator.it() }
|
||||||
|
) {
|
||||||
content(navigator)
|
content(navigator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,8 +19,6 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
|
@ -29,51 +27,36 @@ import androidx.compose.ui.res.painterResource
|
||||||
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 androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalAboutViewModel
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.about.components.badges.AboutBadges
|
import ua.acclorite.book_story.presentation.screens.about.components.badges.AboutBadges
|
||||||
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.AboutState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutScreenRoot() {
|
fun AboutScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
AboutScreen()
|
||||||
val aboutViewModel: AboutViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = aboutViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
AboutScreen(
|
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = aboutViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun AboutScreen(
|
private fun AboutScreen() {
|
||||||
state: State<AboutState>,
|
val state = LocalAboutViewModel.current.state
|
||||||
onNavigate: OnNavigate,
|
val onEvent = LocalAboutViewModel.current.onEvent
|
||||||
onEvent: (AboutEvent) -> Unit
|
val onNavigate = LocalOnNavigate.current
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
if (state.value.showUpdateDialog) {
|
if (state.value.showUpdateDialog) {
|
||||||
AboutUpdateDialog(
|
AboutUpdateDialog()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -245,7 +228,7 @@ private fun AboutScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
AboutBadges(onEvent = onEvent)
|
AboutBadges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,22 @@ package ua.acclorite.book_story.presentation.screens.about.components
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Update
|
import androidx.compose.material.icons.filled.Update
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalAboutViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.AboutState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update dialog. If there is app update transfers to the download page.
|
* Update dialog. If there is app update transfers to the download page.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutUpdateDialog(
|
fun AboutUpdateDialog() {
|
||||||
state: State<AboutState>,
|
val state = LocalAboutViewModel.current.state
|
||||||
onEvent: (AboutEvent) -> Unit
|
val onEvent = LocalAboutViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val update = remember(state.value.showUpdateDialog) {
|
val update = remember(state.value.showUpdateDialog) {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import androidx.compose.ui.unit.Dp
|
||||||
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.Constants
|
import ua.acclorite.book_story.domain.util.Constants
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalAboutViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
|
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
|
||||||
|
|
@ -21,14 +22,11 @@ import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
|
||||||
* About Badges.
|
* About Badges.
|
||||||
* Links all ways to contact me.
|
* Links all ways to contact me.
|
||||||
*
|
*
|
||||||
* @param onEvent [AboutEvent] callback.
|
|
||||||
* @param verticalPadding Vertical item padding.
|
* @param verticalPadding Vertical item padding.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutBadges(
|
fun AboutBadges(verticalPadding: Dp = 18.dp) {
|
||||||
onEvent: (AboutEvent) -> Unit,
|
val onEvent = LocalAboutViewModel.current.onEvent
|
||||||
verticalPadding: Dp = 18.dp
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.screens.about.data
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -12,18 +11,19 @@ import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.domain.use_case.CheckForUpdates
|
import ua.acclorite.book_story.domain.use_case.CheckForUpdates
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.launchActivity
|
import ua.acclorite.book_story.presentation.data.launchActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class AboutViewModel @Inject constructor(
|
class AboutViewModel @Inject constructor(
|
||||||
private val checkForUpdates: CheckForUpdates,
|
private val checkForUpdates: CheckForUpdates,
|
||||||
) : ViewModel() {
|
) : BaseViewModel<AboutState, AboutEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(AboutState())
|
private val _state = MutableStateFlow(AboutState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
fun onEvent(event: AboutEvent) {
|
override fun onEvent(event: AboutEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is AboutEvent.OnNavigateToBrowserPage -> {
|
is AboutEvent.OnNavigateToBrowserPage -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
|
||||||
|
|
@ -16,40 +16,32 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalAboutViewModel
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.nested.credits.components.CreditItem
|
import ua.acclorite.book_story.presentation.screens.about.nested.credits.components.CreditItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CreditsScreenRoot() {
|
fun CreditsScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
CreditsScreen()
|
||||||
val aboutViewModel: AboutViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
CreditsScreen(
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onAboutNavigateEvent = aboutViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun CreditsScreen(
|
private fun CreditsScreen() {
|
||||||
onNavigate: OnNavigate,
|
val onEvent = LocalAboutViewModel.current.onEvent
|
||||||
onAboutNavigateEvent: (AboutEvent.OnNavigateToBrowserPage) -> Unit
|
val onNavigate = LocalOnNavigate.current
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
@ -81,7 +73,7 @@ private fun CreditsScreen(
|
||||||
customItems(Constants.CREDITS, key = { it.name }) {
|
customItems(Constants.CREDITS, key = { it.name }) {
|
||||||
CreditItem(credit = it) {
|
CreditItem(credit = it) {
|
||||||
it.website?.let { website ->
|
it.website?.let { website ->
|
||||||
onAboutNavigateEvent(
|
onEvent(
|
||||||
AboutEvent.OnNavigateToBrowserPage(
|
AboutEvent.OnNavigateToBrowserPage(
|
||||||
page = website,
|
page = website,
|
||||||
context = context,
|
context = context,
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -33,56 +31,46 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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 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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLicenseInfoViewModel
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.LicenseInfoViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
||||||
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
import ua.acclorite.book_story.presentation.ui.SlidingTransition
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) {
|
fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) {
|
||||||
val navigator = LocalNavigator.current
|
val viewModel = LocalLicenseInfoViewModel.current.viewModel
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val licenseInfoViewModel: LicenseInfoViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = licenseInfoViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
licenseInfoViewModel.init(
|
viewModel.init(
|
||||||
screen = screen,
|
screen = screen,
|
||||||
onNavigate = { navigator.it() },
|
onNavigate = onNavigate,
|
||||||
context = context
|
context = context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
LicenseInfoScreen(
|
LicenseInfoScreen()
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = licenseInfoViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun LicenseInfoScreen(
|
private fun LicenseInfoScreen() {
|
||||||
state: State<LicenseInfoState>,
|
val state = LocalLicenseInfoViewModel.current.state
|
||||||
onNavigate: OnNavigate,
|
val onEvent = LocalLicenseInfoViewModel.current.onEvent
|
||||||
onEvent: (LicenseInfoEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
val licenses = remember(state.value.license?.licenses) {
|
val licenses = remember(state.value.license?.licenses) {
|
||||||
state.value.license?.licenses?.toList()
|
state.value.license?.licenses?.toList()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mikepenz.aboutlibraries.Libs
|
import com.mikepenz.aboutlibraries.Libs
|
||||||
import com.mikepenz.aboutlibraries.util.withContext
|
import com.mikepenz.aboutlibraries.util.withContext
|
||||||
|
|
@ -14,18 +13,21 @@ 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.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
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.data.launchActivity
|
import ua.acclorite.book_story.presentation.data.launchActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class LicenseInfoViewModel @Inject constructor() : ViewModel() {
|
class LicenseInfoViewModel @Inject constructor(
|
||||||
|
|
||||||
|
) : BaseViewModel<LicenseInfoState, LicenseInfoEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(LicenseInfoState())
|
private val _state = MutableStateFlow(LicenseInfoState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
fun onEvent(event: LicenseInfoEvent) {
|
override fun onEvent(event: LicenseInfoEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is LicenseInfoEvent.OnOpenLicensePage -> {
|
is LicenseInfoEvent.OnOpenLicensePage -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
|
||||||
|
|
@ -18,51 +18,40 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
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 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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLicensesViewModel
|
||||||
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.LocalOnNavigate
|
||||||
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.LicensesViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LicensesScreenRoot() {
|
fun LicensesScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
val viewModel = LocalLicensesViewModel.current.viewModel
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val licensesViewModel: LicensesViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = licensesViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
licensesViewModel.init(context)
|
viewModel.init(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
LicensesScreen(
|
LicensesScreen()
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun LicensesScreen(
|
private fun LicensesScreen() {
|
||||||
state: State<LicensesState>,
|
val state = LocalLicensesViewModel.current.state
|
||||||
onNavigate: OnNavigate
|
val onNavigate = LocalOnNavigate.current
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState(
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState(
|
||||||
state.value.listState
|
state.value.listState
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package ua.acclorite.book_story.presentation.screens.about.nested.licenses.data
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed class LicensesEvent
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.about.nested.licenses.data
|
package ua.acclorite.book_story.presentation.screens.about.nested.licenses.data
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mikepenz.aboutlibraries.Libs
|
import com.mikepenz.aboutlibraries.Libs
|
||||||
import com.mikepenz.aboutlibraries.util.withJson
|
import com.mikepenz.aboutlibraries.util.withJson
|
||||||
|
|
@ -12,15 +11,18 @@ 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.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class LicensesViewModel @Inject constructor(
|
class LicensesViewModel @Inject constructor(
|
||||||
|
|
||||||
) : ViewModel() {
|
) : BaseViewModel<LicensesState, LicensesEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(LicensesState())
|
private val _state = MutableStateFlow(LicensesState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
override fun onEvent(event: LicensesEvent) {}
|
||||||
|
|
||||||
fun init(context: Context) {
|
fun init(context: Context) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
|
|
||||||
|
|
@ -37,20 +37,17 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
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 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.CustomSnackbar
|
import ua.acclorite.book_story.presentation.components.CustomSnackbar
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
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
|
||||||
|
|
@ -63,60 +60,36 @@ import ua.acclorite.book_story.presentation.screens.book_info.components.details
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoDeleteDialog
|
import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoDeleteDialog
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoMoveDialog
|
import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoMoveDialog
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
|
||||||
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.history.data.HistoryEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoScreenRoot(screen: Screen.BookInfo) {
|
fun BookInfoScreenRoot(screen: Screen.BookInfo) {
|
||||||
val navigator = LocalNavigator.current
|
val viewModel = LocalBookInfoViewModel.current.viewModel
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
val viewModel: BookInfoViewModel = hiltViewModel()
|
|
||||||
val libraryViewModel: LibraryViewModel = hiltViewModel()
|
|
||||||
val historyViewModel: HistoryViewModel = hiltViewModel()
|
|
||||||
val browseViewModel: BrowseViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = viewModel.state.collectAsState()
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.init(
|
viewModel.init(
|
||||||
screen = screen,
|
screen = screen,
|
||||||
onNavigate = { navigator.it() }
|
onNavigate = onNavigate
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BookInfoScreen()
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
onDispose {
|
onDispose {
|
||||||
viewModel.clearViewModel()
|
viewModel.clearViewModel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BookInfoScreen(
|
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = viewModel::onEvent,
|
|
||||||
onLibraryEvent = libraryViewModel::onEvent,
|
|
||||||
onBrowseEvent = browseViewModel::onEvent,
|
|
||||||
onHistoryEvent = historyViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun BookInfoScreen(
|
private fun BookInfoScreen() {
|
||||||
state: State<BookInfoState>,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
|
||||||
onBrowseEvent: (BrowseEvent) -> Unit,
|
|
||||||
onHistoryEvent: (HistoryEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val state = LocalBookInfoViewModel.current.state
|
||||||
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val snackbarState = remember { SnackbarHostState() }
|
val snackbarState = remember { SnackbarHostState() }
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
|
|
@ -132,42 +105,19 @@ private fun BookInfoScreen(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (state.value.showChangeCoverBottomSheet) {
|
if (state.value.showChangeCoverBottomSheet) {
|
||||||
BookInfoChangeCoverBottomSheet(
|
BookInfoChangeCoverBottomSheet()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryUpdateEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showDetailsBottomSheet) {
|
if (state.value.showDetailsBottomSheet) {
|
||||||
BookInfoDetailsBottomSheet(
|
BookInfoDetailsBottomSheet()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showDeleteDialog) {
|
if (state.value.showDeleteDialog) {
|
||||||
BookInfoDeleteDialog(
|
BookInfoDeleteDialog()
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryLoadEvent = onLibraryEvent,
|
|
||||||
onHistoryLoadEvent = onHistoryEvent,
|
|
||||||
onBrowseLoadEvent = onBrowseEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showMoveDialog) {
|
if (state.value.showMoveDialog) {
|
||||||
BookInfoMoveDialog(
|
BookInfoMoveDialog()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showConfirmUpdateDialog) {
|
if (state.value.showConfirmUpdateDialog) {
|
||||||
BookInfoConfirmUpdateDialog(
|
BookInfoConfirmUpdateDialog(snackbarHostState = snackbarState)
|
||||||
snackbarHostState = snackbarState,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryUpdateEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -179,11 +129,6 @@ private fun BookInfoScreen(
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
topBar = {
|
topBar = {
|
||||||
BookInfoTopBar(
|
BookInfoTopBar(
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryEvent = onLibraryEvent,
|
|
||||||
onHistoryEvent = onHistoryEvent,
|
|
||||||
onNavigate = onNavigate,
|
|
||||||
listState = listState,
|
listState = listState,
|
||||||
snackbarState = snackbarState
|
snackbarState = snackbarState
|
||||||
)
|
)
|
||||||
|
|
@ -216,7 +161,7 @@ private fun BookInfoScreen(
|
||||||
Column(Modifier.fillMaxWidth()) {
|
Column(Modifier.fillMaxWidth()) {
|
||||||
Spacer(modifier = Modifier.height(paddingValues.calculateTopPadding() + 12.dp))
|
Spacer(modifier = Modifier.height(paddingValues.calculateTopPadding() + 12.dp))
|
||||||
// Info
|
// Info
|
||||||
BookInfoInfoSection(state = state, onEvent = onEvent)
|
BookInfoInfoSection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -224,16 +169,13 @@ private fun BookInfoScreen(
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
// Statistic
|
// Statistic
|
||||||
BookInfoStatisticSection(state = state)
|
BookInfoStatisticSection()
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
// Description
|
// Description
|
||||||
BookInfoDescriptionSection(
|
BookInfoDescriptionSection()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -26,21 +25,18 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
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.presentation.components.LocalBookInfoViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description section.
|
* Description section.
|
||||||
*
|
|
||||||
* @param state [BookInfoState].
|
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoDescriptionSection(
|
fun BookInfoDescriptionSection() {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val descriptionFocusRequester = remember { FocusRequester() }
|
val descriptionFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
if (!state.value.editDescription) {
|
if (!state.value.editDescription) {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -40,21 +39,18 @@ 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.presentation.components.CustomCoverImage
|
import ua.acclorite.book_story.presentation.components.CustomCoverImage
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BookInfo's Info section.
|
* BookInfo's Info section.
|
||||||
*
|
|
||||||
* @param state [BookInfoState] instance.
|
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoInfoSection(
|
fun BookInfoInfoSection() {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val titleFocusRequester = remember { FocusRequester() }
|
val titleFocusRequester = remember { FocusRequester() }
|
||||||
val authorFocusRequester = remember { FocusRequester() }
|
val authorFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import androidx.compose.material.icons.outlined.Info
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -20,18 +19,17 @@ import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.presentation.components.CustomDropDownMenuItem
|
import ua.acclorite.book_story.presentation.components.CustomDropDownMenuItem
|
||||||
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Book info more dropdown. Has three options: Delete, Move and Details.
|
* Book info more dropdown. Has three options: Delete, Move and Details.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoMoreDropDown(
|
fun BookInfoMoreDropDown(snackbarState: SnackbarHostState) {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
snackbarState: SnackbarHostState
|
|
||||||
) {
|
|
||||||
var showDropDown by remember { mutableStateOf(false) }
|
var showDropDown by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Box {
|
Box {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.StrokeCap
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
|
|
@ -17,15 +16,17 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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.presentation.components.LocalBookInfoViewModel
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistic section.
|
* Statistic section.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoStatisticSection(state: State<BookInfoState>) {
|
fun BookInfoStatisticSection() {
|
||||||
|
val state = LocalBookInfoViewModel.current.state
|
||||||
|
|
||||||
val progress = remember(state.value.book) {
|
val progress = remember(state.value.book) {
|
||||||
"${
|
"${
|
||||||
(state.value.book.progress * 100)
|
(state.value.book.progress * 100)
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,21 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
||||||
|
|
@ -35,26 +36,22 @@ import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
/**
|
/**
|
||||||
* Book Info Top Bar.
|
* Book Info Top Bar.
|
||||||
*
|
*
|
||||||
* @param state [BookInfoState].
|
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
* @param onLibraryEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryEvent [HistoryEvent] callback.
|
|
||||||
* @param onNavigate Navigator callback.
|
|
||||||
* @param listState [LazyListState].
|
* @param listState [LazyListState].
|
||||||
* @param snackbarState [SnackbarHostState].
|
* @param snackbarState [SnackbarHostState].
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoTopBar(
|
fun BookInfoTopBar(
|
||||||
state: State<BookInfoState>,
|
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryEvent: (HistoryEvent) -> Unit,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
snackbarState: SnackbarHostState
|
snackbarState: SnackbarHostState
|
||||||
) {
|
) {
|
||||||
|
val state = LocalBookInfoViewModel.current.state
|
||||||
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val firstVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex } }
|
val firstVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex } }
|
||||||
|
|
||||||
AnimatedTopAppBar(
|
AnimatedTopAppBar(
|
||||||
|
|
@ -125,11 +122,7 @@ fun BookInfoTopBar(
|
||||||
!state.value.editAuthor &&
|
!state.value.editAuthor &&
|
||||||
!state.value.editDescription
|
!state.value.editDescription
|
||||||
) {
|
) {
|
||||||
BookInfoMoreDropDown(
|
BookInfoMoreDropDown(snackbarState = snackbarState)
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
snackbarState = snackbarState
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
CustomAnimatedVisibility(
|
CustomAnimatedVisibility(
|
||||||
visible = state.value.editTitle ||
|
visible = state.value.editTitle ||
|
||||||
|
|
@ -175,7 +168,8 @@ fun BookInfoTopBar(
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
}
|
}
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,35 +13,31 @@ import androidx.compose.material.icons.filled.ImageSearch
|
||||||
import androidx.compose.material.icons.filled.Restore
|
import androidx.compose.material.icons.filled.Restore
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
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.presentation.components.CustomBottomSheet
|
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change cover bottom sheet. Lets user select photo from the gallery and replaces old one.
|
* Change cover bottom sheet. Lets user select photo from the gallery and replaces old one.
|
||||||
*
|
|
||||||
* @param state [BookInfoState] instance.
|
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
* @param onLibraryUpdateEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryUpdateEvent [HistoryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoChangeCoverBottomSheet(
|
fun BookInfoChangeCoverBottomSheet() {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit,
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val photoPicker = rememberLauncherForActivityResult(
|
val photoPicker = rememberLauncherForActivityResult(
|
||||||
contract = ActivityResultContracts.PickVisualMedia(),
|
contract = ActivityResultContracts.PickVisualMedia(),
|
||||||
onResult = { uri ->
|
onResult = { uri ->
|
||||||
|
|
@ -51,8 +47,8 @@ fun BookInfoChangeCoverBottomSheet(
|
||||||
uri,
|
uri,
|
||||||
context,
|
context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -83,8 +79,8 @@ fun BookInfoChangeCoverBottomSheet(
|
||||||
onEvent(
|
onEvent(
|
||||||
BookInfoEvent.OnResetCoverImage(
|
BookInfoEvent.OnResetCoverImage(
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
showResult = {
|
showResult = {
|
||||||
it.asString(context).showToast(context = context)
|
it.asString(context).showToast(context = context)
|
||||||
|
|
@ -117,8 +113,8 @@ fun BookInfoChangeCoverBottomSheet(
|
||||||
onEvent(
|
onEvent(
|
||||||
BookInfoEvent.OnDeleteCover(
|
BookInfoEvent.OnDeleteCover(
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
||||||
|
|
@ -17,17 +20,12 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
* Updates book if action clicked.
|
* Updates book if action clicked.
|
||||||
*
|
*
|
||||||
* @param snackbarHostState [SnackbarHostState].
|
* @param snackbarHostState [SnackbarHostState].
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
* @param onLibraryUpdateEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryUpdateEvent [HistoryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoConfirmUpdateDialog(
|
fun BookInfoConfirmUpdateDialog(snackbarHostState: SnackbarHostState) {
|
||||||
snackbarHostState: SnackbarHostState,
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit,
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit,
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
CustomDialogWithContent(
|
CustomDialogWithContent(
|
||||||
|
|
@ -45,8 +43,8 @@ fun BookInfoConfirmUpdateDialog(
|
||||||
snackbarState = snackbarHostState,
|
snackbarState = snackbarHostState,
|
||||||
context = context,
|
context = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -54,11 +52,3 @@ fun BookInfoConfirmUpdateDialog(
|
||||||
withDivider = false
|
withDivider = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
@ -12,9 +11,9 @@ 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.presentation.components.CustomBottomSheet
|
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
@ -22,15 +21,11 @@ import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Details bottom sheet. Displays name, path, last opened and size of the file.
|
* Details bottom sheet. Displays name, path, last opened and size of the file.
|
||||||
*
|
|
||||||
* @param state [BookInfoState] instance.
|
|
||||||
* @param onEvent [BookInfoEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoDetailsBottomSheet(
|
fun BookInfoDetailsBottomSheet() {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val pattern = remember {
|
val pattern = remember {
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,12 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
||||||
|
|
@ -16,20 +20,14 @@ 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() {
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
onLibraryLoadEvent: (LibraryEvent.OnLoadList) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit,
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
onBrowseLoadEvent: (BrowseEvent.OnLoadList) -> Unit
|
val onBrowseEvent = LocalBrowseViewModel.current.onEvent
|
||||||
) {
|
val onNavigate = LocalOnNavigate.current
|
||||||
val navigator = LocalNavigator.current
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
CustomDialogWithContent(
|
CustomDialogWithContent(
|
||||||
|
|
@ -45,11 +43,11 @@ fun BookInfoDeleteDialog(
|
||||||
onAction = {
|
onAction = {
|
||||||
onEvent(
|
onEvent(
|
||||||
BookInfoEvent.OnDeleteBook(
|
BookInfoEvent.OnDeleteBook(
|
||||||
onNavigate = { navigator.it() },
|
onNavigate = onNavigate,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryLoadEvent(LibraryEvent.OnLoadList)
|
onLibraryEvent(LibraryEvent.OnLoadList)
|
||||||
onBrowseLoadEvent(BrowseEvent.OnLoadList)
|
onBrowseEvent(BrowseEvent.OnLoadList)
|
||||||
onHistoryLoadEvent(HistoryEvent.OnLoadList)
|
onHistoryEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,39 +4,34 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
|
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.components.LocalBookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
|
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState
|
|
||||||
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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move dialog.
|
* Move dialog.
|
||||||
* Moves current book to the selected category.
|
* 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() {
|
||||||
state: State<BookInfoState>,
|
val state = LocalBookInfoViewModel.current.state
|
||||||
onEvent: (BookInfoEvent) -> Unit,
|
val onEvent = LocalBookInfoViewModel.current.onEvent
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
) {
|
val onNavigate = LocalOnNavigate.current
|
||||||
val navigator = LocalNavigator.current
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val categories = remember {
|
val categories = remember {
|
||||||
|
|
@ -61,12 +56,12 @@ fun BookInfoMoveDialog(
|
||||||
BookInfoEvent.OnMoveBook(
|
BookInfoEvent.OnMoveBook(
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
updatePage = {
|
updatePage = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
|
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
|
||||||
},
|
},
|
||||||
onNavigate = { navigator.it() }
|
onNavigate = onNavigate
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
context.getString(R.string.book_moved)
|
context.getString(R.string.book_moved)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import android.content.Context.CLIPBOARD_SERVICE
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -34,6 +33,7 @@ import ua.acclorite.book_story.domain.use_case.ResetCoverImage
|
||||||
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.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
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.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
|
|
@ -54,17 +54,17 @@ class BookInfoViewModel @Inject constructor(
|
||||||
private val getText: GetText,
|
private val getText: GetText,
|
||||||
private val canResetCover: CanResetCover,
|
private val canResetCover: CanResetCover,
|
||||||
private val resetCoverImage: ResetCoverImage,
|
private val resetCoverImage: ResetCoverImage,
|
||||||
) : ViewModel() {
|
) : BaseViewModel<BookInfoState, BookInfoEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(BookInfoState())
|
private val _state = MutableStateFlow(BookInfoState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var eventJob = SupervisorJob()
|
private var eventJob = SupervisorJob()
|
||||||
|
|
||||||
private var snackBarJob: Job? = null
|
private var snackBarJob: Job? = null
|
||||||
private var updateJob: Job? = null
|
private var updateJob: Job? = null
|
||||||
|
|
||||||
fun onEvent(event: BookInfoEvent) {
|
override fun onEvent(event: BookInfoEvent) {
|
||||||
viewModelScope.launch(eventJob + Dispatchers.Main) {
|
viewModelScope.launch(eventJob + Dispatchers.Main) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> {
|
is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> {
|
||||||
|
|
|
||||||
|
|
@ -14,24 +14,19 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
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 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.model.SelectableFile
|
import ua.acclorite.book_story.domain.model.SelectableFile
|
||||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.BrowseEmptyPlaceholder
|
import ua.acclorite.book_story.presentation.screens.browse.components.BrowseEmptyPlaceholder
|
||||||
|
|
@ -41,23 +36,16 @@ import ua.acclorite.book_story.presentation.screens.browse.components.filter_bot
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.top_bar.BrowseTopBar
|
import ua.acclorite.book_story.presentation.screens.browse.components.top_bar.BrowseTopBar
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
||||||
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
||||||
|
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseScreenRoot() {
|
fun BrowseScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
val state = LocalBrowseViewModel.current.state
|
||||||
val viewModel: BrowseViewModel = hiltViewModel()
|
val mainState = LocalMainViewModel.current.state
|
||||||
val libraryViewModel: LibraryViewModel = hiltViewModel()
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
val viewModel = LocalBrowseViewModel.current.viewModel
|
||||||
|
|
||||||
val state = viewModel.state.collectAsState()
|
|
||||||
val mainState = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
val permissionState = rememberPermissionState(
|
val permissionState = rememberPermissionState(
|
||||||
permission = Manifest.permission.READ_EXTERNAL_STORAGE
|
permission = Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
|
@ -72,22 +60,14 @@ fun BrowseScreenRoot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.onEvent(BrowseEvent.OnUpdateScrollOffset)
|
onEvent(BrowseEvent.OnUpdateScrollOffset)
|
||||||
viewModel.onEvent(
|
onEvent(BrowseEvent.OnPermissionCheck(permissionState))
|
||||||
BrowseEvent.OnPermissionCheck(permissionState)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BrowseScreen(
|
BrowseScreen(
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
permissionState = permissionState,
|
permissionState = permissionState,
|
||||||
filteredFiles = filteredFiles.value,
|
filteredFiles = filteredFiles.value,
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = viewModel::onEvent,
|
|
||||||
onMainEvent = mainViewModel::onEvent,
|
|
||||||
onLibraryEvent = libraryViewModel::onEvent
|
|
||||||
)
|
)
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
|
|
@ -103,16 +83,15 @@ fun BrowseScreenRoot() {
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
private fun BrowseScreen(
|
private fun BrowseScreen(
|
||||||
state: State<BrowseState>,
|
|
||||||
mainState: State<MainState>,
|
|
||||||
permissionState: PermissionState,
|
permissionState: PermissionState,
|
||||||
filteredFiles: List<SelectableFile>,
|
filteredFiles: List<SelectableFile>
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onEvent: (BrowseEvent) -> Unit,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit
|
|
||||||
) {
|
) {
|
||||||
|
val state = LocalBrowseViewModel.current.state
|
||||||
|
val mainState = LocalMainViewModel.current.state
|
||||||
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
refreshing = state.value.isRefreshing,
|
refreshing = state.value.isRefreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
|
|
@ -121,22 +100,13 @@ private fun BrowseScreen(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (state.value.requestPermissionDialog) {
|
if (state.value.requestPermissionDialog) {
|
||||||
BrowseStoragePermissionDialog(onEvent, permissionState)
|
BrowseStoragePermissionDialog(permissionState)
|
||||||
}
|
}
|
||||||
if (state.value.showAddingDialog) {
|
if (state.value.showAddingDialog) {
|
||||||
BrowseAddingDialog(
|
BrowseAddingDialog()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryEvent = onLibraryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showFilterBottomSheet) {
|
if (state.value.showFilterBottomSheet) {
|
||||||
BrowseFilterBottomSheet(
|
BrowseFilterBottomSheet()
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -145,12 +115,7 @@ private fun BrowseScreen(
|
||||||
.pullRefresh(refreshState),
|
.pullRefresh(refreshState),
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
topBar = {
|
topBar = {
|
||||||
BrowseTopBar(
|
BrowseTopBar(filteredFiles = filteredFiles)
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
filteredFiles = filteredFiles,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Box(
|
Box(
|
||||||
|
|
@ -160,8 +125,6 @@ private fun BrowseScreen(
|
||||||
) {
|
) {
|
||||||
DefaultTransition(visible = !state.value.isLoading) {
|
DefaultTransition(visible = !state.value.isLoading) {
|
||||||
BrowseLayout(
|
BrowseLayout(
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
filteredFiles = filteredFiles,
|
filteredFiles = filteredFiles,
|
||||||
onLongItemClick = { selectableFile ->
|
onLongItemClick = { selectableFile ->
|
||||||
when (selectableFile.isDirectory) {
|
when (selectableFile.isDirectory) {
|
||||||
|
|
@ -223,11 +186,8 @@ private fun BrowseScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowseEmptyPlaceholder(
|
BrowseEmptyPlaceholder(
|
||||||
state = state,
|
|
||||||
isFilesEmpty = filteredFiles.isEmpty(),
|
isFilesEmpty = filteredFiles.isEmpty(),
|
||||||
storagePermissionState = permissionState,
|
storagePermissionState = permissionState,
|
||||||
onNavigate = onNavigate,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
)
|
||||||
|
|
||||||
PullRefreshIndicator(
|
PullRefreshIndicator(
|
||||||
|
|
@ -255,9 +215,7 @@ private fun BrowseScreen(
|
||||||
state.value.inNestedDirectory
|
state.value.inNestedDirectory
|
||||||
&& mainState.value.browseFilesStructure != BrowseFilesStructure.ALL_FILES
|
&& mainState.value.browseFilesStructure != BrowseFilesStructure.ALL_FILES
|
||||||
) {
|
) {
|
||||||
onEvent(
|
onEvent(BrowseEvent.OnGoBackDirectory)
|
||||||
BrowseEvent.OnGoBackDirectory
|
|
||||||
)
|
|
||||||
return@BackHandler
|
return@BackHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package ua.acclorite.book_story.presentation.screens.browse.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
|
@ -10,34 +9,32 @@ import androidx.compose.ui.res.stringResource
|
||||||
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.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.LocalBrowseViewModel
|
||||||
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.LocalOnNavigate
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.ui.Transitions
|
import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browse Empty Placeholder.
|
* Browse Empty Placeholder.
|
||||||
* Shows error or empty message.
|
* Shows error or empty message.
|
||||||
*
|
*
|
||||||
* @param state [BrowseState].
|
|
||||||
* @param isFilesEmpty Whether the list is empty.
|
* @param isFilesEmpty Whether the list is empty.
|
||||||
* @param storagePermissionState Storage [PermissionState].
|
* @param storagePermissionState Storage [PermissionState].
|
||||||
* @param onNavigate Navigator callback.
|
|
||||||
* @param onEvent [BrowseEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BoxScope.BrowseEmptyPlaceholder(
|
fun BoxScope.BrowseEmptyPlaceholder(
|
||||||
state: State<BrowseState>,
|
|
||||||
isFilesEmpty: Boolean,
|
isFilesEmpty: Boolean,
|
||||||
storagePermissionState: PermissionState,
|
storagePermissionState: PermissionState
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onEvent: (BrowseEvent) -> Unit
|
|
||||||
) {
|
) {
|
||||||
|
val state = LocalBrowseViewModel.current.state
|
||||||
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
CustomAnimatedVisibility(
|
CustomAnimatedVisibility(
|
||||||
visible = state.value.isError,
|
visible = state.value.isError,
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
|
|
||||||
|
|
@ -9,22 +9,22 @@ import androidx.compose.ui.res.stringResource
|
||||||
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.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage permission dialog.
|
* Storage permission dialog.
|
||||||
*
|
*
|
||||||
* @param onEvent [BrowseEvent] callback.
|
|
||||||
* @param permissionState Storage [PermissionState].
|
* @param permissionState Storage [PermissionState].
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseStoragePermissionDialog(
|
fun BrowseStoragePermissionDialog(
|
||||||
onEvent: (BrowseEvent) -> Unit,
|
|
||||||
permissionState: PermissionState
|
permissionState: PermissionState
|
||||||
) {
|
) {
|
||||||
val activity = LocalContext.current as ComponentActivity
|
val activity = LocalContext.current as ComponentActivity
|
||||||
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
|
|
||||||
CustomDialogWithContent(
|
CustomDialogWithContent(
|
||||||
title = stringResource(id = R.string.storage_permission),
|
title = stringResource(id = R.string.storage_permission),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import androidx.compose.material.icons.filled.AddChart
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.StrokeCap
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
|
|
@ -18,30 +17,26 @@ 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.model.NullableBook
|
import ua.acclorite.book_story.domain.model.NullableBook
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.data.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding dialog.
|
* Adding dialog.
|
||||||
* Adds all selected books to the Library.
|
* Adds all selected books to the Library.
|
||||||
*
|
|
||||||
* @param state [BrowseState].
|
|
||||||
* @param onEvent [BrowseEvent] callback.
|
|
||||||
* @param onLibraryEvent [LibraryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseAddingDialog(
|
fun BrowseAddingDialog() {
|
||||||
state: State<BrowseState>,
|
|
||||||
onEvent: (BrowseEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val navigator = LocalNavigator.current
|
val state = LocalBrowseViewModel.current.state
|
||||||
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
CustomDialogWithLazyColumn(
|
CustomDialogWithLazyColumn(
|
||||||
title = stringResource(id = R.string.add_books),
|
title = stringResource(id = R.string.add_books),
|
||||||
|
|
@ -54,7 +49,7 @@ fun BrowseAddingDialog(
|
||||||
onAction = {
|
onAction = {
|
||||||
onEvent(
|
onEvent(
|
||||||
BrowseEvent.OnAddBooks(
|
BrowseEvent.OnAddBooks(
|
||||||
onNavigate = { navigator.it() },
|
onNavigate = onNavigate,
|
||||||
resetScroll = {
|
resetScroll = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0))
|
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0))
|
||||||
onLibraryEvent(LibraryEvent.OnLoadList)
|
onLibraryEvent(LibraryEvent.OnLoadList)
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,11 @@ import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory
|
||||||
|
|
@ -23,19 +20,12 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
|
||||||
/**
|
/**
|
||||||
* Browse Filter Bottom Sheet.
|
* Browse Filter Bottom Sheet.
|
||||||
* Lets user sort, filter and change appearance of the Browse.
|
* Lets user sort, filter and change appearance of the Browse.
|
||||||
*
|
|
||||||
* @param state [BrowseState].
|
|
||||||
* @param mainState [MainState].
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param onEvent [BrowseEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseFilterBottomSheet(
|
fun BrowseFilterBottomSheet() {
|
||||||
state: State<BrowseState>,
|
val state = LocalBrowseViewModel.current.state
|
||||||
mainState: State<MainState>,
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onEvent: (BrowseEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val pagerState = rememberPagerState(state.value.currentPage) { 3 }
|
val pagerState = rememberPagerState(state.value.currentPage) { 3 }
|
||||||
|
|
||||||
LaunchedEffect(pagerState.currentPage) {
|
LaunchedEffect(pagerState.currentPage) {
|
||||||
|
|
@ -67,8 +57,6 @@ fun BrowseFilterBottomSheet(
|
||||||
0 -> {
|
0 -> {
|
||||||
LazyColumn(Modifier.fillMaxSize()) {
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
BrowseGeneralSubcategory(
|
BrowseGeneralSubcategory(
|
||||||
state = mainState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
topPadding = 16.dp,
|
topPadding = 16.dp,
|
||||||
bottomPadding = 8.dp + it
|
bottomPadding = 8.dp + it
|
||||||
|
|
@ -79,8 +67,6 @@ fun BrowseFilterBottomSheet(
|
||||||
1 -> {
|
1 -> {
|
||||||
LazyColumn(Modifier.fillMaxSize()) {
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
BrowseFilterSubcategory(
|
BrowseFilterSubcategory(
|
||||||
state = mainState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
topPadding = 16.dp,
|
topPadding = 16.dp,
|
||||||
bottomPadding = 8.dp + it
|
bottomPadding = 8.dp + it
|
||||||
|
|
@ -91,8 +77,6 @@ fun BrowseFilterBottomSheet(
|
||||||
2 -> {
|
2 -> {
|
||||||
LazyColumn(Modifier.fillMaxSize()) {
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
BrowseSortSubcategory(
|
BrowseSortSubcategory(
|
||||||
state = mainState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
topPadding = 16.dp,
|
topPadding = 16.dp,
|
||||||
bottomPadding = 8.dp + it
|
bottomPadding = 8.dp + it
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,16 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.browse.components.layout
|
package ua.acclorite.book_story.presentation.screens.browse.components.layout
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import ua.acclorite.book_story.domain.model.SelectableFile
|
import ua.acclorite.book_story.domain.model.SelectableFile
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.layout.grid.BrowseGridLayout
|
import ua.acclorite.book_story.presentation.screens.browse.components.layout.grid.BrowseGridLayout
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.layout.list.BrowseListLayout
|
import ua.acclorite.book_story.presentation.screens.browse.components.layout.list.BrowseListLayout
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browse Layout.
|
* Browse Layout.
|
||||||
* Shows Grid or List.
|
* Shows Grid or List.
|
||||||
*
|
*
|
||||||
* @param state [BrowseState].
|
|
||||||
* @param mainState [MainState].
|
|
||||||
* @param filteredFiles Filtered items.
|
* @param filteredFiles Filtered items.
|
||||||
* @param onLongItemClick OnLongItemClick callback.
|
* @param onLongItemClick OnLongItemClick callback.
|
||||||
* @param onFavoriteItemClick OnFavoriteItemClick callback.
|
* @param onFavoriteItemClick OnFavoriteItemClick callback.
|
||||||
|
|
@ -22,17 +18,16 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseLayout(
|
fun BrowseLayout(
|
||||||
state: State<BrowseState>,
|
|
||||||
mainState: State<MainState>,
|
|
||||||
filteredFiles: List<SelectableFile>,
|
filteredFiles: List<SelectableFile>,
|
||||||
onLongItemClick: (SelectableFile) -> Unit,
|
onLongItemClick: (SelectableFile) -> Unit,
|
||||||
onFavoriteItemClick: (SelectableFile) -> Unit,
|
onFavoriteItemClick: (SelectableFile) -> Unit,
|
||||||
onItemClick: (SelectableFile) -> Unit
|
onItemClick: (SelectableFile) -> Unit
|
||||||
) {
|
) {
|
||||||
|
val mainState = LocalMainViewModel.current.state
|
||||||
|
|
||||||
when (mainState.value.browseLayout) {
|
when (mainState.value.browseLayout) {
|
||||||
BrowseLayout.LIST -> {
|
BrowseLayout.LIST -> {
|
||||||
BrowseListLayout(
|
BrowseListLayout(
|
||||||
state = state,
|
|
||||||
filteredFiles = filteredFiles,
|
filteredFiles = filteredFiles,
|
||||||
onLongItemClick = onLongItemClick,
|
onLongItemClick = onLongItemClick,
|
||||||
onFavoriteItemClick = onFavoriteItemClick,
|
onFavoriteItemClick = onFavoriteItemClick,
|
||||||
|
|
@ -42,7 +37,6 @@ fun BrowseLayout(
|
||||||
|
|
||||||
BrowseLayout.GRID -> {
|
BrowseLayout.GRID -> {
|
||||||
BrowseGridLayout(
|
BrowseGridLayout(
|
||||||
state = state,
|
|
||||||
gridSize = mainState.value.browseGridSize,
|
gridSize = mainState.value.browseGridSize,
|
||||||
autoGridSize = mainState.value.browseAutoGridSize,
|
autoGridSize = mainState.value.browseAutoGridSize,
|
||||||
filteredFiles = filteredFiles,
|
filteredFiles = filteredFiles,
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,17 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.domain.model.SelectableFile
|
import ua.acclorite.book_story.domain.model.SelectableFile
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
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.screens.browse.components.layout.BrowseItem
|
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseGridLayout(
|
fun BrowseGridLayout(
|
||||||
state: State<BrowseState>,
|
|
||||||
gridSize: Int,
|
gridSize: Int,
|
||||||
autoGridSize: Boolean,
|
autoGridSize: Boolean,
|
||||||
filteredFiles: List<SelectableFile>,
|
filteredFiles: List<SelectableFile>,
|
||||||
|
|
@ -27,6 +25,8 @@ fun BrowseGridLayout(
|
||||||
onFavoriteItemClick: (SelectableFile) -> Unit,
|
onFavoriteItemClick: (SelectableFile) -> Unit,
|
||||||
onItemClick: (SelectableFile) -> Unit,
|
onItemClick: (SelectableFile) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val state = LocalBrowseViewModel.current.state
|
||||||
|
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = if (autoGridSize) GridCells.Adaptive(170.dp)
|
columns = if (autoGridSize) GridCells.Adaptive(170.dp)
|
||||||
else GridCells.Fixed(gridSize.coerceAtLeast(1)),
|
else GridCells.Fixed(gridSize.coerceAtLeast(1)),
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,23 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.domain.model.SelectableFile
|
import ua.acclorite.book_story.domain.model.SelectableFile
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem
|
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem
|
||||||
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseListLayout(
|
fun BrowseListLayout(
|
||||||
state: State<BrowseState>,
|
|
||||||
filteredFiles: List<SelectableFile>,
|
filteredFiles: List<SelectableFile>,
|
||||||
onLongItemClick: (SelectableFile) -> Unit,
|
onLongItemClick: (SelectableFile) -> Unit,
|
||||||
onFavoriteItemClick: (SelectableFile) -> Unit,
|
onFavoriteItemClick: (SelectableFile) -> Unit,
|
||||||
onItemClick: (SelectableFile) -> Unit,
|
onItemClick: (SelectableFile) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val state = LocalBrowseViewModel.current.state
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = state.value.listState,
|
state = state.value.listState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -39,10 +38,10 @@ 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.CustomSearchTextField
|
import ua.acclorite.book_story.presentation.components.CustomSearchTextField
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.MoreDropDown
|
import ua.acclorite.book_story.presentation.components.MoreDropDown
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
|
import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
|
||||||
|
|
@ -50,19 +49,15 @@ import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
|
||||||
/**
|
/**
|
||||||
* Browse Top Bar.
|
* Browse Top Bar.
|
||||||
*
|
*
|
||||||
* @param state [BrowseState].
|
|
||||||
* @param mainState [MainState].
|
|
||||||
* @param filteredFiles Filtered files.
|
* @param filteredFiles Filtered files.
|
||||||
* @param onEvent [BrowseEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseTopBar(
|
fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
|
||||||
state: State<BrowseState>,
|
val state = LocalBrowseViewModel.current.state
|
||||||
mainState: State<MainState>,
|
val mainState = LocalMainViewModel.current.state
|
||||||
filteredFiles: List<SelectableFile>,
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
onEvent: (BrowseEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val selectedDirectoryName = remember {
|
val selectedDirectoryName = remember {
|
||||||
mutableStateOf(state.value.selectedDirectory.name)
|
mutableStateOf(state.value.selectedDirectory.name)
|
||||||
|
|
@ -245,11 +240,7 @@ fun BrowseTopBar(
|
||||||
},
|
},
|
||||||
|
|
||||||
customContent = {
|
customContent = {
|
||||||
BrowseTopBarDirectoryPath(
|
BrowseTopBarDirectoryPath()
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -28,20 +27,20 @@ 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.presentation.components.CustomAnimatedVisibility
|
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
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.BrowseState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseTopBarDirectoryPath(
|
fun BrowseTopBarDirectoryPath() {
|
||||||
state: State<BrowseState>,
|
val state = LocalBrowseViewModel.current.state
|
||||||
mainState: State<MainState>,
|
val mainState = LocalMainViewModel.current.state
|
||||||
onEvent: (BrowseEvent) -> Unit
|
val onEvent = LocalBrowseViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val rootDirectory = remember {
|
val rootDirectory = remember {
|
||||||
Environment.getExternalStorageDirectory()
|
Environment.getExternalStorageDirectory()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import android.os.Environment
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
|
|
@ -29,6 +28,7 @@ import ua.acclorite.book_story.domain.use_case.GetBookFromFile
|
||||||
import ua.acclorite.book_story.domain.use_case.GetFilesFromDevice
|
import ua.acclorite.book_story.domain.use_case.GetFilesFromDevice
|
||||||
import ua.acclorite.book_story.domain.use_case.InsertBook
|
import ua.acclorite.book_story.domain.use_case.InsertBook
|
||||||
import ua.acclorite.book_story.domain.use_case.UpdateFavoriteDirectory
|
import ua.acclorite.book_story.domain.use_case.UpdateFavoriteDirectory
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
import ua.acclorite.book_story.presentation.data.MainState
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.launchActivity
|
import ua.acclorite.book_story.presentation.data.launchActivity
|
||||||
|
|
@ -43,10 +43,10 @@ class BrowseViewModel @Inject constructor(
|
||||||
private val getFilesFromDevice: GetFilesFromDevice,
|
private val getFilesFromDevice: GetFilesFromDevice,
|
||||||
private val insertBook: InsertBook,
|
private val insertBook: InsertBook,
|
||||||
private val updateFavoriteDirectory: UpdateFavoriteDirectory,
|
private val updateFavoriteDirectory: UpdateFavoriteDirectory,
|
||||||
) : ViewModel() {
|
) : BaseViewModel<BrowseState, BrowseEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(BrowseState())
|
private val _state = MutableStateFlow(BrowseState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var searchQueryJob: Job? = null
|
private var searchQueryJob: Job? = null
|
||||||
private var refreshListJob: Job? = null
|
private var refreshListJob: Job? = null
|
||||||
|
|
@ -67,7 +67,7 @@ class BrowseViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: BrowseEvent) {
|
override fun onEvent(event: BrowseEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is BrowseEvent.OnStoragePermissionRequest -> {
|
is BrowseEvent.OnStoragePermissionRequest -> {
|
||||||
val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
||||||
|
|
|
||||||
|
|
@ -22,68 +22,51 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
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 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.CustomIconButton
|
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
||||||
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.GoBackButton
|
import ua.acclorite.book_story.presentation.components.GoBackButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHelpViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalStartViewModel
|
||||||
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.LocalOnNavigate
|
||||||
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.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.help.components.HelpItem
|
import ua.acclorite.book_story.presentation.screens.help.components.HelpItem
|
||||||
import ua.acclorite.book_story.presentation.screens.help.components.items.HelpClickMeNoteItem
|
import ua.acclorite.book_story.presentation.screens.help.components.items.HelpClickMeNoteItem
|
||||||
import ua.acclorite.book_story.presentation.screens.help.data.HelpState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.help.data.HelpViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.start.data.StartEvent
|
import ua.acclorite.book_story.presentation.screens.start.data.StartEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HelpScreenRoot(screen: Screen.Help) {
|
fun HelpScreenRoot(screen: Screen.Help) {
|
||||||
val navigator = LocalNavigator.current
|
val viewModel = LocalHelpViewModel.current.viewModel
|
||||||
val helpViewModel: HelpViewModel = hiltViewModel()
|
|
||||||
val browseViewModel: BrowseViewModel = hiltViewModel()
|
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
val startViewModel: StartViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = helpViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
helpViewModel.init(screen = screen)
|
viewModel.init(screen = screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
HelpScreen(
|
HelpScreen()
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onMainEvent = mainViewModel::onEvent,
|
|
||||||
onBrowseEvent = browseViewModel::onEvent,
|
|
||||||
onStartEvent = startViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
ExperimentalMaterial3Api::class
|
ExperimentalMaterial3Api::class
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
private fun HelpScreen(
|
private fun HelpScreen() {
|
||||||
state: State<HelpState>,
|
val state = LocalHelpViewModel.current.state
|
||||||
onNavigate: OnNavigate,
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
val onBrowseEvent = LocalBrowseViewModel.current.onEvent
|
||||||
onBrowseEvent: (BrowseEvent) -> Unit,
|
val onStartEvent = LocalStartViewModel.current.onEvent
|
||||||
onStartEvent: (StartEvent) -> Unit
|
val onNavigate = LocalOnNavigate.current
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -171,7 +154,6 @@ private fun HelpScreen(
|
||||||
customItems(Constants.HELP_TIPS, key = { it.title }) { helpTip ->
|
customItems(Constants.HELP_TIPS, key = { it.title }) { helpTip ->
|
||||||
HelpItem(
|
HelpItem(
|
||||||
helpTip = helpTip,
|
helpTip = helpTip,
|
||||||
onNavigate = onNavigate,
|
|
||||||
fromStart = state.value.fromStart
|
fromStart = state.value.fromStart
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import androidx.compose.ui.text.buildAnnotatedString
|
||||||
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.HelpTip
|
import ua.acclorite.book_story.domain.model.HelpTip
|
||||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,15 +39,15 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
* Can be Expanded or Collapsed.
|
* Can be Expanded or Collapsed.
|
||||||
*
|
*
|
||||||
* @param helpTip [HelpTip] to be shown.
|
* @param helpTip [HelpTip] to be shown.
|
||||||
* @param onNavigate Navigator callback.
|
|
||||||
* @param fromStart Whether user came from Start screen.
|
* @param fromStart Whether user came from Start screen.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun HelpItem(
|
fun HelpItem(
|
||||||
helpTip: HelpTip,
|
helpTip: HelpTip,
|
||||||
onNavigate: OnNavigate,
|
|
||||||
fromStart: Boolean
|
fromStart: Boolean
|
||||||
) {
|
) {
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
val showDescription = rememberSaveable {
|
val showDescription = rememberSaveable {
|
||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package ua.acclorite.book_story.presentation.screens.help.data
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed class HelpEvent
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.help.data
|
package ua.acclorite.book_story.presentation.screens.help.data
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
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.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class HelpViewModel @Inject constructor(
|
class HelpViewModel @Inject constructor(
|
||||||
|
|
||||||
) : ViewModel() {
|
) : BaseViewModel<HelpState, HelpEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(HelpState())
|
private val _state = MutableStateFlow(HelpState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
override fun onEvent(event: HelpEvent) {}
|
||||||
|
|
||||||
fun init(screen: Screen.Help) {
|
fun init(screen: Screen.Help) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -36,44 +34,36 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
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 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
|
||||||
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
||||||
import ua.acclorite.book_story.presentation.components.CustomSearchTextField
|
import ua.acclorite.book_story.presentation.components.CustomSearchTextField
|
||||||
import ua.acclorite.book_story.presentation.components.CustomSnackbar
|
import ua.acclorite.book_story.presentation.components.CustomSnackbar
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
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.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
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
|
||||||
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.HistoryState
|
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
||||||
import ua.acclorite.book_story.presentation.ui.Transitions
|
import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryScreenRoot() {
|
fun HistoryScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
val onEvent = LocalHistoryViewModel.current.onEvent
|
||||||
val viewModel: HistoryViewModel = hiltViewModel()
|
|
||||||
val libraryViewModel: LibraryViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = viewModel.state.collectAsState()
|
LaunchedEffect(Unit) {
|
||||||
|
onEvent(HistoryEvent.OnUpdateScrollOffset)
|
||||||
|
}
|
||||||
|
|
||||||
HistoryScreen(
|
HistoryScreen()
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = viewModel::onEvent,
|
|
||||||
onLibraryEvent = libraryViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
|
|
@ -81,13 +71,13 @@ fun HistoryScreenRoot() {
|
||||||
ExperimentalMaterialApi::class
|
ExperimentalMaterialApi::class
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
private fun HistoryScreen(
|
private fun HistoryScreen() {
|
||||||
state: State<HistoryState>,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onEvent: (HistoryEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val state = LocalHistoryViewModel.current.state
|
||||||
|
val onEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
refreshing = state.value.isRefreshing,
|
refreshing = state.value.isRefreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
|
|
@ -97,15 +87,8 @@ private fun HistoryScreen(
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val snackbarState = remember { SnackbarHostState() }
|
val snackbarState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
onEvent(HistoryEvent.OnUpdateScrollOffset)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.value.showDeleteWholeHistoryDialog) {
|
if (state.value.showDeleteWholeHistoryDialog) {
|
||||||
HistoryDeleteWholeHistoryDialog(
|
HistoryDeleteWholeHistoryDialog()
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryLoadEvent = onLibraryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -304,15 +287,3 @@ private fun HistoryScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
||||||
|
|
@ -15,11 +17,10 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
* Delete whole history dialog.
|
* Delete whole history dialog.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryDeleteWholeHistoryDialog(
|
fun HistoryDeleteWholeHistoryDialog() {
|
||||||
onEvent: (HistoryEvent) -> Unit,
|
|
||||||
onLibraryLoadEvent: (LibraryEvent.OnLoadList) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val onEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
|
||||||
CustomDialogWithContent(
|
CustomDialogWithContent(
|
||||||
title = stringResource(id = R.string.delete_history),
|
title = stringResource(id = R.string.delete_history),
|
||||||
|
|
@ -34,7 +35,7 @@ fun HistoryDeleteWholeHistoryDialog(
|
||||||
onAction = {
|
onAction = {
|
||||||
onEvent(
|
onEvent(
|
||||||
HistoryEvent.OnDeleteWholeHistory {
|
HistoryEvent.OnDeleteWholeHistory {
|
||||||
onLibraryLoadEvent(LibraryEvent.OnLoadList)
|
onLibraryEvent(LibraryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
context.getString(R.string.history_deleted)
|
context.getString(R.string.history_deleted)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package ua.acclorite.book_story.presentation.screens.history.data
|
||||||
|
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -21,6 +20,7 @@ import ua.acclorite.book_story.domain.use_case.DeleteWholeHistory
|
||||||
import ua.acclorite.book_story.domain.use_case.GetBooksById
|
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.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.Resource
|
import ua.acclorite.book_story.domain.util.Resource
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
|
@ -36,10 +36,10 @@ class HistoryViewModel @Inject constructor(
|
||||||
private val deleteWholeHistory: DeleteWholeHistory,
|
private val deleteWholeHistory: DeleteWholeHistory,
|
||||||
private val deleteHistory: DeleteHistory,
|
private val deleteHistory: DeleteHistory,
|
||||||
private val getBooksById: GetBooksById
|
private val getBooksById: GetBooksById
|
||||||
) : ViewModel() {
|
) : BaseViewModel<HistoryState, HistoryEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(HistoryState())
|
private val _state = MutableStateFlow(HistoryState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var job: Job? = null
|
private var job: Job? = null
|
||||||
private var job2: Job? = null
|
private var job2: Job? = null
|
||||||
|
|
@ -56,7 +56,7 @@ class HistoryViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: HistoryEvent) {
|
override fun onEvent(event: HistoryEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is HistoryEvent.OnRefreshList -> {
|
is HistoryEvent.OnRefreshList -> {
|
||||||
job3?.cancel()
|
job3?.cancel()
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -41,47 +39,33 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
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 androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
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.CustomAnimatedVisibility
|
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.LocalNavigator
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.history.data.HistoryEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.components.LibraryBookItem
|
import ua.acclorite.book_story.presentation.screens.library.components.LibraryBookItem
|
||||||
import ua.acclorite.book_story.presentation.screens.library.components.LibraryTopBar
|
import ua.acclorite.book_story.presentation.screens.library.components.LibraryTopBar
|
||||||
import ua.acclorite.book_story.presentation.screens.library.components.dialog.LibraryDeleteDialog
|
import ua.acclorite.book_story.presentation.screens.library.components.dialog.LibraryDeleteDialog
|
||||||
import ua.acclorite.book_story.presentation.screens.library.components.dialog.LibraryMoveDialog
|
import ua.acclorite.book_story.presentation.screens.library.components.dialog.LibraryMoveDialog
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
import ua.acclorite.book_story.presentation.ui.DefaultTransition
|
||||||
import ua.acclorite.book_story.presentation.ui.Transitions
|
import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryScreenRoot() {
|
fun LibraryScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
val state = LocalLibraryViewModel.current.state
|
||||||
val viewModel: LibraryViewModel = hiltViewModel()
|
val onEvent = LocalLibraryViewModel.current.onEvent
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
val browseViewModel: BrowseViewModel = hiltViewModel()
|
|
||||||
val historyViewModel: HistoryViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = viewModel.state.collectAsState()
|
|
||||||
val mainState = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
val pagerState = rememberPagerState(
|
val pagerState = rememberPagerState(
|
||||||
initialPage = state.value.currentPage,
|
initialPage = state.value.currentPage,
|
||||||
|
|
@ -90,60 +74,43 @@ fun LibraryScreenRoot() {
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
refreshing = state.value.isRefreshing,
|
refreshing = state.value.isRefreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
viewModel.onEvent(LibraryEvent.OnRefreshList)
|
onEvent(LibraryEvent.OnRefreshList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.onEvent(LibraryEvent.OnScrollToPage(state.value.currentPage, pagerState))
|
onEvent(LibraryEvent.OnScrollToPage(state.value.currentPage, pagerState))
|
||||||
}
|
}
|
||||||
LaunchedEffect(pagerState.currentPage) {
|
LaunchedEffect(pagerState.currentPage) {
|
||||||
if (pagerState.currentPage != state.value.currentPage) {
|
if (pagerState.currentPage != state.value.currentPage) {
|
||||||
viewModel.onEvent(LibraryEvent.OnUpdateCurrentPage(pagerState.currentPage))
|
onEvent(LibraryEvent.OnUpdateCurrentPage(pagerState.currentPage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryScreen(
|
LibraryScreen(
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
pagerState = pagerState,
|
pagerState = pagerState,
|
||||||
refreshState = refreshState,
|
refreshState = refreshState
|
||||||
onEvent = viewModel::onEvent,
|
|
||||||
onBrowseEvent = browseViewModel::onEvent,
|
|
||||||
onHistoryEvent = historyViewModel::onEvent
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun LibraryScreen(
|
private fun LibraryScreen(
|
||||||
state: State<LibraryState>,
|
|
||||||
mainState: State<MainState>,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
pagerState: PagerState,
|
pagerState: PagerState,
|
||||||
refreshState: PullRefreshState,
|
refreshState: PullRefreshState
|
||||||
onEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryEvent: (HistoryEvent) -> Unit,
|
|
||||||
onBrowseEvent: (BrowseEvent) -> Unit
|
|
||||||
) {
|
) {
|
||||||
|
val state = LocalLibraryViewModel.current.state
|
||||||
|
val mainState = LocalMainViewModel.current.state
|
||||||
|
val onEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
var isScrollInProgress by remember { mutableStateOf(false) }
|
var isScrollInProgress by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (state.value.showMoveDialog) {
|
if (state.value.showMoveDialog) {
|
||||||
LibraryMoveDialog(
|
LibraryMoveDialog(pagerState = pagerState)
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onHistoryLoadEvent = onHistoryEvent,
|
|
||||||
pagerState = pagerState
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (state.value.showDeleteDialog) {
|
if (state.value.showDeleteDialog) {
|
||||||
LibraryDeleteDialog(
|
LibraryDeleteDialog()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onBrowseLoadEvent = onBrowseEvent,
|
|
||||||
onHistoryLoadEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -152,11 +119,7 @@ private fun LibraryScreen(
|
||||||
.pullRefresh(refreshState),
|
.pullRefresh(refreshState),
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
topBar = {
|
topBar = {
|
||||||
LibraryTopBar(
|
LibraryTopBar(pagerState = pagerState)
|
||||||
state = state,
|
|
||||||
pagerState = pagerState,
|
|
||||||
onEvent = onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Box(
|
Box(
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -35,25 +34,21 @@ import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar
|
import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar
|
||||||
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
||||||
import ua.acclorite.book_story.presentation.components.CustomSearchTextField
|
import ua.acclorite.book_story.presentation.components.CustomSearchTextField
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.MoreDropDown
|
import ua.acclorite.book_story.presentation.components.MoreDropDown
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library Top Bar.
|
* Library Top Bar.
|
||||||
* Contains [AnimatedTopAppBar] and [LibraryTabRow].
|
* Contains [AnimatedTopAppBar] and [LibraryTabRow].
|
||||||
*
|
*
|
||||||
* @param state [LibraryState].
|
|
||||||
* @param pagerState [PagerState].
|
* @param pagerState [PagerState].
|
||||||
* @param onEvent [LibraryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryTopBar(
|
fun LibraryTopBar(pagerState: PagerState) {
|
||||||
state: State<LibraryState>,
|
val state = LocalLibraryViewModel.current.state
|
||||||
pagerState: PagerState,
|
val onEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onEvent: (LibraryEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
AnimatedTopAppBar(
|
AnimatedTopAppBar(
|
||||||
|
|
|
||||||
|
|
@ -3,28 +3,28 @@ package ua.acclorite.book_story.presentation.screens.library.components.dialog
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.DeleteOutline
|
import androidx.compose.material.icons.outlined.DeleteOutline
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.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
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete dialog. Deletes all selected books.
|
* Delete dialog. Deletes all selected books.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryDeleteDialog(
|
fun LibraryDeleteDialog() {
|
||||||
state: State<LibraryState>,
|
|
||||||
onEvent: (LibraryEvent) -> Unit,
|
|
||||||
onBrowseLoadEvent: (BrowseEvent.OnLoadList) -> Unit,
|
|
||||||
onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val state = LocalLibraryViewModel.current.state
|
||||||
|
val onEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onBrowseEvent = LocalBrowseViewModel.current.onEvent
|
||||||
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
|
||||||
CustomDialogWithContent(
|
CustomDialogWithContent(
|
||||||
title = stringResource(id = R.string.delete_books),
|
title = stringResource(id = R.string.delete_books),
|
||||||
|
|
@ -40,8 +40,8 @@ fun LibraryDeleteDialog(
|
||||||
onAction = {
|
onAction = {
|
||||||
onEvent(
|
onEvent(
|
||||||
LibraryEvent.OnDeleteBooks {
|
LibraryEvent.OnDeleteBooks {
|
||||||
onBrowseLoadEvent(BrowseEvent.OnLoadList)
|
onBrowseEvent(BrowseEvent.OnLoadList)
|
||||||
onHistoryLoadEvent(HistoryEvent.OnLoadList)
|
onHistoryEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
context.getString(R.string.books_deleted)
|
context.getString(R.string.books_deleted)
|
||||||
|
|
|
||||||
|
|
@ -4,30 +4,28 @@ import androidx.compose.foundation.pager.PagerState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
|
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
|
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move dialog. Moves all selected books to the selected category.
|
* Move dialog. Moves all selected books to the selected category.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryMoveDialog(
|
fun LibraryMoveDialog(pagerState: PagerState) {
|
||||||
state: State<LibraryState>,
|
|
||||||
onEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit,
|
|
||||||
pagerState: PagerState
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val state = LocalLibraryViewModel.current.state
|
||||||
|
val onEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
|
||||||
CustomDialogWithLazyColumn(
|
CustomDialogWithLazyColumn(
|
||||||
title = stringResource(id = R.string.move_books),
|
title = stringResource(id = R.string.move_books),
|
||||||
|
|
@ -44,7 +42,7 @@ fun LibraryMoveDialog(
|
||||||
LibraryEvent.OnMoveBooks(
|
LibraryEvent.OnMoveBooks(
|
||||||
pagerState,
|
pagerState,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onHistoryLoadEvent(HistoryEvent.OnLoadList)
|
onHistoryEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.library.data
|
package ua.acclorite.book_story.presentation.screens.library.data
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -18,6 +17,7 @@ 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.domain.util.BaseViewModel
|
||||||
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
|
||||||
|
|
@ -28,10 +28,10 @@ class LibraryViewModel @Inject constructor(
|
||||||
private val updateBooks: UpdateBooks,
|
private val updateBooks: UpdateBooks,
|
||||||
private val deleteBooks: DeleteBooks,
|
private val deleteBooks: DeleteBooks,
|
||||||
private val insertHistory: InsertHistory
|
private val insertHistory: InsertHistory
|
||||||
) : ViewModel() {
|
) : BaseViewModel<LibraryState, LibraryEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(LibraryState())
|
private val _state = MutableStateFlow(LibraryState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private val _isReady = MutableStateFlow(false)
|
private val _isReady = MutableStateFlow(false)
|
||||||
val isReady = _isReady.asStateFlow()
|
val isReady = _isReady.asStateFlow()
|
||||||
|
|
@ -53,7 +53,7 @@ class LibraryViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: LibraryEvent) {
|
override fun onEvent(event: LibraryEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is LibraryEvent.OnScrollToPage -> {
|
is LibraryEvent.OnScrollToPage -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -49,24 +47,22 @@ import androidx.compose.ui.unit.em
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
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.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderEndItem
|
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderEndItem
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderTextParagraph
|
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderTextParagraph
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderBottomBar
|
import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderBottomBar
|
||||||
|
|
@ -75,26 +71,16 @@ import ua.acclorite.book_story.presentation.screens.reader.components.readerFast
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet
|
import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.components.start_item.ReaderStartItem
|
import ua.acclorite.book_story.presentation.screens.reader.components.start_item.ReaderStartItem
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
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.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderScreenRoot(screen: Screen.Reader) {
|
fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
val navigator = LocalNavigator.current
|
val state = LocalReaderViewModel.current.state
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
|
val viewModel = LocalReaderViewModel.current.viewModel
|
||||||
val context = LocalContext.current as ComponentActivity
|
val context = LocalContext.current as ComponentActivity
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
val viewModel: ReaderViewModel = hiltViewModel()
|
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
val libraryViewModel: LibraryViewModel = hiltViewModel()
|
|
||||||
val historyViewModel: HistoryViewModel = hiltViewModel()
|
|
||||||
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = viewModel.state.collectAsState()
|
|
||||||
val mainState = mainViewModel.state.collectAsState()
|
|
||||||
val settingsState = settingsViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
val lazyListState = rememberSaveable(
|
val lazyListState = rememberSaveable(
|
||||||
state.value.listState,
|
state.value.listState,
|
||||||
|
|
@ -111,11 +97,11 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.init(
|
viewModel.init(
|
||||||
screen = screen,
|
screen = screen,
|
||||||
onNavigate = { navigator.it() },
|
onNavigate = onNavigate,
|
||||||
context = context,
|
context = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
historyViewModel.onEvent(HistoryEvent.OnLoadList)
|
onHistoryEvent(HistoryEvent.OnLoadList)
|
||||||
},
|
},
|
||||||
onError = {
|
onError = {
|
||||||
it.asString(context)
|
it.asString(context)
|
||||||
|
|
@ -129,11 +115,13 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LaunchedEffect(lazyListState) {
|
LaunchedEffect(lazyListState) {
|
||||||
viewModel.onUpdateProgress(
|
viewModel.onUpdateProgress {
|
||||||
onLibraryEvent = libraryViewModel::onEvent,
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryEvent = historyViewModel::onEvent
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReaderScreen(lazyListState = lazyListState)
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
onDispose {
|
onDispose {
|
||||||
|
|
@ -145,36 +133,19 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
|
||||||
context.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
context.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderScreen(
|
|
||||||
state = state,
|
|
||||||
mainState = mainState,
|
|
||||||
settingsState = settingsState,
|
|
||||||
lazyListState = lazyListState,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onEvent = viewModel::onEvent,
|
|
||||||
onMainEvent = mainViewModel::onEvent,
|
|
||||||
onSettingsEvent = settingsViewModel::onEvent,
|
|
||||||
onLibraryEvent = libraryViewModel::onEvent,
|
|
||||||
onHistoryEvent = historyViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReaderScreen(
|
private fun ReaderScreen(lazyListState: LazyListState) {
|
||||||
state: State<ReaderState>,
|
val state = LocalReaderViewModel.current.state
|
||||||
mainState: State<MainState>,
|
val mainState = LocalMainViewModel.current.state
|
||||||
settingsState: State<SettingsState>,
|
val settingsState = LocalSettingsViewModel.current.state
|
||||||
lazyListState: LazyListState,
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
onNavigate: OnNavigate,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onEvent: (ReaderEvent) -> Unit,
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryEvent: (HistoryEvent) -> Unit,
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current as ComponentActivity
|
val context = LocalContext.current as ComponentActivity
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
val nestedScrollConnection = remember(state) {
|
val nestedScrollConnection = remember(state) {
|
||||||
object : NestedScrollConnection {
|
object : NestedScrollConnection {
|
||||||
|
|
@ -230,13 +201,7 @@ private fun ReaderScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.value.showSettingsBottomSheet) {
|
if (state.value.showSettingsBottomSheet) {
|
||||||
ReaderSettingsBottomSheet(
|
ReaderSettingsBottomSheet()
|
||||||
mainState = mainState,
|
|
||||||
settingsState = settingsState,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -250,13 +215,7 @@ private fun ReaderScreen(
|
||||||
enter = slideInVertically { -it },
|
enter = slideInVertically { -it },
|
||||||
exit = slideOutVertically { -it }
|
exit = slideOutVertically { -it }
|
||||||
) {
|
) {
|
||||||
ReaderTopBar(
|
ReaderTopBar()
|
||||||
state = state,
|
|
||||||
onNavigate = onNavigate,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryUpdateEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
|
|
@ -266,12 +225,7 @@ private fun ReaderScreen(
|
||||||
enter = slideInVertically { it },
|
enter = slideInVertically { it },
|
||||||
exit = slideOutVertically { it }
|
exit = slideOutVertically { it }
|
||||||
) {
|
) {
|
||||||
ReaderBottomBar(
|
ReaderBottomBar()
|
||||||
state = state,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryUpdateEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
@ -357,7 +311,6 @@ private fun ReaderScreen(
|
||||||
fastColorPresetChangeEnabled = mainState.value.fastColorPresetChange,
|
fastColorPresetChangeEnabled = mainState.value.fastColorPresetChange,
|
||||||
isLoading = state.value.loading,
|
isLoading = state.value.loading,
|
||||||
toolbarHidden = toolbarHidden,
|
toolbarHidden = toolbarHidden,
|
||||||
onSettingsEvent = onSettingsEvent,
|
|
||||||
presetChanged = {
|
presetChanged = {
|
||||||
context
|
context
|
||||||
.getString(
|
.getString(
|
||||||
|
|
@ -373,7 +326,7 @@ private fun ReaderScreen(
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
DisableSelection {
|
DisableSelection {
|
||||||
ReaderStartItem(state = state)
|
ReaderStartItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(18.dp))
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
|
@ -395,8 +348,7 @@ private fun ReaderScreen(
|
||||||
sidePadding = sidePadding,
|
sidePadding = sidePadding,
|
||||||
paragraphIndentation = mainState.value.paragraphIndentation,
|
paragraphIndentation = mainState.value.paragraphIndentation,
|
||||||
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation,
|
doubleClickTranslationEnabled = mainState.value.doubleClickTranslation,
|
||||||
toolbarHidden = toolbarHidden,
|
toolbarHidden = toolbarHidden
|
||||||
onEvent = onEvent
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,13 +356,7 @@ private fun ReaderScreen(
|
||||||
Spacer(modifier = Modifier.height(18.dp))
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
|
||||||
DisableSelection {
|
DisableSelection {
|
||||||
ReaderEndItem(
|
ReaderEndItem()
|
||||||
state = state,
|
|
||||||
onNavigate = onNavigate,
|
|
||||||
onEvent = onEvent,
|
|
||||||
onLibraryEvent = onLibraryEvent,
|
|
||||||
onHistoryUpdateEvent = onHistoryEvent,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -29,33 +28,30 @@ 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.domain.util.OnNavigate
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
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 onNavigate Navigator callback.
|
|
||||||
* @param onEvent [ReaderEvent] callback.
|
|
||||||
* @param onLibraryEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryUpdateEvent [HistoryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderEndItem(
|
fun ReaderEndItem(
|
||||||
state: State<ReaderState>,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onEvent: (ReaderEvent) -> Unit,
|
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit,
|
|
||||||
) {
|
) {
|
||||||
|
val state = LocalReaderViewModel.current.state
|
||||||
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
val context = LocalContext.current as ComponentActivity
|
val context = LocalContext.current as ComponentActivity
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -102,7 +98,7 @@ fun ReaderEndItem(
|
||||||
context = context,
|
context = context,
|
||||||
onUpdateCategories = {
|
onUpdateCategories = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
updatePage = {
|
updatePage = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
|
onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it))
|
||||||
|
|
@ -119,7 +115,7 @@ fun ReaderEndItem(
|
||||||
context = context,
|
context = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
navigate = {
|
navigate = {
|
||||||
onNavigate {
|
onNavigate {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import ua.acclorite.book_story.domain.util.UIText
|
import ua.acclorite.book_story.domain.util.UIText
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,7 +17,6 @@ import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||||
* @param fastColorPresetChangeEnabled Whether this is enabled.
|
* @param fastColorPresetChangeEnabled Whether this is enabled.
|
||||||
* @param isLoading Whether Reader is loading.
|
* @param isLoading Whether Reader is loading.
|
||||||
* @param toolbarHidden Whether toolbar(selection) is hidden.
|
* @param toolbarHidden Whether toolbar(selection) is hidden.
|
||||||
* @param onSettingsEvent [SettingsEvent] callback.
|
|
||||||
* @param presetChanged Callback when Color Preset was changed.
|
* @param presetChanged Callback when Color Preset was changed.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -24,9 +24,10 @@ fun Modifier.readerFastColorPresetChange(
|
||||||
fastColorPresetChangeEnabled: Boolean,
|
fastColorPresetChangeEnabled: Boolean,
|
||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
toolbarHidden: Boolean,
|
toolbarHidden: Boolean,
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
presetChanged: (UIText) -> Unit
|
presetChanged: (UIText) -> Unit
|
||||||
): Modifier {
|
): Modifier {
|
||||||
|
val onSettingsEvent = LocalSettingsViewModel.current.onEvent
|
||||||
|
|
||||||
val offset = remember { mutableFloatStateOf(0f) }
|
val offset = remember { mutableFloatStateOf(0f) }
|
||||||
return this.then(
|
return this.then(
|
||||||
if (fastColorPresetChangeEnabled && toolbarHidden && !isLoading) {
|
if (fastColorPresetChangeEnabled && toolbarHidden && !isLoading) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
import ua.acclorite.book_story.domain.model.FontWithName
|
import ua.acclorite.book_story.domain.model.FontWithName
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.showToast
|
import ua.acclorite.book_story.presentation.data.showToast
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment
|
||||||
|
|
@ -43,7 +44,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.
|
||||||
* @param paragraphIndentation Whether Paragraph Indentation is enabled for this line.
|
* @param paragraphIndentation Whether Paragraph Indentation is enabled for this line.
|
||||||
* @param doubleClickTranslationEnabled Whether Double Click Translation is enabled.
|
* @param doubleClickTranslationEnabled Whether Double Click Translation is enabled.
|
||||||
* @param toolbarHidden Whether selection toolBar is hidden.
|
* @param toolbarHidden Whether selection toolBar is hidden.
|
||||||
* @param onEvent [ReaderEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -60,9 +60,10 @@ fun LazyItemScope.ReaderTextParagraph(
|
||||||
sidePadding: Dp,
|
sidePadding: Dp,
|
||||||
paragraphIndentation: Boolean,
|
paragraphIndentation: Boolean,
|
||||||
doubleClickTranslationEnabled: Boolean,
|
doubleClickTranslationEnabled: Boolean,
|
||||||
toolbarHidden: Boolean,
|
toolbarHidden: Boolean
|
||||||
onEvent: (ReaderEvent) -> Unit
|
|
||||||
) {
|
) {
|
||||||
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
||||||
|
|
|
||||||
|
|
@ -14,36 +14,32 @@ import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.SliderDefaults
|
import androidx.compose.material3.SliderDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
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
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
|
|
||||||
import ua.acclorite.book_story.presentation.ui.Colors
|
import ua.acclorite.book_story.presentation.ui.Colors
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reader bottom bar. Has a slider to change progress.
|
* Reader bottom bar. Has a slider to change progress.
|
||||||
*
|
|
||||||
* @param state [ReaderState].
|
|
||||||
* @param onEvent [ReaderEvent] callback.
|
|
||||||
* @param onLibraryUpdateEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryUpdateEvent [HistoryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderBottomBar(
|
fun ReaderBottomBar() {
|
||||||
state: State<ReaderState>,
|
val state = LocalReaderViewModel.current.state
|
||||||
onEvent: (ReaderEvent) -> Unit,
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
) {
|
|
||||||
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)
|
||||||
|
|
@ -87,8 +83,8 @@ fun ReaderBottomBar(
|
||||||
firstVisibleItemIndex = state.value.listState.firstVisibleItemIndex,
|
firstVisibleItemIndex = state.value.listState.firstVisibleItemIndex,
|
||||||
firstVisibleItemOffset = 0,
|
firstVisibleItemOffset = 0,
|
||||||
refreshList = { book ->
|
refreshList = { book ->
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(book))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(book))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(book))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(book))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
|
@ -22,34 +21,29 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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.components.LocalHistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.data.LocalOnNavigate
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
|
|
||||||
import ua.acclorite.book_story.presentation.ui.Colors
|
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 onNavigate Navigator callback.
|
|
||||||
* @param onEvent [ReaderEvent] callback.
|
|
||||||
* @param onLibraryUpdateEvent [LibraryEvent] callback.
|
|
||||||
* @param onHistoryUpdateEvent [HistoryEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderTopBar(
|
fun ReaderTopBar() {
|
||||||
state: State<ReaderState>,
|
val state = LocalReaderViewModel.current.state
|
||||||
onNavigate: OnNavigate,
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
onEvent: (ReaderEvent) -> Unit,
|
val onLibraryEvent = LocalLibraryViewModel.current.onEvent
|
||||||
onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit,
|
val onHistoryEvent = LocalHistoryViewModel.current.onEvent
|
||||||
onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current as ComponentActivity
|
val context = LocalContext.current as ComponentActivity
|
||||||
|
val onNavigate = LocalOnNavigate.current
|
||||||
|
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
|
@ -62,8 +56,8 @@ fun ReaderTopBar(
|
||||||
ReaderEvent.OnGoBack(
|
ReaderEvent.OnGoBack(
|
||||||
context = context,
|
context = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
navigate = {
|
navigate = {
|
||||||
onNavigate {
|
onNavigate {
|
||||||
|
|
@ -94,8 +88,8 @@ fun ReaderTopBar(
|
||||||
ReaderEvent.OnGoBack(
|
ReaderEvent.OnGoBack(
|
||||||
context = context,
|
context = context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it))
|
onLibraryEvent(LibraryEvent.OnUpdateBook(it))
|
||||||
onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it))
|
onHistoryEvent(HistoryEvent.OnUpdateBook(it))
|
||||||
},
|
},
|
||||||
navigate = {
|
navigate = {
|
||||||
onNavigate {
|
onNavigate {
|
||||||
|
|
|
||||||
|
|
@ -14,67 +14,49 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
import ua.acclorite.book_story.presentation.components.CustomBottomSheet
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings bottom sheet. Has General and Colors categories.
|
* Settings bottom sheet. Has General and Colors categories.
|
||||||
*
|
|
||||||
* @param mainState [MainState].
|
|
||||||
* @param settingsState [SettingsState].
|
|
||||||
* @param onEvent [ReaderEvent] callback.
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param onSettingsEvent [SettingsEvent] callback.
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderSettingsBottomSheet(
|
fun ReaderSettingsBottomSheet() {
|
||||||
mainState: State<MainState>,
|
val state = LocalReaderViewModel.current.state
|
||||||
settingsState: State<SettingsState>,
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
onEvent: (ReaderEvent) -> Unit,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val pagerState = rememberPagerState { 2 }
|
|
||||||
val currentPage by remember { derivedStateOf { pagerState.currentPage } }
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val scrimColor = if (currentPage == 1) Color.Transparent
|
val pagerState = rememberPagerState(state.value.currentPage) { 3 }
|
||||||
else BottomSheetDefaults.ScrimColor
|
|
||||||
|
|
||||||
val animatedScrimColor by animateColorAsState(
|
val animatedScrimColor by animateColorAsState(
|
||||||
targetValue = scrimColor,
|
targetValue = if (pagerState.currentPage == 2) Color.Transparent
|
||||||
animationSpec = tween(300),
|
else BottomSheetDefaults.ScrimColor,
|
||||||
label = "Scrim animation"
|
animationSpec = tween(300)
|
||||||
)
|
)
|
||||||
|
|
||||||
val height = remember(currentPage) {
|
|
||||||
if (currentPage == 1) 0.6f else 0.7f
|
|
||||||
}
|
|
||||||
val animatedHeight by animateFloatAsState(
|
val animatedHeight by animateFloatAsState(
|
||||||
targetValue = height,
|
targetValue = if (pagerState.currentPage == 2) 0.6f else 0.7f,
|
||||||
animationSpec = tween(300),
|
animationSpec = tween(300)
|
||||||
label = "Height animation"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(currentPage) {
|
LaunchedEffect(pagerState.currentPage) {
|
||||||
|
onEvent(
|
||||||
|
ReaderEvent.OnScrollToSettingsPage(
|
||||||
|
page = pagerState.currentPage,
|
||||||
|
pagerState = null
|
||||||
|
)
|
||||||
|
)
|
||||||
onEvent(
|
onEvent(
|
||||||
ReaderEvent.OnShowHideMenu(
|
ReaderEvent.OnShowHideMenu(
|
||||||
currentPage != 1,
|
pagerState.currentPage != 2,
|
||||||
context as ComponentActivity
|
context as ComponentActivity
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -91,17 +73,14 @@ fun ReaderSettingsBottomSheet(
|
||||||
onEvent(ReaderEvent.OnShowHideSettingsBottomSheet)
|
onEvent(ReaderEvent.OnShowHideSettingsBottomSheet)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
ReaderSettingsBottomSheetTabRow(
|
ReaderSettingsBottomSheetTabRow(pagerState = pagerState)
|
||||||
onEvent = onEvent,
|
|
||||||
pagerState = pagerState
|
|
||||||
)
|
|
||||||
|
|
||||||
HorizontalPager(state = pagerState) { page ->
|
HorizontalPager(state = pagerState) { page ->
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
|
if (page == 1) {
|
||||||
|
LazyColumn {
|
||||||
ReaderSettingsCategory(
|
ReaderSettingsCategory(
|
||||||
state = mainState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
titleColor = { MaterialTheme.colorScheme.onSurface },
|
titleColor = { MaterialTheme.colorScheme.onSurface },
|
||||||
topPadding = 16.dp,
|
topPadding = 16.dp,
|
||||||
bottomPadding = 8.dp + it
|
bottomPadding = 8.dp + it
|
||||||
|
|
@ -109,13 +88,9 @@ fun ReaderSettingsBottomSheet(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (page == 2) {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
if (page == 1) {
|
|
||||||
ColorsSubcategory(
|
ColorsSubcategory(
|
||||||
state = mainState,
|
|
||||||
settingsState = settingsState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent,
|
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
backgroundColor = { MaterialTheme.colorScheme.surfaceContainer },
|
backgroundColor = { MaterialTheme.colorScheme.surfaceContainer },
|
||||||
topPadding = 16.dp,
|
topPadding = 16.dp,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,6 +25,9 @@ fun ReaderSettingsBottomSheetTabRow(
|
||||||
pagerState: PagerState
|
pagerState: PagerState
|
||||||
) {
|
) {
|
||||||
val tabItems = listOf(
|
val tabItems = listOf(
|
||||||
|
fun ReaderSettingsBottomSheetTabRow(pagerState: PagerState) {
|
||||||
|
val onEvent = LocalReaderViewModel.current.onEvent
|
||||||
|
|
||||||
stringResource(id = R.string.general_tab),
|
stringResource(id = R.string.general_tab),
|
||||||
stringResource(id = R.string.color_tab)
|
stringResource(id = R.string.color_tab)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -33,16 +32,16 @@ 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.presentation.components.CustomCoverImage
|
import ua.acclorite.book_story.presentation.components.CustomCoverImage
|
||||||
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
|
import ua.acclorite.book_story.presentation.components.LocalReaderViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reader start item. Displays at the beginning of the book.
|
* Reader start item. Displays at the beginning of the book.
|
||||||
*
|
|
||||||
* @param state [ReaderState].
|
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderStartItem(state: State<ReaderState>) {
|
fun ReaderStartItem() {
|
||||||
|
val state = LocalReaderViewModel.current.state
|
||||||
|
|
||||||
val statusBarHeight = WindowInsets
|
val statusBarHeight = WindowInsets
|
||||||
.statusBarsIgnoringVisibility
|
.statusBarsIgnoringVisibility
|
||||||
.asPaddingValues()
|
.asPaddingValues()
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ sealed class ReaderEvent {
|
||||||
|
|
||||||
data class OnScroll(val progress: Float) : ReaderEvent()
|
data class OnScroll(val progress: Float) : ReaderEvent()
|
||||||
data object OnShowHideSettingsBottomSheet : ReaderEvent()
|
data object OnShowHideSettingsBottomSheet : ReaderEvent()
|
||||||
data class OnScrollToSettingsPage(val page: Int, val pagerState: PagerState) : ReaderEvent()
|
data class OnScrollToSettingsPage(val page: Int, val pagerState: PagerState?) : ReaderEvent()
|
||||||
data class OnMoveBookToAlreadyRead(
|
data class OnMoveBookToAlreadyRead(
|
||||||
val context: ComponentActivity,
|
val context: ComponentActivity,
|
||||||
val onUpdateCategories: (Book) -> Unit,
|
val onUpdateCategories: (Book) -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -32,12 +31,11 @@ import ua.acclorite.book_story.domain.use_case.GetBookById
|
||||||
import ua.acclorite.book_story.domain.use_case.GetLatestHistory
|
import ua.acclorite.book_story.domain.use_case.GetLatestHistory
|
||||||
import ua.acclorite.book_story.domain.use_case.GetText
|
import ua.acclorite.book_story.domain.use_case.GetText
|
||||||
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.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.OnNavigate
|
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.Screen
|
import ua.acclorite.book_story.presentation.data.Screen
|
||||||
import ua.acclorite.book_story.presentation.data.launchActivity
|
import ua.acclorite.book_story.presentation.data.launchActivity
|
||||||
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
@ -48,14 +46,14 @@ class ReaderViewModel @Inject constructor(
|
||||||
private val getText: GetText,
|
private val getText: GetText,
|
||||||
private val getLatestHistory: GetLatestHistory,
|
private val getLatestHistory: GetLatestHistory,
|
||||||
private val getBookById: GetBookById
|
private val getBookById: GetBookById
|
||||||
) : ViewModel() {
|
) : BaseViewModel<ReaderState, ReaderEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(ReaderState())
|
private val _state = MutableStateFlow(ReaderState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var eventJob = SupervisorJob()
|
private var eventJob = SupervisorJob()
|
||||||
|
|
||||||
fun onEvent(event: ReaderEvent) {
|
override fun onEvent(event: ReaderEvent) {
|
||||||
viewModelScope.launch(eventJob + Dispatchers.Main) {
|
viewModelScope.launch(eventJob + Dispatchers.Main) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is ReaderEvent.OnTextIsEmpty -> {
|
is ReaderEvent.OnTextIsEmpty -> {
|
||||||
|
|
@ -269,7 +267,6 @@ class ReaderViewModel @Inject constructor(
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
currentPage = if (it.showSettingsBottomSheet) it.currentPage else 0,
|
|
||||||
showSettingsBottomSheet = !it.showSettingsBottomSheet
|
showSettingsBottomSheet = !it.showSettingsBottomSheet
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -278,7 +275,13 @@ class ReaderViewModel @Inject constructor(
|
||||||
|
|
||||||
is ReaderEvent.OnScrollToSettingsPage -> {
|
is ReaderEvent.OnScrollToSettingsPage -> {
|
||||||
launch {
|
launch {
|
||||||
event.pagerState.scrollToPage(event.page)
|
_state.update {
|
||||||
|
event.pagerState?.scrollToPage(event.page)
|
||||||
|
|
||||||
|
it.copy(
|
||||||
|
currentPage = event.page
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,10 +501,7 @@ class ReaderViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FlowPreview::class)
|
@OptIn(FlowPreview::class)
|
||||||
fun onUpdateProgress(
|
fun onUpdateProgress(refreshList: (Book) -> Unit) {
|
||||||
onLibraryEvent: (LibraryEvent) -> Unit,
|
|
||||||
onHistoryEvent: (HistoryEvent) -> Unit
|
|
||||||
) {
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
snapshotFlow {
|
snapshotFlow {
|
||||||
_state.value.listState.firstVisibleItemIndex to _state.value.listState.firstVisibleItemScrollOffset
|
_state.value.listState.firstVisibleItemIndex to _state.value.listState.firstVisibleItemScrollOffset
|
||||||
|
|
@ -538,8 +538,7 @@ class ReaderViewModel @Inject constructor(
|
||||||
firstVisibleItemIndex = firstVisibleItemIndex,
|
firstVisibleItemIndex = firstVisibleItemIndex,
|
||||||
firstVisibleItemOffset = firstVisibleItemScrollOffset,
|
firstVisibleItemOffset = firstVisibleItemScrollOffset,
|
||||||
refreshList = { book ->
|
refreshList = { book ->
|
||||||
onLibraryEvent(LibraryEvent.OnUpdateBook(book))
|
refreshList(book)
|
||||||
onHistoryEvent(HistoryEvent.OnUpdateBook(book))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,26 +24,22 @@ 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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
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.LocalOnNavigate
|
||||||
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
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreenRoot() {
|
fun SettingsScreenRoot() {
|
||||||
val navigator = LocalNavigator.current
|
SettingsScreen()
|
||||||
|
|
||||||
SettingsScreen(onNavigate = { navigator.it() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun SettingsScreen(
|
private fun SettingsScreen() {
|
||||||
onNavigate: OnNavigate
|
val onNavigate = LocalOnNavigate.current
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.screens.settings.data
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
|
|
@ -24,6 +23,7 @@ import ua.acclorite.book_story.domain.use_case.GetColorPresets
|
||||||
import ua.acclorite.book_story.domain.use_case.ReorderColorPresets
|
import ua.acclorite.book_story.domain.use_case.ReorderColorPresets
|
||||||
import ua.acclorite.book_story.domain.use_case.SelectColorPreset
|
import ua.acclorite.book_story.domain.use_case.SelectColorPreset
|
||||||
import ua.acclorite.book_story.domain.use_case.UpdateColorPreset
|
import ua.acclorite.book_story.domain.use_case.UpdateColorPreset
|
||||||
|
import ua.acclorite.book_story.domain.util.BaseViewModel
|
||||||
import ua.acclorite.book_story.domain.util.Constants
|
import ua.acclorite.book_story.domain.util.Constants
|
||||||
import ua.acclorite.book_story.domain.util.ID
|
import ua.acclorite.book_story.domain.util.ID
|
||||||
import ua.acclorite.book_story.domain.util.UIText
|
import ua.acclorite.book_story.domain.util.UIText
|
||||||
|
|
@ -39,10 +39,10 @@ class SettingsViewModel @Inject constructor(
|
||||||
private val deleteColorPreset: DeleteColorPreset,
|
private val deleteColorPreset: DeleteColorPreset,
|
||||||
private val selectColorPreset: SelectColorPreset,
|
private val selectColorPreset: SelectColorPreset,
|
||||||
private val reorderColorPresets: ReorderColorPresets
|
private val reorderColorPresets: ReorderColorPresets
|
||||||
) : ViewModel() {
|
) : BaseViewModel<SettingsState, SettingsEvent>() {
|
||||||
|
|
||||||
private val _state = MutableStateFlow(SettingsState())
|
private val _state = MutableStateFlow(SettingsState())
|
||||||
val state = _state.asStateFlow()
|
override val state = _state.asStateFlow()
|
||||||
|
|
||||||
private val _isReady = MutableStateFlow(false)
|
private val _isReady = MutableStateFlow(false)
|
||||||
val isReady = _isReady.asStateFlow()
|
val isReady = _isReady.asStateFlow()
|
||||||
|
|
@ -93,7 +93,7 @@ class SettingsViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LABEL_NAME_CLASH")
|
@Suppress("LABEL_NAME_CLASH")
|
||||||
fun onEvent(event: SettingsEvent) {
|
override fun onEvent(event: SettingsEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is SettingsEvent.OnGeneralChangeCheckForUpdates -> {
|
is SettingsEvent.OnGeneralChangeCheckForUpdates -> {
|
||||||
if (!event.enable) {
|
if (!event.enable) {
|
||||||
|
|
|
||||||
|
|
@ -13,53 +13,25 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.AppearanceSettingsCategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.AppearanceSettingsCategory
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppearanceSettingsRoot() {
|
fun AppearanceSettingsRoot() {
|
||||||
val navigator = LocalNavigator.current
|
AppearanceSettings()
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = mainViewModel.state.collectAsState()
|
|
||||||
val settingsState = settingsViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
AppearanceSettings(
|
|
||||||
state = state,
|
|
||||||
settingsState = settingsState,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onMainEvent = mainViewModel::onEvent,
|
|
||||||
onSettingsEvent = settingsViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun AppearanceSettings(
|
private fun AppearanceSettings() {
|
||||||
state: State<MainState>,
|
val onNavigate = LocalOnNavigate.current
|
||||||
settingsState: State<SettingsState>,
|
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -91,12 +63,7 @@ private fun AppearanceSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
AppearanceSettingsCategory(
|
AppearanceSettingsCategory()
|
||||||
state = state,
|
|
||||||
settingsState = settingsState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,9 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory
|
||||||
|
|
||||||
|
|
@ -20,34 +15,21 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c
|
||||||
* Appearance Settings Category.
|
* Appearance Settings Category.
|
||||||
* Contains all Appearance settings such as Theme.
|
* Contains all Appearance settings such as Theme.
|
||||||
*
|
*
|
||||||
* @param state [MainState] instance.
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param onSettingsEvent [SettingsEvent] callback.
|
|
||||||
* @param titleColor Title's color.
|
* @param titleColor Title's color.
|
||||||
* @param topPadding Top padding to be applied.
|
* @param topPadding Top padding to be applied.
|
||||||
* @param bottomPadding Bottom padding to be applied.
|
* @param bottomPadding Bottom padding to be applied.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.AppearanceSettingsCategory(
|
fun LazyListScope.AppearanceSettingsCategory(
|
||||||
state: State<MainState>,
|
|
||||||
settingsState: State<SettingsState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
topPadding: Dp = 16.dp,
|
topPadding: Dp = 16.dp,
|
||||||
bottomPadding: Dp = 48.dp
|
bottomPadding: Dp = 48.dp
|
||||||
) {
|
) {
|
||||||
ThemePreferencesSubcategory(
|
ThemePreferencesSubcategory(
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = topPadding,
|
topPadding = topPadding,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
ColorsSubcategory(
|
ColorsSubcategory(
|
||||||
state = state,
|
|
||||||
settingsState = settingsState,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent,
|
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = bottomPadding
|
bottomPadding = bottomPadding
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
|
|
@ -64,10 +63,10 @@ import ua.acclorite.book_story.domain.util.Selected
|
||||||
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
|
||||||
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
import ua.acclorite.book_story.presentation.components.CustomIconButton
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
||||||
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.data.SettingsEvent
|
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
|
import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
|
||||||
import ua.acclorite.book_story.presentation.ui.Transitions
|
import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
|
|
||||||
|
|
@ -78,13 +77,14 @@ import ua.acclorite.book_story.presentation.ui.Transitions
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ColorPresetSetting(
|
fun ColorPresetSetting(
|
||||||
state: State<SettingsState>,
|
|
||||||
onEvent: (SettingsEvent) -> Unit,
|
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
verticalPadding: Dp = 8.dp,
|
verticalPadding: Dp = 8.dp,
|
||||||
horizontalPadding: Dp = 18.dp
|
horizontalPadding: Dp = 18.dp
|
||||||
) {
|
) {
|
||||||
|
val state = LocalSettingsViewModel.current.state
|
||||||
|
val onEvent = LocalSettingsViewModel.current.onEvent
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val reorderableListState = rememberReorderableLazyListState(
|
val reorderableListState = rememberReorderableLazyListState(
|
||||||
lazyListState = state.value.colorPresetsListState
|
lazyListState = state.value.colorPresetsListState
|
||||||
) { from, to ->
|
) { from, to ->
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
import ua.acclorite.book_story.presentation.ui.DarkTheme
|
import ua.acclorite.book_story.presentation.ui.DarkTheme
|
||||||
|
|
||||||
|
|
@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.ui.DarkTheme
|
||||||
* If true, dark theme applied to the app's theme.
|
* If true, dark theme applied to the app's theme.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun DarkThemeSetting(
|
fun DarkThemeSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.dark_theme_option),
|
title = stringResource(id = R.string.dark_theme_option),
|
||||||
buttons = DarkTheme.entries.map {
|
buttons = DarkTheme.entries.map {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SwitchWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
|
||||||
* If true, user can fast change color presets in Reader with swipes.
|
* If true, user can fast change color presets in Reader with swipes.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun FastColorPresetChangeSetting(
|
fun FastColorPresetChangeSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.fastColorPresetChange,
|
selected = state.value.fastColorPresetChange,
|
||||||
title = stringResource(id = R.string.fast_color_preset_change_option),
|
title = stringResource(id = R.string.fast_color_preset_change_option),
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
import ua.acclorite.book_story.presentation.ui.PureDark
|
import ua.acclorite.book_story.presentation.ui.PureDark
|
||||||
|
|
@ -18,10 +17,10 @@ import ua.acclorite.book_story.presentation.ui.isDark
|
||||||
* If true, enables Pure Dark (OLED) theme.
|
* If true, enables Pure Dark (OLED) theme.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun PureDarkSetting(
|
fun PureDarkSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
ExpandingTransition(visible = state.value.darkTheme.isDark()) {
|
ExpandingTransition(visible = state.value.darkTheme.isDark()) {
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.pure_dark_option),
|
title = stringResource(id = R.string.pure_dark_option),
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
import ua.acclorite.book_story.presentation.ui.BookStoryTheme
|
import ua.acclorite.book_story.presentation.ui.BookStoryTheme
|
||||||
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
|
|
@ -25,10 +24,10 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||||
* Lets user change theme contrast levels.
|
* Lets user change theme contrast levels.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ThemeContrastSetting(
|
fun ThemeContrastSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val themeContrastTheme = remember { mutableStateOf(state.value.theme) }
|
val themeContrastTheme = remember { mutableStateOf(state.value.theme) }
|
||||||
|
|
||||||
LaunchedEffect(state.value.theme) {
|
LaunchedEffect(state.value.theme) {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -42,9 +41,9 @@ import ua.acclorite.book_story.domain.util.Constants
|
||||||
import ua.acclorite.book_story.domain.util.UIText
|
import ua.acclorite.book_story.domain.util.UIText
|
||||||
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
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
import ua.acclorite.book_story.presentation.components.customItemsIndexed
|
||||||
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.ui.Theme
|
import ua.acclorite.book_story.presentation.ui.Theme
|
||||||
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
import ua.acclorite.book_story.presentation.ui.ThemeContrast
|
||||||
import ua.acclorite.book_story.presentation.ui.animatedColorScheme
|
import ua.acclorite.book_story.presentation.ui.animatedColorScheme
|
||||||
|
|
@ -57,11 +56,12 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ThemeSetting(
|
fun ThemeSetting(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
verticalPadding: Dp = 8.dp,
|
verticalPadding: Dp = 8.dp,
|
||||||
horizontalPadding: Dp = 18.dp
|
horizontalPadding: Dp = 18.dp
|
||||||
) {
|
) {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
|
|
||||||
val themes = remember {
|
val themes = remember {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES
|
||||||
else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC }
|
else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC }
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -17,10 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
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.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ColorPresetSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ColorPresetSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.FastColorPresetChangeSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.FastColorPresetChangeSetting
|
||||||
|
|
||||||
|
|
@ -29,10 +24,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c
|
||||||
* Contains all settings from Colors.
|
* Contains all settings from Colors.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.ColorsSubcategory(
|
fun LazyListScope.ColorsSubcategory(
|
||||||
state: State<MainState>,
|
|
||||||
settingsState: State<SettingsState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
title: @Composable () -> String = { stringResource(id = R.string.colors_appearance_settings) },
|
title: @Composable () -> String = { stringResource(id = R.string.colors_appearance_settings) },
|
||||||
backgroundColor: @Composable () -> Color = { MaterialTheme.colorScheme.surfaceContainerLow },
|
backgroundColor: @Composable () -> Color = { MaterialTheme.colorScheme.surfaceContainerLow },
|
||||||
|
|
@ -59,18 +50,11 @@ fun LazyListScope.ColorsSubcategory(
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
ColorPresetSetting(
|
ColorPresetSetting(backgroundColor = backgroundColor.invoke())
|
||||||
state = settingsState,
|
|
||||||
backgroundColor = backgroundColor.invoke(),
|
|
||||||
onEvent = onSettingsEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
FastColorPresetChangeSetting(
|
FastColorPresetChangeSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
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.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.DarkThemeSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.DarkThemeSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.PureDarkSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.PureDarkSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting
|
||||||
|
|
@ -29,8 +26,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c
|
||||||
* Contains all settings from Theme Preferences.
|
* Contains all settings from Theme Preferences.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.ThemePreferencesSubcategory(
|
fun LazyListScope.ThemePreferencesSubcategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
title: @Composable () -> String = { stringResource(id = R.string.theme_appearance_settings) },
|
title: @Composable () -> String = { stringResource(id = R.string.theme_appearance_settings) },
|
||||||
showTitle: Boolean = true,
|
showTitle: Boolean = true,
|
||||||
|
|
@ -56,31 +51,19 @@ fun LazyListScope.ThemePreferencesSubcategory(
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
DarkThemeSetting(
|
DarkThemeSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
ThemeSetting(
|
ThemeSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
ThemeContrastSetting(
|
ThemeContrastSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
PureDarkSetting(
|
PureDarkSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
|
||||||
|
|
@ -13,44 +13,25 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.BrowseSettingsCategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.BrowseSettingsCategory
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseSettingsRoot() {
|
fun BrowseSettingsRoot() {
|
||||||
val navigator = LocalNavigator.current
|
BrowseSettings()
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
BrowseSettings(
|
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onMainEvent = mainViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun BrowseSettings(
|
private fun BrowseSettings() {
|
||||||
state: State<MainState>,
|
val onNavigate = LocalOnNavigate.current
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onMainEvent: (MainEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -82,10 +63,7 @@ private fun BrowseSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
BrowseSettingsCategory(
|
BrowseSettingsCategory()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,11 +3,8 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components
|
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components
|
||||||
|
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory
|
||||||
|
|
@ -16,32 +13,22 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
|
||||||
* Browse Settings Category.
|
* Browse Settings Category.
|
||||||
* Contains all Browse settings.
|
* Contains all Browse settings.
|
||||||
*
|
*
|
||||||
* @param state [MainState] instance.
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param topPadding Top padding to be applied.
|
* @param topPadding Top padding to be applied.
|
||||||
* @param bottomPadding Bottom padding to be applied.
|
* @param bottomPadding Bottom padding to be applied.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseSettingsCategory(
|
fun LazyListScope.BrowseSettingsCategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
topPadding: Dp = 16.dp,
|
topPadding: Dp = 16.dp,
|
||||||
bottomPadding: Dp = 48.dp
|
bottomPadding: Dp = 48.dp
|
||||||
) {
|
) {
|
||||||
BrowseGeneralSubcategory(
|
BrowseGeneralSubcategory(
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
topPadding = topPadding,
|
topPadding = topPadding,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
BrowseFilterSubcategory(
|
BrowseFilterSubcategory(
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
BrowseSortSubcategory(
|
BrowseSortSubcategory(
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = bottomPadding
|
bottomPadding = bottomPadding
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
||||||
|
|
||||||
|
|
@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
|
||||||
* Lets user choose between all and folders structure for Browse.
|
* Lets user choose between all and folders structure for Browse.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseFilesStructureSetting(
|
fun BrowseFilesStructureSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.browse_files_structure_option),
|
title = stringResource(id = R.string.browse_files_structure_option),
|
||||||
buttons = BrowseFilesStructure.entries.map {
|
buttons = BrowseFilesStructure.entries.map {
|
||||||
|
|
|
||||||
|
|
@ -13,25 +13,24 @@ import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.domain.util.Constants
|
import ua.acclorite.book_story.domain.util.Constants
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browse Filter setting.
|
* Browse Filter setting.
|
||||||
* Lets user choose which items to filter in Browse.
|
* Lets user choose which items to filter in Browse.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseFilterSetting(
|
fun LazyListScope.BrowseFilterSetting() {
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit
|
|
||||||
) {
|
|
||||||
customItems(Constants.EXTENSIONS, key = { it }) {
|
customItems(Constants.EXTENSIONS, key = { it }) {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
|
|
||||||
FilterItem(
|
FilterItem(
|
||||||
item = it,
|
item = it,
|
||||||
isSelected = state.value.browseIncludedFilterItems.any { item ->
|
isSelected = state.value.browseIncludedFilterItems.any { item ->
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SliderWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
|
|
@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
* Lets user specify grid size to be displayed.
|
* Lets user specify grid size to be displayed.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseGridSizeSetting(
|
fun BrowseGridSizeSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) {
|
ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) {
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.browseGridSize
|
value = state.value.browseGridSize
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
|
||||||
|
|
||||||
|
|
@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
|
||||||
* Lets user choose between layouts(list, grid).
|
* Lets user choose between layouts(list, grid).
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowseLayoutSetting(
|
fun BrowseLayoutSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SegmentedButtonWithTitle(
|
SegmentedButtonWithTitle(
|
||||||
title = stringResource(id = R.string.browse_layout_option),
|
title = stringResource(id = R.string.browse_layout_option),
|
||||||
buttons = BrowseLayout.entries.map {
|
buttons = BrowseLayout.entries.map {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SwitchWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
|
||||||
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
|
|
@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
|
||||||
* If true, shows all favorite directories in root directory and moves them to the top in nested directories.
|
* If true, shows all favorite directories in root directory and moves them to the top in nested directories.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun BrowsePinFavoriteDirectoriesSetting(
|
fun BrowsePinFavoriteDirectoriesSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) {
|
ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) {
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.browsePinFavoriteDirectories,
|
selected = state.value.browsePinFavoriteDirectories,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
@ -25,20 +24,20 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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.presentation.components.LocalMainViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.customItems
|
import ua.acclorite.book_story.presentation.components.customItems
|
||||||
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.screens.settings.nested.browse.data.BrowseSortOrder
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseSortOrder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browse Sort Order setting.
|
* Browse Sort Order setting.
|
||||||
* Lets user choose how to sort files in Browse.
|
* Lets user choose how to sort files in Browse.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseSortOrderSetting(
|
fun LazyListScope.BrowseSortOrderSetting() {
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit
|
|
||||||
) {
|
|
||||||
customItems(BrowseSortOrder.entries, key = { it.name }) {
|
customItems(BrowseSortOrder.entries, key = { it.name }) {
|
||||||
|
val state = LocalMainViewModel.current.state
|
||||||
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
|
|
||||||
SortItem(
|
SortItem(
|
||||||
item = it,
|
item = it,
|
||||||
isSelected = state.value.browseSortOrder == it,
|
isSelected = state.value.browseSortOrder == it,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
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.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilterSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilterSetting
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -26,8 +23,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
|
||||||
* Contains all settings from Filter Browse settings.
|
* Contains all settings from Filter Browse settings.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseFilterSubcategory(
|
fun LazyListScope.BrowseFilterSubcategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
title: @Composable () -> String = { stringResource(id = R.string.filter_browse_settings) },
|
title: @Composable () -> String = { stringResource(id = R.string.filter_browse_settings) },
|
||||||
showTitle: Boolean = true,
|
showTitle: Boolean = true,
|
||||||
|
|
@ -52,10 +47,7 @@ fun LazyListScope.BrowseFilterSubcategory(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowseFilterSetting(
|
BrowseFilterSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Spacer(
|
Spacer(
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
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.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilesStructureSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilesStructureSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseGridSizeSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseGridSizeSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseLayoutSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseLayoutSetting
|
||||||
|
|
@ -29,8 +26,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
|
||||||
* Contains all settings from General Browse settings.
|
* Contains all settings from General Browse settings.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseGeneralSubcategory(
|
fun LazyListScope.BrowseGeneralSubcategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
title: @Composable () -> String = { stringResource(id = R.string.general_browse_settings) },
|
title: @Composable () -> String = { stringResource(id = R.string.general_browse_settings) },
|
||||||
showTitle: Boolean = true,
|
showTitle: Boolean = true,
|
||||||
|
|
@ -56,31 +51,19 @@ fun LazyListScope.BrowseGeneralSubcategory(
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
BrowseFilesStructureSetting(
|
BrowseFilesStructureSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
BrowsePinFavoriteDirectoriesSetting(
|
BrowsePinFavoriteDirectoriesSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
BrowseLayoutSetting(
|
BrowseLayoutSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
BrowseGridSizeSetting(
|
BrowseGridSizeSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast
|
||||||
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.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseSortOrderSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseSortOrderSetting
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -26,8 +23,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
|
||||||
* Contains all settings from Sort Browse settings.
|
* Contains all settings from Sort Browse settings.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.BrowseSortSubcategory(
|
fun LazyListScope.BrowseSortSubcategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
title: @Composable () -> String = { stringResource(id = R.string.sort_browse_settings) },
|
title: @Composable () -> String = { stringResource(id = R.string.sort_browse_settings) },
|
||||||
showTitle: Boolean = true,
|
showTitle: Boolean = true,
|
||||||
|
|
@ -52,10 +47,7 @@ fun LazyListScope.BrowseSortSubcategory(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowseSortOrderSetting(
|
BrowseSortOrderSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Spacer(
|
Spacer(
|
||||||
|
|
|
||||||
|
|
@ -12,50 +12,26 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.GeneralSettingsCategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.GeneralSettingsCategory
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GeneralSettingsRoot() {
|
fun GeneralSettingsRoot() {
|
||||||
val navigator = LocalNavigator.current
|
GeneralSettings()
|
||||||
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
GeneralSettings(
|
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onSettingsEvent = settingsViewModel::onEvent,
|
|
||||||
onMainEvent = mainViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun GeneralSettings(
|
private fun GeneralSettings() {
|
||||||
state: State<MainState>,
|
val onNavigate = LocalOnNavigate.current
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
onMainEvent: (MainEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -86,11 +62,7 @@ private fun GeneralSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
GeneralSettingsCategory(
|
GeneralSettingsCategory()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.coerceAtLeast
|
import androidx.compose.ui.unit.coerceAtLeast
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.AppLanguageSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.AppLanguageSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.CheckForUpdatesSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.CheckForUpdatesSetting
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.DoublePressExitSetting
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.DoublePressExitSetting
|
||||||
|
|
@ -21,16 +17,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.general.comp
|
||||||
* General Settings Category.
|
* General Settings Category.
|
||||||
* Contains all General settings such as App Language.
|
* Contains all General settings such as App Language.
|
||||||
*
|
*
|
||||||
* @param state [MainState] instance.
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param onSettingsEvent [SettingsEvent] callback.
|
|
||||||
* @param topPadding Top padding to be applied.
|
* @param topPadding Top padding to be applied.
|
||||||
* @param bottomPadding Bottom padding to be applied.
|
* @param bottomPadding Bottom padding to be applied.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.GeneralSettingsCategory(
|
fun LazyListScope.GeneralSettingsCategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit,
|
|
||||||
topPadding: Dp = 16.dp,
|
topPadding: Dp = 16.dp,
|
||||||
bottomPadding: Dp = 48.dp
|
bottomPadding: Dp = 48.dp
|
||||||
) {
|
) {
|
||||||
|
|
@ -41,25 +31,15 @@ fun LazyListScope.GeneralSettingsCategory(
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
AppLanguageSetting(
|
AppLanguageSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
CheckForUpdatesSetting(
|
CheckForUpdatesSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
onSettingsEvent = onSettingsEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
DoublePressExitSetting(
|
DoublePressExitSetting()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,12 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.ChipsWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit
|
||||||
* Changes app's language.
|
* Changes app's language.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AppLanguageSetting(
|
fun AppLanguageSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.language_option),
|
title = stringResource(id = R.string.language_option),
|
||||||
chips = Constants.LANGUAGES.sortedBy { it.second }.map {
|
chips = Constants.LANGUAGES.sortedBy { it.second }.map {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Security
|
import androidx.compose.material.icons.filled.Security
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
@ -14,9 +13,10 @@ import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel
|
||||||
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent
|
||||||
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.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
|
||||||
|
|
||||||
|
|
@ -27,12 +27,12 @@ import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
@Composable
|
@Composable
|
||||||
fun CheckForUpdatesSetting(
|
fun CheckForUpdatesSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
onSettingsEvent: (SettingsEvent) -> Unit
|
val onSettingsEvent = LocalSettingsViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val activity = LocalContext.current as ComponentActivity
|
val activity = LocalContext.current as ComponentActivity
|
||||||
|
|
||||||
val notificationsPermissionState = rememberPermissionState(
|
val notificationsPermissionState = rememberPermissionState(
|
||||||
permission = Manifest.permission.POST_NOTIFICATIONS
|
permission = Manifest.permission.POST_NOTIFICATIONS
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SwitchWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
|
||||||
*/
|
*/
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
@Composable
|
@Composable
|
||||||
fun DoublePressExitSetting(
|
fun DoublePressExitSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.doublePressExit,
|
selected = state.value.doublePressExit,
|
||||||
title = stringResource(id = R.string.double_press_exit_option),
|
title = stringResource(id = R.string.double_press_exit_option),
|
||||||
|
|
|
||||||
|
|
@ -12,44 +12,25 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.CustomLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomLazyColumn
|
||||||
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.LocalOnNavigate
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainViewModel
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderSettingsRoot() {
|
fun ReaderSettingsRoot() {
|
||||||
val navigator = LocalNavigator.current
|
ReaderSettings()
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
|
||||||
|
|
||||||
val state = mainViewModel.state.collectAsState()
|
|
||||||
|
|
||||||
ReaderSettings(
|
|
||||||
state = state,
|
|
||||||
onNavigate = { navigator.it() },
|
|
||||||
onMainEvent = mainViewModel::onEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReaderSettings(
|
private fun ReaderSettings() {
|
||||||
state: State<MainState>,
|
val onNavigate = LocalOnNavigate.current
|
||||||
onNavigate: OnNavigate,
|
|
||||||
onMainEvent: (MainEvent) -> Unit
|
|
||||||
) {
|
|
||||||
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -80,10 +61,7 @@ private fun ReaderSettings(
|
||||||
.padding(top = paddingValues.calculateTopPadding()),
|
.padding(top = paddingValues.calculateTopPadding()),
|
||||||
state = scrollState.second
|
state = scrollState.second
|
||||||
) {
|
) {
|
||||||
ReaderSettingsCategory(
|
ReaderSettingsCategory()
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,13 +5,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
import ua.acclorite.book_story.presentation.components.CategoryTitle
|
||||||
import ua.acclorite.book_story.presentation.data.MainEvent
|
|
||||||
import ua.acclorite.book_story.presentation.data.MainState
|
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.FontSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.FontSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TextSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TextSubcategory
|
||||||
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory
|
||||||
|
|
@ -20,36 +17,26 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo
|
||||||
* Reader Settings Category.
|
* Reader Settings Category.
|
||||||
* Contains all Reader settings.
|
* Contains all Reader settings.
|
||||||
*
|
*
|
||||||
* @param state [MainState] instance.
|
|
||||||
* @param onMainEvent [MainEvent] callback.
|
|
||||||
* @param titleColor Color that [CategoryTitle] has.
|
* @param titleColor Color that [CategoryTitle] has.
|
||||||
* @param topPadding Top padding to be applied.
|
* @param topPadding Top padding to be applied.
|
||||||
* @param bottomPadding Bottom padding to be applied.
|
* @param bottomPadding Bottom padding to be applied.
|
||||||
*/
|
*/
|
||||||
fun LazyListScope.ReaderSettingsCategory(
|
fun LazyListScope.ReaderSettingsCategory(
|
||||||
state: State<MainState>,
|
|
||||||
onMainEvent: (MainEvent) -> Unit,
|
|
||||||
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary },
|
||||||
topPadding: Dp = 16.dp,
|
topPadding: Dp = 16.dp,
|
||||||
bottomPadding: Dp = 48.dp
|
bottomPadding: Dp = 48.dp
|
||||||
) {
|
) {
|
||||||
FontSubcategory(
|
FontSubcategory(
|
||||||
state = state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = topPadding,
|
topPadding = topPadding,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
TextSubcategory(
|
TextSubcategory(
|
||||||
state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = 0.dp
|
bottomPadding = 0.dp
|
||||||
)
|
)
|
||||||
TranslatorSubcategory(
|
TranslatorSubcategory(
|
||||||
state,
|
|
||||||
onMainEvent = onMainEvent,
|
|
||||||
titleColor = titleColor,
|
titleColor = titleColor,
|
||||||
topPadding = 22.dp,
|
topPadding = 22.dp,
|
||||||
bottomPadding = bottomPadding
|
bottomPadding = bottomPadding
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SwitchWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
|
||||||
* Changes Reader's double click translation.
|
* Changes Reader's double click translation.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun DoubleClickTranslationSetting(
|
fun DoubleClickTranslationSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.doubleClickTranslation,
|
selected = state.value.doubleClickTranslation,
|
||||||
title = stringResource(id = R.string.double_click_translation_option),
|
title = stringResource(id = R.string.double_click_translation_option),
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,13 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.ChipsWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,10 +16,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit
|
||||||
* Changes Reader's font, uses fonts from [Constants.FONTS].
|
* Changes Reader's font, uses fonts from [Constants.FONTS].
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun FontFamilySetting(
|
fun FontFamilySetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
val fontFamily = remember(state.value.fontFamily) {
|
||||||
Constants.FONTS.find {
|
Constants.FONTS.find {
|
||||||
it.id == state.value.fontFamily
|
it.id == state.value.fontFamily
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SliderWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
|
||||||
* Changes Reader's font size.
|
* Changes Reader's font size.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun FontSizeSetting(
|
fun FontSizeSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.fontSize to "pt",
|
value = state.value.fontSize to "pt",
|
||||||
fromValue = 10,
|
fromValue = 10,
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,14 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
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.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SegmentedButtonWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -18,10 +17,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.Segmente
|
||||||
* Changes Reader's font style (Normal/Italic).
|
* Changes Reader's font style (Normal/Italic).
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun FontStyleSetting(
|
fun FontStyleSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
val fontFamily = remember(state.value.fontFamily) {
|
val fontFamily = remember(state.value.fontFamily) {
|
||||||
Constants.FONTS.find {
|
Constants.FONTS.find {
|
||||||
it.id == state.value.fontFamily
|
it.id == state.value.fontFamily
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SliderWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
|
||||||
* Changes Reader's letter spacing.
|
* Changes Reader's letter spacing.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun LetterSpacingSetting(
|
fun LetterSpacingSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.letterSpacing to "pt",
|
value = state.value.letterSpacing to "pt",
|
||||||
fromValue = -8,
|
fromValue = -8,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SliderWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
|
||||||
* Changes Reader's line height.
|
* Changes Reader's line height.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun LineHeightSetting(
|
fun LineHeightSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.lineHeight to "pt",
|
value = state.value.lineHeight to "pt",
|
||||||
fromValue = 1,
|
fromValue = 1,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SliderWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
|
||||||
* Changes Reader's paragraph height.
|
* Changes Reader's paragraph height.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ParagraphHeightSetting(
|
fun ParagraphHeightSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SliderWithTitle(
|
SliderWithTitle(
|
||||||
value = state.value.paragraphHeight to "pt",
|
value = state.value.paragraphHeight to "pt",
|
||||||
fromValue = 0,
|
fromValue = 0,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.presentation.components.LocalMainViewModel
|
||||||
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.screens.settings.components.SwitchWithTitle
|
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
|
||||||
* Changes Reader's paragraph indentation.
|
* Changes Reader's paragraph indentation.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ParagraphIndentationSetting(
|
fun ParagraphIndentationSetting() {
|
||||||
state: State<MainState>,
|
val state = LocalMainViewModel.current.state
|
||||||
onMainEvent: (MainEvent) -> Unit
|
val onMainEvent = LocalMainViewModel.current.onEvent
|
||||||
) {
|
|
||||||
SwitchWithTitle(
|
SwitchWithTitle(
|
||||||
selected = state.value.paragraphIndentation,
|
selected = state.value.paragraphIndentation,
|
||||||
title = stringResource(id = R.string.paragraph_indentation_option)
|
title = stringResource(id = R.string.paragraph_indentation_option)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue