Merge pull request #3404 from mauriciocolli/feed-add-filter-sub-list
Add filter to the feed group dialog to show only ungrouped subscriptions
This commit is contained in:
commit
07cead7e99
|
@ -22,10 +22,42 @@ abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
|
|||
|
||||
@Query("""
|
||||
SELECT * FROM subscriptions
|
||||
|
||||
WHERE name LIKE '%' || :filter || '%'
|
||||
|
||||
ORDER BY name COLLATE NOCASE ASC
|
||||
""")
|
||||
abstract fun filterByName(filter: String): Flowable<List<SubscriptionEntity>>
|
||||
abstract fun getSubscriptionsFiltered(filter: String): Flowable<List<SubscriptionEntity>>
|
||||
|
||||
@Query("""
|
||||
SELECT * FROM subscriptions s
|
||||
|
||||
LEFT JOIN feed_group_subscription_join fgs
|
||||
ON s.uid = fgs.subscription_id
|
||||
|
||||
WHERE (fgs.subscription_id IS NULL OR fgs.group_id = :currentGroupId)
|
||||
|
||||
ORDER BY name COLLATE NOCASE ASC
|
||||
""")
|
||||
abstract fun getSubscriptionsOnlyUngrouped(
|
||||
currentGroupId: Long
|
||||
): Flowable<List<SubscriptionEntity>>
|
||||
|
||||
@Query("""
|
||||
SELECT * FROM subscriptions s
|
||||
|
||||
LEFT JOIN feed_group_subscription_join fgs
|
||||
ON s.uid = fgs.subscription_id
|
||||
|
||||
WHERE (fgs.subscription_id IS NULL OR fgs.group_id = :currentGroupId)
|
||||
AND s.name LIKE '%' || :filter || '%'
|
||||
|
||||
ORDER BY name COLLATE NOCASE ASC
|
||||
""")
|
||||
abstract fun getSubscriptionsOnlyUngroupedFiltered(
|
||||
currentGroupId: Long,
|
||||
filter: String
|
||||
): Flowable<List<SubscriptionEntity>>
|
||||
|
||||
@Query("SELECT * FROM subscriptions WHERE url LIKE :url AND service_id = :serviceId")
|
||||
abstract fun getSubscriptionFlowable(serviceId: Int, url: String): Flowable<List<SubscriptionEntity>>
|
||||
|
@ -59,7 +91,7 @@ abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
|
|||
entity.uid = uidFromInsert
|
||||
} else {
|
||||
val subscriptionIdFromDb = getSubscriptionIdInternal(entity.serviceId, entity.url)
|
||||
?: throw IllegalStateException("Subscription cannot be null just after insertion.")
|
||||
?: throw IllegalStateException("Subscription cannot be null just after insertion.")
|
||||
entity.uid = subscriptionIdFromDb
|
||||
|
||||
update(entity)
|
||||
|
|
|
@ -2,9 +2,11 @@ package org.schabi.newpipe.local.subscription
|
|||
|
||||
import android.content.Context
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.schabi.newpipe.NewPipeDatabase
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionDAO
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||
import org.schabi.newpipe.extractor.ListInfo
|
||||
|
@ -21,11 +23,28 @@ class SubscriptionManager(context: Context) {
|
|||
fun subscriptionTable(): SubscriptionDAO = subscriptionTable
|
||||
fun subscriptions() = subscriptionTable.all
|
||||
|
||||
fun filterByName(filter: String) = subscriptionTable.filterByName(filter)
|
||||
fun getSubscriptions(
|
||||
currentGroupId: Long = FeedGroupEntity.GROUP_ALL_ID,
|
||||
filterQuery: String = "",
|
||||
showOnlyUngrouped: Boolean = false
|
||||
): Flowable<List<SubscriptionEntity>> {
|
||||
return when {
|
||||
filterQuery.isNotEmpty() -> {
|
||||
return if (showOnlyUngrouped) {
|
||||
subscriptionTable.getSubscriptionsOnlyUngroupedFiltered(
|
||||
currentGroupId, filterQuery)
|
||||
} else {
|
||||
subscriptionTable.getSubscriptionsFiltered(filterQuery)
|
||||
}
|
||||
}
|
||||
showOnlyUngrouped -> subscriptionTable.getSubscriptionsOnlyUngrouped(currentGroupId)
|
||||
else -> subscriptionTable.all
|
||||
}
|
||||
}
|
||||
|
||||
fun upsertAll(infoList: List<ChannelInfo>): List<SubscriptionEntity> {
|
||||
val listEntities = subscriptionTable.upsertAll(
|
||||
infoList.map { SubscriptionEntity.from(it) })
|
||||
infoList.map { SubscriptionEntity.from(it) })
|
||||
|
||||
database.runInTransaction {
|
||||
infoList.forEachIndexed { index, info ->
|
||||
|
@ -37,13 +56,13 @@ class SubscriptionManager(context: Context) {
|
|||
}
|
||||
|
||||
fun updateChannelInfo(info: ChannelInfo): Completable = subscriptionTable.getSubscription(info.serviceId, info.url)
|
||||
.flatMapCompletable {
|
||||
Completable.fromRunnable {
|
||||
it.setData(info.name, info.avatarUrl, info.description, info.subscriberCount)
|
||||
subscriptionTable.update(it)
|
||||
feedDatabaseManager.upsertAll(it.uid, info.relatedItems)
|
||||
}
|
||||
.flatMapCompletable {
|
||||
Completable.fromRunnable {
|
||||
it.setData(info.name, info.avatarUrl, info.description, info.subscriberCount)
|
||||
subscriptionTable.update(it)
|
||||
feedDatabaseManager.upsertAll(it.uid, info.relatedItems)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFromInfo(subscriptionId: Long, info: ListInfo<StreamInfoItem>) {
|
||||
val subscriptionEntity = subscriptionTable.getSubscription(subscriptionId)
|
||||
|
@ -59,8 +78,8 @@ class SubscriptionManager(context: Context) {
|
|||
|
||||
fun deleteSubscription(serviceId: Int, url: String): Completable {
|
||||
return Completable.fromCallable { subscriptionTable.deleteSubscription(serviceId, url) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
fun insertSubscription(subscriptionEntity: SubscriptionEntity, info: ChannelInfo) {
|
||||
|
|
|
@ -65,6 +65,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
@State @JvmField var iconsListState: Parcelable? = null
|
||||
@State @JvmField var wasSearchSubscriptionsVisible = false
|
||||
@State @JvmField var subscriptionsCurrentSearchQuery = ""
|
||||
@State @JvmField var subscriptionsShowOnlyUngrouped = false
|
||||
|
||||
private val subscriptionMainSection = Section()
|
||||
private val subscriptionEmptyFooter = Section()
|
||||
|
@ -116,7 +117,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
|
||||
viewModel = ViewModelProvider(this,
|
||||
FeedGroupDialogViewModel.Factory(requireContext(),
|
||||
groupId, subscriptionsCurrentSearchQuery)
|
||||
groupId, subscriptionsCurrentSearchQuery, subscriptionsShowOnlyUngrouped)
|
||||
).get(FeedGroupDialogViewModel::class.java)
|
||||
|
||||
viewModel.groupLiveData.observe(viewLifecycleOwner, Observer(::handleGroup))
|
||||
|
@ -216,6 +217,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
true
|
||||
}
|
||||
|
||||
headerMenu.findItem(R.id.feed_group_toggle_show_only_ungrouped_subscriptions).apply {
|
||||
isChecked = subscriptionsShowOnlyUngrouped
|
||||
setOnMenuItemClickListener {
|
||||
subscriptionsShowOnlyUngrouped = !subscriptionsShowOnlyUngrouped
|
||||
it.isChecked = subscriptionsShowOnlyUngrouped
|
||||
viewModel.toggleShowOnlyUngrouped(subscriptionsShowOnlyUngrouped)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
toolbar_search_clear.setOnClickListener {
|
||||
if (TextUtils.isEmpty(toolbar_search_edit_text.text)) {
|
||||
hideSearch()
|
||||
|
|
|
@ -20,24 +20,25 @@ import org.schabi.newpipe.local.subscription.item.PickerSubscriptionItem
|
|||
class FeedGroupDialogViewModel(
|
||||
applicationContext: Context,
|
||||
private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
|
||||
initialQuery: String = ""
|
||||
initialQuery: String = "",
|
||||
initialShowOnlyUngrouped: Boolean = false
|
||||
) : ViewModel() {
|
||||
|
||||
private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(applicationContext)
|
||||
private var subscriptionManager = SubscriptionManager(applicationContext)
|
||||
|
||||
private var filterSubscriptions = BehaviorProcessor.create<String>()
|
||||
private var allSubscriptions = subscriptionManager.subscriptions()
|
||||
private var toggleShowOnlyUngrouped = BehaviorProcessor.create<Boolean>()
|
||||
|
||||
private var subscriptionsFlowable = filterSubscriptions
|
||||
.startWith(initialQuery)
|
||||
private var subscriptionsFlowable = Flowable
|
||||
.combineLatest(
|
||||
filterSubscriptions.startWith(initialQuery),
|
||||
toggleShowOnlyUngrouped.startWith(initialShowOnlyUngrouped),
|
||||
BiFunction { t1: String, t2: Boolean -> Filter(t1, t2) }
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.switchMap { query ->
|
||||
if (query.isEmpty()) {
|
||||
allSubscriptions
|
||||
} else {
|
||||
subscriptionManager.filterByName(query)
|
||||
}
|
||||
.switchMap { filter ->
|
||||
subscriptionManager.getSubscriptions(groupId, filter.query, filter.showOnlyUngrouped)
|
||||
}.map { list -> list.map { PickerSubscriptionItem(it) } }
|
||||
|
||||
private val mutableGroupLiveData = MutableLiveData<FeedGroupEntity>()
|
||||
|
@ -100,20 +101,27 @@ class FeedGroupDialogViewModel(
|
|||
filterSubscriptions.onNext("")
|
||||
}
|
||||
|
||||
fun toggleShowOnlyUngrouped(showOnlyUngrouped: Boolean) {
|
||||
toggleShowOnlyUngrouped.onNext(showOnlyUngrouped)
|
||||
}
|
||||
|
||||
sealed class DialogEvent {
|
||||
object ProcessingEvent : DialogEvent()
|
||||
object SuccessEvent : DialogEvent()
|
||||
}
|
||||
|
||||
data class Filter(val query: String, val showOnlyUngrouped: Boolean)
|
||||
|
||||
class Factory(
|
||||
private val context: Context,
|
||||
private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
|
||||
private val initialQuery: String = ""
|
||||
private val initialQuery: String = "",
|
||||
private val initialShowOnlyUngrouped: Boolean = false
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
return FeedGroupDialogViewModel(context.applicationContext,
|
||||
groupId, initialQuery) as T
|
||||
groupId, initialQuery, initialShowOnlyUngrouped) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_search"
|
||||
android:icon="?attr/ic_search"
|
||||
android:title="@string/search"
|
||||
app:showAsAction="always" />
|
||||
app:showAsAction="always"
|
||||
tools:ignore="AlwaysShowAction" />
|
||||
|
||||
<item
|
||||
android:id="@+id/feed_group_toggle_show_only_ungrouped_subscriptions"
|
||||
android:checkable="true"
|
||||
android:checked="false"
|
||||
android:title="@string/feed_group_show_only_ungrouped_subscriptions"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
|
@ -637,6 +637,7 @@
|
|||
<string name="feed_group_dialog_name_input">Name</string>
|
||||
<string name="feed_group_dialog_delete_message">Do you want to delete this group?</string>
|
||||
<string name="feed_create_new_group_button_title">New</string>
|
||||
<string name="feed_group_show_only_ungrouped_subscriptions">Show only ungrouped subscriptions</string>
|
||||
<string name="settings_category_feed_title">Feed</string>
|
||||
<string name="feed_update_threshold_title">Feed update threshold</string>
|
||||
<string name="feed_update_threshold_summary">Time after last update before a subscription is considered outdated — %s</string>
|
||||
|
|
Loading…
Reference in New Issue