diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEffect.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEffect.kt new file mode 100644 index 00000000..2b733634 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEffect.kt @@ -0,0 +1,20 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.presentation.library + +import androidx.compose.runtime.Immutable + +@Immutable +sealed class LibraryEffect { + data object OnRequestFocus : LibraryEffect() + data object OnBooksMoved : LibraryEffect() + data object OnBooksDeleted : LibraryEffect() + data object OnNavigateToLibrarySettings : LibraryEffect() + data object OnNavigateToBrowse : LibraryEffect() + data class OnNavigateToBookInfo(val id: Int) : LibraryEffect() + data class OnNavigateToReader(val id: Int) : LibraryEffect() +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEvent.kt index c2799fec..432712e8 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEvent.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryEvent.kt @@ -6,9 +6,7 @@ package ua.acclorite.book_story.presentation.library -import android.content.Context import androidx.compose.runtime.Immutable -import androidx.compose.ui.focus.FocusRequester import ua.acclorite.book_story.domain.model.library.Category @Immutable @@ -28,9 +26,7 @@ sealed class LibraryEvent { data object OnSearch : LibraryEvent() - data class OnRequestFocus( - val focusRequester: FocusRequester - ) : LibraryEvent() + data object OnRequestFocus : LibraryEvent() data object OnClearSelectedBooks : LibraryEvent() @@ -42,19 +38,28 @@ sealed class LibraryEvent { data object OnShowMoveDialog : LibraryEvent() data class OnActionMoveDialog( - val selectedCategories: List, - val context: Context + val selectedCategories: List ) : LibraryEvent() data object OnShowDeleteDialog : LibraryEvent() - data class OnActionDeleteDialog( - val context: Context - ) : LibraryEvent() + data object OnActionDeleteDialog : LibraryEvent() data object OnDismissDialog : LibraryEvent() data object OnShowFilterBottomSheet : LibraryEvent() data object OnDismissBottomSheet : LibraryEvent() + + data object OnNavigateToLibrarySettings : LibraryEvent() + + data object OnNavigateToBrowse : LibraryEvent() + + data class OnNavigateToBookInfo( + val id: Int + ) : LibraryEvent() + + data class OnNavigateToReader( + val id: Int + ) : LibraryEvent() } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryModel.kt index 139f904a..44ae6c10 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryModel.kt @@ -12,7 +12,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow @@ -20,17 +23,14 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext -import kotlinx.coroutines.yield -import ua.acclorite.book_story.R -import ua.acclorite.book_story.domain.model.library.Book import ua.acclorite.book_story.domain.use_case.book.DeleteBookUseCase import ua.acclorite.book_story.domain.use_case.book.SearchBooksUseCase import ua.acclorite.book_story.domain.use_case.book.UpdateBookUseCase import ua.acclorite.book_story.presentation.browse.BrowseScreen import ua.acclorite.book_story.presentation.history.HistoryScreen import ua.acclorite.book_story.presentation.library.model.SelectableBook -import ua.acclorite.book_story.ui.common.helpers.showToast import javax.inject.Inject +import kotlin.coroutines.coroutineContext @HiltViewModel class LibraryModel @Inject constructor( @@ -44,22 +44,21 @@ class LibraryModel @Inject constructor( private val _state = MutableStateFlow(LibraryState()) val state = _state.asStateFlow() + private val _effects = MutableSharedFlow() + val effects = _effects.asSharedFlow() + init { - viewModelScope.launch(Dispatchers.IO) { - onEvent( - LibraryEvent.OnRefreshList( - loading = true, - hideSearch = true - ) + onEvent( + LibraryEvent.OnRefreshList( + loading = true, + hideSearch = true ) - } + ) /* Observe channel - - - - - - - - - - - */ - viewModelScope.launch(Dispatchers.IO) { + viewModelScope.launch { LibraryScreen.refreshListChannel.receiveAsFlow().collectLatest { delay(it) - yield() - onEvent( LibraryEvent.OnRefreshList( loading = false, @@ -75,33 +74,42 @@ class LibraryModel @Inject constructor( private var searchQueryChange: Job? = null fun onEvent(event: LibraryEvent) { - when (event) { - is LibraryEvent.OnRefreshList -> { - refreshJob?.cancel() - refreshJob = viewModelScope.launch(Dispatchers.IO) { - _state.update { - it.copy( - isRefreshing = true, - isLoading = event.loading, - showSearch = if (event.hideSearch) false else it.showSearch - ) - } + viewModelScope.launch { + when (event) { + is LibraryEvent.OnRefreshList -> { + refreshJob?.cancel() + refreshJob = viewModelScope.launch(Dispatchers.Default) { + _state.update { + it.copy( + isRefreshing = true, + isLoading = event.loading, + showSearch = if (event.hideSearch) false else it.showSearch + ) + } - yield() - getBooksFromDatabase() + ensureActive() + val books = searchBooksUseCase( + if (_state.value.showSearch) _state.value.searchQuery + else "" + ).map { book -> SelectableBook(book, false) } + _state.update { + it.copy( + books = books, + hasSelectedItems = false, + isLoading = false + ) + } - delay(500) - _state.update { - it.copy( - isRefreshing = false, - isLoading = false - ) + delay(500) // Delay for UI smoothness + _state.update { + it.copy( + isRefreshing = false + ) + } } } - } - is LibraryEvent.OnSearchVisibility -> { - viewModelScope.launch(Dispatchers.IO) { + is LibraryEvent.OnSearchVisibility -> { if (!event.show) { onEvent( LibraryEvent.OnRefreshList( @@ -109,41 +117,31 @@ class LibraryModel @Inject constructor( hideSearch = true ) ) - } else { - _state.update { - it.copy( - searchQuery = "", - hasFocused = false - ) - } } _state.update { it.copy( - showSearch = event.show + showSearch = event.show, + searchQuery = if (event.show) "" else it.searchQuery, + hasFocused = if (event.show) false else it.hasFocused ) } } - } - is LibraryEvent.OnSearchQueryChange -> { - viewModelScope.launch { + is LibraryEvent.OnSearchQueryChange -> { _state.update { it.copy( searchQuery = event.query ) } searchQueryChange?.cancel() - searchQueryChange = launch(Dispatchers.IO) { + searchQueryChange = viewModelScope.launch(Dispatchers.IO) { delay(500) - yield() onEvent(LibraryEvent.OnSearch) } } - } - is LibraryEvent.OnSearch -> { - viewModelScope.launch(Dispatchers.IO) { + is LibraryEvent.OnSearch -> { onEvent( LibraryEvent.OnRefreshList( loading = false, @@ -151,12 +149,10 @@ class LibraryModel @Inject constructor( ) ) } - } - is LibraryEvent.OnRequestFocus -> { - viewModelScope.launch(Dispatchers.Main) { + is LibraryEvent.OnRequestFocus -> { if (!_state.value.hasFocused) { - event.focusRequester.requestFocus() + _effects.emit(LibraryEffect.OnRequestFocus) _state.update { it.copy( hasFocused = true @@ -164,170 +160,152 @@ class LibraryModel @Inject constructor( } } } - } - is LibraryEvent.OnClearSelectedBooks -> { - viewModelScope.launch(Dispatchers.IO) { - _state.update { - it.copy( - books = it.books.map { book -> book.copy(selected = false) }, - hasSelectedItems = false - ) + is LibraryEvent.OnClearSelectedBooks -> { + withContext(Dispatchers.Default) { + _state.update { + it.copy( + books = it.books.map { book -> book.copy(selected = false) }, + hasSelectedItems = false + ) + } } } - } - is LibraryEvent.OnSelectBook -> { - viewModelScope.launch(Dispatchers.IO) { - val editedList = _state.value.books.map { - if (it.data.id == event.id) it.copy(selected = event.select ?: !it.selected) - else it - } + is LibraryEvent.OnSelectBook -> { + withContext(Dispatchers.Default) { + val editedList = _state.value.books.map { + if (it.data.id == event.id) it.copy( + selected = event.select ?: !it.selected + ) + else it + } - _state.update { - it.copy( - books = editedList, - selectedItemsCount = editedList.filter { book -> book.selected }.size, - hasSelectedItems = editedList.any { book -> book.selected } - ) + _state.update { + it.copy( + books = editedList, + selectedItemsCount = editedList.filter { book -> book.selected }.size, + hasSelectedItems = editedList.any { book -> book.selected } + ) + } } } - } - is LibraryEvent.OnShowMoveDialog -> { - viewModelScope.launch { + is LibraryEvent.OnShowMoveDialog -> { _state.update { it.copy( dialog = LibraryScreen.MOVE_DIALOG ) } } - } - is LibraryEvent.OnActionMoveDialog -> { - viewModelScope.launch { - _state.value.books.forEach { book -> - if (!book.selected) return@forEach - updateBookUseCase( - book.data.copy( - categories = event.selectedCategories.map { it.id } - ) - ) - } - - _state.update { - it.copy( - books = it.books.map { book -> - if (!book.selected) return@map book - book.copy( - data = book.data.copy( - categories = event.selectedCategories.map { it.id } - ), - selected = false + is LibraryEvent.OnActionMoveDialog -> { + withContext(Dispatchers.Default) { + _state.value.books.forEach { book -> + if (!book.selected) return@forEach + updateBookUseCase( + book.data.copy( + categories = event.selectedCategories.map { it.id } ) - }, - hasSelectedItems = false, - dialog = null - ) - } + ) + } - HistoryScreen.refreshListChannel.trySend(0) + _state.update { + it.copy( + books = it.books.map { book -> + if (!book.selected) return@map book + book.copy( + data = book.data.copy( + categories = event.selectedCategories.map { it.id } + ), + selected = false + ) + }, + hasSelectedItems = false, + dialog = null + ) + } - withContext(Dispatchers.Main) { - event.context - .getString(R.string.books_moved) - .showToast(context = event.context) + HistoryScreen.refreshListChannel.trySend(0) + _effects.emit(LibraryEffect.OnBooksMoved) } } - } - is LibraryEvent.OnShowDeleteDialog -> { - viewModelScope.launch { + is LibraryEvent.OnShowDeleteDialog -> { _state.update { it.copy( dialog = LibraryScreen.DELETE_DIALOG ) } } - } - is LibraryEvent.OnActionDeleteDialog -> { - viewModelScope.launch { - _state.value.books.forEach { - if (!it.selected) return@forEach - deleteBookUseCase(it.data) - } + is LibraryEvent.OnActionDeleteDialog -> { + withContext(Dispatchers.Default) { + _state.value.books.forEach { + if (!it.selected) return@forEach + deleteBookUseCase(it.data) + } - _state.update { - it.copy( - books = it.books.filter { book -> !book.selected }, - hasSelectedItems = false, - dialog = null - ) - } + _state.update { + it.copy( + books = it.books.filter { book -> !book.selected }, + hasSelectedItems = false, + dialog = null + ) + } - HistoryScreen.refreshListChannel.trySend(0) - BrowseScreen.refreshListChannel.trySend(Unit) - - withContext(Dispatchers.Main) { - event.context - .getString(R.string.books_deleted) - .showToast(context = event.context) + HistoryScreen.refreshListChannel.trySend(0) + BrowseScreen.refreshListChannel.trySend(Unit) + _effects.emit(LibraryEffect.OnBooksDeleted) } } - } - is LibraryEvent.OnDismissDialog -> { - viewModelScope.launch { + is LibraryEvent.OnDismissDialog -> { _state.update { it.copy( dialog = null ) } } - } - is LibraryEvent.OnShowFilterBottomSheet -> { - viewModelScope.launch { + is LibraryEvent.OnShowFilterBottomSheet -> { _state.update { it.copy( bottomSheet = LibraryScreen.FILTER_BOTTOM_SHEET ) } } - } - is LibraryEvent.OnDismissBottomSheet -> { - viewModelScope.launch { + is LibraryEvent.OnDismissBottomSheet -> { _state.update { it.copy( bottomSheet = null ) } } + + is LibraryEvent.OnNavigateToLibrarySettings -> { + _effects.emit(LibraryEffect.OnNavigateToLibrarySettings) + } + + is LibraryEvent.OnNavigateToBrowse -> { + _effects.emit(LibraryEffect.OnNavigateToBrowse) + } + + is LibraryEvent.OnNavigateToBookInfo -> { + _effects.emit(LibraryEffect.OnNavigateToBookInfo(event.id)) + } + + is LibraryEvent.OnNavigateToReader -> { + _effects.emit(LibraryEffect.OnNavigateToReader(event.id)) + } } } } - private suspend fun getBooksFromDatabase( - query: String = if (_state.value.showSearch) _state.value.searchQuery else "" - ) { - val books = searchBooksUseCase(query) - .sortedWith(compareByDescending { it.lastOpened }.thenBy { it.title }) - .map { book -> SelectableBook(book, false) } - - _state.update { - it.copy( - books = books, - hasSelectedItems = false, - isLoading = false - ) - } - } - private suspend inline fun MutableStateFlow.update(function: (T) -> T) { mutex.withLock { - yield() + coroutineContext.ensureActive() this.value = function(this.value) } } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt index 4bbda1bd..97620ccb 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryScreen.kt @@ -23,16 +23,11 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize -import ua.acclorite.book_story.presentation.book_info.BookInfoScreen -import ua.acclorite.book_story.presentation.browse.BrowseScreen -import ua.acclorite.book_story.presentation.history.HistoryScreen import ua.acclorite.book_story.presentation.navigator.Screen -import ua.acclorite.book_story.presentation.reader.ReaderScreen -import ua.acclorite.book_story.presentation.settings.LibrarySettingsScreen import ua.acclorite.book_story.presentation.settings.SettingsModel import ua.acclorite.book_story.ui.common.helpers.LocalSettings import ua.acclorite.book_story.ui.library.LibraryContent -import ua.acclorite.book_story.ui.navigator.LocalNavigator +import ua.acclorite.book_story.ui.library.LibraryEffects @Parcelize object LibraryScreen : Screen, Parcelable { @@ -58,7 +53,6 @@ object LibraryScreen : Screen, Parcelable { @OptIn(ExperimentalMaterialApi::class) @Composable override fun Content() { - val navigator = LocalNavigator.current val screenModel = hiltViewModel() val settingsModel = hiltViewModel() val settings = LocalSettings.current @@ -105,6 +99,11 @@ object LibraryScreen : Screen, Parcelable { } } + LibraryEffects( + effects = screenModel.effects, + focusRequester = focusRequester + ) + LibraryContent( books = state.value.books, selectedItemsCount = state.value.selectedItemsCount, @@ -150,19 +149,10 @@ object LibraryScreen : Screen, Parcelable { showFilterBottomSheet = screenModel::onEvent, dismissBottomSheet = screenModel::onEvent, dismissDialog = screenModel::onEvent, - navigateToBrowse = { - navigator.push(BrowseScreen) - }, - navigateToReader = { - HistoryScreen.insertHistoryChannel.trySend(it) - navigator.push(ReaderScreen(it)) - }, - navigateToBookInfo = { - navigator.push(BookInfoScreen(bookId = it)) - }, - navigateToLibrarySettings = { - navigator.push(LibrarySettingsScreen) - } + navigateToBrowse = screenModel::onEvent, + navigateToReader = screenModel::onEvent, + navigateToBookInfo = screenModel::onEvent, + navigateToLibrarySettings = screenModel::onEvent ) } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt index bae81a4b..ca1678e6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryContent.kt @@ -69,10 +69,10 @@ fun LibraryContent( dismissDialog: (LibraryEvent.OnDismissDialog) -> Unit, showFilterBottomSheet: (LibraryEvent.OnShowFilterBottomSheet) -> Unit, dismissBottomSheet: (LibraryEvent.OnDismissBottomSheet) -> Unit, - navigateToBrowse: () -> Unit, - navigateToBookInfo: (id: Int) -> Unit, - navigateToReader: (id: Int) -> Unit, - navigateToLibrarySettings: () -> Unit + navigateToBrowse: (LibraryEvent.OnNavigateToBrowse) -> Unit, + navigateToBookInfo: (LibraryEvent.OnNavigateToBookInfo) -> Unit, + navigateToReader: (LibraryEvent.OnNavigateToReader) -> Unit, + navigateToLibrarySettings: (LibraryEvent.OnNavigateToLibrarySettings) -> Unit ) { LibraryDialog( dialog = dialog, @@ -146,6 +146,6 @@ fun LibraryContent( pagerState = pagerState, doublePressExit = doublePressExit, clearSelectedBooks = clearSelectedBooks, - searchVisibility = searchVisibility, + searchVisibility = searchVisibility ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDeleteDialog.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDeleteDialog.kt index e7c0ea90..a7d66a6e 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDeleteDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDeleteDialog.kt @@ -9,7 +9,6 @@ package ua.acclorite.book_story.ui.library import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.DeleteOutline 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.library.LibraryEvent @@ -21,8 +20,6 @@ fun LibraryDeleteDialog( actionDeleteDialog: (LibraryEvent.OnActionDeleteDialog) -> Unit, dismissDialog: (LibraryEvent.OnDismissDialog) -> Unit ) { - val context = LocalContext.current - Dialog( title = stringResource(id = R.string.delete_books), icon = Icons.Outlined.DeleteOutline, @@ -35,11 +32,7 @@ fun LibraryDeleteDialog( dismissDialog(LibraryEvent.OnDismissDialog) }, onAction = { - actionDeleteDialog( - LibraryEvent.OnActionDeleteDialog( - context = context - ) - ) + actionDeleteDialog(LibraryEvent.OnActionDeleteDialog) }, withContent = false ) diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDialog.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDialog.kt index 1a092f8f..5fe756c8 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryDialog.kt @@ -22,7 +22,7 @@ fun LibraryDialog( actionMoveDialog: (LibraryEvent.OnActionMoveDialog) -> Unit, actionDeleteDialog: (LibraryEvent.OnActionDeleteDialog) -> Unit, dismissDialog: (LibraryEvent.OnDismissDialog) -> Unit, - navigateToLibrarySettings: () -> Unit + navigateToLibrarySettings: (LibraryEvent.OnNavigateToLibrarySettings) -> Unit ) { when (dialog) { LibraryScreen.MOVE_DIALOG -> { diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEffects.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEffects.kt new file mode 100644 index 00000000..b92b3c15 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEffects.kt @@ -0,0 +1,65 @@ +/* + * Book's Story — free and open-source Material You eBook reader. + * Copyright (C) 2024-2025 Acclorite + * SPDX-License-Identifier: GPL-3.0-only + */ + +package ua.acclorite.book_story.ui.library + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.platform.LocalContext +import kotlinx.coroutines.flow.SharedFlow +import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.book_info.BookInfoScreen +import ua.acclorite.book_story.presentation.browse.BrowseScreen +import ua.acclorite.book_story.presentation.history.HistoryScreen +import ua.acclorite.book_story.presentation.library.LibraryEffect +import ua.acclorite.book_story.presentation.reader.ReaderScreen +import ua.acclorite.book_story.presentation.settings.LibrarySettingsScreen +import ua.acclorite.book_story.ui.common.helpers.showToast +import ua.acclorite.book_story.ui.navigator.LocalNavigator + +@Composable +fun LibraryEffects(effects: SharedFlow, focusRequester: FocusRequester) { + val context = LocalContext.current + val navigator = LocalNavigator.current + + LaunchedEffect(effects, focusRequester, context, navigator) { + effects.collect { effect -> + when (effect) { + is LibraryEffect.OnRequestFocus -> { + focusRequester.requestFocus() + } + + is LibraryEffect.OnBooksMoved -> { + context.getString(R.string.books_moved) + .showToast(context = context) + } + + is LibraryEffect.OnBooksDeleted -> { + context.getString(R.string.books_deleted) + .showToast(context = context) + } + + is LibraryEffect.OnNavigateToLibrarySettings -> { + navigator.push(LibrarySettingsScreen) + } + + is LibraryEffect.OnNavigateToBrowse -> { + navigator.push(BrowseScreen) + } + + is LibraryEffect.OnNavigateToBookInfo -> { + navigator.push(BookInfoScreen(bookId = effect.id)) + } + + is LibraryEffect.OnNavigateToReader -> { + HistoryScreen.insertHistoryChannel.trySend(effect.id) + navigator.push(ReaderScreen(effect.id)) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEmptyPlaceholder.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEmptyPlaceholder.kt index c555d342..0e607b21 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEmptyPlaceholder.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryEmptyPlaceholder.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import ua.acclorite.book_story.R +import ua.acclorite.book_story.presentation.library.LibraryEvent import ua.acclorite.book_story.ui.common.components.placeholder.EmptyPlaceholder import ua.acclorite.book_story.ui.theme.Transitions @@ -24,7 +25,7 @@ fun BoxScope.LibraryEmptyPlaceholder( isLoading: Boolean, isRefreshing: Boolean, isBooksEmpty: Boolean, - navigateToBrowse: () -> Unit + navigateToBrowse: (LibraryEvent.OnNavigateToBrowse) -> Unit ) { AnimatedVisibility( visible = !isLoading @@ -40,7 +41,7 @@ fun BoxScope.LibraryEmptyPlaceholder( modifier = Modifier.align(Alignment.Center), actionTitle = stringResource(id = R.string.add_book) ) { - navigateToBrowse() + navigateToBrowse(LibraryEvent.OnNavigateToBrowse) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryMoveDialog.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryMoveDialog.kt index 8b66c8d1..2a3f8e30 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryMoveDialog.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryMoveDialog.kt @@ -14,7 +14,6 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember 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 @@ -31,10 +30,8 @@ fun LibraryMoveDialog( categories: List, actionMoveDialog: (LibraryEvent.OnActionMoveDialog) -> Unit, dismissDialog: (LibraryEvent.OnDismissDialog) -> Unit, - navigateToLibrarySettings: () -> Unit + navigateToLibrarySettings: (LibraryEvent.OnNavigateToLibrarySettings) -> Unit ) { - val context = LocalContext.current - val selectedBooks = remember { derivedStateOf { books.filter { it.selected } @@ -61,14 +58,13 @@ fun LibraryMoveDialog( onAction = { actionMoveDialog( LibraryEvent.OnActionMoveDialog( - selectedCategories = selectedCategories, - context = context + selectedCategories = selectedCategories ) ) }, secondaryAction = stringResource(id = R.string.edit), onSecondaryAction = { - navigateToLibrarySettings() + navigateToLibrarySettings(LibraryEvent.OnNavigateToLibrarySettings) dismissDialog(LibraryEvent.OnDismissDialog) }, withContent = true, diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryPager.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryPager.kt index 9afb26f3..f86408f6 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryPager.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryPager.kt @@ -44,9 +44,9 @@ fun LibraryPager( isLoading: Boolean, isRefreshing: Boolean, selectBook: (LibraryEvent.OnSelectBook) -> Unit, - navigateToBrowse: () -> Unit, - navigateToBookInfo: (id: Int) -> Unit, - navigateToReader: (id: Int) -> Unit, + navigateToBrowse: (LibraryEvent.OnNavigateToBrowse) -> Unit, + navigateToBookInfo: (LibraryEvent.OnNavigateToBookInfo) -> Unit, + navigateToReader: (LibraryEvent.OnNavigateToReader) -> Unit, ) { val categorizedBooks = remember( books, @@ -172,8 +172,20 @@ fun LibraryPager( ) ) }, - navigateToBookInfo = { navigateToBookInfo(book.data.id) }, - navigateToReader = { navigateToReader(book.data.id) }, + navigateToBookInfo = { + navigateToBookInfo( + LibraryEvent.OnNavigateToBookInfo( + book.data.id + ) + ) + }, + navigateToReader = { + navigateToReader( + LibraryEvent.OnNavigateToReader( + book.data.id + ) + ) + } ) } } diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryScaffold.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryScaffold.kt index 798aaef0..ee8e16d3 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryScaffold.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryScaffold.kt @@ -63,9 +63,9 @@ fun LibraryScaffold( showMoveDialog: (LibraryEvent.OnShowMoveDialog) -> Unit, showDeleteDialog: (LibraryEvent.OnShowDeleteDialog) -> Unit, showFilterBottomSheet: (LibraryEvent.OnShowFilterBottomSheet) -> Unit, - navigateToBrowse: () -> Unit, - navigateToBookInfo: (id: Int) -> Unit, - navigateToReader: (id: Int) -> Unit, + navigateToBrowse: (LibraryEvent.OnNavigateToBrowse) -> Unit, + navigateToBookInfo: (LibraryEvent.OnNavigateToBookInfo) -> Unit, + navigateToReader: (LibraryEvent.OnNavigateToReader) -> Unit, ) { Scaffold( Modifier diff --git a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryTopBar.kt b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryTopBar.kt index 9de12052..096f55ac 100644 --- a/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/ui/library/LibraryTopBar.kt @@ -189,7 +189,7 @@ fun LibraryTopBar( modifier = Modifier .focusRequester(focusRequester) .onGloballyPositioned { - requestFocus(LibraryEvent.OnRequestFocus(focusRequester)) + requestFocus(LibraryEvent.OnRequestFocus) }, initialQuery = searchQuery, onQueryChange = {