🛠️ ViewModel accessing reformat

* Reformatted a way to get State and Event in Composables
This commit is contained in:
Acclorite 2024-10-16 23:10:35 +03:00
parent 119ff0b956
commit 4a31a916bf
112 changed files with 1154 additions and 1060 deletions

View file

@ -10,7 +10,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.ime
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
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
@ -18,12 +17,13 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager 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 androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.bottom_navigation_bar.BottomNavigationBar import ua.acclorite.book_story.presentation.core.components.bottom_navigation_bar.BottomNavigationBar
import ua.acclorite.book_story.presentation.core.components.custom_navigation_rail.CustomNavigationRail import ua.acclorite.book_story.presentation.core.components.custom_navigation_rail.CustomNavigationRail
import ua.acclorite.book_story.presentation.core.navigation.NavigationHost import ua.acclorite.book_story.presentation.core.navigation.NavigationHost
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.about.AboutScreenRoot import ua.acclorite.book_story.presentation.screens.about.AboutScreenRoot
import ua.acclorite.book_story.presentation.screens.about.nested.credits.CreditsScreenRoot import ua.acclorite.book_story.presentation.screens.about.nested.credits.CreditsScreenRoot
@ -76,7 +76,12 @@ class Activity : AppCompatActivity() {
} }
// Initializing all variables // Initializing all variables
mainViewModel.init(libraryViewModel, settingsViewModel) mainViewModel.onEvent(
MainEvent.OnInit(
libraryViewModelReady = libraryViewModel.isReady,
settingsViewModelReady = settingsViewModel.isReady
)
)
// Splash screen // Splash screen
installSplashScreen().apply { installSplashScreen().apply {
@ -90,8 +95,8 @@ class Activity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
setContent { setContent {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val isLoaded = mainViewModel.isReady.collectAsState() val isLoaded = mainViewModel.isReady.collectAsStateWithLifecycle()
val density = LocalDensity.current val density = LocalDensity.current
val imeInsets = WindowInsets.ime val imeInsets = WindowInsets.ime

View file

@ -1,91 +0,0 @@
package ua.acclorite.book_story.presentation.core.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.presentation.core.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>()

View file

@ -174,7 +174,7 @@ class Navigator @AssistedInject constructor(
* *
* @param screen [Screen]. * @param screen [Screen].
*/ */
fun putScreen(screen: Screen) { fun putScreen(screen: Screen) = viewModelScope.launch(Dispatchers.Main.immediate) {
var found = false var found = false
for ((index, arg) in screens.value.withIndex()) { for ((index, arg) in screens.value.withIndex()) {
@ -219,7 +219,7 @@ class Navigator @AssistedInject constructor(
screen: Screen, screen: Screen,
useBackAnimation: Boolean = false, useBackAnimation: Boolean = false,
saveInBackStack: Boolean = true saveInBackStack: Boolean = true
) = viewModelScope.launch(Dispatchers.Default) { ) = viewModelScope.launch(Dispatchers.Main.immediate) {
if (screen.getRoute() == currentScreen.value) { if (screen.getRoute() == currentScreen.value) {
return@launch return@launch
} }
@ -242,7 +242,7 @@ class Navigator @AssistedInject constructor(
*/ */
fun navigateBack( fun navigateBack(
useBackAnimation: Boolean = true useBackAnimation: Boolean = true
) = viewModelScope.launch(Dispatchers.Default) { ) = viewModelScope.launch(Dispatchers.Main.immediate) {
if (canGoBack()) { if (canGoBack()) {
savedStateHandle[USE_BACK_ANIM] = useBackAnimation savedStateHandle[USE_BACK_ANIM] = useBackAnimation
savedStateHandle[CURRENT_SCREEN] = backStack.value.last() savedStateHandle[CURRENT_SCREEN] = backStack.value.last()

View file

@ -1,9 +0,0 @@
package ua.acclorite.book_story.presentation.core.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)
}

View file

@ -20,7 +20,6 @@ fun Intent.launchActivity(
activity: ComponentActivity, activity: ComponentActivity,
createChooser: Boolean = false, createChooser: Boolean = false,
openInNewWindow: Boolean = true, openInNewWindow: Boolean = true,
success: (() -> Unit)? = null,
error: () -> Unit error: () -> Unit
) { ) {
val intent = if (createChooser) Intent.createChooser(this, "") else this val intent = if (createChooser) Intent.createChooser(this, "") else this
@ -35,8 +34,6 @@ fun Intent.launchActivity(
error() error()
return return
} }
success?.invoke()
} }
fun Float.calculateProgress(digits: Int): String { fun Float.calculateProgress(digits: Int): String {

View file

@ -0,0 +1,26 @@
package ua.acclorite.book_story.presentation.core.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.StateFlow
abstract class UiViewModel<S, E> : ViewModel() {
abstract val state: StateFlow<S>
abstract fun onEvent(event: E)
companion object {
@Composable
inline fun <reified V : UiViewModel<S, E>, S, E> getState(): State<S> {
return hiltViewModel<V>().state.collectAsStateWithLifecycle()
}
@Composable
inline fun <reified V : UiViewModel<S, E>, S, E> getEvent(): (E) -> Unit {
return hiltViewModel<V>()::onEvent
}
}
}

View file

@ -1,9 +1,15 @@
package ua.acclorite.book_story.presentation.data package ua.acclorite.book_story.presentation.data
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import kotlinx.coroutines.flow.StateFlow
@Immutable @Immutable
sealed class MainEvent { sealed class MainEvent {
data class OnInit(
val libraryViewModelReady: StateFlow<Boolean>,
val settingsViewModelReady: StateFlow<Boolean>
) : MainEvent()
data class OnChangeLanguage(val value: String) : MainEvent() data class OnChangeLanguage(val value: String) : MainEvent()
data class OnChangeTheme(val value: String) : MainEvent() data class OnChangeTheme(val value: String) : MainEvent()
data class OnChangeDarkTheme(val value: String) : MainEvent() data class OnChangeDarkTheme(val value: String) : MainEvent()

View file

@ -1,5 +1,6 @@
package ua.acclorite.book_story.presentation.data package ua.acclorite.book_story.presentation.data
import androidx.compose.runtime.Composable
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -12,16 +13,13 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage
import ua.acclorite.book_story.domain.use_case.data_store.GetAllSettings import ua.acclorite.book_story.domain.use_case.data_store.GetAllSettings
import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore
import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseFilesStructure
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseLayout import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseLayout
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseSortOrder import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseSortOrder
@ -42,7 +40,15 @@ 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
) : BaseViewModel<MainState, MainEvent>() { ) : UiViewModel<MainState, MainEvent>() {
companion object {
@Composable
fun getState() = getState<MainViewModel, MainState, MainEvent>()
@Composable
fun getEvent() = getEvent<MainViewModel, MainState, MainEvent>()
}
private val _isReady = MutableStateFlow(false) private val _isReady = MutableStateFlow(false)
val isReady = _isReady.asStateFlow() val isReady = _isReady.asStateFlow()
@ -56,9 +62,10 @@ class MainViewModel @Inject constructor(
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
override fun onEvent(event: MainEvent) { override fun onEvent(event: MainEvent) {
viewModelScope.launch(Dispatchers.IO) {
when (event) { when (event) {
is MainEvent.OnChangeLanguage -> handleLanguageUpdate(event.value) is MainEvent.OnInit -> init(event)
is MainEvent.OnChangeLanguage -> handleLanguageUpdate(event)
is MainEvent.OnChangeDarkTheme -> handleDatastoreUpdate( is MainEvent.OnChangeDarkTheme -> handleDatastoreUpdate(
key = DataStoreConstants.DARK_THEME, key = DataStoreConstants.DARK_THEME,
@ -240,7 +247,7 @@ class MainViewModel @Inject constructor(
) )
is MainEvent.OnChangeBrowseIncludedFilterItem -> handleBrowseIncludedFilterItemUpdate( is MainEvent.OnChangeBrowseIncludedFilterItem -> handleBrowseIncludedFilterItemUpdate(
event.value event
) )
is MainEvent.OnChangeTextAlignment -> handleDatastoreUpdate( is MainEvent.OnChangeTextAlignment -> handleDatastoreUpdate(
@ -364,12 +371,8 @@ class MainViewModel @Inject constructor(
) )
} }
} }
}
fun init( private fun init(event: MainEvent.OnInit) {
libraryViewModel: LibraryViewModel,
settingsViewModel: SettingsViewModel,
) {
viewModelScope.launch(Dispatchers.Main) { viewModelScope.launch(Dispatchers.Main) {
val settings = getAllSettings.execute() val settings = getAllSettings.execute()
@ -391,8 +394,8 @@ class MainViewModel @Inject constructor(
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
combine( combine(
libraryViewModel.isReady, event.libraryViewModelReady,
settingsViewModel.isReady event.settingsViewModelReady
) { (libraryViewModelReady, settingsViewModelReady) -> ) { (libraryViewModelReady, settingsViewModelReady) ->
libraryViewModelReady && settingsViewModelReady libraryViewModelReady && settingsViewModelReady
}.collectLatest { ready -> }.collectLatest { ready ->
@ -421,19 +424,21 @@ class MainViewModel @Inject constructor(
} }
} }
private suspend fun handleLanguageUpdate(value: String) { private fun handleLanguageUpdate(event: MainEvent.OnChangeLanguage) {
withContext(Dispatchers.Main) { viewModelScope.launch(Dispatchers.Main) {
changeLanguage.execute(value) changeLanguage.execute(event.value)
updateStateWithSavedHandle { updateStateWithSavedHandle {
it.copy(language = value) it.copy(language = event.value)
} }
} }
} }
private suspend fun handleBrowseIncludedFilterItemUpdate(value: String) { private fun handleBrowseIncludedFilterItemUpdate(
event: MainEvent.OnChangeBrowseIncludedFilterItem
) {
val set = _state.value.browseIncludedFilterItems.toMutableSet() val set = _state.value.browseIncludedFilterItems.toMutableSet()
if (!set.add(value)) { if (!set.add(event.value)) {
set.remove(value) set.remove(event.value)
} }
handleDatastoreUpdate( handleDatastoreUpdate(
key = DataStoreConstants.BROWSE_INCLUDED_FILTER_ITEMS, key = DataStoreConstants.BROWSE_INCLUDED_FILTER_ITEMS,
@ -444,6 +449,22 @@ class MainViewModel @Inject constructor(
) )
} }
/**
* Handles and updates Datastore.
*/
private fun <V> handleDatastoreUpdate(
key: Preferences.Key<V>,
value: V,
updateState: V.(MainState) -> MainState
) {
viewModelScope.launch(Dispatchers.IO) {
setDatastore.execute(key = key, value = value)
updateStateWithSavedHandle {
value.updateState(it)
}
}
}
/** /**
* Updates [MainState] along with [SavedStateHandle]. * Updates [MainState] along with [SavedStateHandle].
*/ */
@ -455,20 +476,4 @@ class MainViewModel @Inject constructor(
function(it) function(it)
} }
} }
/**
* Handles and updates Datastore.
*/
private suspend fun <V> handleDatastoreUpdate(
key: Preferences.Key<V>,
value: V,
updateState: V.(MainState) -> MainState
) {
withContext(Dispatchers.IO) {
setDatastore.execute(key = key, value = value)
updateStateWithSavedHandle {
value.updateState(it)
}
}
}
} }

View file

@ -30,7 +30,6 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalAboutViewModel
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
@ -40,6 +39,7 @@ 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.AboutViewModel
@Composable @Composable
fun AboutScreenRoot() { fun AboutScreenRoot() {
@ -49,8 +49,8 @@ fun AboutScreenRoot() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun AboutScreen() { private fun AboutScreen() {
val state = LocalAboutViewModel.current.state val state = AboutViewModel.getState()
val onEvent = LocalAboutViewModel.current.onEvent val onEvent = AboutViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -7,19 +7,19 @@ 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.core.components.LocalAboutViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
/** /**
* 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() {
val state = LocalAboutViewModel.current.state val state = AboutViewModel.getState()
val onEvent = LocalAboutViewModel.current.onEvent val onEvent = AboutViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val update = remember(state.value.showUpdateDialog) { val update = remember(state.value.showUpdateDialog) {

View file

@ -13,10 +13,10 @@ import androidx.compose.ui.platform.LocalContext
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.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.LocalAboutViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel
/** /**
* About Badges. * About Badges.
@ -26,7 +26,7 @@ import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent
*/ */
@Composable @Composable
fun AboutBadges(verticalPadding: Dp = 18.dp) { fun AboutBadges(verticalPadding: Dp = 18.dp) {
val onEvent = LocalAboutViewModel.current.onEvent val onEvent = AboutViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
Box( Box(

View file

@ -3,6 +3,7 @@ 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.compose.runtime.Composable
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
@ -11,14 +12,22 @@ 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.remote.CheckForUpdates import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.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,
) : BaseViewModel<AboutState, AboutEvent>() { ) : UiViewModel<AboutState, AboutEvent>() {
companion object {
@Composable
fun getState() = getState<AboutViewModel, AboutState, AboutEvent>()
@Composable
fun getEvent() = getEvent<AboutViewModel, AboutState, AboutEvent>()
}
private val _state = MutableStateFlow(AboutState()) private val _state = MutableStateFlow(AboutState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -91,11 +100,3 @@ class AboutViewModel @Inject constructor(
} }
} }
} }

View file

@ -20,12 +20,12 @@ import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalAboutViewModel
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent import ua.acclorite.book_story.presentation.screens.about.data.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
@ -36,7 +36,7 @@ fun CreditsScreenRoot() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun CreditsScreen() { private fun CreditsScreen() {
val onEvent = LocalAboutViewModel.current.onEvent val onEvent = AboutViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -36,27 +36,33 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalLicenseInfoViewModel
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.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 viewModel = LocalLicenseInfoViewModel.current.viewModel val onEvent = LicenseInfoViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init( onEvent(
LicenseInfoEvent.OnInit(
screen = screen, screen = screen,
onNavigate = onNavigate, navigateBack = {
onNavigate {
navigateBack()
}
},
context = context context = context
) )
)
} }
LicenseInfoScreen() LicenseInfoScreen()
@ -65,8 +71,8 @@ fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun LicenseInfoScreen() { private fun LicenseInfoScreen() {
val state = LocalLicenseInfoViewModel.current.state val state = LicenseInfoViewModel.getState()
val onEvent = LocalLicenseInfoViewModel.current.onEvent val onEvent = LicenseInfoViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current

View file

@ -2,9 +2,16 @@ package ua.acclorite.book_story.presentation.screens.about.nested.license_info.d
import android.content.Context import android.content.Context
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.presentation.core.navigation.Screen
@Immutable @Immutable
sealed class LicenseInfoEvent { sealed class LicenseInfoEvent {
data class OnInit(
val screen: Screen.About.LicenseInfo,
val navigateBack: () -> Unit,
val context: Context
) : LicenseInfoEvent()
data class OnOpenLicensePage( data class OnOpenLicensePage(
val page: String, val page: String,
val context: Context, val context: Context,

View file

@ -1,9 +1,9 @@
package ua.acclorite.book_story.presentation.screens.about.nested.license_info.data package ua.acclorite.book_story.presentation.screens.about.nested.license_info.data
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.compose.runtime.Composable
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
@ -13,24 +13,31 @@ 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.OnNavigate import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LicenseInfoViewModel @Inject constructor( class LicenseInfoViewModel @Inject constructor(
) : BaseViewModel<LicenseInfoState, LicenseInfoEvent>() { ) : UiViewModel<LicenseInfoState, LicenseInfoEvent>() {
companion object {
@Composable
fun getState() = getState<LicenseInfoViewModel, LicenseInfoState, LicenseInfoEvent>()
@Composable
fun getEvent() = getEvent<LicenseInfoViewModel, LicenseInfoState, LicenseInfoEvent>()
}
private val _state = MutableStateFlow(LicenseInfoState()) private val _state = MutableStateFlow(LicenseInfoState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
override fun onEvent(event: LicenseInfoEvent) { override fun onEvent(event: LicenseInfoEvent) {
when (event) { when (event) {
is LicenseInfoEvent.OnInit -> init(event)
is LicenseInfoEvent.OnOpenLicensePage -> { is LicenseInfoEvent.OnOpenLicensePage -> {
viewModelScope.launch {
val intent = Intent( val intent = Intent(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
Uri.parse(event.page) Uri.parse(event.page)
@ -42,22 +49,19 @@ class LicenseInfoViewModel @Inject constructor(
} }
} }
} }
}
fun init(screen: Screen.About.LicenseInfo, onNavigate: OnNavigate, context: Context) { private fun init(event: LicenseInfoEvent.OnInit) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
_state.update { _state.update {
it.copy(license = null) it.copy(license = null)
} }
val license = Libs.Builder().withContext(context).build().libraries.find { val license = Libs.Builder().withContext(event.context).build().libraries.find {
it.uniqueId == screen.licenseId it.uniqueId == event.screen.licenseId
} }
if (license == null) { if (license == null) {
onNavigate { event.navigateBack()
navigateBack()
}
return@launch return@launch
} }

View file

@ -28,19 +28,20 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalLicensesViewModel
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.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.LicensesEvent
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesViewModel
@Composable @Composable
fun LicensesScreenRoot() { fun LicensesScreenRoot() {
val viewModel = LocalLicensesViewModel.current.viewModel val onEvent = LicensesViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init(context) onEvent(LicensesEvent.OnInit(context = context))
} }
LicensesScreen() LicensesScreen()
@ -49,7 +50,7 @@ fun LicensesScreenRoot() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun LicensesScreen() { private fun LicensesScreen() {
val state = LocalLicensesViewModel.current.state val state = LicensesViewModel.getState()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState( val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState(

View file

@ -1,6 +1,11 @@
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 androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@Immutable @Immutable
sealed class LicensesEvent sealed class LicensesEvent {
data class OnInit(
val context: Context
) : LicensesEvent()
}

View file

@ -1,6 +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 androidx.compose.runtime.Composable
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
@ -11,20 +11,34 @@ 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.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LicensesViewModel @Inject constructor( class LicensesViewModel @Inject constructor(
) : BaseViewModel<LicensesState, LicensesEvent>() { ) : UiViewModel<LicensesState, LicensesEvent>() {
companion object {
@Composable
fun getState() = getState<LicensesViewModel, LicensesState, LicensesEvent>()
@Composable
fun getEvent() = getEvent<LicensesViewModel, LicensesState, LicensesEvent>()
}
private val _state = MutableStateFlow(LicensesState()) private val _state = MutableStateFlow(LicensesState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
override fun onEvent(event: LicensesEvent) {} override fun onEvent(event: LicensesEvent) {
viewModelScope.launch(Dispatchers.Main) {
when (event) {
is LicensesEvent.OnInit -> init(event)
}
}
}
fun init(context: Context) { private fun init(event: LicensesEvent.OnInit) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
if (_state.value.licenses.isNotEmpty()) { if (_state.value.licenses.isNotEmpty()) {
return@launch return@launch
@ -32,7 +46,7 @@ class LicensesViewModel @Inject constructor(
val licenses = Libs val licenses = Libs
.Builder() .Builder()
.withJson(context, R.raw.aboutlibraries) .withJson(event.context, R.raw.aboutlibraries)
.build() .build()
.libraries .libraries
.toList() .toList()

View file

@ -46,7 +46,6 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomSnackbar import ua.acclorite.book_story.presentation.core.components.CustomSnackbar
import ua.acclorite.book_story.presentation.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground
@ -61,22 +60,25 @@ import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.
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.BookInfoViewModel
@Composable @Composable
fun BookInfoScreenRoot(screen: Screen.BookInfo) { fun BookInfoScreenRoot(screen: Screen.BookInfo) {
val viewModel = LocalBookInfoViewModel.current.viewModel val onEvent = BookInfoViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
val snackbarState = remember { SnackbarHostState() } val snackbarState = remember { SnackbarHostState() }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init( onEvent(
BookInfoEvent.OnInit(
screen = screen, screen = screen,
snackbarState = snackbarState, snackbarState = snackbarState,
onNavigate = onNavigate, onNavigate = onNavigate,
context = context context = context
) )
)
} }
BookInfoScreen( BookInfoScreen(
@ -85,7 +87,7 @@ fun BookInfoScreenRoot(screen: Screen.BookInfo) {
DisposableEffect(Unit) { DisposableEffect(Unit) {
onDispose { onDispose {
viewModel.clearViewModel() onEvent(BookInfoEvent.OnClearViewModel)
} }
} }
} }
@ -94,8 +96,8 @@ fun BookInfoScreenRoot(screen: Screen.BookInfo) {
@Composable @Composable
private fun BookInfoScreen(snackbarState: SnackbarHostState) { private fun BookInfoScreen(snackbarState: SnackbarHostState) {
val context = LocalContext.current val context = LocalContext.current
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val listState = rememberLazyListState() val listState = rememberLazyListState()

View file

@ -22,17 +22,17 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
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.BookInfoViewModel
/** /**
* Description section. * Description section.
*/ */
@Composable @Composable
fun BookInfoDescriptionSection() { fun BookInfoDescriptionSection() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val descriptionFocusRequester = remember { FocusRequester() } val descriptionFocusRequester = remember { FocusRequester() }

View file

@ -36,17 +36,17 @@ 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.core.components.CustomCoverImage import ua.acclorite.book_story.presentation.core.components.CustomCoverImage
import ua.acclorite.book_story.presentation.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
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.BookInfoViewModel
/** /**
* BookInfo's Info section. * BookInfo's Info section.
*/ */
@Composable @Composable
fun BookInfoInfoSection() { fun BookInfoInfoSection() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val titleFocusRequester = remember { FocusRequester() } val titleFocusRequester = remember { FocusRequester() }
val authorFocusRequester = remember { FocusRequester() } val authorFocusRequester = remember { FocusRequester() }

View file

@ -11,10 +11,10 @@ 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.Position import ua.acclorite.book_story.domain.util.Position
import ua.acclorite.book_story.presentation.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
import ua.acclorite.book_story.presentation.core.navigation.NavigationItem import ua.acclorite.book_story.presentation.core.navigation.NavigationItem
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.BookInfoViewModel
/** /**
* Book Info More Bottom Sheet. * Book Info More Bottom Sheet.
@ -24,7 +24,7 @@ import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
*/ */
@Composable @Composable
fun BookInfoMoreBottomSheet(snackbarState: SnackbarHostState) { fun BookInfoMoreBottomSheet(snackbarState: SnackbarHostState) {
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
CustomBottomSheet( CustomBottomSheet(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),

View file

@ -18,15 +18,15 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
/** /**
* Statistic section. * Statistic section.
*/ */
@Composable @Composable
fun BookInfoStatisticSection() { fun BookInfoStatisticSection() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val progress by remember { val progress by remember {
derivedStateOf { derivedStateOf {

View file

@ -24,14 +24,14 @@ import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarDat
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
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.BookInfoViewModel
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.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
@ -47,10 +47,10 @@ fun BookInfoTopBar(
listState: LazyListState, listState: LazyListState,
snackbarState: SnackbarHostState snackbarState: SnackbarHostState
) { ) {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -18,24 +18,24 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BookInfoViewModel
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
/** /**
* 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.
*/ */
@Composable @Composable
fun BookInfoChangeCoverBottomSheet() { fun BookInfoChangeCoverBottomSheet() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onEvent = LocalBookInfoViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val photoPicker = rememberLauncherForActivityResult( val photoPicker = rememberLauncherForActivityResult(

View file

@ -10,10 +10,10 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BookInfoViewModel
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@ -24,8 +24,8 @@ import java.util.Locale
*/ */
@Composable @Composable
fun BookInfoDetailsBottomSheet() { fun BookInfoDetailsBottomSheet() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val pattern = remember { val pattern = remember {

View file

@ -7,13 +7,13 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.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.book_info.data.BookInfoViewModel
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
/** /**
* Confirm update dialog. * Confirm update dialog.
@ -23,9 +23,9 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
*/ */
@Composable @Composable
fun BookInfoConfirmUpdateDialog(snackbarHostState: SnackbarHostState) { fun BookInfoConfirmUpdateDialog(snackbarHostState: SnackbarHostState) {
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
CustomDialogWithContent( CustomDialogWithContent(

View file

@ -6,27 +6,27 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BookInfoViewModel
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.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
/** /**
* Delete dialog. Deletes current book. * Delete dialog. Deletes current book.
*/ */
@Composable @Composable
fun BookInfoDeleteDialog() { fun BookInfoDeleteDialog() {
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val onBrowseEvent = LocalBrowseViewModel.current.onEvent val onBrowseEvent = BrowseViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -10,16 +10,16 @@ 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.core.components.LocalBookInfoViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BookInfoViewModel
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
/** /**
* Move dialog. * Move dialog.
@ -27,10 +27,10 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
*/ */
@Composable @Composable
fun BookInfoMoveDialog() { fun BookInfoMoveDialog() {
val state = LocalBookInfoViewModel.current.state val state = BookInfoViewModel.getState()
val onEvent = LocalBookInfoViewModel.current.onEvent val onEvent = BookInfoViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -10,9 +10,19 @@ import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.domain.model.Chapter import ua.acclorite.book_story.domain.model.Chapter
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.core.navigation.Screen
@Immutable @Immutable
sealed class BookInfoEvent { sealed class BookInfoEvent {
data class OnInit(
val screen: Screen.BookInfo,
val snackbarState: SnackbarHostState,
val context: Context,
val onNavigate: OnNavigate
) : BookInfoEvent()
data object OnClearViewModel : BookInfoEvent()
data object OnShowHideChangeCoverBottomSheet : BookInfoEvent() data object OnShowHideChangeCoverBottomSheet : BookInfoEvent()
data object OnShowHideDetailsBottomSheet : BookInfoEvent() data object OnShowHideDetailsBottomSheet : BookInfoEvent()

View file

@ -4,12 +4,11 @@ package ua.acclorite.book_story.presentation.screens.book_info.data
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context
import android.content.Context.CLIPBOARD_SERVICE 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.SnackbarHostState
import androidx.compose.material3.SnackbarResult import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.Composable
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,11 +33,10 @@ import ua.acclorite.book_story.domain.use_case.book.UpdateBook
import ua.acclorite.book_story.domain.use_case.book.UpdateBookWithText import ua.acclorite.book_story.domain.use_case.book.UpdateBookWithText
import ua.acclorite.book_story.domain.use_case.book.UpdateCoverImageOfBook import ua.acclorite.book_story.domain.use_case.book.UpdateCoverImageOfBook
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.domain.util.OnNavigate
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -55,7 +53,15 @@ class BookInfoViewModel @Inject constructor(
private val canResetCover: CanResetCover, private val canResetCover: CanResetCover,
private val resetCoverImage: ResetCoverImage, private val resetCoverImage: ResetCoverImage,
private val checkForTextUpdate: CheckForTextUpdate, private val checkForTextUpdate: CheckForTextUpdate,
) : BaseViewModel<BookInfoState, BookInfoEvent>() { ) : UiViewModel<BookInfoState, BookInfoEvent>() {
companion object {
@Composable
fun getState() = getState<BookInfoViewModel, BookInfoState, BookInfoEvent>()
@Composable
fun getEvent() = getEvent<BookInfoViewModel, BookInfoState, BookInfoEvent>()
}
private val _state = MutableStateFlow(BookInfoState()) private val _state = MutableStateFlow(BookInfoState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -68,6 +74,10 @@ class BookInfoViewModel @Inject constructor(
override 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.OnInit -> init(event)
is BookInfoEvent.OnClearViewModel -> clearViewModel()
is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> { is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> {
_state.update { _state.update {
it.copy( it.copy(
@ -740,17 +750,12 @@ class BookInfoViewModel @Inject constructor(
} }
} }
fun init( private fun init(event: BookInfoEvent.OnInit) {
screen: Screen.BookInfo,
snackbarState: SnackbarHostState,
context: Context,
onNavigate: OnNavigate
) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val book = getBookById.execute(screen.bookId) val book = getBookById.execute(event.screen.bookId)
if (book == null) { if (book == null) {
onNavigate { event.onNavigate {
navigateBack() navigateBack()
} }
return@launch return@launch
@ -763,17 +768,17 @@ class BookInfoViewModel @Inject constructor(
} }
clear() clear()
if (screen.startUpdate) { if (event.screen.startUpdate) {
onEvent( onEvent(
BookInfoEvent.OnCheckForTextUpdate( BookInfoEvent.OnCheckForTextUpdate(
snackbarState = snackbarState, snackbarState = event.snackbarState,
context = context context = event.context
) )
) )
onNavigate { event.onNavigate {
putScreen( putScreen(
Screen.BookInfo( Screen.BookInfo(
screen.bookId, event.screen.bookId,
false false
) )
) )
@ -783,13 +788,7 @@ class BookInfoViewModel @Inject constructor(
} }
} }
private suspend fun clear() { private fun clearViewModel() {
eventJob.cancel()
eventJob.join()
eventJob = SupervisorJob()
}
fun clearViewModel() {
viewModelScope.launch(Dispatchers.Main) { viewModelScope.launch(Dispatchers.Main) {
_state.update { _state.update {
BookInfoState() BookInfoState()
@ -800,4 +799,10 @@ class BookInfoViewModel @Inject constructor(
eventJob = SupervisorJob() eventJob = SupervisorJob()
} }
} }
private suspend fun clear() {
eventJob.cancel()
eventJob.join()
eventJob = SupervisorJob()
}
} }

View file

@ -24,11 +24,10 @@ 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.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.browse.components.BrowseEmptyPlaceholder import ua.acclorite.book_story.presentation.screens.browse.components.BrowseEmptyPlaceholder
import ua.acclorite.book_story.presentation.screens.browse.components.BrowseStoragePermissionDialog import ua.acclorite.book_story.presentation.screens.browse.components.BrowseStoragePermissionDialog
import ua.acclorite.book_story.presentation.screens.browse.components.adding_dialog.BrowseAddingDialog import ua.acclorite.book_story.presentation.screens.browse.components.adding_dialog.BrowseAddingDialog
@ -36,16 +35,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.BrowseViewModel
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 state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val viewModel = LocalBrowseViewModel.current.viewModel
val permissionState = rememberPermissionState( val permissionState = rememberPermissionState(
permission = Manifest.permission.READ_EXTERNAL_STORAGE permission = Manifest.permission.READ_EXTERNAL_STORAGE
@ -55,7 +54,10 @@ fun BrowseScreenRoot() {
state.value.selectedDirectory state.value.selectedDirectory
) { ) {
derivedStateOf { derivedStateOf {
viewModel.filterList(mainState.value) BrowseViewModel.filterList(
browseState = state.value,
mainState = mainState.value
)
} }
} }
@ -72,7 +74,7 @@ fun BrowseScreenRoot() {
DisposableEffect(Unit) { DisposableEffect(Unit) {
onDispose { onDispose {
viewModel.clearViewModel() onEvent(BrowseEvent.OnClearViewModel)
} }
} }
} }
@ -86,9 +88,9 @@ private fun BrowseScreen(
permissionState: PermissionState, permissionState: PermissionState,
filteredFiles: List<SelectableFile> filteredFiles: List<SelectableFile>
) { ) {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -10,12 +10,12 @@ 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.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.core.components.is_messages.IsError import ua.acclorite.book_story.presentation.core.components.is_messages.IsError
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.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.ui.Transitions import ua.acclorite.book_story.presentation.ui.Transitions
/** /**
@ -31,8 +31,8 @@ fun BoxScope.BrowseEmptyPlaceholder(
isFilesEmpty: Boolean, isFilesEmpty: Boolean,
storagePermissionState: PermissionState storagePermissionState: PermissionState
) { ) {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
CustomAnimatedVisibility( CustomAnimatedVisibility(

View file

@ -9,9 +9,9 @@ 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.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
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
/** /**
* Storage permission dialog. * Storage permission dialog.
@ -24,7 +24,7 @@ fun BrowseStoragePermissionDialog(
permissionState: PermissionState permissionState: PermissionState
) { ) {
val activity = LocalContext.current as ComponentActivity val activity = LocalContext.current as ComponentActivity
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
CustomDialogWithContent( CustomDialogWithContent(
title = stringResource(id = R.string.storage_permission), title = stringResource(id = R.string.storage_permission),

View file

@ -18,13 +18,13 @@ 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.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BrowseViewModel
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 java.util.UUID import java.util.UUID
/** /**
@ -34,9 +34,9 @@ import java.util.UUID
@Composable @Composable
fun BrowseAddingDialog() { fun BrowseAddingDialog() {
val context = LocalContext.current val context = LocalContext.current
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
CustomDialogWithLazyColumn( CustomDialogWithLazyColumn(

View file

@ -10,9 +10,9 @@ import androidx.compose.runtime.LaunchedEffect
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.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
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.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,8 +23,8 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo
*/ */
@Composable @Composable
fun BrowseFilterBottomSheet() { fun BrowseFilterBottomSheet() {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val pagerState = rememberPagerState(state.value.currentPage) { 3 } val pagerState = rememberPagerState(state.value.currentPage) { 3 }

View file

@ -2,7 +2,7 @@ package ua.acclorite.book_story.presentation.screens.browse.components.layout
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
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.settings.nested.browse.data.BrowseLayout import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout
@ -23,7 +23,7 @@ fun BrowseLayout(
onFavoriteItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit onItemClick: (SelectableFile) -> Unit
) { ) {
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
when (mainState.value.browseLayout) { when (mainState.value.browseLayout) {
BrowseLayout.LIST -> { BrowseLayout.LIST -> {

View file

@ -11,9 +11,9 @@ import androidx.compose.runtime.Composable
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.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.header import ua.acclorite.book_story.presentation.core.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.BrowseViewModel
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
@ -25,7 +25,7 @@ fun BrowseGridLayout(
onFavoriteItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit,
) { ) {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
LazyVerticalGrid( LazyVerticalGrid(
columns = if (autoGridSize) GridCells.Adaptive(170.dp) columns = if (autoGridSize) GridCells.Adaptive(170.dp)

View file

@ -9,8 +9,8 @@ import androidx.compose.runtime.Composable
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.core.components.LocalBrowseViewModel
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.BrowseViewModel
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
@ -20,7 +20,7 @@ fun BrowseListLayout(
onFavoriteItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit,
onItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit,
) { ) {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
LazyColumn( LazyColumn(
state = state.value.listState, state = state.value.listState,

View file

@ -29,10 +29,10 @@ import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
import ua.acclorite.book_story.presentation.data.MainViewModel
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.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
@ -44,9 +44,9 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun BrowseTopBar(filteredFiles: List<SelectableFile>) { fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
val selectedDirectoryName = remember { val selectedDirectoryName = remember {

View file

@ -27,18 +27,18 @@ 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.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.data.MainViewModel
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.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() {
val state = LocalBrowseViewModel.current.state val state = BrowseViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalBrowseViewModel.current.onEvent val onEvent = BrowseViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val rootDirectory = remember { val rootDirectory = remember {

View file

@ -16,6 +16,8 @@ import java.io.File
@Immutable @Immutable
sealed class BrowseEvent { sealed class BrowseEvent {
data object OnClearViewModel : BrowseEvent()
data class OnStoragePermissionRequest( data class OnStoragePermissionRequest(
val activity: ComponentActivity, val activity: ComponentActivity,
val storagePermissionState: PermissionState val storagePermissionState: PermissionState

View file

@ -9,6 +9,7 @@ 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.compose.runtime.Composable
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,7 +30,7 @@ import ua.acclorite.book_story.domain.use_case.favorite_directory.UpdateFavorite
import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile
import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
@ -43,7 +44,115 @@ 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,
) : BaseViewModel<BrowseState, BrowseEvent>() { ) : UiViewModel<BrowseState, BrowseEvent>() {
companion object {
@Composable
fun getState() = getState<BrowseViewModel, BrowseState, BrowseEvent>()
@Composable
fun getEvent() = getEvent<BrowseViewModel, BrowseState, BrowseEvent>()
fun filterList(browseState: BrowseState, mainState: MainState): List<SelectableFile> {
fun <T> thenCompareBy(
selector: (T) -> Comparable<*>?
): Comparator<T> {
return if (mainState.browseSortOrderDescending) {
compareByDescending(selector)
} else {
compareBy(selector)
}
}
fun List<SelectableFile>.filterFiles(): List<SelectableFile> {
if (mainState.browseIncludedFilterItems.isEmpty()) {
return this
}
return filter { file ->
when (file.isDirectory) {
true -> {
return@filter this.filter {
if (file == it) {
return@filter false
}
it.fileOrDirectory.path.startsWith(file.fileOrDirectory.path)
}.filterFiles().isNotEmpty()
}
false -> {
return@filter mainState.browseIncludedFilterItems.any {
file.fileOrDirectory.path.endsWith(
it, ignoreCase = true
)
}
}
}
}
}
return browseState.selectableFiles
.filterFiles()
.filter {
if (
browseState.hasSearched
|| mainState.browseFilesStructure == BrowseFilesStructure.ALL_FILES
) {
return@filter !it.isDirectory
}
if (
Environment.getExternalStorageDirectory() == browseState.selectedDirectory
&& it.isFavorite
&& mainState.browsePinFavoriteDirectories
) {
return@filter true
}
it.parentDirectory == browseState.selectedDirectory
}
.sortedWith(
compareByDescending<SelectableFile> {
when (mainState.browsePinFavoriteDirectories) {
true -> it.isFavorite
false -> true
}
}.then(
compareByDescending {
when (mainState.browseSortOrder != BrowseSortOrder.FILE_TYPE) {
true -> it.isDirectory
false -> true
}
}
).then(
thenCompareBy {
when (mainState.browseSortOrder) {
BrowseSortOrder.NAME -> {
it.fileOrDirectory.name.lowercase().trim()
}
BrowseSortOrder.FILE_TYPE -> {
it.isDirectory
}
BrowseSortOrder.FILE_FORMAT -> {
it.fileOrDirectory.extension
}
BrowseSortOrder.FILE_SIZE -> {
it.fileOrDirectory.length()
}
BrowseSortOrder.LAST_MODIFIED -> {
it.fileOrDirectory.lastModified()
}
}
}
)
)
}
}
private val _state = MutableStateFlow(BrowseState()) private val _state = MutableStateFlow(BrowseState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -69,6 +178,8 @@ class BrowseViewModel @Inject constructor(
override fun onEvent(event: BrowseEvent) { override fun onEvent(event: BrowseEvent) {
when (event) { when (event) {
is BrowseEvent.OnClearViewModel -> clearViewModel()
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
@ -605,104 +716,12 @@ class BrowseViewModel @Inject constructor(
} }
} }
fun filterList(mainState: MainState): List<SelectableFile> { private fun clearViewModel() {
fun <T> thenCompareBy( viewModelScope.launch(Dispatchers.Main) {
selector: (T) -> Comparable<*>? _state.update {
): Comparator<T> { it.copy(isError = false)
return if (mainState.browseSortOrderDescending) {
compareByDescending(selector)
} else {
compareBy(selector)
} }
} }
fun List<SelectableFile>.filterFiles(): List<SelectableFile> {
if (mainState.browseIncludedFilterItems.isEmpty()) {
return this
}
return filter { file ->
when (file.isDirectory) {
true -> {
return@filter this.filter {
if (file == it) {
return@filter false
}
it.fileOrDirectory.path.startsWith(file.fileOrDirectory.path)
}.filterFiles().isNotEmpty()
}
false -> {
return@filter mainState.browseIncludedFilterItems.any {
file.fileOrDirectory.path.endsWith(
it, ignoreCase = true
)
}
}
}
}
}
return _state.value.selectableFiles
.filterFiles()
.filter {
if (
_state.value.hasSearched
|| mainState.browseFilesStructure == BrowseFilesStructure.ALL_FILES
) {
return@filter !it.isDirectory
}
if (
Environment.getExternalStorageDirectory() == _state.value.selectedDirectory
&& it.isFavorite
&& mainState.browsePinFavoriteDirectories
) {
return@filter true
}
it.parentDirectory == _state.value.selectedDirectory
}
.sortedWith(
compareByDescending<SelectableFile> {
when (mainState.browsePinFavoriteDirectories) {
true -> it.isFavorite
false -> true
}
}.then(
compareByDescending {
when (mainState.browseSortOrder != BrowseSortOrder.FILE_TYPE) {
true -> it.isDirectory
false -> true
}
}
).then(
thenCompareBy {
when (mainState.browseSortOrder) {
BrowseSortOrder.NAME -> {
it.fileOrDirectory.name.lowercase().trim()
}
BrowseSortOrder.FILE_TYPE -> {
it.isDirectory
}
BrowseSortOrder.FILE_FORMAT -> {
it.fileOrDirectory.extension
}
BrowseSortOrder.FILE_SIZE -> {
it.fileOrDirectory.length()
}
BrowseSortOrder.LAST_MODIFIED -> {
it.fileOrDirectory.lastModified()
}
}
}
)
)
} }
private suspend fun getFilesFromDownloads( private suspend fun getFilesFromDownloads(
@ -721,12 +740,4 @@ class BrowseViewModel @Inject constructor(
} }
} }
} }
fun clearViewModel() {
viewModelScope.launch(Dispatchers.Main) {
_state.update {
it.copy(isError = false)
}
}
}
} }

View file

@ -32,26 +32,31 @@ import ua.acclorite.book_story.domain.util.Position
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.GoBackButton
import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHelpViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.LocalStartViewModel
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
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.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.HelpEvent
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 viewModel = LocalHelpViewModel.current.viewModel val onEvent = HelpViewModel.getEvent()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init(screen = screen) onEvent(
HelpEvent.OnInit(
screen = screen
)
)
} }
HelpScreen() HelpScreen()
@ -62,10 +67,10 @@ fun HelpScreenRoot(screen: Screen.Help) {
) )
@Composable @Composable
private fun HelpScreen() { private fun HelpScreen() {
val state = LocalHelpViewModel.current.state val state = HelpViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val onBrowseEvent = LocalBrowseViewModel.current.onEvent val onBrowseEvent = BrowseViewModel.getEvent()
val onStartEvent = LocalStartViewModel.current.onEvent val onStartEvent = StartViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()

View file

@ -1,6 +1,11 @@
package ua.acclorite.book_story.presentation.screens.help.data package ua.acclorite.book_story.presentation.screens.help.data
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.presentation.core.navigation.Screen
@Immutable @Immutable
sealed class HelpEvent sealed class HelpEvent {
data class OnInit(
val screen: Screen.Help
) : HelpEvent()
}

View file

@ -1,32 +1,40 @@
package ua.acclorite.book_story.presentation.screens.help.data package ua.acclorite.book_story.presentation.screens.help.data
import androidx.lifecycle.viewModelScope import androidx.compose.runtime.Composable
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 ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class HelpViewModel @Inject constructor( class HelpViewModel @Inject constructor(
) : BaseViewModel<HelpState, HelpEvent>() { ) : UiViewModel<HelpState, HelpEvent>() {
companion object {
@Composable
fun getState() = getState<HelpViewModel, HelpState, HelpEvent>()
@Composable
fun getEvent() = getEvent<HelpViewModel, HelpState, HelpEvent>()
}
private val _state = MutableStateFlow(HelpState()) private val _state = MutableStateFlow(HelpState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
override fun onEvent(event: HelpEvent) {} override fun onEvent(event: HelpEvent) {
when (event) {
is HelpEvent.OnInit -> init(event)
}
}
fun init(screen: Screen.Help) { private fun init(event: HelpEvent.OnInit) {
viewModelScope.launch {
_state.update { _state.update {
it.copy( it.copy(
fromStart = screen.fromStart fromStart = event.screen.fromStart
) )
} }
} }
}
} }

View file

@ -43,8 +43,6 @@ import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibi
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.core.components.CustomSnackbar import ua.acclorite.book_story.presentation.core.components.CustomSnackbar
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
@ -52,13 +50,15 @@ import ua.acclorite.book_story.presentation.core.navigation.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.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 onEvent = LocalHistoryViewModel.current.onEvent val onEvent = HistoryViewModel.getEvent()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
onEvent(HistoryEvent.OnUpdateScrollOffset) onEvent(HistoryEvent.OnUpdateScrollOffset)
@ -74,9 +74,9 @@ fun HistoryScreenRoot() {
@Composable @Composable
private fun HistoryScreen() { private fun HistoryScreen() {
val context = LocalContext.current val context = LocalContext.current
val state = LocalHistoryViewModel.current.state val state = HistoryViewModel.getState()
val onEvent = LocalHistoryViewModel.current.onEvent val onEvent = HistoryViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val refreshState = rememberPullRefreshState( val refreshState = rememberPullRefreshState(

View file

@ -6,12 +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.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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
/** /**
* Delete whole history dialog. * Delete whole history dialog.
@ -19,8 +19,8 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
@Composable @Composable
fun HistoryDeleteWholeHistoryDialog() { fun HistoryDeleteWholeHistoryDialog() {
val context = LocalContext.current val context = LocalContext.current
val onEvent = LocalHistoryViewModel.current.onEvent val onEvent = HistoryViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
CustomDialogWithContent( CustomDialogWithContent(
title = stringResource(id = R.string.delete_history), title = stringResource(id = R.string.delete_history),

View file

@ -2,6 +2,7 @@ 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.compose.runtime.Composable
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,7 +22,7 @@ import ua.acclorite.book_story.domain.use_case.history.DeleteWholeHistory
import ua.acclorite.book_story.domain.use_case.history.GetHistory import ua.acclorite.book_story.domain.use_case.history.GetHistory
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
@ -35,7 +36,15 @@ 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
) : BaseViewModel<HistoryState, HistoryEvent>() { ) : UiViewModel<HistoryState, HistoryEvent>() {
companion object {
@Composable
fun getState() = getState<HistoryViewModel, HistoryState, HistoryEvent>()
@Composable
fun getEvent() = getEvent<HistoryViewModel, HistoryState, HistoryEvent>()
}
private val _state = MutableStateFlow(HistoryState()) private val _state = MutableStateFlow(HistoryState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -137,7 +146,7 @@ class HistoryViewModel @Inject constructor(
job2?.cancel() job2?.cancel()
event.snackbarState.currentSnackbarData?.dismiss() event.snackbarState.currentSnackbarData?.dismiss()
job2 = viewModelScope.launch(Dispatchers.IO) { job2 = launch(Dispatchers.IO) {
yield() yield()
delay(10000) delay(10000)
yield() yield()

View file

@ -47,25 +47,25 @@ 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.Selected import ua.acclorite.book_story.domain.util.Selected
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.header import ua.acclorite.book_story.presentation.core.components.header
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.data.MainViewModel
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.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 state = LocalLibraryViewModel.current.state val state = LibraryViewModel.getState()
val onEvent = LocalLibraryViewModel.current.onEvent val onEvent = LibraryViewModel.getEvent()
val pagerState = rememberPagerState( val pagerState = rememberPagerState(
initialPage = state.value.currentPage, initialPage = state.value.currentPage,
@ -99,9 +99,9 @@ private fun LibraryScreen(
pagerState: PagerState, pagerState: PagerState,
refreshState: PullRefreshState refreshState: PullRefreshState
) { ) {
val state = LocalLibraryViewModel.current.state val state = LibraryViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalLibraryViewModel.current.onEvent val onEvent = LibraryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
var isScrollInProgress by remember { mutableStateOf(false) } var isScrollInProgress by remember { mutableStateOf(false) }

View file

@ -35,9 +35,9 @@ import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
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
/** /**
* Library Top Bar. * Library Top Bar.
@ -48,8 +48,8 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun LibraryTopBar(pagerState: PagerState) { fun LibraryTopBar(pagerState: PagerState) {
val state = LocalLibraryViewModel.current.state val state = LibraryViewModel.getState()
val onEvent = LocalLibraryViewModel.current.onEvent val onEvent = LibraryViewModel.getEvent()
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
AnimatedTopAppBar( AnimatedTopAppBar(

View file

@ -6,14 +6,14 @@ 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.core.components.LocalBrowseViewModel
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.BrowseViewModel
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
/** /**
* Delete dialog. Deletes all selected books. * Delete dialog. Deletes all selected books.
@ -21,10 +21,10 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
@Composable @Composable
fun LibraryDeleteDialog() { fun LibraryDeleteDialog() {
val context = LocalContext.current val context = LocalContext.current
val state = LocalLibraryViewModel.current.state val state = LibraryViewModel.getState()
val onEvent = LocalLibraryViewModel.current.onEvent val onEvent = LibraryViewModel.getEvent()
val onBrowseEvent = LocalBrowseViewModel.current.onEvent val onBrowseEvent = BrowseViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
CustomDialogWithContent( CustomDialogWithContent(
title = stringResource(id = R.string.delete_books), title = stringResource(id = R.string.delete_books),

View file

@ -9,13 +9,13 @@ 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.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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
/** /**
* Move dialog. Moves all selected books to the selected category. * Move dialog. Moves all selected books to the selected category.
@ -23,9 +23,9 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
@Composable @Composable
fun LibraryMoveDialog(pagerState: PagerState) { fun LibraryMoveDialog(pagerState: PagerState) {
val context = LocalContext.current val context = LocalContext.current
val state = LocalLibraryViewModel.current.state val state = LibraryViewModel.getState()
val onEvent = LocalLibraryViewModel.current.onEvent val onEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
CustomDialogWithLazyColumn( CustomDialogWithLazyColumn(
title = stringResource(id = R.string.move_books), title = stringResource(id = R.string.move_books),

View file

@ -1,5 +1,6 @@
package ua.acclorite.book_story.presentation.screens.library.data package ua.acclorite.book_story.presentation.screens.library.data
import androidx.compose.runtime.Composable
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,7 +19,7 @@ import ua.acclorite.book_story.domain.use_case.book.GetBooks
import ua.acclorite.book_story.domain.use_case.book.UpdateBook import ua.acclorite.book_story.domain.use_case.book.UpdateBook
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
@ -28,7 +29,15 @@ class LibraryViewModel @Inject constructor(
private val updateBook: UpdateBook, private val updateBook: UpdateBook,
private val deleteBooks: DeleteBooks, private val deleteBooks: DeleteBooks,
private val insertHistory: InsertHistory private val insertHistory: InsertHistory
) : BaseViewModel<LibraryState, LibraryEvent>() { ) : UiViewModel<LibraryState, LibraryEvent>() {
companion object {
@Composable
fun getState() = getState<LibraryViewModel, LibraryState, LibraryEvent>()
@Composable
fun getEvent() = getEvent<LibraryViewModel, LibraryState, LibraryEvent>()
}
private val _state = MutableStateFlow(LibraryState()) private val _state = MutableStateFlow(LibraryState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -382,15 +391,3 @@ class LibraryViewModel @Inject constructor(
} }
} }
} }

View file

@ -61,19 +61,17 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Chapter import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomSelectionContainer import ua.acclorite.book_story.presentation.core.components.CustomSelectionContainer
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.components.LocalSettingsViewModel
import ua.acclorite.book_story.presentation.core.components.is_messages.IsError import ua.acclorite.book_story.presentation.core.components.is_messages.IsError
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.data.MainViewModel
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.ReaderChapter import ua.acclorite.book_story.presentation.screens.reader.components.ReaderChapter
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderChaptersDrawer import ua.acclorite.book_story.presentation.screens.reader.components.ReaderChaptersDrawer
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderPerceptionExpander import ua.acclorite.book_story.presentation.screens.reader.components.ReaderPerceptionExpander
@ -83,16 +81,17 @@ import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.Re
import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderTopBar import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderTopBar
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.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment
@Composable @Composable
fun ReaderScreenRoot(screen: Screen.Reader) { fun ReaderScreenRoot(screen: Screen.Reader) {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val viewModel = LocalReaderViewModel.current.viewModel
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
@ -110,9 +109,14 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
} }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.init( onEvent(
ReaderEvent.OnInit(
screen = screen, screen = screen,
onNavigate = onNavigate, navigateBack = {
onNavigate {
navigateBack()
}
},
fullscreenMode = mainState.value.fullscreen, fullscreenMode = mainState.value.fullscreen,
checkForTextUpdate = mainState.value.checkForTextUpdate, checkForTextUpdate = mainState.value.checkForTextUpdate,
checkForTextUpdateToast = { checkForTextUpdateToast = {
@ -133,6 +137,7 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
.showToast(context = context) .showToast(context = context)
} }
) )
)
} }
LaunchedEffect(canScroll) { LaunchedEffect(canScroll) {
if (!canScroll && !state.value.showMenu && !state.value.loading) { if (!canScroll && !state.value.showMenu && !state.value.loading) {
@ -164,10 +169,14 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
} }
} }
LaunchedEffect(lazyListState) { LaunchedEffect(lazyListState) {
viewModel.onUpdateProgress { onEvent(
ReaderEvent.OnUpdateProgress(
refreshList = {
onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onLibraryEvent(LibraryEvent.OnUpdateBook(it))
onHistoryEvent(HistoryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it))
} }
)
)
} }
DisposableEffect(mainState.value.screenOrientation) { DisposableEffect(mainState.value.screenOrientation) {
context.requestedOrientation = mainState.value.screenOrientation.code context.requestedOrientation = mainState.value.screenOrientation.code
@ -180,7 +189,7 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
DisposableEffect(Unit) { DisposableEffect(Unit) {
onDispose { onDispose {
viewModel.clearViewModel() onEvent(ReaderEvent.OnClearViewModel)
WindowCompat.getInsetsController( WindowCompat.getInsetsController(
context.window, context.window,
context.window.decorView context.window.decorView
@ -194,12 +203,12 @@ fun ReaderScreenRoot(screen: Screen.Reader) {
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable @Composable
private fun ReaderScreen(lazyListState: LazyListState) { private fun ReaderScreen(lazyListState: LazyListState) {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val settingsState = LocalSettingsViewModel.current.state val settingsState = SettingsViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current

View file

@ -11,16 +11,16 @@ 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.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawer import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawer
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerSelectableItem import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerSelectableItem
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerTitleItem import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerTitleItem
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
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.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
/** /**
* Reader Chapters Drawer. * Reader Chapters Drawer.
@ -28,10 +28,10 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
*/ */
@Composable @Composable
fun ReaderChaptersDrawer() { fun ReaderChaptersDrawer() {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
CustomModalDrawer( CustomModalDrawer(
show = state.value.showChaptersDrawer, show = state.value.showChaptersDrawer,

View file

@ -7,8 +7,8 @@ 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.core.components.LocalSettingsViewModel
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.SettingsViewModel
/** /**
* Reader Fast Color Preset Change. * Reader Fast Color Preset Change.
@ -24,7 +24,7 @@ fun Modifier.readerFastColorPresetChange(
isLoading: Boolean, isLoading: Boolean,
presetChanged: (UIText) -> Unit presetChanged: (UIText) -> Unit
): Modifier { ): Modifier {
val onSettingsEvent = LocalSettingsViewModel.current.onEvent val onSettingsEvent = SettingsViewModel.getEvent()
val offset = remember { mutableFloatStateOf(0f) } val offset = remember { mutableFloatStateOf(0f) }
return this.then( return this.then(

View file

@ -26,10 +26,10 @@ import androidx.compose.ui.unit.TextUnit
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.FontWithName import ua.acclorite.book_story.domain.model.FontWithName
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.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.reader.data.ReaderViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment
/** /**
@ -65,7 +65,7 @@ fun LazyItemScope.ReaderTextParagraph(
doubleClickTranslationEnabled: Boolean, doubleClickTranslationEnabled: Boolean,
toolbarHidden: Boolean toolbarHidden: Boolean
) { ) {
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
Column( Column(

View file

@ -7,10 +7,10 @@ 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.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
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.ReaderViewModel
/** /**
* Reader Update Dialog. * Reader Update Dialog.
@ -18,7 +18,7 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
*/ */
@Composable @Composable
fun ReaderUpdateDialog() { fun ReaderUpdateDialog() {
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current

View file

@ -31,14 +31,14 @@ 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.Direction import ua.acclorite.book_story.domain.util.Direction
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
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.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
import ua.acclorite.book_story.presentation.ui.Colors import ua.acclorite.book_story.presentation.ui.Colors
import ua.acclorite.book_story.presentation.ui.HorizontalExpandingTransition import ua.acclorite.book_story.presentation.ui.HorizontalExpandingTransition
@ -48,10 +48,10 @@ import ua.acclorite.book_story.presentation.ui.HorizontalExpandingTransition
*/ */
@Composable @Composable
fun ReaderBottomBar() { fun ReaderBottomBar() {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val bookProgress by remember { val bookProgress by remember {
derivedStateOf { derivedStateOf {
@ -168,10 +168,10 @@ fun ReaderBottomBar() {
*/ */
@Composable @Composable
private fun BottomBarSlider() { private fun BottomBarSlider() {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
Slider( Slider(
value = state.value.book.progress, value = state.value.book.progress,

View file

@ -38,18 +38,18 @@ import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.LocalHistoryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.data.MainViewModel
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.readerFastColorPresetChange import ua.acclorite.book_story.presentation.screens.reader.components.readerFastColorPresetChange
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.ReaderViewModel
import ua.acclorite.book_story.presentation.ui.Colors import ua.acclorite.book_story.presentation.ui.Colors
/** /**
@ -58,11 +58,11 @@ import ua.acclorite.book_story.presentation.ui.Colors
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ReaderTopBar() { fun ReaderTopBar() {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val onLibraryEvent = LocalLibraryViewModel.current.onEvent val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = LocalHistoryViewModel.current.onEvent val onHistoryEvent = HistoryViewModel.getEvent()
val context = LocalContext.current as ComponentActivity val context = LocalContext.current as ComponentActivity
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current

View file

@ -20,10 +20,10 @@ 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.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet
import ua.acclorite.book_story.presentation.data.MainViewModel
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.ReaderViewModel
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.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.MiscSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.MiscSubcategory
@ -39,9 +39,9 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ReaderSettingsBottomSheet() { fun ReaderSettingsBottomSheet() {
val state = LocalReaderViewModel.current.state val state = ReaderViewModel.getState()
val mainState = LocalMainViewModel.current.state val mainState = MainViewModel.getState()
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val pagerState = rememberPagerState(state.value.currentPage) { 3 } val pagerState = rememberPagerState(state.value.currentPage) { 3 }

View file

@ -4,9 +4,9 @@ import androidx.compose.foundation.pager.PagerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.components.LocalReaderViewModel
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheetTabRow import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheetTabRow
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.ReaderViewModel
/** /**
* Settings bottom sheet tab row. * Settings bottom sheet tab row.
@ -16,8 +16,7 @@ import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
*/ */
@Composable @Composable
fun ReaderSettingsBottomSheetTabRow(pagerState: PagerState) { fun ReaderSettingsBottomSheetTabRow(pagerState: PagerState) {
val onEvent = LocalReaderViewModel.current.onEvent val onEvent = ReaderViewModel.getEvent()
val tabItems = listOf( val tabItems = listOf(
stringResource(id = R.string.general_tab), stringResource(id = R.string.general_tab),
stringResource(id = R.string.reader_tab), stringResource(id = R.string.reader_tab),

View file

@ -6,9 +6,27 @@ import androidx.compose.runtime.Immutable
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
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.core.navigation.Screen
@Immutable @Immutable
sealed class ReaderEvent { sealed class ReaderEvent {
data class OnInit(
val screen: Screen.Reader,
val navigateBack: () -> Unit,
val fullscreenMode: Boolean,
val checkForTextUpdate: Boolean,
val checkForTextUpdateToast: () -> Unit,
val activity: ComponentActivity,
val refreshList: (Book) -> Unit,
val onError: (UIText) -> Unit
) : ReaderEvent()
data class OnUpdateProgress(
val refreshList: (Book) -> Unit
) : ReaderEvent()
data object OnClearViewModel : ReaderEvent()
data object OnTextIsEmpty : ReaderEvent() data object OnTextIsEmpty : ReaderEvent()
data class OnLoadText( data class OnLoadText(

View file

@ -4,6 +4,7 @@ import android.app.SearchManager
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.compose.runtime.Composable
import androidx.compose.runtime.snapshotFlow 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
@ -25,18 +26,16 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
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.Chapter import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.domain.use_case.book.CheckForTextUpdate import ua.acclorite.book_story.domain.use_case.book.CheckForTextUpdate
import ua.acclorite.book_story.domain.use_case.book.GetBookById import ua.acclorite.book_story.domain.use_case.book.GetBookById
import ua.acclorite.book_story.domain.use_case.book.GetText import ua.acclorite.book_story.domain.use_case.book.GetText
import ua.acclorite.book_story.domain.use_case.book.UpdateBook import ua.acclorite.book_story.domain.use_case.book.UpdateBook
import ua.acclorite.book_story.domain.use_case.history.GetLatestHistory import ua.acclorite.book_story.domain.use_case.history.GetLatestHistory
import ua.acclorite.book_story.domain.util.OnNavigate
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.coerceAndPreventNaN import ua.acclorite.book_story.presentation.core.util.coerceAndPreventNaN
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
@ -50,7 +49,15 @@ class ReaderViewModel @Inject constructor(
private val getLatestHistory: GetLatestHistory, private val getLatestHistory: GetLatestHistory,
private val getBookById: GetBookById, private val getBookById: GetBookById,
private val checkForTextUpdate: CheckForTextUpdate private val checkForTextUpdate: CheckForTextUpdate
) : BaseViewModel<ReaderState, ReaderEvent>() { ) : UiViewModel<ReaderState, ReaderEvent>() {
companion object {
@Composable
fun getState() = getState<ReaderViewModel, ReaderState, ReaderEvent>()
@Composable
fun getEvent() = getEvent<ReaderViewModel, ReaderState, ReaderEvent>()
}
private val _state = MutableStateFlow(ReaderState()) private val _state = MutableStateFlow(ReaderState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -62,6 +69,12 @@ class ReaderViewModel @Inject constructor(
override 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.OnInit -> init(event)
is ReaderEvent.OnUpdateProgress -> updateProgress(event)
is ReaderEvent.OnClearViewModel -> clearViewModel()
is ReaderEvent.OnTextIsEmpty -> { is ReaderEvent.OnTextIsEmpty -> {
_state.update { _state.update {
it.copy( it.copy(
@ -505,23 +518,12 @@ class ReaderViewModel @Inject constructor(
} }
} }
fun init( private fun init(event: ReaderEvent.OnInit) {
screen: Screen.Reader,
onNavigate: OnNavigate,
fullscreenMode: Boolean,
checkForTextUpdate: Boolean,
checkForTextUpdateToast: () -> Unit,
activity: ComponentActivity,
refreshList: (Book) -> Unit,
onError: (UIText) -> Unit
) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val book = getBookById.execute(screen.bookId) val book = getBookById.execute(event.screen.bookId)
if (book == null) { if (book == null) {
onNavigate { event.navigateBack()
navigateBack()
}
return@launch return@launch
} }
@ -530,13 +532,13 @@ class ReaderViewModel @Inject constructor(
} }
clear() clear()
withContext(Dispatchers.Default) { withContext(Dispatchers.Main) {
onEvent( onEvent(
ReaderEvent.OnShowHideMenu( ReaderEvent.OnShowHideMenu(
show = false, show = false,
fullscreenMode = fullscreenMode, fullscreenMode = event.fullscreenMode,
saveCheckpoint = false, saveCheckpoint = false,
activity = activity activity = event.activity
) )
) )
} }
@ -544,17 +546,17 @@ class ReaderViewModel @Inject constructor(
onEvent( onEvent(
ReaderEvent.OnLoadText( ReaderEvent.OnLoadText(
checkForUpdate = { checkForUpdate = {
if (checkForTextUpdate) { if (event.checkForTextUpdate) {
onEvent( onEvent(
ReaderEvent.OnCheckTextForUpdate { ReaderEvent.OnCheckTextForUpdate {
checkForTextUpdateToast() event.checkForTextUpdateToast()
} }
) )
} }
}, },
refreshList = { refreshList(it) }, refreshList = { event.refreshList(it) },
onError = { onError = {
onError(it) event.onError(it)
}, },
onTextIsEmpty = { onTextIsEmpty = {
onEvent(ReaderEvent.OnTextIsEmpty) onEvent(ReaderEvent.OnTextIsEmpty)
@ -565,7 +567,7 @@ class ReaderViewModel @Inject constructor(
} }
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
fun onUpdateProgress(refreshList: (Book) -> Unit) { private fun updateProgress(event: ReaderEvent.OnUpdateProgress) {
viewModelScope.launch(Dispatchers.Main) { viewModelScope.launch(Dispatchers.Main) {
snapshotFlow { snapshotFlow {
_state.value.listState.run { firstVisibleItemIndex to firstVisibleItemScrollOffset } _state.value.listState.run { firstVisibleItemIndex to firstVisibleItemScrollOffset }
@ -587,11 +589,23 @@ class ReaderViewModel @Inject constructor(
} }
updateBook.execute(_state.value.book) updateBook.execute(_state.value.book)
refreshList(_state.value.book) event.refreshList(_state.value.book)
} }
} }
} }
private fun clearViewModel() {
viewModelScope.launch(Dispatchers.Main) {
_state.update {
ReaderState()
}
eventJob.cancel()
eventJob.join()
eventJob = SupervisorJob()
}
}
private fun updateChapter(index: Int) { private fun updateChapter(index: Int) {
val (currentChapter, currentChapterProgress) = calculateCurrentChapter(index) val (currentChapter, currentChapterProgress) = calculateCurrentChapter(index)
_state.update { _state.update {
@ -664,16 +678,4 @@ class ReaderViewModel @Inject constructor(
eventJob.join() eventJob.join()
eventJob = SupervisorJob() eventJob = SupervisorJob()
} }
fun clearViewModel() {
viewModelScope.launch(Dispatchers.Main) {
_state.update {
ReaderState()
}
eventJob.cancel()
eventJob.join()
eventJob = SupervisorJob()
}
}
} }

View file

@ -3,6 +3,7 @@ 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.compose.runtime.Composable
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
@ -26,7 +27,7 @@ import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPreset
import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.ID
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.util.BaseViewModel import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
import kotlin.random.Random import kotlin.random.Random
@ -39,7 +40,15 @@ 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
) : BaseViewModel<SettingsState, SettingsEvent>() { ) : UiViewModel<SettingsState, SettingsEvent>() {
companion object {
@Composable
fun getState() = getState<SettingsViewModel, SettingsState, SettingsEvent>()
@Composable
fun getEvent() = getEvent<SettingsViewModel, SettingsState, SettingsEvent>()
}
private val _state = MutableStateFlow(SettingsState()) private val _state = MutableStateFlow(SettingsState())
override val state = _state.asStateFlow() override val state = _state.asStateFlow()
@ -169,7 +178,8 @@ class SettingsViewModel @Inject constructor(
selectedPresetIndex - 1 selectedPresetIndex - 1
} }
} }
val previousColorPreset = colorPresets.getOrNull(previousColorPresetIndex) val previousColorPreset =
colorPresets.getOrNull(previousColorPresetIndex)
?: return@launch ?: return@launch
yield() yield()
@ -290,7 +300,8 @@ class SettingsViewModel @Inject constructor(
return@launch return@launch
} }
val nextPosition = if (position == _state.value.colorPresets.lastIndex) { val nextPosition =
if (position == _state.value.colorPresets.lastIndex) {
position - 1 position - 1
} else { } else {
position position

View file

@ -4,8 +4,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.core.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.MainViewModel
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.ui.ExpandingTransition import ua.acclorite.book_story.presentation.ui.ExpandingTransition
import ua.acclorite.book_story.presentation.ui.isDark import ua.acclorite.book_story.presentation.ui.isDark
@ -17,8 +17,8 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
*/ */
@Composable @Composable
fun AbsoluteDarkSetting() { fun AbsoluteDarkSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
ExpandingTransition( ExpandingTransition(

View file

@ -63,9 +63,9 @@ import ua.acclorite.book_story.domain.util.Selected
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.CategoryTitle
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomIconButton
import ua.acclorite.book_story.presentation.core.components.LocalSettingsViewModel
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.SettingsViewModel
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
@ -80,8 +80,8 @@ fun ColorPresetSetting(
verticalPadding: Dp = 8.dp, verticalPadding: Dp = 8.dp,
horizontalPadding: Dp = 18.dp horizontalPadding: Dp = 18.dp
) { ) {
val state = LocalSettingsViewModel.current.state val state = SettingsViewModel.getState()
val onEvent = LocalSettingsViewModel.current.onEvent val onEvent = SettingsViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
val reorderableListState = rememberReorderableLazyListState( val reorderableListState = rememberReorderableLazyListState(

View file

@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +16,8 @@ import ua.acclorite.book_story.presentation.ui.DarkTheme
*/ */
@Composable @Composable
fun DarkThemeSetting() { fun DarkThemeSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SegmentedButtonWithTitle( SegmentedButtonWithTitle(
title = stringResource(id = R.string.dark_theme_option), title = stringResource(id = R.string.dark_theme_option),

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun FastColorPresetChangeSetting() { fun FastColorPresetChangeSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.fastColorPresetChange, selected = state.value.fastColorPresetChange,

View file

@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +18,8 @@ import ua.acclorite.book_story.presentation.ui.isDark
*/ */
@Composable @Composable
fun PureDarkSetting() { fun PureDarkSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ExpandingTransition(visible = state.value.darkTheme.isDark()) { ExpandingTransition(visible = state.value.darkTheme.isDark()) {
SegmentedButtonWithTitle( SegmentedButtonWithTitle(

View file

@ -9,8 +9,8 @@ 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.core.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.MainViewModel
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,8 +25,8 @@ import ua.acclorite.book_story.presentation.ui.isPureDark
*/ */
@Composable @Composable
fun ThemeContrastSetting() { fun ThemeContrastSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val themeContrastTheme = remember { mutableStateOf(state.value.theme) } val themeContrastTheme = remember { mutableStateOf(state.value.theme) }

View file

@ -41,9 +41,9 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.CategoryTitle
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
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.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
@ -59,8 +59,8 @@ fun ThemeSetting(
verticalPadding: Dp = 8.dp, verticalPadding: Dp = 8.dp,
horizontalPadding: Dp = 18.dp horizontalPadding: Dp = 18.dp
) { ) {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
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

View file

@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +16,8 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
*/ */
@Composable @Composable
fun BrowseFilesStructureSetting() { fun BrowseFilesStructureSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SegmentedButtonWithTitle( SegmentedButtonWithTitle(
title = stringResource(id = R.string.browse_files_structure_option), title = stringResource(id = R.string.browse_files_structure_option),

View file

@ -18,9 +18,9 @@ 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.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel
/** /**
* Browse Filter setting. * Browse Filter setting.
@ -28,8 +28,8 @@ import ua.acclorite.book_story.presentation.data.MainEvent
*/ */
fun LazyListScope.BrowseFilterSetting() { fun LazyListScope.BrowseFilterSetting() {
items(Constants.EXTENSIONS, key = { it }) { items(Constants.EXTENSIONS, key = { it }) {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
FilterItem( FilterItem(
item = it, item = it,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +15,8 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
*/ */
@Composable @Composable
fun BrowseGridSizeSetting() { fun BrowseGridSizeSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) { ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) {
SliderWithTitle( SliderWithTitle(

View file

@ -5,8 +5,8 @@ import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +16,8 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
*/ */
@Composable @Composable
fun BrowseLayoutSetting() { fun BrowseLayoutSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SegmentedButtonWithTitle( SegmentedButtonWithTitle(
title = stringResource(id = R.string.browse_layout_option), title = stringResource(id = R.string.browse_layout_option),

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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,8 +15,8 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
*/ */
@Composable @Composable
fun BrowsePinFavoriteDirectoriesSetting() { fun BrowsePinFavoriteDirectoriesSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) { ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) {
SwitchWithTitle( SwitchWithTitle(

View file

@ -25,8 +25,8 @@ 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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseSortOrder import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseSortOrder
/** /**
@ -35,8 +35,8 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.
*/ */
fun LazyListScope.BrowseSortOrderSetting() { fun LazyListScope.BrowseSortOrderSetting() {
items(BrowseSortOrder.entries, key = { it.name }) { items(BrowseSortOrder.entries, key = { it.name }) {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SortItem( SortItem(
item = it, item = it,

View file

@ -5,9 +5,9 @@ import androidx.compose.runtime.Composable
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.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
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.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
/** /**
@ -16,8 +16,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit
*/ */
@Composable @Composable
fun AppLanguageSetting() { fun AppLanguageSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ChipsWithTitle( ChipsWithTitle(
title = stringResource(id = R.string.language_option), title = stringResource(id = R.string.language_option),

View file

@ -13,12 +13,12 @@ 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.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.components.LocalSettingsViewModel
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.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.MainViewModel
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
import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel
/** /**
* Check For Updates setting. * Check For Updates setting.
@ -28,9 +28,9 @@ import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
@Composable @Composable
fun CheckForUpdatesSetting() { fun CheckForUpdatesSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val onSettingsEvent = LocalSettingsViewModel.current.onEvent val onSettingsEvent = SettingsViewModel.getEvent()
val activity = LocalContext.current as ComponentActivity val activity = LocalContext.current as ComponentActivity
val notificationsPermissionState = rememberPermissionState( val notificationsPermissionState = rememberPermissionState(

View file

@ -4,8 +4,8 @@ import android.annotation.SuppressLint
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -15,8 +15,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
@Composable @Composable
fun DoublePressExitSetting() { fun DoublePressExitSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.doublePressExit, selected = state.value.doublePressExit,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun CheckForTextUpdateSetting() { fun CheckForTextUpdateSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.checkForTextUpdate, selected = state.value.checkForTextUpdate,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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.ui.ExpandingTransition import ua.acclorite.book_story.presentation.ui.ExpandingTransition
@ -14,8 +14,8 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
*/ */
@Composable @Composable
fun CheckForTextUpdateToastSetting() { fun CheckForTextUpdateToastSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ExpandingTransition(visible = state.value.checkForTextUpdate) { ExpandingTransition(visible = state.value.checkForTextUpdate) {
SwitchWithTitle( SwitchWithTitle(

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun CutoutPaddingSetting() { fun CutoutPaddingSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.cutoutPadding, selected = state.value.cutoutPadding,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun DoubleClickTranslationSetting() { fun DoubleClickTranslationSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.doubleClickTranslation, selected = state.value.doubleClickTranslation,

View file

@ -6,9 +6,9 @@ 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.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
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.screens.settings.components.ChipsWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle
/** /**
@ -17,8 +17,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit
*/ */
@Composable @Composable
fun FontFamilySetting() { fun FontFamilySetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val fontFamily = remember(state.value.fontFamily) { val fontFamily = remember(state.value.fontFamily) {
Constants.FONTS.find { Constants.FONTS.find {

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun FontSizeSetting() { fun FontSizeSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.fontSize to "pt", value = state.value.fontSize to "pt",

View file

@ -7,9 +7,9 @@ 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.presentation.core.components.LocalMainViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
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.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle
/** /**
@ -18,8 +18,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.Segmente
*/ */
@Composable @Composable
fun FontStyleSetting() { fun FontStyleSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
val fontFamily = remember(state.value.fontFamily) { val fontFamily = remember(state.value.fontFamily) {
Constants.FONTS.find { Constants.FONTS.find {

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun FullscreenSetting() { fun FullscreenSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.fullscreen, selected = state.value.fullscreen,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun HideBarsOnFastScrollSetting() { fun HideBarsOnFastScrollSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.hideBarsOnFastScroll, selected = state.value.hideBarsOnFastScroll,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun KeepScreenOnSetting() { fun KeepScreenOnSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.keepScreenOn, selected = state.value.keepScreenOn,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun LetterSpacingSetting() { fun LetterSpacingSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.letterSpacing to "pt", value = state.value.letterSpacing to "pt",

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun LineHeightSetting() { fun LineHeightSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.lineHeight to "pt", value = state.value.lineHeight to "pt",

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun ParagraphHeightSetting() { fun ParagraphHeightSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.paragraphHeight to "pt", value = state.value.paragraphHeight to "pt",

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
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.reader.data.ReaderTextAlignment import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment
import ua.acclorite.book_story.presentation.ui.ExpandingTransition import ua.acclorite.book_story.presentation.ui.ExpandingTransition
@ -15,8 +15,8 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition
*/ */
@Composable @Composable
fun ParagraphIndentationSetting() { fun ParagraphIndentationSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
ExpandingTransition( ExpandingTransition(
visible = state.value.textAlignment != ReaderTextAlignment.CENTER && visible = state.value.textAlignment != ReaderTextAlignment.CENTER &&

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun PerceptionExpanderPaddingSetting() { fun PerceptionExpanderPaddingSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.perceptionExpanderPadding to "pt", value = state.value.perceptionExpanderPadding to "pt",

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi
*/ */
@Composable @Composable
fun PerceptionExpanderSetting() { fun PerceptionExpanderSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SwitchWithTitle( SwitchWithTitle(
selected = state.value.perceptionExpander, selected = state.value.perceptionExpander,

View file

@ -3,8 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.core.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.MainViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle
/** /**
@ -13,8 +13,8 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi
*/ */
@Composable @Composable
fun PerceptionExpanderThicknessSetting() { fun PerceptionExpanderThicknessSetting() {
val state = LocalMainViewModel.current.state val state = MainViewModel.getState()
val onMainEvent = LocalMainViewModel.current.onEvent val onMainEvent = MainViewModel.getEvent()
SliderWithTitle( SliderWithTitle(
value = state.value.perceptionExpanderThickness to "pt", value = state.value.perceptionExpanderThickness to "pt",

Some files were not shown because too many files have changed in this diff Show more