Control FAB with Compose in SourceFeed
This commit is contained in:
parent
e6767b747b
commit
d0518515e9
@ -101,6 +101,7 @@ sealed class SourceFeedUI {
|
||||
@Composable
|
||||
fun SourceFeedScreen(
|
||||
presenter: SourceFeedPresenter,
|
||||
onFabClick: () -> Unit,
|
||||
onClickBrowse: () -> Unit,
|
||||
onClickLatest: () -> Unit,
|
||||
onClickSavedSearch: (SavedSearch) -> Unit,
|
||||
@ -117,6 +118,12 @@ fun SourceFeedScreen(
|
||||
downloadedOnlyMode = presenter.isDownloadOnly,
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
BrowseSourceFloatingActionButton(
|
||||
isVisible = presenter.filterItems.isNotEmpty(),
|
||||
onFabClick = onFabClick,
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
Crossfade(targetState = presenter.isLoading) { state ->
|
||||
when (state) {
|
||||
|
@ -1,14 +1,20 @@
|
||||
package eu.kanade.presentation.browse
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.toItems
|
||||
|
||||
@Stable
|
||||
interface SourceFeedState {
|
||||
val isLoading: Boolean
|
||||
var searchQuery: String?
|
||||
val filters: FilterList
|
||||
val filterItems: List<IFlexible<*>>
|
||||
val items: List<SourceFeedUI>?
|
||||
}
|
||||
|
||||
@ -19,5 +25,7 @@ fun SourceFeedState(): SourceFeedState {
|
||||
class SourceFeedStateImpl : SourceFeedState {
|
||||
override var isLoading: Boolean by mutableStateOf(true)
|
||||
override var searchQuery: String? by mutableStateOf(null)
|
||||
override var filters: FilterList by mutableStateOf(FilterList())
|
||||
override val filterItems: List<IFlexible<*>> by derivedStateOf { filters.toItems() }
|
||||
override var items: List<SourceFeedUI>? by mutableStateOf(null)
|
||||
}
|
||||
|
@ -4,9 +4,7 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.domain.source.interactor.GetRemoteManga
|
||||
import eu.kanade.presentation.browse.SourceFeedScreen
|
||||
@ -14,7 +12,6 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||
@ -38,8 +35,7 @@ import xyz.nulldev.ts.api.http.serializer.FilterSerializer
|
||||
* [SourceFeedCardAdapter.OnMangaClickListener] called when manga is clicked in global search
|
||||
*/
|
||||
open class SourceFeedController :
|
||||
FullComposeController<SourceFeedPresenter>,
|
||||
FabController {
|
||||
FullComposeController<SourceFeedPresenter> {
|
||||
|
||||
constructor(source: CatalogueSource?) : super(
|
||||
bundleOf(
|
||||
@ -58,8 +54,6 @@ open class SourceFeedController :
|
||||
|
||||
var source: CatalogueSource? = null
|
||||
|
||||
private var actionFab: ExtendedFloatingActionButton? = null
|
||||
|
||||
/**
|
||||
* Sheet containing filter items.
|
||||
*/
|
||||
@ -89,10 +83,6 @@ open class SourceFeedController :
|
||||
private val filterSerializer = FilterSerializer()
|
||||
|
||||
fun initFilterSheet() {
|
||||
if (presenter.sourceFilters.isEmpty()) {
|
||||
actionFab?.text = activity!!.getString(R.string.saved_searches)
|
||||
}
|
||||
|
||||
filterSheet = SourceFilterSheet(
|
||||
activity!!,
|
||||
// SY -->
|
||||
@ -101,7 +91,7 @@ open class SourceFeedController :
|
||||
emptyList(),
|
||||
// SY <--
|
||||
onFilterClicked = {
|
||||
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
|
||||
val allDefault = presenter.filters == presenter.source.getFilterList()
|
||||
filterSheet?.dismiss()
|
||||
if (allDefault) {
|
||||
onBrowseClick(
|
||||
@ -110,7 +100,7 @@ open class SourceFeedController :
|
||||
} else {
|
||||
onBrowseClick(
|
||||
presenter.searchQuery?.nullIfBlank(),
|
||||
filters = Json.encodeToString(filterSerializer.serialize(presenter.sourceFilters)),
|
||||
filters = Json.encodeToString(filterSerializer.serialize(presenter.filters)),
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -135,9 +125,9 @@ open class SourceFeedController :
|
||||
return@launchUI
|
||||
}
|
||||
|
||||
presenter.sourceFilters = FilterList(search.filterList)
|
||||
presenter.setFilters(FilterList(search.filterList))
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
|
||||
val allDefault = presenter.filters == presenter.source.getFilterList()
|
||||
filterSheet?.dismiss()
|
||||
|
||||
if (!allDefault) {
|
||||
@ -171,35 +161,13 @@ open class SourceFeedController :
|
||||
filterSheet?.setSavedSearches(presenter.loadSearches())
|
||||
}
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
|
||||
// TODO: [ExtendedFloatingActionButton] hide/show methods don't work properly
|
||||
filterSheet?.setOnShowListener { actionFab?.isVisible = false }
|
||||
filterSheet?.setOnDismissListener { actionFab?.isVisible = true }
|
||||
|
||||
actionFab?.setOnClickListener { filterSheet?.show() }
|
||||
|
||||
actionFab?.isVisible = true
|
||||
}
|
||||
|
||||
override fun configureFab(fab: ExtendedFloatingActionButton) {
|
||||
actionFab = fab
|
||||
|
||||
// Controlled by initFilterSheet()
|
||||
fab.isVisible = false
|
||||
|
||||
fab.setText(R.string.action_filter)
|
||||
fab.setIconResource(R.drawable.ic_filter_list_24dp)
|
||||
}
|
||||
|
||||
override fun cleanupFab(fab: ExtendedFloatingActionButton) {
|
||||
fab.setOnClickListener(null)
|
||||
actionFab = null
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun ComposeContent() {
|
||||
SourceFeedScreen(
|
||||
presenter = presenter,
|
||||
onFabClick = { filterSheet?.show() },
|
||||
onClickBrowse = ::onBrowseClick,
|
||||
onClickLatest = ::onLatestClick,
|
||||
onClickSavedSearch = ::onSavedSearchClick,
|
||||
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.browse.source.feed
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.getValue
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.domain.manga.interactor.GetManga
|
||||
import eu.kanade.domain.manga.interactor.InsertManga
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
@ -12,7 +11,6 @@ import eu.kanade.domain.source.interactor.CountFeedSavedSearchBySourceId
|
||||
import eu.kanade.domain.source.interactor.DeleteFeedSavedSearchById
|
||||
import eu.kanade.domain.source.interactor.GetExhSavedSearch
|
||||
import eu.kanade.domain.source.interactor.GetFeedSavedSearchBySourceId
|
||||
import eu.kanade.domain.source.interactor.GetSavedSearchBySourceId
|
||||
import eu.kanade.domain.source.interactor.GetSavedSearchBySourceIdFeed
|
||||
import eu.kanade.domain.source.interactor.InsertFeedSavedSearch
|
||||
import eu.kanade.presentation.browse.SourceFeedState
|
||||
@ -27,8 +25,7 @@ import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.toItems
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO
|
||||
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
@ -53,8 +50,6 @@ import xyz.nulldev.ts.api.http.serializer.FilterSerializer
|
||||
* Function calls should be done from here. UI calls should be done from the controller.
|
||||
*
|
||||
* @param source the source.
|
||||
* @param handler manages the database calls.
|
||||
* @param preferences manages the preference calls.
|
||||
*/
|
||||
open class SourceFeedPresenter(
|
||||
private val state: SourceFeedStateImpl = SourceFeedState() as SourceFeedStateImpl,
|
||||
@ -66,7 +61,6 @@ open class SourceFeedPresenter(
|
||||
private val getFeedSavedSearchBySourceId: GetFeedSavedSearchBySourceId = Injekt.get(),
|
||||
private val getSavedSearchBySourceIdFeed: GetSavedSearchBySourceIdFeed = Injekt.get(),
|
||||
private val countFeedSavedSearchBySourceId: CountFeedSavedSearchBySourceId = Injekt.get(),
|
||||
private val getSavedSearchBySourceId: GetSavedSearchBySourceId = Injekt.get(),
|
||||
private val insertFeedSavedSearch: InsertFeedSavedSearch = Injekt.get(),
|
||||
private val deleteFeedSavedSearchById: DeleteFeedSavedSearchById = Injekt.get(),
|
||||
private val getExhSavedSearch: GetExhSavedSearch = Injekt.get(),
|
||||
@ -90,21 +84,10 @@ open class SourceFeedPresenter(
|
||||
*/
|
||||
private var fetchImageSubscription: Subscription? = null
|
||||
|
||||
/**
|
||||
* Modifiable list of filters.
|
||||
*/
|
||||
var sourceFilters = FilterList()
|
||||
set(value) {
|
||||
field = value
|
||||
filterItems = value.toItems()
|
||||
}
|
||||
|
||||
var filterItems: List<IFlexible<*>> = emptyList()
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
sourceFilters = source.getFilterList()
|
||||
setFilters(source.getFilterList())
|
||||
|
||||
getFeedSavedSearchBySourceId.subscribe(source.id)
|
||||
.onEach {
|
||||
@ -122,16 +105,16 @@ open class SourceFeedPresenter(
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
fun setFilters(filters: FilterList) {
|
||||
state.filters = filters
|
||||
}
|
||||
|
||||
suspend fun hasTooManyFeeds(): Boolean {
|
||||
return countFeedSavedSearchBySourceId.await(source.id) > 10
|
||||
}
|
||||
|
||||
suspend fun getSourceSavedSearches(): List<SavedSearch> {
|
||||
return getSavedSearchBySourceId.await(source.id)
|
||||
}
|
||||
|
||||
fun createFeed(savedSearchId: Long) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
insertFeedSavedSearch.await(
|
||||
FeedSavedSearch(
|
||||
id = -1,
|
||||
@ -144,7 +127,7 @@ open class SourceFeedPresenter(
|
||||
}
|
||||
|
||||
fun deleteFeed(feed: FeedSavedSearch) {
|
||||
launchIO {
|
||||
presenterScope.launchNonCancellableIO {
|
||||
deleteFeedSavedSearchById.await(feed.id)
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
return filter == (other as SelectItem).filter
|
||||
return filter == (other as AutoComplete).filter
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
Loading…
x
Reference in New Issue
Block a user