diff --git a/app/src/main/java/ua/acclorite/book_story/Activity.kt b/app/src/main/java/ua/acclorite/book_story/Activity.kt index 24d595eb..894ced5b 100644 --- a/app/src/main/java/ua/acclorite/book_story/Activity.kt +++ b/app/src/main/java/ua/acclorite/book_story/Activity.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat import dagger.hilt.android.AndroidEntryPoint +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.bottom_navigation_bar.BottomNavigationBar import ua.acclorite.book_story.presentation.components.custom_navigation_rail.CustomNavigationRail import ua.acclorite.book_story.presentation.data.MainViewModel @@ -89,8 +90,8 @@ class Activity : AppCompatActivity() { WindowCompat.setDecorFitsSystemWindows(window, false) setContent { + val state = LocalMainViewModel.current.state val isLoaded = mainViewModel.isReady.collectAsState() - val state = mainViewModel.state.collectAsState() val density = LocalDensity.current val imeInsets = WindowInsets.ime diff --git a/app/src/main/java/ua/acclorite/book_story/domain/util/BaseViewModel.kt b/app/src/main/java/ua/acclorite/book_story/domain/util/BaseViewModel.kt new file mode 100644 index 00000000..40d764a2 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/util/BaseViewModel.kt @@ -0,0 +1,9 @@ +package ua.acclorite.book_story.domain.util + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.StateFlow + +abstract class BaseViewModel : ViewModel() { + abstract val state: StateFlow + abstract fun onEvent(event: E) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/ViewModelCompositionProvider.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/ViewModelCompositionProvider.kt new file mode 100644 index 00000000..58c66107 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/ViewModelCompositionProvider.kt @@ -0,0 +1,91 @@ +package ua.acclorite.book_story.presentation.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.compositionLocalOf +import androidx.hilt.navigation.compose.hiltViewModel +import ua.acclorite.book_story.domain.util.BaseViewModel +import ua.acclorite.book_story.presentation.data.MainEvent +import ua.acclorite.book_story.presentation.data.MainState +import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent +import ua.acclorite.book_story.presentation.screens.about.data.AboutState +import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel +import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoEvent +import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoState +import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel +import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesEvent +import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState +import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesViewModel +import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent +import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState +import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel +import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent +import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState +import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel +import ua.acclorite.book_story.presentation.screens.help.data.HelpEvent +import ua.acclorite.book_story.presentation.screens.help.data.HelpState +import ua.acclorite.book_story.presentation.screens.help.data.HelpViewModel +import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent +import ua.acclorite.book_story.presentation.screens.history.data.HistoryState +import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel +import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent +import ua.acclorite.book_story.presentation.screens.library.data.LibraryState +import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel +import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent +import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState +import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel +import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent +import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState +import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel +import ua.acclorite.book_story.presentation.screens.start.data.StartEvent +import ua.acclorite.book_story.presentation.screens.start.data.StartState +import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel + +data class ViewModelComposition( + val state: State, + val onEvent: (E) -> Unit, + val viewModel: V +) + +@Composable +inline fun , S, E> viewModelComposition( +): ProvidableCompositionLocal> { + val viewModel: V = hiltViewModel() + val state = viewModel.state.collectAsState() + + return compositionLocalOf { + ViewModelComposition( + state = state, + onEvent = viewModel::onEvent, + viewModel = viewModel + ) + } +} + +val LocalMainViewModel + @Composable get() = viewModelComposition() +val LocalLibraryViewModel + @Composable get() = viewModelComposition() +val LocalHistoryViewModel + @Composable get() = viewModelComposition() +val LocalBrowseViewModel + @Composable get() = viewModelComposition() +val LocalBookInfoViewModel + @Composable get() = viewModelComposition() +val LocalReaderViewModel + @Composable get() = viewModelComposition() +val LocalSettingsViewModel + @Composable get() = viewModelComposition() +val LocalAboutViewModel + @Composable get() = viewModelComposition() +val LocalLicensesViewModel + @Composable get() = viewModelComposition() +val LocalLicenseInfoViewModel + @Composable get() = viewModelComposition() +val LocalHelpViewModel + @Composable get() = viewModelComposition() +val LocalStartViewModel + @Composable get() = viewModelComposition() \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt index 5b3c1c3b..eb6081e2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainState.kt @@ -82,6 +82,10 @@ data class MainState( val browseIncludedFilterItems: List = provideDefaultValue { emptyList() }, ) : Parcelable { companion object { + private fun provideDefaultValue(calculation: () -> D): D { + return calculation() + } + /** * Initializes [MainState] by given [Map]. * If no value provided in [data], assigns default value. @@ -209,8 +213,4 @@ data class MainState( } } } -} - -private fun provideDefaultValue(calculation: () -> D): D { - return calculation() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt index 7f095a5b..447eae89 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt @@ -1,7 +1,6 @@ package ua.acclorite.book_story.presentation.data import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -16,6 +15,7 @@ import ua.acclorite.book_story.domain.use_case.ChangeLanguage import ua.acclorite.book_story.domain.use_case.CheckForUpdates import ua.acclorite.book_story.domain.use_case.GetAllSettings import ua.acclorite.book_story.domain.use_case.SetDatastore +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.DataStoreConstants import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel @@ -41,7 +41,7 @@ class MainViewModel @Inject constructor( private val changeLanguage: ChangeLanguage, private val checkForUpdates: CheckForUpdates, private val getAllSettings: GetAllSettings -) : ViewModel() { +) : BaseViewModel() { private val _isReady = MutableStateFlow(false) val isReady = _isReady.asStateFlow() @@ -52,9 +52,9 @@ class MainViewModel @Inject constructor( private val _state: MutableStateFlow = MutableStateFlow( stateHandle[Constants.MAIN_STATE] ?: MainState() ) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() - fun onEvent(event: MainEvent) { + override fun onEvent(event: MainEvent) { when (event) { is MainEvent.OnChangeLanguage -> { viewModelScope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt index 4f72e898..839fbd6d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/Navigation.kt @@ -44,6 +44,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import kotlinx.serialization.Serializable +import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.Route import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.ui.Transitions @@ -54,11 +55,14 @@ private const val USE_BACK_ANIM = "use_back_animation" private const val SCREENS = "screens" /** - * Passed in [CompositionLocalProvider] and can be accessed through [LocalNavigator].current. + * Passed in [CompositionLocalProvider]. */ val LocalNavigator = compositionLocalOf { error("Cannot initialize Navigator.") } +val LocalOnNavigate = compositionLocalOf { + error("Cannot initialize Navigator.") +} /** * Screens. Should be [Serializable] to be able to pass them inside [SavedStateHandle]. @@ -434,7 +438,10 @@ fun NavigationHost( .background(colorBetweenAnimations) ) - CompositionLocalProvider(LocalNavigator provides navigator) { + CompositionLocalProvider( + LocalNavigator provides navigator, + LocalOnNavigate provides { navigator.it() } + ) { content(navigator) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt index 2979d1b5..7191dc2b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/AboutScreen.kt @@ -19,8 +19,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -29,51 +27,36 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalAboutViewModel import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.showToast 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.badges.AboutBadges import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent -import ua.acclorite.book_story.presentation.screens.about.data.AboutState -import ua.acclorite.book_story.presentation.screens.about.data.AboutViewModel @Composable fun AboutScreenRoot() { - val navigator = LocalNavigator.current - val aboutViewModel: AboutViewModel = hiltViewModel() - - val state = aboutViewModel.state.collectAsState() - - AboutScreen( - state = state, - onNavigate = { navigator.it() }, - onEvent = aboutViewModel::onEvent - ) + AboutScreen() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun AboutScreen( - state: State, - onNavigate: OnNavigate, - onEvent: (AboutEvent) -> Unit -) { +private fun AboutScreen() { + val state = LocalAboutViewModel.current.state + val onEvent = LocalAboutViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current + val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() if (state.value.showUpdateDialog) { - AboutUpdateDialog( - state = state, - onEvent = onEvent - ) + AboutUpdateDialog() } Scaffold( @@ -245,7 +228,7 @@ private fun AboutScreen( } item { - AboutBadges(onEvent = onEvent) + AboutBadges() } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/AboutUpdateDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/AboutUpdateDialog.kt index a296eab3..8452af7f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/AboutUpdateDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/AboutUpdateDialog.kt @@ -3,24 +3,22 @@ package ua.acclorite.book_story.presentation.screens.about.components import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Update import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalAboutViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent -import ua.acclorite.book_story.presentation.screens.about.data.AboutState /** * Update dialog. If there is app update transfers to the download page. */ @Composable -fun AboutUpdateDialog( - state: State, - onEvent: (AboutEvent) -> Unit -) { +fun AboutUpdateDialog() { + val state = LocalAboutViewModel.current.state + val onEvent = LocalAboutViewModel.current.onEvent val context = LocalContext.current val update = remember(state.value.showUpdateDialog) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/badges/AboutBadges.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/badges/AboutBadges.kt index 3cbdd66f..359221df 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/badges/AboutBadges.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/components/badges/AboutBadges.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.presentation.components.LocalAboutViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent @@ -21,14 +22,11 @@ import ua.acclorite.book_story.presentation.screens.about.data.AboutEvent * About Badges. * Links all ways to contact me. * - * @param onEvent [AboutEvent] callback. * @param verticalPadding Vertical item padding. */ @Composable -fun AboutBadges( - onEvent: (AboutEvent) -> Unit, - verticalPadding: Dp = 18.dp -) { +fun AboutBadges(verticalPadding: Dp = 18.dp) { + val onEvent = LocalAboutViewModel.current.onEvent val context = LocalContext.current Box( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/data/AboutViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/data/AboutViewModel.kt index ce37344d..d20ac4d2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/data/AboutViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/data/AboutViewModel.kt @@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.screens.about.data import android.content.Intent import android.net.Uri import androidx.activity.ComponentActivity -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -12,18 +11,19 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.use_case.CheckForUpdates +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.presentation.data.launchActivity import javax.inject.Inject @HiltViewModel class AboutViewModel @Inject constructor( private val checkForUpdates: CheckForUpdates, -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(AboutState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() - fun onEvent(event: AboutEvent) { + override fun onEvent(event: AboutEvent) { when (event) { is AboutEvent.OnNavigateToBrowserPage -> { viewModelScope.launch { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt index a44863e6..3effecd4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/credits/CreditsScreen.kt @@ -16,40 +16,32 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalAboutViewModel import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.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 @Composable fun CreditsScreenRoot() { - val navigator = LocalNavigator.current - val aboutViewModel: AboutViewModel = hiltViewModel() - - CreditsScreen( - onNavigate = { navigator.it() }, - onAboutNavigateEvent = aboutViewModel::onEvent - ) + CreditsScreen() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun CreditsScreen( - onNavigate: OnNavigate, - onAboutNavigateEvent: (AboutEvent.OnNavigateToBrowserPage) -> Unit -) { - val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() +private fun CreditsScreen() { + val onEvent = LocalAboutViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current + val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() + Scaffold( Modifier .fillMaxSize() @@ -81,7 +73,7 @@ private fun CreditsScreen( customItems(Constants.CREDITS, key = { it.name }) { CreditItem(credit = it) { it.website?.let { website -> - onAboutNavigateEvent( + onEvent( AboutEvent.OnNavigateToBrowserPage( page = website, context = context, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt index 9a0ed9c9..325d5257 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/LicenseInfoScreen.kt @@ -23,8 +23,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -33,56 +31,46 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalLicenseInfoViewModel import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.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.LicenseInfoState -import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.SlidingTransition @Composable fun LicenseInfoScreenRoot(screen: Screen.About.LicenseInfo) { - val navigator = LocalNavigator.current + val viewModel = LocalLicenseInfoViewModel.current.viewModel + val onNavigate = LocalOnNavigate.current val context = LocalContext.current - val licenseInfoViewModel: LicenseInfoViewModel = hiltViewModel() - - val state = licenseInfoViewModel.state.collectAsState() LaunchedEffect(Unit) { - licenseInfoViewModel.init( + viewModel.init( screen = screen, - onNavigate = { navigator.it() }, + onNavigate = onNavigate, context = context ) } - LicenseInfoScreen( - state = state, - onNavigate = { navigator.it() }, - onEvent = licenseInfoViewModel::onEvent - ) + LicenseInfoScreen() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun LicenseInfoScreen( - state: State, - onNavigate: OnNavigate, - onEvent: (LicenseInfoEvent) -> Unit -) { - val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() +private fun LicenseInfoScreen() { + val state = LocalLicenseInfoViewModel.current.state + val onEvent = LocalLicenseInfoViewModel.current.onEvent val context = LocalContext.current + val onNavigate = LocalOnNavigate.current + val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val licenses = remember(state.value.license?.licenses) { state.value.license?.licenses?.toList() } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt index 707e1b97..c2b4b9f0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/license_info/data/LicenseInfoViewModel.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.Intent import android.net.Uri import androidx.activity.ComponentActivity -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.util.withContext @@ -14,18 +13,21 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.launchActivity import javax.inject.Inject @HiltViewModel -class LicenseInfoViewModel @Inject constructor() : ViewModel() { +class LicenseInfoViewModel @Inject constructor( + +) : BaseViewModel() { private val _state = MutableStateFlow(LicenseInfoState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() - fun onEvent(event: LicenseInfoEvent) { + override fun onEvent(event: LicenseInfoEvent) { when (event) { is LicenseInfoEvent.OnOpenLicensePage -> { viewModelScope.launch { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt index cd60477a..ce89a1da 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/LicensesScreen.kt @@ -18,51 +18,40 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalLicensesViewModel import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.about.nested.licenses.components.LicenseItem -import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesState -import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesViewModel @Composable fun LicensesScreenRoot() { - val navigator = LocalNavigator.current + val viewModel = LocalLicensesViewModel.current.viewModel val context = LocalContext.current - val licensesViewModel: LicensesViewModel = hiltViewModel() - - val state = licensesViewModel.state.collectAsState() LaunchedEffect(Unit) { - licensesViewModel.init(context) + viewModel.init(context) } - LicensesScreen( - state = state, - onNavigate = { navigator.it() } - ) + LicensesScreen() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun LicensesScreen( - state: State, - onNavigate: OnNavigate -) { +private fun LicensesScreen() { + val state = LocalLicensesViewModel.current.state + val onNavigate = LocalOnNavigate.current + val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState( state.value.listState ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesEvent.kt new file mode 100644 index 00000000..51fb80e5 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesEvent.kt @@ -0,0 +1,6 @@ +package ua.acclorite.book_story.presentation.screens.about.nested.licenses.data + +import androidx.compose.runtime.Immutable + +@Immutable +sealed class LicensesEvent \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesViewModel.kt index e5aa7335..bbe0d1dc 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/about/nested/licenses/data/LicensesViewModel.kt @@ -1,7 +1,6 @@ package ua.acclorite.book_story.presentation.screens.about.nested.licenses.data import android.content.Context -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.util.withJson @@ -12,15 +11,18 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import ua.acclorite.book_story.R +import ua.acclorite.book_story.domain.util.BaseViewModel import javax.inject.Inject @HiltViewModel class LicensesViewModel @Inject constructor( -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(LicensesState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() + + override fun onEvent(event: LicensesEvent) {} fun init(context: Context) { viewModelScope.launch(Dispatchers.IO) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt index ca0792f1..6461b0bd 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/BookInfoScreen.kt @@ -37,20 +37,17 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomSnackbar -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDescriptionSection @@ -63,60 +60,36 @@ import ua.acclorite.book_story.presentation.screens.book_info.components.details import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoDeleteDialog import ua.acclorite.book_story.presentation.screens.book_info.components.dialog.BookInfoMoveDialog import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel -import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent -import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel -import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel @Composable fun BookInfoScreenRoot(screen: Screen.BookInfo) { - val navigator = LocalNavigator.current - - val viewModel: BookInfoViewModel = hiltViewModel() - val libraryViewModel: LibraryViewModel = hiltViewModel() - val historyViewModel: HistoryViewModel = hiltViewModel() - val browseViewModel: BrowseViewModel = hiltViewModel() - - val state = viewModel.state.collectAsState() + val viewModel = LocalBookInfoViewModel.current.viewModel + val onNavigate = LocalOnNavigate.current LaunchedEffect(Unit) { viewModel.init( screen = screen, - onNavigate = { navigator.it() } + onNavigate = onNavigate ) } + BookInfoScreen() + DisposableEffect(Unit) { onDispose { viewModel.clearViewModel() } } - - BookInfoScreen( - state = state, - onNavigate = { navigator.it() }, - onEvent = viewModel::onEvent, - onLibraryEvent = libraryViewModel::onEvent, - onBrowseEvent = browseViewModel::onEvent, - onHistoryEvent = historyViewModel::onEvent - ) } @OptIn(ExperimentalMaterialApi::class) @Composable -private fun BookInfoScreen( - state: State, - onNavigate: OnNavigate, - onEvent: (BookInfoEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit, - onBrowseEvent: (BrowseEvent) -> Unit, - onHistoryEvent: (HistoryEvent) -> Unit -) { +private fun BookInfoScreen() { val context = LocalContext.current + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current + val listState = rememberLazyListState() val snackbarState = remember { SnackbarHostState() } val refreshState = rememberPullRefreshState( @@ -132,42 +105,19 @@ private fun BookInfoScreen( ) if (state.value.showChangeCoverBottomSheet) { - BookInfoChangeCoverBottomSheet( - state = state, - onEvent = onEvent, - onLibraryUpdateEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent - ) + BookInfoChangeCoverBottomSheet() } if (state.value.showDetailsBottomSheet) { - BookInfoDetailsBottomSheet( - state = state, - onEvent = onEvent - ) + BookInfoDetailsBottomSheet() } if (state.value.showDeleteDialog) { - BookInfoDeleteDialog( - onEvent = onEvent, - onLibraryLoadEvent = onLibraryEvent, - onHistoryLoadEvent = onHistoryEvent, - onBrowseLoadEvent = onBrowseEvent - ) + BookInfoDeleteDialog() } if (state.value.showMoveDialog) { - BookInfoMoveDialog( - state = state, - onEvent = onEvent, - onLibraryEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent - ) + BookInfoMoveDialog() } if (state.value.showConfirmUpdateDialog) { - BookInfoConfirmUpdateDialog( - snackbarHostState = snackbarState, - onEvent = onEvent, - onLibraryUpdateEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent - ) + BookInfoConfirmUpdateDialog(snackbarHostState = snackbarState) } Scaffold( @@ -179,11 +129,6 @@ private fun BookInfoScreen( containerColor = MaterialTheme.colorScheme.surface, topBar = { BookInfoTopBar( - state = state, - onEvent = onEvent, - onLibraryEvent = onLibraryEvent, - onHistoryEvent = onHistoryEvent, - onNavigate = onNavigate, listState = listState, snackbarState = snackbarState ) @@ -216,7 +161,7 @@ private fun BookInfoScreen( Column(Modifier.fillMaxWidth()) { Spacer(modifier = Modifier.height(paddingValues.calculateTopPadding() + 12.dp)) // Info - BookInfoInfoSection(state = state, onEvent = onEvent) + BookInfoInfoSection() } } } @@ -224,16 +169,13 @@ private fun BookInfoScreen( item { Spacer(modifier = Modifier.height(24.dp)) // Statistic - BookInfoStatisticSection(state = state) + BookInfoStatisticSection() } item { Spacer(modifier = Modifier.height(24.dp)) // Description - BookInfoDescriptionSection( - state = state, - onEvent = onEvent - ) + BookInfoDescriptionSection() } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoDescriptionSection.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoDescriptionSection.kt index 6279b310..ff8910fa 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoDescriptionSection.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoDescriptionSection.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -26,21 +25,18 @@ import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState /** * Description section. - * - * @param state [BookInfoState]. - * @param onEvent [BookInfoEvent] callback. */ @OptIn(ExperimentalFoundationApi::class) @Composable -fun BookInfoDescriptionSection( - state: State, - onEvent: (BookInfoEvent) -> Unit -) { +fun BookInfoDescriptionSection() { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + val descriptionFocusRequester = remember { FocusRequester() } if (!state.value.editDescription) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt index e9bcb05a..fec6e90c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoInfoSection.kt @@ -25,7 +25,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -40,21 +39,18 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomCoverImage +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState /** * BookInfo's Info section. - * - * @param state [BookInfoState] instance. - * @param onEvent [BookInfoEvent] callback. */ @OptIn(ExperimentalFoundationApi::class) @Composable -fun BookInfoInfoSection( - state: State, - onEvent: (BookInfoEvent) -> Unit -) { +fun BookInfoInfoSection() { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + val titleFocusRequester = remember { FocusRequester() } val authorFocusRequester = remember { FocusRequester() } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt index dd8e1b11..1568dbb7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoMoreDropDown.kt @@ -9,7 +9,6 @@ import androidx.compose.material.icons.outlined.Info import androidx.compose.material3.DropdownMenu import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -20,18 +19,17 @@ import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomDropDownMenuItem import ua.acclorite.book_story.presentation.components.CustomIconButton +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState /** * Book info more dropdown. Has three options: Delete, Move and Details. */ @Composable -fun BookInfoMoreDropDown( - state: State, - onEvent: (BookInfoEvent) -> Unit, - snackbarState: SnackbarHostState -) { +fun BookInfoMoreDropDown(snackbarState: SnackbarHostState) { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + var showDropDown by remember { mutableStateOf(false) } Box { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt index e342e859..33f61059 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoStatisticSection.kt @@ -9,7 +9,6 @@ import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.StrokeCap @@ -17,15 +16,17 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel import ua.acclorite.book_story.presentation.data.removeDigits import ua.acclorite.book_story.presentation.data.removeTrailingZero -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState /** * Statistic section. */ @Composable -fun BookInfoStatisticSection(state: State) { +fun BookInfoStatisticSection() { + val state = LocalBookInfoViewModel.current.state + val progress = remember(state.value.book) { "${ (state.value.book.progress * 100) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt index bcf394e8..51595d07 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt @@ -13,20 +13,21 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.ui.DefaultTransition @@ -35,26 +36,22 @@ import ua.acclorite.book_story.presentation.ui.Transitions /** * Book Info Top Bar. * - * @param state [BookInfoState]. - * @param onEvent [BookInfoEvent] callback. - * @param onLibraryEvent [LibraryEvent] callback. - * @param onHistoryEvent [HistoryEvent] callback. - * @param onNavigate Navigator callback. * @param listState [LazyListState]. * @param snackbarState [SnackbarHostState]. */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun BookInfoTopBar( - state: State, - onEvent: (BookInfoEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit, - onHistoryEvent: (HistoryEvent) -> Unit, - onNavigate: OnNavigate, listState: LazyListState, snackbarState: SnackbarHostState ) { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current + val firstVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex } } AnimatedTopAppBar( @@ -125,11 +122,7 @@ fun BookInfoTopBar( !state.value.editAuthor && !state.value.editDescription ) { - BookInfoMoreDropDown( - state = state, - onEvent = onEvent, - snackbarState = snackbarState - ) + BookInfoMoreDropDown(snackbarState = snackbarState) } CustomAnimatedVisibility( visible = state.value.editTitle || @@ -175,7 +168,8 @@ fun BookInfoTopBar( onLibraryEvent(LibraryEvent.OnUpdateBook(it)) onHistoryEvent(HistoryEvent.OnUpdateBook(it)) } - )) + ) + ) } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt index 43a57a8d..8af2906d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/change_cover_bottom_sheet/BookInfoChangeCoverBottomSheet.kt @@ -13,35 +13,31 @@ import androidx.compose.material.icons.filled.ImageSearch import androidx.compose.material.icons.filled.Restore import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomBottomSheet +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** * Change cover bottom sheet. Lets user select photo from the gallery and replaces old one. - * - * @param state [BookInfoState] instance. - * @param onEvent [BookInfoEvent] callback. - * @param onLibraryUpdateEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @Composable -fun BookInfoChangeCoverBottomSheet( - state: State, - onEvent: (BookInfoEvent) -> Unit, - onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit -) { +fun BookInfoChangeCoverBottomSheet() { + val state = LocalBookInfoViewModel.current.state + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val onEvent = LocalBookInfoViewModel.current.onEvent val context = LocalContext.current + val photoPicker = rememberLauncherForActivityResult( contract = ActivityResultContracts.PickVisualMedia(), onResult = { uri -> @@ -51,8 +47,8 @@ fun BookInfoChangeCoverBottomSheet( uri, context, refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) } ) ) @@ -83,8 +79,8 @@ fun BookInfoChangeCoverBottomSheet( onEvent( BookInfoEvent.OnResetCoverImage( refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, showResult = { it.asString(context).showToast(context = context) @@ -117,8 +113,8 @@ fun BookInfoChangeCoverBottomSheet( onEvent( BookInfoEvent.OnDeleteCover( refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) } ) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt index 4ef6b8d2..20078617 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/confirm_update_dialog/BookInfoConfirmUpateDialog.kt @@ -7,6 +7,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent @@ -17,17 +20,12 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent * Updates book if action clicked. * * @param snackbarHostState [SnackbarHostState]. - * @param onEvent [BookInfoEvent] callback. - * @param onLibraryUpdateEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @Composable -fun BookInfoConfirmUpdateDialog( - snackbarHostState: SnackbarHostState, - onEvent: (BookInfoEvent) -> Unit, - onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit, -) { +fun BookInfoConfirmUpdateDialog(snackbarHostState: SnackbarHostState) { + val onEvent = LocalBookInfoViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent val context = LocalContext.current CustomDialogWithContent( @@ -45,20 +43,12 @@ fun BookInfoConfirmUpdateDialog( snackbarState = snackbarHostState, context = context, refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) } ) ) }, withDivider = false ) -} - - - - - - - - +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt index 177449e8..31ea6cfb 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/details_bottom_sheet/BookInfoDetailsBottomSheet.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -12,9 +11,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomBottomSheet +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState import java.io.File import java.text.SimpleDateFormat import java.util.Date @@ -22,15 +21,11 @@ import java.util.Locale /** * Details bottom sheet. Displays name, path, last opened and size of the file. - * - * @param state [BookInfoState] instance. - * @param onEvent [BookInfoEvent] callback. */ @Composable -fun BookInfoDetailsBottomSheet( - state: State, - onEvent: (BookInfoEvent) -> Unit -) { +fun BookInfoDetailsBottomSheet() { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent val context = LocalContext.current val pattern = remember { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt index 0b81c656..30d53e82 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoDeleteDialog.kt @@ -6,8 +6,12 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent @@ -16,20 +20,14 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** * Delete dialog. Deletes current book. - * - * @param onEvent [BookInfoEvent] callback. - * @param onLibraryLoadEvent [LibraryEvent] callback. - * @param onHistoryLoadEvent [HistoryEvent] callback. - * @param onBrowseLoadEvent [BrowseEvent] callback. */ @Composable -fun BookInfoDeleteDialog( - onEvent: (BookInfoEvent) -> Unit, - onLibraryLoadEvent: (LibraryEvent.OnLoadList) -> Unit, - onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit, - onBrowseLoadEvent: (BrowseEvent.OnLoadList) -> Unit -) { - val navigator = LocalNavigator.current +fun BookInfoDeleteDialog() { + val onEvent = LocalBookInfoViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val onBrowseEvent = LocalBrowseViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current CustomDialogWithContent( @@ -45,11 +43,11 @@ fun BookInfoDeleteDialog( onAction = { onEvent( BookInfoEvent.OnDeleteBook( - onNavigate = { navigator.it() }, + onNavigate = onNavigate, refreshList = { - onLibraryLoadEvent(LibraryEvent.OnLoadList) - onBrowseLoadEvent(BrowseEvent.OnLoadList) - onHistoryLoadEvent(HistoryEvent.OnLoadList) + onLibraryEvent(LibraryEvent.OnLoadList) + onBrowseEvent(BrowseEvent.OnLoadList) + onHistoryEvent(HistoryEvent.OnLoadList) } ) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt index 99f72651..8a7d3f60 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/dialog/BookInfoMoveDialog.kt @@ -4,39 +4,34 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.DriveFileMove import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Category +import ua.acclorite.book_story.presentation.components.LocalBookInfoViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent -import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoState import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** * Move dialog. * Moves current book to the selected category. - * - * @param state [BookInfoState]. - * @param onEvent [BookInfoEvent] callback. - * @param onLibraryEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @Composable -fun BookInfoMoveDialog( - state: State, - onEvent: (BookInfoEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit -) { - val navigator = LocalNavigator.current +fun BookInfoMoveDialog() { + val state = LocalBookInfoViewModel.current.state + val onEvent = LocalBookInfoViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current val categories = remember { @@ -61,12 +56,12 @@ fun BookInfoMoveDialog( BookInfoEvent.OnMoveBook( refreshList = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, updatePage = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) }, - onNavigate = { navigator.it() } + onNavigate = onNavigate ) ) context.getString(R.string.book_moved) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt index 582d5a51..6658787d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/data/BookInfoViewModel.kt @@ -8,7 +8,6 @@ import android.content.Context.CLIPBOARD_SERVICE import android.graphics.BitmapFactory import android.os.Build import androidx.compose.material3.SnackbarResult -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -34,6 +33,7 @@ import ua.acclorite.book_story.domain.use_case.ResetCoverImage import ua.acclorite.book_story.domain.use_case.UpdateBookWithText import ua.acclorite.book_story.domain.use_case.UpdateBooks import ua.acclorite.book_story.domain.use_case.UpdateCoverImageOfBook +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.presentation.data.Screen @@ -54,17 +54,17 @@ class BookInfoViewModel @Inject constructor( private val getText: GetText, private val canResetCover: CanResetCover, private val resetCoverImage: ResetCoverImage, -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(BookInfoState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private var eventJob = SupervisorJob() private var snackBarJob: Job? = null private var updateJob: Job? = null - fun onEvent(event: BookInfoEvent) { + override fun onEvent(event: BookInfoEvent) { viewModelScope.launch(eventJob + Dispatchers.Main) { when (event) { is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt index ea3e2ced..4f344d85 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/BrowseScreen.kt @@ -14,24 +14,19 @@ import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.rememberPermissionState import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.SelectableFile -import ua.acclorite.book_story.domain.util.OnNavigate -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.browse.components.BrowseEmptyPlaceholder @@ -41,23 +36,16 @@ import ua.acclorite.book_story.presentation.screens.browse.components.filter_bot import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseLayout import ua.acclorite.book_story.presentation.screens.browse.components.top_bar.BrowseTopBar import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel -import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import ua.acclorite.book_story.presentation.ui.DefaultTransition @OptIn(ExperimentalPermissionsApi::class) @Composable fun BrowseScreenRoot() { - val navigator = LocalNavigator.current - val viewModel: BrowseViewModel = hiltViewModel() - val libraryViewModel: LibraryViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - - val state = viewModel.state.collectAsState() - val mainState = mainViewModel.state.collectAsState() + val state = LocalBrowseViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val viewModel = LocalBrowseViewModel.current.viewModel val permissionState = rememberPermissionState( permission = Manifest.permission.READ_EXTERNAL_STORAGE @@ -72,22 +60,14 @@ fun BrowseScreenRoot() { } LaunchedEffect(Unit) { - viewModel.onEvent(BrowseEvent.OnUpdateScrollOffset) - viewModel.onEvent( - BrowseEvent.OnPermissionCheck(permissionState) - ) + onEvent(BrowseEvent.OnUpdateScrollOffset) + onEvent(BrowseEvent.OnPermissionCheck(permissionState)) } BrowseScreen( - state = state, - mainState = mainState, permissionState = permissionState, filteredFiles = filteredFiles.value, - onNavigate = { navigator.it() }, - onEvent = viewModel::onEvent, - onMainEvent = mainViewModel::onEvent, - onLibraryEvent = libraryViewModel::onEvent ) DisposableEffect(Unit) { @@ -103,16 +83,15 @@ fun BrowseScreenRoot() { ) @Composable private fun BrowseScreen( - state: State, - mainState: State, permissionState: PermissionState, - filteredFiles: List, - onNavigate: OnNavigate, - onEvent: (BrowseEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit + filteredFiles: List ) { + val state = LocalBrowseViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current val context = LocalContext.current + val refreshState = rememberPullRefreshState( refreshing = state.value.isRefreshing, onRefresh = { @@ -121,22 +100,13 @@ private fun BrowseScreen( ) if (state.value.requestPermissionDialog) { - BrowseStoragePermissionDialog(onEvent, permissionState) + BrowseStoragePermissionDialog(permissionState) } if (state.value.showAddingDialog) { - BrowseAddingDialog( - state = state, - onEvent = onEvent, - onLibraryEvent = onLibraryEvent - ) + BrowseAddingDialog() } if (state.value.showFilterBottomSheet) { - BrowseFilterBottomSheet( - state = state, - mainState = mainState, - onMainEvent = onMainEvent, - onEvent = onEvent - ) + BrowseFilterBottomSheet() } Scaffold( @@ -145,12 +115,7 @@ private fun BrowseScreen( .pullRefresh(refreshState), containerColor = MaterialTheme.colorScheme.surface, topBar = { - BrowseTopBar( - state = state, - mainState = mainState, - filteredFiles = filteredFiles, - onEvent = onEvent - ) + BrowseTopBar(filteredFiles = filteredFiles) } ) { padding -> Box( @@ -160,8 +125,6 @@ private fun BrowseScreen( ) { DefaultTransition(visible = !state.value.isLoading) { BrowseLayout( - state = state, - mainState = mainState, filteredFiles = filteredFiles, onLongItemClick = { selectableFile -> when (selectableFile.isDirectory) { @@ -223,11 +186,8 @@ private fun BrowseScreen( } BrowseEmptyPlaceholder( - state = state, isFilesEmpty = filteredFiles.isEmpty(), storagePermissionState = permissionState, - onNavigate = onNavigate, - onEvent = onEvent ) PullRefreshIndicator( @@ -255,9 +215,7 @@ private fun BrowseScreen( state.value.inNestedDirectory && mainState.value.browseFilesStructure != BrowseFilesStructure.ALL_FILES ) { - onEvent( - BrowseEvent.OnGoBackDirectory - ) + onEvent(BrowseEvent.OnGoBackDirectory) return@BackHandler } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseEmptyPlaceholder.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseEmptyPlaceholder.kt index 437ef621..6fad53ae 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseEmptyPlaceholder.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseEmptyPlaceholder.kt @@ -2,7 +2,6 @@ package ua.acclorite.book_story.presentation.screens.browse.components import androidx.compose.foundation.layout.BoxScope import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -10,34 +9,32 @@ import androidx.compose.ui.res.stringResource import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.components.is_messages.IsError +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.ui.Transitions /** * Browse Empty Placeholder. * Shows error or empty message. * - * @param state [BrowseState]. * @param isFilesEmpty Whether the list is empty. * @param storagePermissionState Storage [PermissionState]. - * @param onNavigate Navigator callback. - * @param onEvent [BrowseEvent] callback. */ @OptIn(ExperimentalPermissionsApi::class) @Composable fun BoxScope.BrowseEmptyPlaceholder( - state: State, isFilesEmpty: Boolean, - storagePermissionState: PermissionState, - onNavigate: OnNavigate, - onEvent: (BrowseEvent) -> Unit + storagePermissionState: PermissionState ) { + val state = LocalBrowseViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current + CustomAnimatedVisibility( visible = state.value.isError, modifier = Modifier.align(Alignment.Center), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseStoragePermissionDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseStoragePermissionDialog.kt index d901035e..7bdfc834 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseStoragePermissionDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/BrowseStoragePermissionDialog.kt @@ -9,22 +9,22 @@ import androidx.compose.ui.res.stringResource import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent /** * Storage permission dialog. * - * @param onEvent [BrowseEvent] callback. * @param permissionState Storage [PermissionState]. */ @OptIn(ExperimentalPermissionsApi::class) @Composable fun BrowseStoragePermissionDialog( - onEvent: (BrowseEvent) -> Unit, permissionState: PermissionState ) { val activity = LocalContext.current as ComponentActivity + val onEvent = LocalBrowseViewModel.current.onEvent CustomDialogWithContent( title = stringResource(id = R.string.storage_permission), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt index b614df46..b4508220 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/adding_dialog/BrowseAddingDialog.kt @@ -9,7 +9,6 @@ import androidx.compose.material.icons.filled.AddChart import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.StrokeCap @@ -18,30 +17,26 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.NullableBook +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent /** * Adding dialog. * Adds all selected books to the Library. - * - * @param state [BrowseState]. - * @param onEvent [BrowseEvent] callback. - * @param onLibraryEvent [LibraryEvent] callback. */ @Composable -fun BrowseAddingDialog( - state: State, - onEvent: (BrowseEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit -) { +fun BrowseAddingDialog() { val context = LocalContext.current - val navigator = LocalNavigator.current + val state = LocalBrowseViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current CustomDialogWithLazyColumn( title = stringResource(id = R.string.add_books), @@ -54,7 +49,7 @@ fun BrowseAddingDialog( onAction = { onEvent( BrowseEvent.OnAddBooks( - onNavigate = { navigator.it() }, + onNavigate = onNavigate, resetScroll = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(0)) onLibraryEvent(LibraryEvent.OnLoadList) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/filter_bottom_sheet/BrowseFilterBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/filter_bottom_sheet/BrowseFilterBottomSheet.kt index 8c3e275c..b18050b5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/filter_bottom_sheet/BrowseFilterBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/filter_bottom_sheet/BrowseFilterBottomSheet.kt @@ -8,14 +8,11 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ua.acclorite.book_story.presentation.components.CustomBottomSheet -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory @@ -23,19 +20,12 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo /** * Browse Filter Bottom Sheet. * Lets user sort, filter and change appearance of the Browse. - * - * @param state [BrowseState]. - * @param mainState [MainState]. - * @param onMainEvent [MainEvent] callback. - * @param onEvent [BrowseEvent] callback. */ @Composable -fun BrowseFilterBottomSheet( - state: State, - mainState: State, - onMainEvent: (MainEvent) -> Unit, - onEvent: (BrowseEvent) -> Unit -) { +fun BrowseFilterBottomSheet() { + val state = LocalBrowseViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val pagerState = rememberPagerState(state.value.currentPage) { 3 } LaunchedEffect(pagerState.currentPage) { @@ -67,8 +57,6 @@ fun BrowseFilterBottomSheet( 0 -> { LazyColumn(Modifier.fillMaxSize()) { BrowseGeneralSubcategory( - state = mainState, - onMainEvent = onMainEvent, showTitle = false, topPadding = 16.dp, bottomPadding = 8.dp + it @@ -79,8 +67,6 @@ fun BrowseFilterBottomSheet( 1 -> { LazyColumn(Modifier.fillMaxSize()) { BrowseFilterSubcategory( - state = mainState, - onMainEvent = onMainEvent, showTitle = false, topPadding = 16.dp, bottomPadding = 8.dp + it @@ -91,8 +77,6 @@ fun BrowseFilterBottomSheet( 2 -> { LazyColumn(Modifier.fillMaxSize()) { BrowseSortSubcategory( - state = mainState, - onMainEvent = onMainEvent, showTitle = false, topPadding = 16.dp, bottomPadding = 8.dp + it diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/BrowseLayout.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/BrowseLayout.kt index 17490f6f..26971cdb 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/BrowseLayout.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/BrowseLayout.kt @@ -1,20 +1,16 @@ package ua.acclorite.book_story.presentation.screens.browse.components.layout import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import ua.acclorite.book_story.domain.model.SelectableFile -import ua.acclorite.book_story.presentation.data.MainState +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.screens.browse.components.layout.grid.BrowseGridLayout import ua.acclorite.book_story.presentation.screens.browse.components.layout.list.BrowseListLayout -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout /** * Browse Layout. * Shows Grid or List. * - * @param state [BrowseState]. - * @param mainState [MainState]. * @param filteredFiles Filtered items. * @param onLongItemClick OnLongItemClick callback. * @param onFavoriteItemClick OnFavoriteItemClick callback. @@ -22,17 +18,16 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data. */ @Composable fun BrowseLayout( - state: State, - mainState: State, filteredFiles: List, onLongItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit ) { + val mainState = LocalMainViewModel.current.state + when (mainState.value.browseLayout) { BrowseLayout.LIST -> { BrowseListLayout( - state = state, filteredFiles = filteredFiles, onLongItemClick = onLongItemClick, onFavoriteItemClick = onFavoriteItemClick, @@ -42,7 +37,6 @@ fun BrowseLayout( BrowseLayout.GRID -> { BrowseGridLayout( - state = state, gridSize = mainState.value.browseGridSize, autoGridSize = mainState.value.browseAutoGridSize, filteredFiles = filteredFiles, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/grid/BrowseGridLayout.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/grid/BrowseGridLayout.kt index 33e02c00..f00c55d4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/grid/BrowseGridLayout.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/grid/BrowseGridLayout.kt @@ -7,19 +7,17 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ua.acclorite.book_story.domain.model.SelectableFile +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.header import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout @Composable fun BrowseGridLayout( - state: State, gridSize: Int, autoGridSize: Boolean, filteredFiles: List, @@ -27,6 +25,8 @@ fun BrowseGridLayout( onFavoriteItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit, ) { + val state = LocalBrowseViewModel.current.state + LazyVerticalGrid( columns = if (autoGridSize) GridCells.Adaptive(170.dp) else GridCells.Fixed(gridSize.coerceAtLeast(1)), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/list/BrowseListLayout.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/list/BrowseListLayout.kt index 9dd3bb93..a3af424a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/list/BrowseListLayout.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/layout/list/BrowseListLayout.kt @@ -5,23 +5,23 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ua.acclorite.book_story.domain.model.SelectableFile +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout @Composable fun BrowseListLayout( - state: State, filteredFiles: List, onLongItemClick: (SelectableFile) -> Unit, onFavoriteItemClick: (SelectableFile) -> Unit, onItemClick: (SelectableFile) -> Unit, ) { + val state = LocalBrowseViewModel.current.state + LazyColumn( state = state.value.listState, modifier = Modifier diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt index cf024c77..262b52e6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt @@ -22,7 +22,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -39,10 +38,10 @@ import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomSearchTextField +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.MoreDropDown -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace @@ -50,19 +49,15 @@ import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace /** * Browse Top Bar. * - * @param state [BrowseState]. - * @param mainState [MainState]. * @param filteredFiles Filtered files. - * @param onEvent [BrowseEvent] callback. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun BrowseTopBar( - state: State, - mainState: State, - filteredFiles: List, - onEvent: (BrowseEvent) -> Unit -) { +fun BrowseTopBar(filteredFiles: List) { + val state = LocalBrowseViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent + val focusRequester = remember { FocusRequester() } val selectedDirectoryName = remember { mutableStateOf(state.value.selectedDirectory.name) @@ -245,11 +240,7 @@ fun BrowseTopBar( }, customContent = { - BrowseTopBarDirectoryPath( - state = state, - mainState = mainState, - onEvent = onEvent - ) + BrowseTopBarDirectoryPath() } ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBarDirectoryPath.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBarDirectoryPath.kt index 202edeec..c84a66f6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBarDirectoryPath.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBarDirectoryPath.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -28,20 +27,20 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.customItemsIndexed -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import java.io.File @Composable -fun BrowseTopBarDirectoryPath( - state: State, - mainState: State, - onEvent: (BrowseEvent) -> Unit -) { +fun BrowseTopBarDirectoryPath() { + val state = LocalBrowseViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalBrowseViewModel.current.onEvent val context = LocalContext.current + val rootDirectory = remember { Environment.getExternalStorageDirectory() } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt index 2c94f57e..6fc6bdd1 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/data/BrowseViewModel.kt @@ -9,7 +9,6 @@ import android.os.Environment import android.provider.Settings import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.grid.LazyGridState -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted @@ -29,6 +28,7 @@ import ua.acclorite.book_story.domain.use_case.GetBookFromFile import ua.acclorite.book_story.domain.use_case.GetFilesFromDevice import ua.acclorite.book_story.domain.use_case.InsertBook import ua.acclorite.book_story.domain.use_case.UpdateFavoriteDirectory +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.launchActivity @@ -43,10 +43,10 @@ class BrowseViewModel @Inject constructor( private val getFilesFromDevice: GetFilesFromDevice, private val insertBook: InsertBook, private val updateFavoriteDirectory: UpdateFavoriteDirectory, -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(BrowseState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private var searchQueryJob: Job? = null private var refreshListJob: Job? = null @@ -67,7 +67,7 @@ class BrowseViewModel @Inject constructor( } } - fun onEvent(event: BrowseEvent) { + override fun onEvent(event: BrowseEvent) { when (event) { is BrowseEvent.OnStoragePermissionRequest -> { val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt index cbc5d02c..30a29157 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/HelpScreen.kt @@ -22,68 +22,51 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalHelpViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.customItems -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel 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.data.HelpState -import ua.acclorite.book_story.presentation.screens.help.data.HelpViewModel import ua.acclorite.book_story.presentation.screens.start.data.StartEvent -import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel @Composable fun HelpScreenRoot(screen: Screen.Help) { - val navigator = LocalNavigator.current - val helpViewModel: HelpViewModel = hiltViewModel() - val browseViewModel: BrowseViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - val startViewModel: StartViewModel = hiltViewModel() - - val state = helpViewModel.state.collectAsState() + val viewModel = LocalHelpViewModel.current.viewModel LaunchedEffect(Unit) { - helpViewModel.init(screen = screen) + viewModel.init(screen = screen) } - HelpScreen( - state = state, - onNavigate = { navigator.it() }, - onMainEvent = mainViewModel::onEvent, - onBrowseEvent = browseViewModel::onEvent, - onStartEvent = startViewModel::onEvent - ) + HelpScreen() } @OptIn( ExperimentalMaterial3Api::class ) @Composable -private fun HelpScreen( - state: State, - onNavigate: OnNavigate, - onMainEvent: (MainEvent) -> Unit, - onBrowseEvent: (BrowseEvent) -> Unit, - onStartEvent: (StartEvent) -> Unit -) { +private fun HelpScreen() { + val state = LocalHelpViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val onBrowseEvent = LocalBrowseViewModel.current.onEvent + val onStartEvent = LocalStartViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current + val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( @@ -171,7 +154,6 @@ private fun HelpScreen( customItems(Constants.HELP_TIPS, key = { it.title }) { helpTip -> HelpItem( helpTip = helpTip, - onNavigate = onNavigate, fromStart = state.value.fromStart ) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpItem.kt index ed582b7e..40cd6330 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/components/HelpItem.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.HelpTip -import ua.acclorite.book_story.domain.util.OnNavigate +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.ui.ExpandingTransition /** @@ -39,15 +39,15 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition * Can be Expanded or Collapsed. * * @param helpTip [HelpTip] to be shown. - * @param onNavigate Navigator callback. * @param fromStart Whether user came from Start screen. */ @Composable fun HelpItem( helpTip: HelpTip, - onNavigate: OnNavigate, fromStart: Boolean ) { + val onNavigate = LocalOnNavigate.current + val showDescription = rememberSaveable { mutableStateOf(false) } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt new file mode 100644 index 00000000..4c28b37d --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpEvent.kt @@ -0,0 +1,6 @@ +package ua.acclorite.book_story.presentation.screens.help.data + +import androidx.compose.runtime.Immutable + +@Immutable +sealed class HelpEvent \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt index 7fe472e3..b0955e3f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/help/data/HelpViewModel.kt @@ -1,22 +1,24 @@ package ua.acclorite.book_story.presentation.screens.help.data -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.presentation.data.Screen import javax.inject.Inject @HiltViewModel class HelpViewModel @Inject constructor( -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(HelpState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() + + override fun onEvent(event: HelpEvent) {} fun init(screen: Screen.Help) { viewModelScope.launch { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt index dd86b041..26d0e1b7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt @@ -24,8 +24,6 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -36,44 +34,36 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomSearchTextField import ua.acclorite.book_story.presentation.components.CustomSnackbar +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.history.components.HistoryDeleteWholeHistoryDialog 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.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.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions @Composable fun HistoryScreenRoot() { - val navigator = LocalNavigator.current - val viewModel: HistoryViewModel = hiltViewModel() - val libraryViewModel: LibraryViewModel = hiltViewModel() + val onEvent = LocalHistoryViewModel.current.onEvent - val state = viewModel.state.collectAsState() + LaunchedEffect(Unit) { + onEvent(HistoryEvent.OnUpdateScrollOffset) + } - HistoryScreen( - state = state, - onNavigate = { navigator.it() }, - onEvent = viewModel::onEvent, - onLibraryEvent = libraryViewModel::onEvent - ) + HistoryScreen() } @OptIn( @@ -81,13 +71,13 @@ fun HistoryScreenRoot() { ExperimentalMaterialApi::class ) @Composable -private fun HistoryScreen( - state: State, - onNavigate: OnNavigate, - onEvent: (HistoryEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit -) { +private fun HistoryScreen() { val context = LocalContext.current + val state = LocalHistoryViewModel.current.state + val onEvent = LocalHistoryViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current + val refreshState = rememberPullRefreshState( refreshing = state.value.isRefreshing, onRefresh = { @@ -97,15 +87,8 @@ private fun HistoryScreen( val focusRequester = remember { FocusRequester() } val snackbarState = remember { SnackbarHostState() } - LaunchedEffect(Unit) { - onEvent(HistoryEvent.OnUpdateScrollOffset) - } - if (state.value.showDeleteWholeHistoryDialog) { - HistoryDeleteWholeHistoryDialog( - onEvent = onEvent, - onLibraryLoadEvent = onLibraryEvent - ) + HistoryDeleteWholeHistoryDialog() } Scaffold( @@ -303,16 +286,4 @@ private fun HistoryScreen( navigate(Screen.Library) } } -} - - - - - - - - - - - - +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryDeleteWholeHistoryDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryDeleteWholeHistoryDialog.kt index c943735f..e0cdf01e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryDeleteWholeHistoryDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/components/HistoryDeleteWholeHistoryDialog.kt @@ -6,6 +6,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent @@ -15,11 +17,10 @@ import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent * Delete whole history dialog. */ @Composable -fun HistoryDeleteWholeHistoryDialog( - onEvent: (HistoryEvent) -> Unit, - onLibraryLoadEvent: (LibraryEvent.OnLoadList) -> Unit -) { +fun HistoryDeleteWholeHistoryDialog() { val context = LocalContext.current + val onEvent = LocalHistoryViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent CustomDialogWithContent( title = stringResource(id = R.string.delete_history), @@ -34,7 +35,7 @@ fun HistoryDeleteWholeHistoryDialog( onAction = { onEvent( HistoryEvent.OnDeleteWholeHistory { - onLibraryLoadEvent(LibraryEvent.OnLoadList) + onLibraryEvent(LibraryEvent.OnLoadList) } ) context.getString(R.string.history_deleted) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt index d15807f2..8ad3a9ec 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/data/HistoryViewModel.kt @@ -2,7 +2,6 @@ package ua.acclorite.book_story.presentation.screens.history.data import androidx.compose.foundation.lazy.LazyListState import androidx.compose.material3.SnackbarResult -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -21,6 +20,7 @@ import ua.acclorite.book_story.domain.use_case.DeleteWholeHistory import ua.acclorite.book_story.domain.use_case.GetBooksById import ua.acclorite.book_story.domain.use_case.GetHistory import ua.acclorite.book_story.domain.use_case.InsertHistory +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.presentation.data.Screen import java.text.SimpleDateFormat @@ -36,10 +36,10 @@ class HistoryViewModel @Inject constructor( private val deleteWholeHistory: DeleteWholeHistory, private val deleteHistory: DeleteHistory, private val getBooksById: GetBooksById -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(HistoryState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private var job: Job? = null private var job2: Job? = null @@ -56,7 +56,7 @@ class HistoryViewModel @Inject constructor( } } - fun onEvent(event: HistoryEvent) { + override fun onEvent(event: HistoryEvent) { when (event) { is HistoryEvent.OnRefreshList -> { job3?.cancel() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt index 3df3172d..607ef92e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/LibraryScreen.kt @@ -27,8 +27,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -41,47 +39,33 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.launch import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Category -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.header import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.showToast -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel -import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent -import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel import ua.acclorite.book_story.presentation.screens.library.components.LibraryBookItem import ua.acclorite.book_story.presentation.screens.library.components.LibraryTopBar 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.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryState -import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.Transitions @Composable fun LibraryScreenRoot() { - val navigator = LocalNavigator.current - val viewModel: LibraryViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - val browseViewModel: BrowseViewModel = hiltViewModel() - val historyViewModel: HistoryViewModel = hiltViewModel() - - val state = viewModel.state.collectAsState() - val mainState = mainViewModel.state.collectAsState() + val state = LocalLibraryViewModel.current.state + val onEvent = LocalLibraryViewModel.current.onEvent val pagerState = rememberPagerState( initialPage = state.value.currentPage, @@ -90,60 +74,43 @@ fun LibraryScreenRoot() { val refreshState = rememberPullRefreshState( refreshing = state.value.isRefreshing, onRefresh = { - viewModel.onEvent(LibraryEvent.OnRefreshList) + onEvent(LibraryEvent.OnRefreshList) } ) LaunchedEffect(Unit) { - viewModel.onEvent(LibraryEvent.OnScrollToPage(state.value.currentPage, pagerState)) + onEvent(LibraryEvent.OnScrollToPage(state.value.currentPage, pagerState)) } LaunchedEffect(pagerState.currentPage) { if (pagerState.currentPage != state.value.currentPage) { - viewModel.onEvent(LibraryEvent.OnUpdateCurrentPage(pagerState.currentPage)) + onEvent(LibraryEvent.OnUpdateCurrentPage(pagerState.currentPage)) } } LibraryScreen( - state = state, - mainState = mainState, - onNavigate = { navigator.it() }, pagerState = pagerState, - refreshState = refreshState, - onEvent = viewModel::onEvent, - onBrowseEvent = browseViewModel::onEvent, - onHistoryEvent = historyViewModel::onEvent + refreshState = refreshState ) } @OptIn(ExperimentalMaterialApi::class) @Composable private fun LibraryScreen( - state: State, - mainState: State, - onNavigate: OnNavigate, pagerState: PagerState, - refreshState: PullRefreshState, - onEvent: (LibraryEvent) -> Unit, - onHistoryEvent: (HistoryEvent) -> Unit, - onBrowseEvent: (BrowseEvent) -> Unit + refreshState: PullRefreshState ) { + val state = LocalLibraryViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalLibraryViewModel.current.onEvent + val onNavigate = LocalOnNavigate.current + var isScrollInProgress by remember { mutableStateOf(false) } if (state.value.showMoveDialog) { - LibraryMoveDialog( - state = state, - onEvent = onEvent, - onHistoryLoadEvent = onHistoryEvent, - pagerState = pagerState - ) + LibraryMoveDialog(pagerState = pagerState) } if (state.value.showDeleteDialog) { - LibraryDeleteDialog( - state = state, - onEvent = onEvent, - onBrowseLoadEvent = onBrowseEvent, - onHistoryLoadEvent = onHistoryEvent - ) + LibraryDeleteDialog() } Scaffold( @@ -152,11 +119,7 @@ private fun LibraryScreen( .pullRefresh(refreshState), containerColor = MaterialTheme.colorScheme.surface, topBar = { - LibraryTopBar( - state = state, - pagerState = pagerState, - onEvent = onEvent - ) + LibraryTopBar(pagerState = pagerState) } ) { paddingValues -> Box( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt index 66b6ca5b..3424ab8c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt @@ -20,7 +20,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -35,25 +34,21 @@ import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomSearchTextField +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryState /** * Library Top Bar. * Contains [AnimatedTopAppBar] and [LibraryTabRow]. * - * @param state [LibraryState]. * @param pagerState [PagerState]. - * @param onEvent [LibraryEvent] callback. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun LibraryTopBar( - state: State, - pagerState: PagerState, - onEvent: (LibraryEvent) -> Unit -) { +fun LibraryTopBar(pagerState: PagerState) { + val state = LocalLibraryViewModel.current.state + val onEvent = LocalLibraryViewModel.current.onEvent val focusRequester = remember { FocusRequester() } AnimatedTopAppBar( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryDeleteDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryDeleteDialog.kt index e5ac4e54..78717cdc 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryDeleteDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryDeleteDialog.kt @@ -3,28 +3,28 @@ package ua.acclorite.book_story.presentation.screens.library.components.dialog import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.DeleteOutline import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryState /** * Delete dialog. Deletes all selected books. */ @Composable -fun LibraryDeleteDialog( - state: State, - onEvent: (LibraryEvent) -> Unit, - onBrowseLoadEvent: (BrowseEvent.OnLoadList) -> Unit, - onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit -) { +fun LibraryDeleteDialog() { val context = LocalContext.current + val state = LocalLibraryViewModel.current.state + val onEvent = LocalLibraryViewModel.current.onEvent + val onBrowseEvent = LocalBrowseViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent CustomDialogWithContent( title = stringResource(id = R.string.delete_books), @@ -40,8 +40,8 @@ fun LibraryDeleteDialog( onAction = { onEvent( LibraryEvent.OnDeleteBooks { - onBrowseLoadEvent(BrowseEvent.OnLoadList) - onHistoryLoadEvent(HistoryEvent.OnLoadList) + onBrowseEvent(BrowseEvent.OnLoadList) + onHistoryEvent(HistoryEvent.OnLoadList) } ) context.getString(R.string.books_deleted) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt index 71955694..284eb85f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/dialog/LibraryMoveDialog.kt @@ -4,30 +4,28 @@ import androidx.compose.foundation.pager.PagerState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.DriveFileMove import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Category +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryState /** * Move dialog. Moves all selected books to the selected category. */ @Composable -fun LibraryMoveDialog( - state: State, - onEvent: (LibraryEvent) -> Unit, - onHistoryLoadEvent: (HistoryEvent.OnLoadList) -> Unit, - pagerState: PagerState -) { +fun LibraryMoveDialog(pagerState: PagerState) { val context = LocalContext.current + val state = LocalLibraryViewModel.current.state + val onEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent CustomDialogWithLazyColumn( title = stringResource(id = R.string.move_books), @@ -44,7 +42,7 @@ fun LibraryMoveDialog( LibraryEvent.OnMoveBooks( pagerState, refreshList = { - onHistoryLoadEvent(HistoryEvent.OnLoadList) + onHistoryEvent(HistoryEvent.OnLoadList) } ) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt index eb58b2fb..d3cd81b7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/data/LibraryViewModel.kt @@ -1,6 +1,5 @@ package ua.acclorite.book_story.presentation.screens.library.data -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -18,6 +17,7 @@ import ua.acclorite.book_story.domain.use_case.DeleteBooks import ua.acclorite.book_story.domain.use_case.GetBooks import ua.acclorite.book_story.domain.use_case.InsertHistory import ua.acclorite.book_story.domain.use_case.UpdateBooks +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.presentation.data.Screen import java.util.Date import javax.inject.Inject @@ -28,10 +28,10 @@ class LibraryViewModel @Inject constructor( private val updateBooks: UpdateBooks, private val deleteBooks: DeleteBooks, private val insertHistory: InsertHistory -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(LibraryState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private val _isReady = MutableStateFlow(false) val isReady = _isReady.asStateFlow() @@ -53,7 +53,7 @@ class LibraryViewModel @Inject constructor( } } - fun onEvent(event: LibraryEvent) { + override fun onEvent(event: LibraryEvent) { when (event) { is LibraryEvent.OnScrollToPage -> { viewModelScope.launch { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt index e66ae8cb..d3e6982b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt @@ -26,8 +26,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -49,24 +47,22 @@ import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.util.Constants -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomSelectionContainer +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel +import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel import ua.acclorite.book_story.presentation.components.customItemsIndexed import ua.acclorite.book_story.presentation.components.is_messages.IsError -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent -import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.screens.reader.components.ReaderEndItem import ua.acclorite.book_story.presentation.screens.reader.components.ReaderTextParagraph import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderBottomBar @@ -75,26 +71,16 @@ import ua.acclorite.book_story.presentation.screens.reader.components.readerFast import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet import ua.acclorite.book_story.presentation.screens.reader.components.start_item.ReaderStartItem import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel @Composable fun ReaderScreenRoot(screen: Screen.Reader) { - val navigator = LocalNavigator.current + val state = LocalReaderViewModel.current.state + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val viewModel = LocalReaderViewModel.current.viewModel val context = LocalContext.current as ComponentActivity + val onNavigate = LocalOnNavigate.current - val viewModel: ReaderViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - val libraryViewModel: LibraryViewModel = hiltViewModel() - val historyViewModel: HistoryViewModel = hiltViewModel() - val settingsViewModel: SettingsViewModel = hiltViewModel() - - val state = viewModel.state.collectAsState() - val mainState = mainViewModel.state.collectAsState() - val settingsState = settingsViewModel.state.collectAsState() val lazyListState = rememberSaveable( state.value.listState, @@ -111,11 +97,11 @@ fun ReaderScreenRoot(screen: Screen.Reader) { LaunchedEffect(Unit) { viewModel.init( screen = screen, - onNavigate = { navigator.it() }, + onNavigate = onNavigate, context = context, refreshList = { - libraryViewModel.onEvent(LibraryEvent.OnUpdateBook(it)) - historyViewModel.onEvent(HistoryEvent.OnLoadList) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnLoadList) }, onError = { it.asString(context) @@ -129,12 +115,14 @@ fun ReaderScreenRoot(screen: Screen.Reader) { } } LaunchedEffect(lazyListState) { - viewModel.onUpdateProgress( - onLibraryEvent = libraryViewModel::onEvent, - onHistoryEvent = historyViewModel::onEvent - ) + viewModel.onUpdateProgress { + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) + } } + ReaderScreen(lazyListState = lazyListState) + DisposableEffect(Unit) { onDispose { viewModel.clearViewModel() @@ -145,36 +133,19 @@ fun ReaderScreenRoot(screen: Screen.Reader) { context.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } } - - ReaderScreen( - state = state, - mainState = mainState, - settingsState = settingsState, - lazyListState = lazyListState, - onNavigate = { navigator.it() }, - onEvent = viewModel::onEvent, - onMainEvent = mainViewModel::onEvent, - onSettingsEvent = settingsViewModel::onEvent, - onLibraryEvent = libraryViewModel::onEvent, - onHistoryEvent = historyViewModel::onEvent - ) } @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -private fun ReaderScreen( - state: State, - mainState: State, - settingsState: State, - lazyListState: LazyListState, - onNavigate: OnNavigate, - onEvent: (ReaderEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit, - onHistoryEvent: (HistoryEvent) -> Unit, -) { +private fun ReaderScreen(lazyListState: LazyListState) { + val state = LocalReaderViewModel.current.state + val mainState = LocalMainViewModel.current.state + val settingsState = LocalSettingsViewModel.current.state + val onEvent = LocalReaderViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent val context = LocalContext.current as ComponentActivity + val onNavigate = LocalOnNavigate.current val nestedScrollConnection = remember(state) { object : NestedScrollConnection { @@ -230,13 +201,7 @@ private fun ReaderScreen( } if (state.value.showSettingsBottomSheet) { - ReaderSettingsBottomSheet( - mainState = mainState, - settingsState = settingsState, - onEvent = onEvent, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent - ) + ReaderSettingsBottomSheet() } Scaffold( @@ -250,13 +215,7 @@ private fun ReaderScreen( enter = slideInVertically { -it }, exit = slideOutVertically { -it } ) { - ReaderTopBar( - state = state, - onNavigate = onNavigate, - onEvent = onEvent, - onLibraryUpdateEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent - ) + ReaderTopBar() } }, bottomBar = { @@ -266,12 +225,7 @@ private fun ReaderScreen( enter = slideInVertically { it }, exit = slideOutVertically { it } ) { - ReaderBottomBar( - state = state, - onEvent = onEvent, - onLibraryUpdateEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent - ) + ReaderBottomBar() } } ) { @@ -357,7 +311,6 @@ private fun ReaderScreen( fastColorPresetChangeEnabled = mainState.value.fastColorPresetChange, isLoading = state.value.loading, toolbarHidden = toolbarHidden, - onSettingsEvent = onSettingsEvent, presetChanged = { context .getString( @@ -373,7 +326,7 @@ private fun ReaderScreen( ) { item { DisableSelection { - ReaderStartItem(state = state) + ReaderStartItem() } Spacer(modifier = Modifier.height(18.dp)) @@ -395,8 +348,7 @@ private fun ReaderScreen( sidePadding = sidePadding, paragraphIndentation = mainState.value.paragraphIndentation, doubleClickTranslationEnabled = mainState.value.doubleClickTranslation, - toolbarHidden = toolbarHidden, - onEvent = onEvent + toolbarHidden = toolbarHidden ) } @@ -404,13 +356,7 @@ private fun ReaderScreen( Spacer(modifier = Modifier.height(18.dp)) DisableSelection { - ReaderEndItem( - state = state, - onNavigate = onNavigate, - onEvent = onEvent, - onLibraryEvent = onLibraryEvent, - onHistoryUpdateEvent = onHistoryEvent, - ) + ReaderEndItem() } } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt index b5c070c5..ad7eee46 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderEndItem.kt @@ -17,7 +17,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -29,33 +28,30 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.Category -import ua.acclorite.book_story.domain.util.OnNavigate +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState /** * Reader end item. Displays at the end of the book. - * - * @param state [ReaderState]. - * @param onNavigate Navigator callback. - * @param onEvent [ReaderEvent] callback. - * @param onLibraryEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @OptIn(ExperimentalLayoutApi::class) @Composable fun ReaderEndItem( - state: State, - onNavigate: OnNavigate, - onEvent: (ReaderEvent) -> Unit, - onLibraryEvent: (LibraryEvent) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit, ) { + val state = LocalReaderViewModel.current.state + val onEvent = LocalReaderViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent val context = LocalContext.current as ComponentActivity + val onNavigate = LocalOnNavigate.current + val buttonText = remember { context.getString( if (state.value.book.category != Category.ALREADY_READ) R.string.move_to_read @@ -102,7 +98,7 @@ fun ReaderEndItem( context = context, onUpdateCategories = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, updatePage = { onLibraryEvent(LibraryEvent.OnUpdateCurrentPage(it)) @@ -119,7 +115,7 @@ fun ReaderEndItem( context = context, refreshList = { onLibraryEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { onNavigate { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderFastColorPresetChange.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderFastColorPresetChange.kt index 0644ba20..b75d395d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderFastColorPresetChange.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderFastColorPresetChange.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.pointerInput import ua.acclorite.book_story.domain.util.UIText +import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent /** @@ -16,7 +17,6 @@ import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent * @param fastColorPresetChangeEnabled Whether this is enabled. * @param isLoading Whether Reader is loading. * @param toolbarHidden Whether toolbar(selection) is hidden. - * @param onSettingsEvent [SettingsEvent] callback. * @param presetChanged Callback when Color Preset was changed. */ @Composable @@ -24,9 +24,10 @@ fun Modifier.readerFastColorPresetChange( fastColorPresetChangeEnabled: Boolean, isLoading: Boolean, toolbarHidden: Boolean, - onSettingsEvent: (SettingsEvent) -> Unit, presetChanged: (UIText) -> Unit ): Modifier { + val onSettingsEvent = LocalSettingsViewModel.current.onEvent + val offset = remember { mutableFloatStateOf(0f) } return this.then( if (fastColorPresetChangeEnabled && toolbarHidden && !isLoading) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderTextParagraph.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderTextParagraph.kt index fbe46297..6b28b079 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderTextParagraph.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/ReaderTextParagraph.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.FontWithName +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel import ua.acclorite.book_story.presentation.data.showToast import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment @@ -43,7 +44,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data. * @param paragraphIndentation Whether Paragraph Indentation is enabled for this line. * @param doubleClickTranslationEnabled Whether Double Click Translation is enabled. * @param toolbarHidden Whether selection toolBar is hidden. - * @param onEvent [ReaderEvent] callback. */ @OptIn(ExperimentalFoundationApi::class) @Composable @@ -60,9 +60,10 @@ fun LazyItemScope.ReaderTextParagraph( sidePadding: Dp, paragraphIndentation: Boolean, doubleClickTranslationEnabled: Boolean, - toolbarHidden: Boolean, - onEvent: (ReaderEvent) -> Unit + toolbarHidden: Boolean ) { + val onEvent = LocalReaderViewModel.current.onEvent + Column( modifier = Modifier .animateItem(fadeInSpec = null, fadeOutSpec = null) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt index 5d3de79c..309f450b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderBottomBar.kt @@ -14,36 +14,32 @@ import androidx.compose.material3.Slider import androidx.compose.material3.SliderDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel import ua.acclorite.book_story.presentation.data.removeDigits import ua.acclorite.book_story.presentation.data.removeTrailingZero import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState import ua.acclorite.book_story.presentation.ui.Colors /** * Reader bottom bar. Has a slider to change progress. - * - * @param state [ReaderState]. - * @param onEvent [ReaderEvent] callback. - * @param onLibraryUpdateEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @Composable -fun ReaderBottomBar( - state: State, - onEvent: (ReaderEvent) -> Unit, - onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit -) { +fun ReaderBottomBar() { + val state = LocalReaderViewModel.current.state + val onEvent = LocalReaderViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent + val progress by remember(state.value.book.progress) { derivedStateOf { (state.value.book.progress * 100) @@ -87,8 +83,8 @@ fun ReaderBottomBar( firstVisibleItemIndex = state.value.listState.firstVisibleItemIndex, firstVisibleItemOffset = 0, refreshList = { book -> - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(book)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(book)) + onLibraryEvent(LibraryEvent.OnUpdateBook(book)) + onHistoryEvent(HistoryEvent.OnUpdateBook(book)) } ) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt index 48575e3e..ee84ee57 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/app_bar/ReaderTopBar.kt @@ -14,7 +14,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontFamily @@ -22,34 +21,29 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.sp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomIconButton +import ua.acclorite.book_story.presentation.components.LocalHistoryViewModel +import ua.acclorite.book_story.presentation.components.LocalLibraryViewModel +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState import ua.acclorite.book_story.presentation.ui.Colors /** * Reader top bar. Displays title of the book. - * - * @param state [ReaderState]. - * @param onNavigate Navigator callback. - * @param onEvent [ReaderEvent] callback. - * @param onLibraryUpdateEvent [LibraryEvent] callback. - * @param onHistoryUpdateEvent [HistoryEvent] callback. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ReaderTopBar( - state: State, - onNavigate: OnNavigate, - onEvent: (ReaderEvent) -> Unit, - onLibraryUpdateEvent: (LibraryEvent.OnUpdateBook) -> Unit, - onHistoryUpdateEvent: (HistoryEvent.OnUpdateBook) -> Unit -) { +fun ReaderTopBar() { + val state = LocalReaderViewModel.current.state + val onEvent = LocalReaderViewModel.current.onEvent + val onLibraryEvent = LocalLibraryViewModel.current.onEvent + val onHistoryEvent = LocalHistoryViewModel.current.onEvent val context = LocalContext.current as ComponentActivity + val onNavigate = LocalOnNavigate.current TopAppBar( navigationIcon = { @@ -62,8 +56,8 @@ fun ReaderTopBar( ReaderEvent.OnGoBack( context = context, refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { onNavigate { @@ -94,8 +88,8 @@ fun ReaderTopBar( ReaderEvent.OnGoBack( context = context, refreshList = { - onLibraryUpdateEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryUpdateEvent(HistoryEvent.OnUpdateBook(it)) + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) }, navigate = { onNavigate { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt index 21c94108..cda87514 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheet.kt @@ -14,67 +14,49 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import ua.acclorite.book_story.presentation.components.CustomBottomSheet -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory /** * Settings bottom sheet. Has General and Colors categories. - * - * @param mainState [MainState]. - * @param settingsState [SettingsState]. - * @param onEvent [ReaderEvent] callback. - * @param onMainEvent [MainEvent] callback. - * @param onSettingsEvent [SettingsEvent] callback. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ReaderSettingsBottomSheet( - mainState: State, - settingsState: State, - onEvent: (ReaderEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit -) { - val pagerState = rememberPagerState { 2 } - val currentPage by remember { derivedStateOf { pagerState.currentPage } } +fun ReaderSettingsBottomSheet() { + val state = LocalReaderViewModel.current.state + val onEvent = LocalReaderViewModel.current.onEvent val context = LocalContext.current - val scrimColor = if (currentPage == 1) Color.Transparent - else BottomSheetDefaults.ScrimColor + val pagerState = rememberPagerState(state.value.currentPage) { 3 } val animatedScrimColor by animateColorAsState( - targetValue = scrimColor, - animationSpec = tween(300), - label = "Scrim animation" + targetValue = if (pagerState.currentPage == 2) Color.Transparent + else BottomSheetDefaults.ScrimColor, + animationSpec = tween(300) ) - - val height = remember(currentPage) { - if (currentPage == 1) 0.6f else 0.7f - } val animatedHeight by animateFloatAsState( - targetValue = height, - animationSpec = tween(300), - label = "Height animation" + targetValue = if (pagerState.currentPage == 2) 0.6f else 0.7f, + animationSpec = tween(300) ) - LaunchedEffect(currentPage) { + LaunchedEffect(pagerState.currentPage) { + onEvent( + ReaderEvent.OnScrollToSettingsPage( + page = pagerState.currentPage, + pagerState = null + ) + ) onEvent( ReaderEvent.OnShowHideMenu( - currentPage != 1, + pagerState.currentPage != 2, context as ComponentActivity ) ) @@ -91,17 +73,14 @@ fun ReaderSettingsBottomSheet( onEvent(ReaderEvent.OnShowHideSettingsBottomSheet) } ) { - ReaderSettingsBottomSheetTabRow( - onEvent = onEvent, - pagerState = pagerState - ) + ReaderSettingsBottomSheetTabRow(pagerState = pagerState) HorizontalPager(state = pagerState) { page -> LazyColumn { if (page == 0) { + if (page == 1) { + LazyColumn { ReaderSettingsCategory( - state = mainState, - onMainEvent = onMainEvent, titleColor = { MaterialTheme.colorScheme.onSurface }, topPadding = 16.dp, bottomPadding = 8.dp + it @@ -109,13 +88,9 @@ fun ReaderSettingsBottomSheet( } } - LazyColumn { - if (page == 1) { + if (page == 2) { + LazyColumn { ColorsSubcategory( - state = mainState, - settingsState = settingsState, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent, showTitle = false, backgroundColor = { MaterialTheme.colorScheme.surfaceContainer }, topPadding = 16.dp, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt index 784d2b53..b6289a63 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/settings_bottom_sheet/ReaderSettingsBottomSheetTabRow.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent /** @@ -24,6 +25,9 @@ fun ReaderSettingsBottomSheetTabRow( pagerState: PagerState ) { val tabItems = listOf( +fun ReaderSettingsBottomSheetTabRow(pagerState: PagerState) { + val onEvent = LocalReaderViewModel.current.onEvent + stringResource(id = R.string.general_tab), stringResource(id = R.string.color_tab) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/start_item/ReaderStartItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/start_item/ReaderStartItem.kt index 0eb1e82f..3fef6ce0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/start_item/ReaderStartItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/components/start_item/ReaderStartItem.kt @@ -23,7 +23,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -33,16 +32,16 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CustomCoverImage -import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState +import ua.acclorite.book_story.presentation.components.LocalReaderViewModel /** * Reader start item. Displays at the beginning of the book. - * - * @param state [ReaderState]. */ @OptIn(ExperimentalLayoutApi::class) @Composable -fun ReaderStartItem(state: State) { +fun ReaderStartItem() { + val state = LocalReaderViewModel.current.state + val statusBarHeight = WindowInsets .statusBarsIgnoringVisibility .asPaddingValues() diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt index 36a149af..3554e14f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt @@ -36,7 +36,7 @@ sealed class ReaderEvent { data class OnScroll(val progress: Float) : ReaderEvent() data object OnShowHideSettingsBottomSheet : ReaderEvent() - data class OnScrollToSettingsPage(val page: Int, val pagerState: PagerState) : ReaderEvent() + data class OnScrollToSettingsPage(val page: Int, val pagerState: PagerState?) : ReaderEvent() data class OnMoveBookToAlreadyRead( val context: ComponentActivity, val onUpdateCategories: (Book) -> Unit, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt index f583b1c7..0513a82f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.snapshotFlow import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -32,12 +31,11 @@ import ua.acclorite.book_story.domain.use_case.GetBookById import ua.acclorite.book_story.domain.use_case.GetLatestHistory import ua.acclorite.book_story.domain.use_case.GetText import ua.acclorite.book_story.domain.use_case.UpdateBooks +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.launchActivity -import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent -import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import javax.inject.Inject import kotlin.math.roundToInt @@ -48,14 +46,14 @@ class ReaderViewModel @Inject constructor( private val getText: GetText, private val getLatestHistory: GetLatestHistory, private val getBookById: GetBookById -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(ReaderState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private var eventJob = SupervisorJob() - fun onEvent(event: ReaderEvent) { + override fun onEvent(event: ReaderEvent) { viewModelScope.launch(eventJob + Dispatchers.Main) { when (event) { is ReaderEvent.OnTextIsEmpty -> { @@ -269,7 +267,6 @@ class ReaderViewModel @Inject constructor( launch(Dispatchers.IO) { _state.update { it.copy( - currentPage = if (it.showSettingsBottomSheet) it.currentPage else 0, showSettingsBottomSheet = !it.showSettingsBottomSheet ) } @@ -278,7 +275,13 @@ class ReaderViewModel @Inject constructor( is ReaderEvent.OnScrollToSettingsPage -> { launch { - event.pagerState.scrollToPage(event.page) + _state.update { + event.pagerState?.scrollToPage(event.page) + + it.copy( + currentPage = event.page + ) + } } } @@ -498,10 +501,7 @@ class ReaderViewModel @Inject constructor( } @OptIn(FlowPreview::class) - fun onUpdateProgress( - onLibraryEvent: (LibraryEvent) -> Unit, - onHistoryEvent: (HistoryEvent) -> Unit - ) { + fun onUpdateProgress(refreshList: (Book) -> Unit) { viewModelScope.launch { snapshotFlow { _state.value.listState.firstVisibleItemIndex to _state.value.listState.firstVisibleItemScrollOffset @@ -538,8 +538,7 @@ class ReaderViewModel @Inject constructor( firstVisibleItemIndex = firstVisibleItemIndex, firstVisibleItemOffset = firstVisibleItemScrollOffset, refreshList = { book -> - onLibraryEvent(LibraryEvent.OnUpdateBook(book)) - onHistoryEvent(HistoryEvent.OnUpdateBook(book)) + refreshList(book) } ) ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt index 1ae5608a..ab102116 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/SettingsScreen.kt @@ -24,26 +24,22 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryItem @Composable fun SettingsScreenRoot() { - val navigator = LocalNavigator.current - - SettingsScreen(onNavigate = { navigator.it() }) + SettingsScreen() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun SettingsScreen( - onNavigate: OnNavigate -) { +private fun SettingsScreen() { + val onNavigate = LocalOnNavigate.current val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/data/SettingsViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/data/SettingsViewModel.kt index 8d5cc3bf..74a9105a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/data/SettingsViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/data/SettingsViewModel.kt @@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.screens.settings.data import android.content.Intent import android.os.Build import android.provider.Settings -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted @@ -24,6 +23,7 @@ import ua.acclorite.book_story.domain.use_case.GetColorPresets import ua.acclorite.book_story.domain.use_case.ReorderColorPresets import ua.acclorite.book_story.domain.use_case.SelectColorPreset import ua.acclorite.book_story.domain.use_case.UpdateColorPreset +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.UIText @@ -39,10 +39,10 @@ class SettingsViewModel @Inject constructor( private val deleteColorPreset: DeleteColorPreset, private val selectColorPreset: SelectColorPreset, private val reorderColorPresets: ReorderColorPresets -) : ViewModel() { +) : BaseViewModel() { private val _state = MutableStateFlow(SettingsState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private val _isReady = MutableStateFlow(false) val isReady = _isReady.asStateFlow() @@ -93,7 +93,7 @@ class SettingsViewModel @Inject constructor( } @Suppress("LABEL_NAME_CLASH") - fun onEvent(event: SettingsEvent) { + override fun onEvent(event: SettingsEvent) { when (event) { is SettingsEvent.OnGeneralChangeCheckForUpdates -> { if (!event.enable) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt index 6ce66473..8c379ea4 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/AppearanceSettings.kt @@ -13,53 +13,25 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel -import ua.acclorite.book_story.presentation.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.data.LocalOnNavigate import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.AppearanceSettingsCategory @Composable fun AppearanceSettingsRoot() { - val navigator = LocalNavigator.current - val mainViewModel: MainViewModel = hiltViewModel() - val settingsViewModel: SettingsViewModel = hiltViewModel() - - val state = mainViewModel.state.collectAsState() - val settingsState = settingsViewModel.state.collectAsState() - - AppearanceSettings( - state = state, - settingsState = settingsState, - onNavigate = { navigator.it() }, - onMainEvent = mainViewModel::onEvent, - onSettingsEvent = settingsViewModel::onEvent - ) + AppearanceSettings() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun AppearanceSettings( - state: State, - settingsState: State, - onNavigate: OnNavigate, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit -) { +private fun AppearanceSettings() { + val onNavigate = LocalOnNavigate.current val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( @@ -91,12 +63,7 @@ private fun AppearanceSettings( .padding(top = paddingValues.calculateTopPadding()), state = scrollState.second ) { - AppearanceSettingsCategory( - state = state, - settingsState = settingsState, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent - ) + AppearanceSettingsCategory() } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/AppearanceSettingsCategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/AppearanceSettingsCategory.kt index c9300fc9..ea8cce2c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/AppearanceSettingsCategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/AppearanceSettingsCategory.kt @@ -5,14 +5,9 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance. import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ColorsSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory @@ -20,34 +15,21 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c * Appearance Settings Category. * Contains all Appearance settings such as Theme. * - * @param state [MainState] instance. - * @param onMainEvent [MainEvent] callback. - * @param onSettingsEvent [SettingsEvent] callback. * @param titleColor Title's color. * @param topPadding Top padding to be applied. * @param bottomPadding Bottom padding to be applied. */ fun LazyListScope.AppearanceSettingsCategory( - state: State, - settingsState: State, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, topPadding: Dp = 16.dp, bottomPadding: Dp = 48.dp ) { ThemePreferencesSubcategory( - state = state, - onMainEvent = onMainEvent, titleColor = titleColor, topPadding = topPadding, bottomPadding = 0.dp ) ColorsSubcategory( - state = state, - settingsState = settingsState, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent, titleColor = titleColor, topPadding = 22.dp, bottomPadding = bottomPadding diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ColorPresetSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ColorPresetSetting.kt index e3b73cf1..c829af51 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ColorPresetSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ColorPresetSetting.kt @@ -36,7 +36,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow @@ -64,10 +63,10 @@ import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomIconButton +import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel import ua.acclorite.book_story.presentation.components.customItemsIndexed import ua.acclorite.book_story.presentation.screens.settings.components.ColorPickerWithTitle import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace import ua.acclorite.book_story.presentation.ui.Transitions @@ -78,13 +77,14 @@ import ua.acclorite.book_story.presentation.ui.Transitions @OptIn(ExperimentalFoundationApi::class) @Composable fun ColorPresetSetting( - state: State, - onEvent: (SettingsEvent) -> Unit, backgroundColor: Color, verticalPadding: Dp = 8.dp, horizontalPadding: Dp = 18.dp ) { + val state = LocalSettingsViewModel.current.state + val onEvent = LocalSettingsViewModel.current.onEvent val context = LocalContext.current + val reorderableListState = rememberReorderableLazyListState( lazyListState = state.value.colorPresetsListState ) { from, to -> diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/DarkThemeSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/DarkThemeSetting.kt index 321c6a94..4acd4a45 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/DarkThemeSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/DarkThemeSetting.kt @@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance. import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.ui.DarkTheme @@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.ui.DarkTheme * If true, dark theme applied to the app's theme. */ @Composable -fun DarkThemeSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun DarkThemeSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SegmentedButtonWithTitle( title = stringResource(id = R.string.dark_theme_option), buttons = DarkTheme.entries.map { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/FastColorPresetChangeSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/FastColorPresetChangeSetting.kt index c17447d7..b052207f 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/FastColorPresetChangeSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/FastColorPresetChangeSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi * If true, user can fast change color presets in Reader with swipes. */ @Composable -fun FastColorPresetChangeSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun FastColorPresetChangeSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SwitchWithTitle( selected = state.value.fastColorPresetChange, title = stringResource(id = R.string.fast_color_preset_change_option), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/PureDarkSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/PureDarkSetting.kt index 669b141a..40b5a411 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/PureDarkSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/PureDarkSetting.kt @@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance. import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState 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.PureDark @@ -18,10 +17,10 @@ import ua.acclorite.book_story.presentation.ui.isDark * If true, enables Pure Dark (OLED) theme. */ @Composable -fun PureDarkSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun PureDarkSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + ExpandingTransition(visible = state.value.darkTheme.isDark()) { SegmentedButtonWithTitle( title = stringResource(id = R.string.pure_dark_option), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeContrastSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeContrastSetting.kt index c73e1258..4257171c 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeContrastSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeContrastSetting.kt @@ -3,15 +3,14 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.appearance. import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState 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.ExpandingTransition @@ -25,10 +24,10 @@ import ua.acclorite.book_story.presentation.ui.isPureDark * Lets user change theme contrast levels. */ @Composable -fun ThemeContrastSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun ThemeContrastSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val themeContrastTheme = remember { mutableStateOf(state.value.theme) } LaunchedEffect(state.value.theme) { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeSetting.kt index d0a112ef..4e15ce1b 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/settings/ThemeSetting.kt @@ -27,7 +27,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -42,9 +41,9 @@ import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.customItemsIndexed import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.ui.Theme import ua.acclorite.book_story.presentation.ui.ThemeContrast import ua.acclorite.book_story.presentation.ui.animatedColorScheme @@ -57,11 +56,12 @@ import ua.acclorite.book_story.presentation.ui.isPureDark */ @Composable fun ThemeSetting( - state: State, - onMainEvent: (MainEvent) -> Unit, verticalPadding: Dp = 8.dp, horizontalPadding: Dp = 18.dp ) { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val themes = remember { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Constants.THEMES else Constants.THEMES.dropWhile { it.first == Theme.DYNAMIC } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ColorsSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ColorsSubcategory.kt index 408e066b..70159772 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ColorsSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ColorsSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,10 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsState import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ColorPresetSetting import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.FastColorPresetChangeSetting @@ -29,10 +24,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c * Contains all settings from Colors. */ fun LazyListScope.ColorsSubcategory( - state: State, - settingsState: State, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.colors_appearance_settings) }, backgroundColor: @Composable () -> Color = { MaterialTheme.colorScheme.surfaceContainerLow }, @@ -59,18 +50,11 @@ fun LazyListScope.ColorsSubcategory( } item { - ColorPresetSetting( - state = settingsState, - backgroundColor = backgroundColor.invoke(), - onEvent = onSettingsEvent - ) + ColorPresetSetting(backgroundColor = backgroundColor.invoke()) } item { - FastColorPresetChangeSetting( - state = state, - onMainEvent = onMainEvent - ) + FastColorPresetChangeSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt index 87acf1fa..edca37a3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/appearance/components/subcategories/ThemePreferencesSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.DarkThemeSetting import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.PureDarkSetting import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.settings.ThemeContrastSetting @@ -29,8 +26,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.c * Contains all settings from Theme Preferences. */ fun LazyListScope.ThemePreferencesSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.theme_appearance_settings) }, showTitle: Boolean = true, @@ -56,31 +51,19 @@ fun LazyListScope.ThemePreferencesSubcategory( } item { - DarkThemeSetting( - state = state, - onMainEvent = onMainEvent - ) + DarkThemeSetting() } item { - ThemeSetting( - state = state, - onMainEvent = onMainEvent - ) + ThemeSetting() } item { - ThemeContrastSetting( - state = state, - onMainEvent = onMainEvent - ) + ThemeContrastSetting() } item { - PureDarkSetting( - state = state, - onMainEvent = onMainEvent - ) + PureDarkSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/BrowseSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/BrowseSettings.kt index 61277839..f58d95ff 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/BrowseSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/BrowseSettings.kt @@ -13,44 +13,25 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.BrowseSettingsCategory @Composable fun BrowseSettingsRoot() { - val navigator = LocalNavigator.current - val mainViewModel: MainViewModel = hiltViewModel() - - val state = mainViewModel.state.collectAsState() - - BrowseSettings( - state = state, - onNavigate = { navigator.it() }, - onMainEvent = mainViewModel::onEvent - ) + BrowseSettings() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun BrowseSettings( - state: State, - onNavigate: OnNavigate, - onMainEvent: (MainEvent) -> Unit -) { +private fun BrowseSettings() { + val onNavigate = LocalOnNavigate.current val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( @@ -82,10 +63,7 @@ private fun BrowseSettings( .padding(top = paddingValues.calculateTopPadding()), state = scrollState.second ) { - BrowseSettingsCategory( - state = state, - onMainEvent = onMainEvent - ) + BrowseSettingsCategory() } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/BrowseSettingsCategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/BrowseSettingsCategory.kt index 380a64bd..b121b9c7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/BrowseSettingsCategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/BrowseSettingsCategory.kt @@ -3,11 +3,8 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.runtime.State import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseGeneralSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseSortSubcategory @@ -16,32 +13,22 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo * Browse Settings Category. * Contains all Browse settings. * - * @param state [MainState] instance. - * @param onMainEvent [MainEvent] callback. * @param topPadding Top padding to be applied. * @param bottomPadding Bottom padding to be applied. */ fun LazyListScope.BrowseSettingsCategory( - state: State, - onMainEvent: (MainEvent) -> Unit, topPadding: Dp = 16.dp, bottomPadding: Dp = 48.dp ) { BrowseGeneralSubcategory( - state = state, - onMainEvent = onMainEvent, topPadding = topPadding, bottomPadding = 0.dp ) BrowseFilterSubcategory( - state = state, - onMainEvent = onMainEvent, topPadding = 22.dp, bottomPadding = 0.dp ) BrowseSortSubcategory( - state = state, - onMainEvent = onMainEvent, topPadding = 22.dp, bottomPadding = bottomPadding ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilesStructureSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilesStructureSetting.kt index 9631f29c..f0d1e2ba 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilesStructureSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilesStructureSetting.kt @@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure @@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data. * Lets user choose between all and folders structure for Browse. */ @Composable -fun BrowseFilesStructureSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun BrowseFilesStructureSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SegmentedButtonWithTitle( title = stringResource(id = R.string.browse_files_structure_option), buttons = BrowseFilesStructure.entries.map { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilterSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilterSetting.kt index b925d003..1c32bbdc 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilterSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseFilterSetting.kt @@ -13,25 +13,24 @@ import androidx.compose.material3.Checkbox import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState /** * Browse Filter setting. * Lets user choose which items to filter in Browse. */ -fun LazyListScope.BrowseFilterSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun LazyListScope.BrowseFilterSetting() { customItems(Constants.EXTENSIONS, key = { it }) { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + FilterItem( item = it, isSelected = state.value.browseIncludedFilterItems.any { item -> diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseGridSizeSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseGridSizeSetting.kt index c66c0e03..da9836bd 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseGridSizeSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseGridSizeSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState 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.ui.ExpandingTransition @@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition * Lets user specify grid size to be displayed. */ @Composable -fun BrowseGridSizeSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun BrowseGridSizeSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + ExpandingTransition(visible = state.value.browseLayout == BrowseLayout.GRID) { SliderWithTitle( value = state.value.browseGridSize diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseLayoutSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseLayoutSetting.kt index cb211ac9..2aabe781 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseLayoutSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseLayoutSetting.kt @@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.comp import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout @@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data. * Lets user choose between layouts(list, grid). */ @Composable -fun BrowseLayoutSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun BrowseLayoutSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SegmentedButtonWithTitle( title = stringResource(id = R.string.browse_layout_option), buttons = BrowseLayout.entries.map { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowsePinFavoriteDirectoriesSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowsePinFavoriteDirectoriesSetting.kt index 95d81bed..e45d3049 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowsePinFavoriteDirectoriesSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowsePinFavoriteDirectoriesSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState 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.ui.ExpandingTransition @@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.ui.ExpandingTransition * If true, shows all favorite directories in root directory and moves them to the top in nested directories. */ @Composable -fun BrowsePinFavoriteDirectoriesSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun BrowsePinFavoriteDirectoriesSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + ExpandingTransition(visible = state.value.browseFilesStructure == BrowseFilesStructure.DIRECTORIES) { SwitchWithTitle( selected = state.value.browsePinFavoriteDirectories, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseSortOrderSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseSortOrderSetting.kt index 40026847..f7e49bf5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseSortOrderSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/settings/BrowseSortOrderSetting.kt @@ -17,7 +17,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -25,20 +24,20 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.components.customItems import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseSortOrder /** * Browse Sort Order setting. * Lets user choose how to sort files in Browse. */ -fun LazyListScope.BrowseSortOrderSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun LazyListScope.BrowseSortOrderSetting() { customItems(BrowseSortOrder.entries, key = { it.name }) { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SortItem( item = it, isSelected = state.value.browseSortOrder == it, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseFilterSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseFilterSubcategory.kt index fbbb02c3..432b3ec3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseFilterSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseFilterSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilterSetting /** @@ -26,8 +23,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo * Contains all settings from Filter Browse settings. */ fun LazyListScope.BrowseFilterSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.filter_browse_settings) }, showTitle: Boolean = true, @@ -52,10 +47,7 @@ fun LazyListScope.BrowseFilterSubcategory( } } - BrowseFilterSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowseFilterSetting() item { Spacer( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseGeneralSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseGeneralSubcategory.kt index da51fd50..fff49040 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseGeneralSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseGeneralSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseFilesStructureSetting import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseGridSizeSetting import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseLayoutSetting @@ -29,8 +26,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo * Contains all settings from General Browse settings. */ fun LazyListScope.BrowseGeneralSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.general_browse_settings) }, showTitle: Boolean = true, @@ -56,31 +51,19 @@ fun LazyListScope.BrowseGeneralSubcategory( } item { - BrowseFilesStructureSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowseFilesStructureSetting() } item { - BrowsePinFavoriteDirectoriesSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowsePinFavoriteDirectoriesSetting() } item { - BrowseLayoutSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowseLayoutSetting() } item { - BrowseGridSizeSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowseGridSizeSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseSortSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseSortSubcategory.kt index 38ce68f2..7dcb49ac 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseSortSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/browse/components/subcategories/BrowseSortSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.settings.BrowseSortOrderSetting /** @@ -26,8 +23,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.browse.compo * Contains all settings from Sort Browse settings. */ fun LazyListScope.BrowseSortSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.sort_browse_settings) }, showTitle: Boolean = true, @@ -52,10 +47,7 @@ fun LazyListScope.BrowseSortSubcategory( } } - BrowseSortOrderSetting( - state = state, - onMainEvent = onMainEvent - ) + BrowseSortOrderSetting() item { Spacer( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt index 8f0a5e8b..8fbb8a63 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/GeneralSettings.kt @@ -12,50 +12,26 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.GeneralSettingsCategory @Composable fun GeneralSettingsRoot() { - val navigator = LocalNavigator.current - val settingsViewModel: SettingsViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - - val state = mainViewModel.state.collectAsState() - - GeneralSettings( - state = state, - onNavigate = { navigator.it() }, - onSettingsEvent = settingsViewModel::onEvent, - onMainEvent = mainViewModel::onEvent - ) + GeneralSettings() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun GeneralSettings( - state: State, - onNavigate: OnNavigate, - onSettingsEvent: (SettingsEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit -) { +private fun GeneralSettings() { + val onNavigate = LocalOnNavigate.current val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( @@ -86,11 +62,7 @@ private fun GeneralSettings( .padding(top = paddingValues.calculateTopPadding()), state = scrollState.second ) { - GeneralSettingsCategory( - state = state, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent - ) + GeneralSettingsCategory() } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/GeneralSettingsCategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/GeneralSettingsCategory.kt index 51f90778..37141667 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/GeneralSettingsCategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/GeneralSettingsCategory.kt @@ -5,14 +5,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.AppLanguageSetting import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.CheckForUpdatesSetting import ua.acclorite.book_story.presentation.screens.settings.nested.general.components.settings.DoublePressExitSetting @@ -21,16 +17,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.general.comp * General Settings Category. * Contains all General settings such as App Language. * - * @param state [MainState] instance. - * @param onMainEvent [MainEvent] callback. - * @param onSettingsEvent [SettingsEvent] callback. * @param topPadding Top padding to be applied. * @param bottomPadding Bottom padding to be applied. */ fun LazyListScope.GeneralSettingsCategory( - state: State, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit, topPadding: Dp = 16.dp, bottomPadding: Dp = 48.dp ) { @@ -41,25 +31,15 @@ fun LazyListScope.GeneralSettingsCategory( } item { - AppLanguageSetting( - state = state, - onMainEvent = onMainEvent - ) + AppLanguageSetting() } item { - CheckForUpdatesSetting( - state = state, - onMainEvent = onMainEvent, - onSettingsEvent = onSettingsEvent - ) + CheckForUpdatesSetting() } item { - DoublePressExitSetting( - state = state, - onMainEvent = onMainEvent - ) + DoublePressExitSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/AppLanguageSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/AppLanguageSetting.kt index 7f982c38..e50674f6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/AppLanguageSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/AppLanguageSetting.kt @@ -2,13 +2,12 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle /** @@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit * Changes app's language. */ @Composable -fun AppLanguageSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun AppLanguageSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + ChipsWithTitle( title = stringResource(id = R.string.language_option), chips = Constants.LANGUAGES.sortedBy { it.second }.map { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/CheckForUpdatesSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/CheckForUpdatesSetting.kt index 2708bce3..ac0dc8b3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/CheckForUpdatesSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/CheckForUpdatesSetting.kt @@ -6,7 +6,6 @@ import androidx.activity.ComponentActivity import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Security import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext @@ -14,9 +13,10 @@ import androidx.compose.ui.res.stringResource import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberPermissionState import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.components.LocalSettingsViewModel import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent @@ -27,12 +27,12 @@ import ua.acclorite.book_story.presentation.screens.settings.data.SettingsEvent @OptIn(ExperimentalPermissionsApi::class) @SuppressLint("InlinedApi") @Composable -fun CheckForUpdatesSetting( - state: State, - onMainEvent: (MainEvent) -> Unit, - onSettingsEvent: (SettingsEvent) -> Unit -) { +fun CheckForUpdatesSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val onSettingsEvent = LocalSettingsViewModel.current.onEvent val activity = LocalContext.current as ComponentActivity + val notificationsPermissionState = rememberPermissionState( permission = Manifest.permission.POST_NOTIFICATIONS ) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/DoublePressExitSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/DoublePressExitSetting.kt index c2616efd..f2c2542e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/DoublePressExitSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/general/components/settings/DoublePressExitSetting.kt @@ -2,11 +2,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.general.com import android.annotation.SuppressLint import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle /** @@ -15,10 +14,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi */ @SuppressLint("InlinedApi") @Composable -fun DoublePressExitSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun DoublePressExitSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SwitchWithTitle( selected = state.value.doublePressExit, title = stringResource(id = R.string.double_press_exit_option), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt index ffe66118..12b319ad 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/ReaderSettings.kt @@ -12,44 +12,25 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.presentation.components.CustomLazyColumn import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState -import ua.acclorite.book_story.presentation.data.LocalNavigator -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState -import ua.acclorite.book_story.presentation.data.MainViewModel +import ua.acclorite.book_story.presentation.data.LocalOnNavigate import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.ReaderSettingsCategory @Composable fun ReaderSettingsRoot() { - val navigator = LocalNavigator.current - val mainViewModel: MainViewModel = hiltViewModel() - - val state = mainViewModel.state.collectAsState() - - ReaderSettings( - state = state, - onNavigate = { navigator.it() }, - onMainEvent = mainViewModel::onEvent - ) + ReaderSettings() } @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun ReaderSettings( - state: State, - onNavigate: OnNavigate, - onMainEvent: (MainEvent) -> Unit -) { +private fun ReaderSettings() { + val onNavigate = LocalOnNavigate.current val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() Scaffold( @@ -80,10 +61,7 @@ private fun ReaderSettings( .padding(top = paddingValues.calculateTopPadding()), state = scrollState.second ) { - ReaderSettingsCategory( - state = state, - onMainEvent = onMainEvent - ) + ReaderSettingsCategory() } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/ReaderSettingsCategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/ReaderSettingsCategory.kt index 18841159..63d184cb 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/ReaderSettingsCategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/ReaderSettingsCategory.kt @@ -5,13 +5,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.FontSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TextSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.subcategories.TranslatorSubcategory @@ -20,36 +17,26 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo * Reader Settings Category. * Contains all Reader settings. * - * @param state [MainState] instance. - * @param onMainEvent [MainEvent] callback. * @param titleColor Color that [CategoryTitle] has. * @param topPadding Top padding to be applied. * @param bottomPadding Bottom padding to be applied. */ fun LazyListScope.ReaderSettingsCategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, topPadding: Dp = 16.dp, bottomPadding: Dp = 48.dp ) { FontSubcategory( - state = state, - onMainEvent = onMainEvent, titleColor = titleColor, topPadding = topPadding, bottomPadding = 0.dp ) TextSubcategory( - state, - onMainEvent = onMainEvent, titleColor = titleColor, topPadding = 22.dp, bottomPadding = 0.dp ) TranslatorSubcategory( - state, - onMainEvent = onMainEvent, titleColor = titleColor, topPadding = 22.dp, bottomPadding = bottomPadding diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/DoubleClickTranslationSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/DoubleClickTranslationSetting.kt index e8466dac..a34f0fd0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/DoubleClickTranslationSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/DoubleClickTranslationSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi * Changes Reader's double click translation. */ @Composable -fun DoubleClickTranslationSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun DoubleClickTranslationSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SwitchWithTitle( selected = state.value.doubleClickTranslation, title = stringResource(id = R.string.double_click_translation_option), diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontFamilySetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontFamilySetting.kt index d0a15304..8c429056 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontFamilySetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontFamilySetting.kt @@ -2,14 +2,13 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWithTitle /** @@ -17,10 +16,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.ChipsWit * Changes Reader's font, uses fonts from [Constants.FONTS]. */ @Composable -fun FontFamilySetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun FontFamilySetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val fontFamily = remember(state.value.fontFamily) { Constants.FONTS.find { it.id == state.value.fontFamily diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontSizeSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontSizeSetting.kt index 88cb2069..a86258c2 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontSizeSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontSizeSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi * Changes Reader's font size. */ @Composable -fun FontSizeSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun FontSizeSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SliderWithTitle( value = state.value.fontSize to "pt", fromValue = 10, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontStyleSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontStyleSetting.kt index 660eafe3..b0f4b565 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontStyleSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/FontStyleSetting.kt @@ -2,15 +2,14 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle /** @@ -18,10 +17,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.Segmente * Changes Reader's font style (Normal/Italic). */ @Composable -fun FontStyleSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun FontStyleSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + val fontFamily = remember(state.value.fontFamily) { Constants.FONTS.find { it.id == state.value.fontFamily diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LetterSpacingSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LetterSpacingSetting.kt index 4417fef9..4e047be9 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LetterSpacingSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LetterSpacingSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi * Changes Reader's letter spacing. */ @Composable -fun LetterSpacingSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun LetterSpacingSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SliderWithTitle( value = state.value.letterSpacing to "pt", fromValue = -8, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LineHeightSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LineHeightSetting.kt index f2969a3d..eddf7818 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LineHeightSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/LineHeightSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi * Changes Reader's line height. */ @Composable -fun LineHeightSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun LineHeightSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SliderWithTitle( value = state.value.lineHeight to "pt", fromValue = 1, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphHeightSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphHeightSetting.kt index 6143c69a..e53ecfd0 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphHeightSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphHeightSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi * Changes Reader's paragraph height. */ @Composable -fun ParagraphHeightSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun ParagraphHeightSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SliderWithTitle( value = state.value.paragraphHeight to "pt", fromValue = 0, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphIndentationSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphIndentationSetting.kt index df0361dd..8e151e27 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphIndentationSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/ParagraphIndentationSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SwitchWi * Changes Reader's paragraph indentation. */ @Composable -fun ParagraphIndentationSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun ParagraphIndentationSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SwitchWithTitle( selected = state.value.paragraphIndentation, title = stringResource(id = R.string.paragraph_indentation_option) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/SidePaddingSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/SidePaddingSetting.kt index 89dd7011..2c9b9716 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/SidePaddingSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/SidePaddingSetting.kt @@ -1,11 +1,10 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SliderWithTitle /** @@ -13,10 +12,10 @@ import ua.acclorite.book_story.presentation.screens.settings.components.SliderWi * Changes Reader's side padding. */ @Composable -fun SidePaddingSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun SidePaddingSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SliderWithTitle( value = state.value.sidePadding to "pt", fromValue = 1, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/TextAlignmentSetting.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/TextAlignmentSetting.kt index 838a9cee..0d4af30d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/TextAlignmentSetting.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/settings/TextAlignmentSetting.kt @@ -2,12 +2,11 @@ package ua.acclorite.book_story.presentation.screens.settings.nested.reader.comp import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem +import ua.acclorite.book_story.presentation.components.LocalMainViewModel import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.components.SegmentedButtonWithTitle import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data.ReaderTextAlignment @@ -16,10 +15,10 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.data. * Changes Reader's text alignment (Start/Justify/Center/End). */ @Composable -fun TextAlignmentSetting( - state: State, - onMainEvent: (MainEvent) -> Unit -) { +fun TextAlignmentSetting() { + val state = LocalMainViewModel.current.state + val onMainEvent = LocalMainViewModel.current.onEvent + SegmentedButtonWithTitle( title = stringResource(id = R.string.text_alignment_option), buttons = ReaderTextAlignment.entries.map { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/FontSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/FontSubcategory.kt index 8bebab86..7472e4e5 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/FontSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/FontSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontFamilySetting import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontSizeSetting import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.FontStyleSetting @@ -29,8 +26,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo * Contains all settings from Font. */ fun LazyListScope.FontSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.font_reader_settings) }, showTitle: Boolean = true, @@ -56,31 +51,19 @@ fun LazyListScope.FontSubcategory( } item { - FontFamilySetting( - state = state, - onMainEvent = onMainEvent - ) + FontFamilySetting() } item { - FontStyleSetting( - state = state, - onMainEvent = onMainEvent - ) + FontStyleSetting() } item { - FontSizeSetting( - state = state, - onMainEvent = onMainEvent - ) + FontSizeSetting() } item { - LetterSpacingSetting( - state = state, - onMainEvent = onMainEvent - ) + LetterSpacingSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TextSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TextSubcategory.kt index 6b278781..47506b01 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TextSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TextSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.LineHeightSetting import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.ParagraphHeightSetting import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.ParagraphIndentationSetting @@ -30,8 +27,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo * Contains all settings from Text. */ fun LazyListScope.TextSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.text_reader_settings) }, showTitle: Boolean = true, @@ -57,38 +52,23 @@ fun LazyListScope.TextSubcategory( } item { - TextAlignmentSetting( - state = state, - onMainEvent = onMainEvent - ) + TextAlignmentSetting() } item { - SidePaddingSetting( - state = state, - onMainEvent = onMainEvent - ) + SidePaddingSetting() } item { - LineHeightSetting( - state = state, - onMainEvent = onMainEvent - ) + LineHeightSetting() } item { - ParagraphHeightSetting( - state = state, - onMainEvent = onMainEvent - ) + ParagraphHeightSetting() } item { - ParagraphIndentationSetting( - state = state, - onMainEvent = onMainEvent - ) + ParagraphIndentationSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TranslatorSubcategory.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TranslatorSubcategory.kt index 86c1bbe5..30f21891 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TranslatorSubcategory.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/settings/nested/reader/components/subcategories/TranslatorSubcategory.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -17,8 +16,6 @@ import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.components.CategoryTitle -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.reader.components.settings.DoubleClickTranslationSetting /** @@ -26,8 +23,6 @@ import ua.acclorite.book_story.presentation.screens.settings.nested.reader.compo * Contains all settings from Translator. */ fun LazyListScope.TranslatorSubcategory( - state: State, - onMainEvent: (MainEvent) -> Unit, titleColor: @Composable () -> Color = { MaterialTheme.colorScheme.primary }, title: @Composable () -> String = { stringResource(id = R.string.translator_reader_settings) }, showTitle: Boolean = true, @@ -53,10 +48,7 @@ fun LazyListScope.TranslatorSubcategory( } item { - DoubleClickTranslationSetting( - state = state, - onMainEvent - ) + DoubleClickTranslationSetting() } item { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/StartScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/StartScreen.kt index f9a5f775..2f253412 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/StartScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/StartScreen.kt @@ -8,33 +8,20 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.ui.platform.LocalContext -import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.rememberPermissionState -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.browse.data.BrowseEvent -import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.screens.start.components.StartDone import ua.acclorite.book_story.presentation.screens.start.components.StartSettings 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 @SuppressLint("InlinedApi") @Composable fun StartScreenRoot() { - val startViewModel: StartViewModel = hiltViewModel() - val mainViewModel: MainViewModel = hiltViewModel() - val browseViewModel: BrowseViewModel = hiltViewModel() + val viewModel = LocalStartViewModel.current.viewModel - val state = startViewModel.state.collectAsState() - val mainState = mainViewModel.state.collectAsState() val storagePermissionState = rememberPermissionState( permission = Manifest.permission.READ_EXTERNAL_STORAGE ) @@ -43,20 +30,15 @@ fun StartScreenRoot() { ) LaunchedEffect(Unit) { - startViewModel.checkPermissions( + viewModel.checkPermissions( storagePermissionState = storagePermissionState, notificationPermissionState = notificationsPermissionState ) } StartScreen( - state = state, - mainState = mainState, storagePermissionState = storagePermissionState, notificationsPermissionState = notificationsPermissionState, - onEvent = startViewModel::onEvent, - onMainEvent = mainViewModel::onEvent, - onBrowseEvent = browseViewModel::onEvent ) } @@ -64,33 +46,20 @@ fun StartScreenRoot() { @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "InlinedApi") @Composable private fun StartScreen( - state: State, - mainState: State, storagePermissionState: PermissionState, - notificationsPermissionState: PermissionState, - onEvent: (StartEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, - onBrowseEvent: (BrowseEvent) -> Unit, + notificationsPermissionState: PermissionState ) { + val onEvent = LocalStartViewModel.current.onEvent val activity = LocalContext.current as ComponentActivity // Settings StartSettings( - state = state, - mainState = mainState, - onEvent = onEvent, - onMainEvent = onMainEvent, storagePermissionState = storagePermissionState, notificationsPermissionState = notificationsPermissionState ) // Done - StartDone( - state = state, - onEvent = onEvent, - onMainEvent = onMainEvent, - onBrowseEvent = onBrowseEvent - ) + StartDone() BackHandler { onEvent( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartAppearanceScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartAppearanceScreen.kt index 13f0856b..b46e7eba 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartAppearanceScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartAppearanceScreen.kt @@ -1,24 +1,16 @@ package ua.acclorite.book_story.presentation.screens.start.components import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.runtime.State import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.components.subcategories.ThemePreferencesSubcategory /** * Appearance settings. */ -fun LazyListScope.startAppearanceScreen( - mainState: State, - onMainEvent: (MainEvent) -> Unit -) { +fun LazyListScope.startAppearanceScreen() { ThemePreferencesSubcategory( - state = mainState, - onMainEvent = onMainEvent, title = { stringResource(id = R.string.start_theme_preferences) }, topPadding = 16.dp, bottomPadding = 8.dp diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt index 25f566e0..a847f31d 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartDone.kt @@ -20,7 +20,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -28,34 +27,29 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.components.LocalBrowseViewModel +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.start.data.StartEvent -import ua.acclorite.book_story.presentation.screens.start.data.StartState /** * Start Done screen. - * - * @param state [StartState]. - * @param onEvent [StartEvent] callback. - * @param onMainEvent [MainEvent] callback. - * @param onBrowseEvent [BrowseEvent] callback. */ @Composable -fun StartDone( - state: State, - onEvent: (StartEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, - onBrowseEvent: (BrowseEvent) -> Unit -) { +fun StartDone() { + val state = LocalStartViewModel.current.state + val onEvent = LocalStartViewModel.current.onEvent + val onMainEvent = LocalMainViewModel.current.onEvent + val onBrowseEvent = LocalBrowseViewModel.current.onEvent val navigator = LocalNavigator.current StartNavigationTransition( modifier = Modifier .verticalScroll(rememberScrollState()) .padding(48.dp), - state = state, visible = state.value.isDone, verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationScreenItem.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationScreenItem.kt index ac7ba656..8eafb952 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationScreenItem.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationScreenItem.kt @@ -6,12 +6,11 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Modifier import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomLazyColumn +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.screens.start.data.StartNavigationScreen -import ua.acclorite.book_story.presentation.screens.start.data.StartState import ua.acclorite.book_story.presentation.ui.Transitions /** @@ -19,10 +18,10 @@ import ua.acclorite.book_story.presentation.ui.Transitions */ @Composable fun StartNavigationScreenItem( - state: State, screen: StartNavigationScreen, content: LazyListScope.() -> Unit ) { + val state = LocalStartViewModel.current.state val listState = rememberLazyListState() CustomAnimatedVisibility( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationTransition.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationTransition.kt index 1b84a208..56c637e7 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationTransition.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartNavigationTransition.kt @@ -8,11 +8,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility -import ua.acclorite.book_story.presentation.screens.start.data.StartState +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.ui.Transitions /** @@ -21,13 +20,14 @@ import ua.acclorite.book_story.presentation.ui.Transitions @Composable fun StartNavigationTransition( modifier: Modifier = Modifier, - state: State, visible: Boolean, bottomBar: @Composable () -> Unit, horizontalAlignment: Alignment.Horizontal = Alignment.Start, verticalArrangement: Arrangement.Vertical = Arrangement.Top, content: @Composable ColumnScope.() -> Unit ) { + val state = LocalStartViewModel.current.state + CustomAnimatedVisibility( visible = visible, enter = if (state.value.useBackAnimation) Transitions.BackSlidingTransitionIn diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartSettings.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartSettings.kt index 3d3aa75f..c98d25ad 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/components/StartSettings.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -32,33 +31,28 @@ import com.google.accompanist.permissions.PermissionState import ua.acclorite.book_story.R import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.util.Constants -import ua.acclorite.book_story.presentation.data.MainEvent -import ua.acclorite.book_story.presentation.data.MainState +import ua.acclorite.book_story.presentation.components.LocalMainViewModel +import ua.acclorite.book_story.presentation.components.LocalStartViewModel import ua.acclorite.book_story.presentation.screens.start.components.permissions.startPermissionsScreen import ua.acclorite.book_story.presentation.screens.start.data.StartEvent import ua.acclorite.book_story.presentation.screens.start.data.StartNavigationScreen -import ua.acclorite.book_story.presentation.screens.start.data.StartState /** * Start Settings. * - * @param state [StartState]. - * @param mainState [MainState]. - * @param onEvent [StartEvent] callback. - * @param onMainEvent [MainEvent] callback. * @param storagePermissionState Storage [PermissionState]. * @param notificationsPermissionState Notifications [PermissionState]. */ @OptIn(ExperimentalPermissionsApi::class) @Composable fun StartSettings( - state: State, - mainState: State, - onEvent: (StartEvent) -> Unit, - onMainEvent: (MainEvent) -> Unit, storagePermissionState: PermissionState, notificationsPermissionState: PermissionState ) { + val state = LocalStartViewModel.current.state + val mainState = LocalMainViewModel.current.state + val onEvent = LocalStartViewModel.current.onEvent + val onMainEvent = LocalMainViewModel.current.onEvent val activity = LocalContext.current as ComponentActivity val languages = remember(mainState.value.language) { @@ -74,7 +68,6 @@ fun StartSettings( StartNavigationTransition( modifier = Modifier.padding(horizontal = 18.dp), - state = state, visible = !state.value.isDone, bottomBar = { Column { @@ -126,24 +119,18 @@ fun StartSettings( ), ) { StartNavigationScreenItem( - state = state, screen = StartNavigationScreen.LANGUAGE_FIRST ) { startLanguageScreen(onMainEvent = onMainEvent, languages = languages) } StartNavigationScreenItem( - state = state, screen = StartNavigationScreen.APPEARANCE_SECOND ) { - startAppearanceScreen( - mainState = mainState, - onMainEvent = onMainEvent - ) + startAppearanceScreen() } StartNavigationScreenItem( - state = state, screen = StartNavigationScreen.PERMISSIONS_THIRD ) { startPermissionsScreen( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt index 684d3695..3060b03e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/start/data/StartViewModel.kt @@ -5,7 +5,6 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.provider.Settings -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState @@ -20,21 +19,24 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.yield +import ua.acclorite.book_story.domain.util.BaseViewModel import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.launchActivity import javax.inject.Inject @OptIn(ExperimentalPermissionsApi::class) @HiltViewModel -class StartViewModel @Inject constructor() : ViewModel() { +class StartViewModel @Inject constructor( + +) : BaseViewModel() { private val _state = MutableStateFlow(StartState()) - val state = _state.asStateFlow() + override val state = _state.asStateFlow() private var storagePermissionJob: Job? = null private var notificationsPermissionJob: Job? = null - fun onEvent(event: StartEvent) { + override fun onEvent(event: StartEvent) { when (event) { is StartEvent.OnGoBack -> { storagePermissionJob?.cancel()