Migrate library settings sheet to Compose

This commit is contained in:
arkon
2022-12-09 17:34:24 -05:00
parent 94232a4937
commit 727399611d
12 changed files with 443 additions and 830 deletions

View File

@@ -33,7 +33,7 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup
import eu.kanade.tachiyomi.widget.TriState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
@@ -149,8 +149,8 @@ class LibraryScreenModel(
prefs.filterStarted or
prefs.filterBookmarked or
prefs.filterCompleted
) != TriStateGroup.State.DISABLED.value
val b = trackFilter.values.any { it != TriStateGroup.State.DISABLED.value }
) != TriState.DISABLED.value
val b = trackFilter.values.any { it != TriState.DISABLED.value }
a || b
}
.distinctUntilChanged()
@@ -179,17 +179,17 @@ class LibraryScreenModel(
val isNotLoggedInAnyTrack = loggedInTrackServices.isEmpty()
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateGroup.State.ENABLED_NOT.value) it.key else null }
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateGroup.State.ENABLED_IS.value) it.key else null }
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_NOT.value) it.key else null }
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_IS.value) it.key else null }
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{
if (!downloadedOnly && filterDownloaded == TriStateGroup.State.DISABLED.value) return@downloaded true
if (!downloadedOnly && filterDownloaded == TriState.DISABLED.value) return@downloaded true
val isDownloaded = it.libraryManga.manga.isLocal() ||
it.downloadCount > 0 ||
downloadManager.getDownloadCount(it.libraryManga.manga) > 0
return@downloaded if (downloadedOnly || filterDownloaded == TriStateGroup.State.ENABLED_IS.value) {
return@downloaded if (downloadedOnly || filterDownloaded == TriState.ENABLED_IS.value) {
isDownloaded
} else {
!isDownloaded
@@ -197,10 +197,10 @@ class LibraryScreenModel(
}
val filterFnUnread: (LibraryItem) -> Boolean = unread@{
if (filterUnread == TriStateGroup.State.DISABLED.value) return@unread true
if (filterUnread == TriState.DISABLED.value) return@unread true
val isUnread = it.libraryManga.unreadCount > 0
return@unread if (filterUnread == TriStateGroup.State.ENABLED_IS.value) {
return@unread if (filterUnread == TriState.ENABLED_IS.value) {
isUnread
} else {
!isUnread
@@ -208,10 +208,10 @@ class LibraryScreenModel(
}
val filterFnStarted: (LibraryItem) -> Boolean = started@{
if (filterStarted == TriStateGroup.State.DISABLED.value) return@started true
if (filterStarted == TriState.DISABLED.value) return@started true
val hasStarted = it.libraryManga.hasStarted
return@started if (filterStarted == TriStateGroup.State.ENABLED_IS.value) {
return@started if (filterStarted == TriState.ENABLED_IS.value) {
hasStarted
} else {
!hasStarted
@@ -219,10 +219,10 @@ class LibraryScreenModel(
}
val filterFnBookmarked: (LibraryItem) -> Boolean = bookmarked@{
if (filterBookmarked == TriStateGroup.State.DISABLED.value) return@bookmarked true
if (filterBookmarked == TriState.DISABLED.value) return@bookmarked true
val hasBookmarks = it.libraryManga.hasBookmarks
return@bookmarked if (filterBookmarked == TriStateGroup.State.ENABLED_IS.value) {
return@bookmarked if (filterBookmarked == TriState.ENABLED_IS.value) {
hasBookmarks
} else {
!hasBookmarks
@@ -230,10 +230,10 @@ class LibraryScreenModel(
}
val filterFnCompleted: (LibraryItem) -> Boolean = completed@{
if (filterCompleted == TriStateGroup.State.DISABLED.value) return@completed true
if (filterCompleted == TriState.DISABLED.value) return@completed true
val isCompleted = it.libraryManga.manga.status.toInt() == SManga.COMPLETED
return@completed if (filterCompleted == TriStateGroup.State.ENABLED_IS.value) {
return@completed if (filterCompleted == TriState.ENABLED_IS.value) {
isCompleted
} else {
!isCompleted
@@ -572,6 +572,10 @@ class LibraryScreenModel(
}
}
fun showSettingsDialog() {
mutableState.update { it.copy(dialog = Dialog.SettingsSheet) }
}
fun clearSelection() {
mutableState.update { it.copy(selection = emptyList()) }
}
@@ -690,6 +694,7 @@ class LibraryScreenModel(
}
sealed class Dialog {
object SettingsSheet : Dialog()
data class ChangeCategory(val manga: List<Manga>, val initialSelection: List<CheckboxState<Category>>) : Dialog()
data class DeleteManga(val manga: List<Manga>) : Dialog()
}

View File

@@ -0,0 +1,84 @@
package eu.kanade.tachiyomi.ui.library
import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.SetDisplayModeForCategory
import eu.kanade.domain.category.interactor.SetSortModeForCategory
import eu.kanade.domain.library.service.LibraryPreferences
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.util.preference.toggle
import eu.kanade.tachiyomi.widget.TriState
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.util.lang.launchIO
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.library.model.LibrarySort
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class LibrarySettingsScreenModel(
val preferences: BasePreferences = Injekt.get(),
val libraryPreferences: LibraryPreferences = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val setDisplayModeForCategory: SetDisplayModeForCategory = Injekt.get(),
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
trackManager: TrackManager = Injekt.get(),
) : StateScreenModel<LibrarySettingsScreenModel.State>(State()) {
val trackServices = trackManager.services.filter { service -> service.isLogged }
init {
coroutineScope.launchIO {
getCategories.subscribe()
.collectLatest {
mutableState.update { state ->
state.copy(
categories = it,
)
}
}
}
}
fun togglePreference(preference: (LibraryPreferences) -> Preference<Boolean>) {
preference(libraryPreferences).toggle()
}
fun toggleFilter(preference: (LibraryPreferences) -> Preference<Int>) {
preference(libraryPreferences).getAndSet {
when (it) {
TriState.DISABLED.value -> TriState.ENABLED_IS.value
TriState.ENABLED_IS.value -> TriState.ENABLED_NOT.value
TriState.ENABLED_NOT.value -> TriState.DISABLED.value
else -> throw IllegalStateException("Unknown TriStateGroup state: $this")
}
}
}
fun toggleTracker(id: Int) {
toggleFilter { libraryPreferences.filterTracking(id) }
}
fun setDisplayMode(category: Category, mode: LibraryDisplayMode) {
coroutineScope.launchIO {
setDisplayModeForCategory.await(category, mode)
}
}
fun setSort(category: Category, mode: LibrarySort.Type, direction: LibrarySort.Direction) {
coroutineScope.launchIO {
setSortModeForCategory.await(category, mode, direction)
}
}
@Immutable
data class State(
val categories: List<Category> = emptyList(),
)
}

View File

@@ -1,474 +0,0 @@
package eu.kanade.tachiyomi.ui.library
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.View
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.SetDisplayModeForCategory
import eu.kanade.domain.category.interactor.SetSortModeForCategory
import eu.kanade.domain.library.service.LibraryPreferences
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
import eu.kanade.tachiyomi.widget.sheet.TabbedBottomSheetDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import tachiyomi.core.util.lang.launchIO
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.library.model.LibrarySort
import tachiyomi.domain.library.model.display
import tachiyomi.domain.library.model.sort
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
class LibrarySettingsSheet(
activity: Activity,
private val trackManager: TrackManager = Injekt.get(),
private val setDisplayModeForCategory: SetDisplayModeForCategory = Injekt.get(),
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
) : TabbedBottomSheetDialog(activity) {
val filters: Filter
private val sort: Sort
private val display: Display
val sheetScope = CoroutineScope(Job() + Dispatchers.IO)
init {
filters = Filter(activity)
sort = Sort(activity)
display = Display(activity)
}
/**
* adjusts selected button to match real state.
* @param currentCategory ID of currently shown category
*/
fun show(currentCategory: Category) {
filters.adjustFilterSelection()
sort.currentCategory = currentCategory
sort.adjustDisplaySelection()
display.currentCategory = currentCategory
display.adjustDisplaySelection()
super.show()
}
override fun getTabViews(): List<View> = listOf(
filters,
sort,
display,
)
override fun getTabTitles(): List<Int> = listOf(
R.string.action_filter,
R.string.action_sort,
R.string.action_display,
)
/**
* Filters group (unread, downloaded, ...).
*/
inner class Filter @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Settings(context, attrs) {
private val filterGroup = FilterGroup()
init {
setGroups(listOf(filterGroup))
}
// Refreshes Filter Setting selections
fun adjustFilterSelection() {
filterGroup.initModels()
filterGroup.items.forEach { adapter.notifyItemChanged(it) }
}
/**
* Returns true if there's at least one filter from [FilterGroup] active.
*/
fun hasActiveFilters(): Boolean {
return filterGroup.items.filterIsInstance<Item.TriStateGroup>().any { it.state != State.DISABLED.value }
}
inner class FilterGroup : Group {
private val downloaded = Item.TriStateGroup(R.string.label_downloaded, this)
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
private val started = Item.TriStateGroup(R.string.label_started, this)
private val bookmarked = Item.TriStateGroup(R.string.action_filter_bookmarked, this)
private val completed = Item.TriStateGroup(R.string.completed, this)
private val trackFilters: Map<Long, Item.TriStateGroup>
override val header = null
override val items: List<Item>
override val footer = null
init {
trackManager.services.filter { service -> service.isLogged }
.also { services ->
val size = services.size
trackFilters = services.associate { service ->
Pair(service.id, Item.TriStateGroup(getServiceResId(service, size), this))
}
val list: MutableList<Item> = mutableListOf(downloaded, unread, started, bookmarked, completed)
if (size > 1) list.add(Item.Header(R.string.action_filter_tracked))
list.addAll(trackFilters.values)
items = list
}
}
private fun getServiceResId(service: TrackService, size: Int): Int {
return if (size > 1) service.nameRes() else R.string.action_filter_tracked
}
override fun initModels() {
if (preferences.downloadedOnly().get()) {
downloaded.state = State.ENABLED_IS.value
downloaded.enabled = false
} else {
downloaded.state = libraryPreferences.filterDownloaded().get()
downloaded.enabled = true
}
unread.state = libraryPreferences.filterUnread().get()
started.state = libraryPreferences.filterStarted().get()
bookmarked.state = libraryPreferences.filterBookmarked().get()
completed.state = libraryPreferences.filterCompleted().get()
trackFilters.forEach { trackFilter ->
trackFilter.value.state = libraryPreferences.filterTracking(trackFilter.key.toInt()).get()
}
}
override fun onItemClicked(item: Item) {
item as Item.TriStateGroup
val newState = when (item.state) {
State.DISABLED.value -> State.ENABLED_IS.value
State.ENABLED_IS.value -> State.ENABLED_NOT.value
State.ENABLED_NOT.value -> State.DISABLED.value
else -> throw Exception("Unknown State")
}
item.state = newState
when (item) {
downloaded -> libraryPreferences.filterDownloaded().set(newState)
unread -> libraryPreferences.filterUnread().set(newState)
started -> libraryPreferences.filterStarted().set(newState)
bookmarked -> libraryPreferences.filterBookmarked().set(newState)
completed -> libraryPreferences.filterCompleted().set(newState)
else -> {
trackFilters.forEach { trackFilter ->
if (trackFilter.value == item) {
libraryPreferences.filterTracking(trackFilter.key.toInt()).set(newState)
}
}
}
}
adapter.notifyItemChanged(item)
}
}
}
/**
* Sorting group (alphabetically, by last read, ...) and ascending or descending.
*/
inner class Sort @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Settings(context, attrs) {
private val sort = SortGroup()
init {
setGroups(listOf(sort))
}
// Refreshes Display Setting selections
fun adjustDisplaySelection() {
sort.initModels()
sort.items.forEach { adapter.notifyItemChanged(it) }
}
inner class SortGroup : Group {
private val alphabetically = Item.MultiSort(R.string.action_sort_alpha, this)
private val total = Item.MultiSort(R.string.action_sort_total, this)
private val lastRead = Item.MultiSort(R.string.action_sort_last_read, this)
private val lastChecked = Item.MultiSort(R.string.action_sort_last_manga_update, this)
private val unread = Item.MultiSort(R.string.action_sort_unread_count, this)
private val latestChapter = Item.MultiSort(R.string.action_sort_latest_chapter, this)
private val chapterFetchDate = Item.MultiSort(R.string.action_sort_chapter_fetch_date, this)
private val dateAdded = Item.MultiSort(R.string.action_sort_date_added, this)
override val header = null
override val items =
listOf(alphabetically, lastRead, lastChecked, unread, total, latestChapter, chapterFetchDate, dateAdded)
override val footer = null
override fun initModels() {
val sort = currentCategory.sort
val order = if (sort.isAscending) Item.MultiSort.SORT_ASC else Item.MultiSort.SORT_DESC
alphabetically.state =
if (sort.type == LibrarySort.Type.Alphabetical) order else Item.MultiSort.SORT_NONE
lastRead.state =
if (sort.type == LibrarySort.Type.LastRead) order else Item.MultiSort.SORT_NONE
lastChecked.state =
if (sort.type == LibrarySort.Type.LastUpdate) order else Item.MultiSort.SORT_NONE
unread.state =
if (sort.type == LibrarySort.Type.UnreadCount) order else Item.MultiSort.SORT_NONE
total.state =
if (sort.type == LibrarySort.Type.TotalChapters) order else Item.MultiSort.SORT_NONE
latestChapter.state =
if (sort.type == LibrarySort.Type.LatestChapter) order else Item.MultiSort.SORT_NONE
chapterFetchDate.state =
if (sort.type == LibrarySort.Type.ChapterFetchDate) order else Item.MultiSort.SORT_NONE
dateAdded.state =
if (sort.type == LibrarySort.Type.DateAdded) order else Item.MultiSort.SORT_NONE
}
override fun onItemClicked(item: Item) {
item as Item.MultiStateGroup
val prevState = item.state
item.group.items.forEach {
(it as Item.MultiStateGroup).state =
Item.MultiSort.SORT_NONE
}
item.state = when (prevState) {
Item.MultiSort.SORT_NONE -> Item.MultiSort.SORT_ASC
Item.MultiSort.SORT_ASC -> Item.MultiSort.SORT_DESC
Item.MultiSort.SORT_DESC -> Item.MultiSort.SORT_ASC
else -> throw Exception("Unknown state")
}
setSortPreference(item)
item.group.items.forEach { adapter.notifyItemChanged(it) }
}
private fun setSortPreference(item: Item.MultiStateGroup) {
val mode = when (item) {
alphabetically -> LibrarySort.Type.Alphabetical
lastRead -> LibrarySort.Type.LastRead
lastChecked -> LibrarySort.Type.LastUpdate
unread -> LibrarySort.Type.UnreadCount
total -> LibrarySort.Type.TotalChapters
latestChapter -> LibrarySort.Type.LatestChapter
chapterFetchDate -> LibrarySort.Type.ChapterFetchDate
dateAdded -> LibrarySort.Type.DateAdded
else -> throw NotImplementedError("Unknown display mode")
}
val direction = if (item.state == Item.MultiSort.SORT_ASC) {
LibrarySort.Direction.Ascending
} else {
LibrarySort.Direction.Descending
}
sheetScope.launchIO {
setSortModeForCategory.await(currentCategory!!, mode, direction)
}
}
}
}
/**
* Display group, to show the library as a list or a grid.
*/
inner class Display @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Settings(context, attrs) {
private val displayGroup: DisplayGroup
private val badgeGroup: BadgeGroup
private val tabsGroup: TabsGroup
private val otherGroup: OtherGroup
init {
displayGroup = DisplayGroup()
badgeGroup = BadgeGroup()
tabsGroup = TabsGroup()
otherGroup = OtherGroup()
setGroups(listOf(displayGroup, badgeGroup, tabsGroup, otherGroup))
}
// Refreshes Display Setting selections
fun adjustDisplaySelection() {
val mode = getDisplayModePreference()
displayGroup.setGroupSelections(mode)
displayGroup.items.forEach { adapter.notifyItemChanged(it) }
}
// Gets user preference of currently selected display mode at current category
private fun getDisplayModePreference(): LibraryDisplayMode {
return currentCategory.display
}
inner class DisplayGroup : Group {
private val compactGrid = Item.Radio(R.string.action_display_grid, this)
private val comfortableGrid = Item.Radio(R.string.action_display_comfortable_grid, this)
private val coverOnlyGrid = Item.Radio(R.string.action_display_cover_only_grid, this)
private val list = Item.Radio(R.string.action_display_list, this)
override val header = Item.Header(R.string.action_display_mode)
override val items = listOf(compactGrid, comfortableGrid, coverOnlyGrid, list)
override val footer = null
override fun initModels() {
val mode = getDisplayModePreference()
setGroupSelections(mode)
}
override fun onItemClicked(item: Item) {
item as Item.Radio
if (item.checked) return
item.group.items.forEach { (it as Item.Radio).checked = false }
item.checked = true
setDisplayModePreference(item)
item.group.items.forEach { adapter.notifyItemChanged(it) }
}
// Sets display group selections based on given mode
fun setGroupSelections(mode: LibraryDisplayMode) {
compactGrid.checked = mode == LibraryDisplayMode.CompactGrid
comfortableGrid.checked = mode == LibraryDisplayMode.ComfortableGrid
coverOnlyGrid.checked = mode == LibraryDisplayMode.CoverOnlyGrid
list.checked = mode == LibraryDisplayMode.List
}
private fun setDisplayModePreference(item: Item) {
val flag = when (item) {
compactGrid -> LibraryDisplayMode.CompactGrid
comfortableGrid -> LibraryDisplayMode.ComfortableGrid
coverOnlyGrid -> LibraryDisplayMode.CoverOnlyGrid
list -> LibraryDisplayMode.List
else -> throw NotImplementedError("Unknown display mode")
}
sheetScope.launchIO {
setDisplayModeForCategory.await(currentCategory!!, flag)
}
}
}
inner class BadgeGroup : Group {
private val downloadBadge = Item.CheckboxGroup(R.string.action_display_download_badge, this)
private val localBadge = Item.CheckboxGroup(R.string.action_display_local_badge, this)
private val languageBadge = Item.CheckboxGroup(R.string.action_display_language_badge, this)
override val header = Item.Header(R.string.badges_header)
override val items = listOf(downloadBadge, localBadge, languageBadge)
override val footer = null
override fun initModels() {
downloadBadge.checked = libraryPreferences.downloadBadge().get()
localBadge.checked = libraryPreferences.localBadge().get()
languageBadge.checked = libraryPreferences.languageBadge().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
when (item) {
downloadBadge -> libraryPreferences.downloadBadge().set((item.checked))
localBadge -> libraryPreferences.localBadge().set((item.checked))
languageBadge -> libraryPreferences.languageBadge().set((item.checked))
else -> {}
}
adapter.notifyItemChanged(item)
}
}
inner class TabsGroup : Group {
private val showTabs = Item.CheckboxGroup(R.string.action_display_show_tabs, this)
private val showNumberOfItems = Item.CheckboxGroup(R.string.action_display_show_number_of_items, this)
override val header = Item.Header(R.string.tabs_header)
override val items = listOf(showTabs, showNumberOfItems)
override val footer = null
override fun initModels() {
showTabs.checked = libraryPreferences.categoryTabs().get()
showNumberOfItems.checked = libraryPreferences.categoryNumberOfItems().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
when (item) {
showTabs -> libraryPreferences.categoryTabs().set(item.checked)
showNumberOfItems -> libraryPreferences.categoryNumberOfItems().set(item.checked)
else -> {}
}
adapter.notifyItemChanged(item)
}
}
inner class OtherGroup : Group {
private val showContinueReadingButton = Item.CheckboxGroup(R.string.action_display_show_continue_reading_button, this)
override val header = Item.Header(R.string.other_header)
override val items = listOf(showContinueReadingButton)
override val footer = null
override fun initModels() {
showContinueReadingButton.checked = libraryPreferences.showContinueReadingButton().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
when (item) {
showContinueReadingButton -> libraryPreferences.showContinueReadingButton().set(item.checked)
else -> {}
}
adapter.notifyItemChanged(item)
}
}
}
open inner class Settings(context: Context, attrs: AttributeSet?) :
ExtendedNavigationView(context, attrs) {
val preferences: BasePreferences by injectLazy()
val libraryPreferences: LibraryPreferences by injectLazy()
lateinit var adapter: Adapter
/**
* Click listener to notify the parent fragment when an item from a group is clicked.
*/
var onGroupClicked: (Group) -> Unit = {}
var currentCategory: Category? = null
fun setGroups(groups: List<Group>) {
adapter = Adapter(groups.map { it.createItems() }.flatten())
recycler.adapter = adapter
groups.forEach { it.initModels() }
addView(recycler)
}
/**
* Adapter of the recycler view.
*/
inner class Adapter(items: List<Item>) : ExtendedNavigationView.Adapter(items) {
override fun onItemClicked(item: Item) {
if (item is GroupedItem) {
item.group.onItemClicked(item)
onGroupClicked(item.group)
}
}
}
}
}

View File

@@ -33,6 +33,7 @@ import eu.kanade.presentation.category.ChangeCategoryDialog
import eu.kanade.presentation.components.EmptyScreen
import eu.kanade.presentation.components.EmptyScreenAction
import eu.kanade.presentation.library.DeleteLibraryMangaDialog
import eu.kanade.presentation.library.LibrarySettingsDialog
import eu.kanade.presentation.library.components.LibraryContent
import eu.kanade.presentation.library.components.LibraryToolbar
import eu.kanade.presentation.manga.components.LibraryBottomActionMenu
@@ -83,6 +84,7 @@ object LibraryTab : Tab {
val haptic = LocalHapticFeedback.current
val screenModel = rememberScreenModel { LibraryScreenModel() }
val settingsScreenModel = rememberScreenModel { LibrarySettingsScreenModel() }
val state by screenModel.state.collectAsState()
val snackbarHostState = remember { SnackbarHostState() }
@@ -95,9 +97,6 @@ object LibraryTab : Tab {
}
started
}
val onClickFilter: () -> Unit = {
scope.launch { sendSettingsSheetIntent(state.categories[screenModel.activeCategoryIndex]) }
}
Scaffold(
topBar = { scrollBehavior ->
@@ -114,7 +113,7 @@ object LibraryTab : Tab {
onClickUnselectAll = screenModel::clearSelection,
onClickSelectAll = { screenModel.selectAll(screenModel.activeCategoryIndex) },
onClickInvertSelection = { screenModel.invertSelection(screenModel.activeCategoryIndex) },
onClickFilter = onClickFilter,
onClickFilter = { screenModel.showSettingsDialog() },
onClickRefresh = { onClickRefresh(null) },
onClickOpenRandomManga = {
scope.launch {
@@ -201,6 +200,11 @@ object LibraryTab : Tab {
val onDismissRequest = screenModel::closeDialog
when (val dialog = state.dialog) {
is LibraryScreenModel.Dialog.SettingsSheet -> LibrarySettingsDialog(
onDismissRequest = onDismissRequest,
screenModel = settingsScreenModel,
activeCategoryIndex = screenModel.activeCategoryIndex,
)
is LibraryScreenModel.Dialog.ChangeCategory -> {
ChangeCategoryDialog(
initialSelection = dialog.initialSelection,
@@ -235,8 +239,8 @@ object LibraryTab : Tab {
}
}
LaunchedEffect(state.selectionMode) {
HomeScreen.showBottomNav(!state.selectionMode)
LaunchedEffect(state.selectionMode, state.dialog) {
HomeScreen.showBottomNav(!state.selectionMode && state.dialog !is LibraryScreenModel.Dialog.SettingsSheet)
}
LaunchedEffect(state.isLoading) {
@@ -247,7 +251,7 @@ object LibraryTab : Tab {
LaunchedEffect(Unit) {
launch { queryEvent.receiveAsFlow().collect(screenModel::search) }
launch { requestSettingsSheetEvent.receiveAsFlow().collectLatest { onClickFilter() } }
launch { requestSettingsSheetEvent.receiveAsFlow().collectLatest { screenModel.showSettingsDialog() } }
}
}
@@ -257,8 +261,5 @@ object LibraryTab : Tab {
// For opening settings sheet in LibraryController
private val requestSettingsSheetEvent = Channel<Unit>()
private val openSettingsSheetEvent_ = Channel<Category>()
val openSettingsSheetEvent = openSettingsSheetEvent_.receiveAsFlow()
private suspend fun sendSettingsSheetIntent(category: Category) = openSettingsSheetEvent_.send(category)
suspend fun requestOpenSettingsSheet() = requestSettingsSheetEvent.send(Unit)
private suspend fun requestOpenSettingsSheet() = requestSettingsSheetEvent.send(Unit)
}

View File

@@ -78,8 +78,6 @@ import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen
import eu.kanade.tachiyomi.ui.home.HomeScreen
import eu.kanade.tachiyomi.ui.library.LibrarySettingsSheet
import eu.kanade.tachiyomi.ui.library.LibraryTab
import eu.kanade.tachiyomi.ui.manga.MangaScreen
import eu.kanade.tachiyomi.ui.more.NewUpdateScreen
import eu.kanade.tachiyomi.util.system.dpToPx
@@ -87,7 +85,6 @@ import eu.kanade.tachiyomi.util.system.isNavigationBarNeedsScrim
import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.setComposeContent
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.callbackFlow
@@ -100,7 +97,6 @@ import kotlinx.coroutines.launch
import logcat.LogPriority
import tachiyomi.core.Constants
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.category.model.Category
import tachiyomi.presentation.core.components.material.Scaffold
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -121,11 +117,6 @@ class MainActivity : BaseActivity() {
// To be checked by splash screen. If true then splash screen will be removed.
var ready = false
/**
* Sheet containing filter/sort/display items.
*/
private var settingsSheet: LibrarySettingsSheet? = null
private var navigator: Navigator? = null
override fun onCreate(savedInstanceState: Bundle?) {
@@ -160,11 +151,6 @@ class MainActivity : BaseActivity() {
// Draw edge-to-edge
WindowCompat.setDecorFitsSystemWindows(window, false)
settingsSheet = LibrarySettingsSheet(this)
LibraryTab.openSettingsSheetEvent
.onEach(::showSettingsSheet)
.launchIn(lifecycleScope)
setComposeContent {
val incognito by preferences.incognitoMode().collectAsState()
val downloadOnly by preferences.downloadedOnly().collectAsState()
@@ -303,14 +289,6 @@ class MainActivity : BaseActivity() {
}
}
private fun showSettingsSheet(category: Category? = null) {
if (category != null) {
settingsSheet?.show(category)
} else {
lifecycleScope.launch { LibraryTab.requestOpenSettingsSheet() }
}
}
@Composable
private fun ConfirmExit() {
val scope = rememberCoroutineScope()
@@ -470,12 +448,6 @@ class MainActivity : BaseActivity() {
return true
}
override fun onDestroy() {
settingsSheet?.sheetScope?.cancel()
settingsSheet = null
super.onDestroy()
}
override fun onBackPressed() {
if (navigator?.size == 1 &&
!onBackPressedDispatcher.hasEnabledCallbacks() &&