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:
Tobias Groza 2020-07-02 22:53:11 +02:00 committed by GitHub
commit 07cead7e99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 27 deletions

View file

@ -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)

View file

@ -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) {

View file

@ -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()

View file

@ -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
}
}
}

View file

@ -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>

View file

@ -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>