2019-04-28 22:43:54 +02:00
|
|
|
package org.schabi.newpipe.local.feed
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
import android.util.Log
|
2020-10-31 21:55:45 +01:00
|
|
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|
|
|
import io.reactivex.rxjava3.core.Completable
|
|
|
|
import io.reactivex.rxjava3.core.Flowable
|
|
|
|
import io.reactivex.rxjava3.core.Maybe
|
|
|
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.MainActivity.DEBUG
|
|
|
|
import org.schabi.newpipe.NewPipeDatabase
|
|
|
|
import org.schabi.newpipe.database.feed.model.FeedEntity
|
|
|
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
2019-12-16 08:36:04 +01:00
|
|
|
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
|
|
|
import org.schabi.newpipe.extractor.stream.StreamType
|
|
|
|
import org.schabi.newpipe.local.subscription.FeedGroupIcon
|
2020-11-04 18:07:40 +01:00
|
|
|
import java.time.LocalDate
|
|
|
|
import java.time.OffsetDateTime
|
|
|
|
import java.time.ZoneOffset
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
class FeedDatabaseManager(context: Context) {
|
|
|
|
private val database = NewPipeDatabase.getInstance(context)
|
|
|
|
private val feedTable = database.feedDAO()
|
|
|
|
private val feedGroupTable = database.feedGroupDAO()
|
|
|
|
private val streamTable = database.streamDAO()
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
/**
|
|
|
|
* Only items that are newer than this will be saved.
|
|
|
|
*/
|
2020-10-18 08:16:55 +02:00
|
|
|
val FEED_OLDEST_ALLOWED_DATE: OffsetDateTime = LocalDate.now().minusWeeks(13)
|
2020-11-04 18:07:40 +01:00
|
|
|
.atStartOfDay().atOffset(ZoneOffset.UTC)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun groups() = feedGroupTable.getAll()
|
|
|
|
|
|
|
|
fun database() = database
|
|
|
|
|
2020-01-28 06:59:49 +01:00
|
|
|
fun asStreamItems(groupId: Long = FeedGroupEntity.GROUP_ALL_ID): Flowable<List<StreamInfoItem>> {
|
|
|
|
val streams = when (groupId) {
|
|
|
|
FeedGroupEntity.GROUP_ALL_ID -> feedTable.getAllStreams()
|
|
|
|
else -> feedTable.getAllStreamsFromGroup(groupId)
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2020-10-31 21:55:45 +01:00
|
|
|
return streams.map {
|
2019-04-28 22:43:54 +02:00
|
|
|
val items = ArrayList<StreamInfoItem>(it.size)
|
2020-10-31 21:55:45 +01:00
|
|
|
it.mapTo(items) { stream -> stream.toStreamInfoItem() }
|
2019-04-28 22:43:54 +02:00
|
|
|
return@map items
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-18 08:16:55 +02:00
|
|
|
fun outdatedSubscriptions(outdatedThreshold: OffsetDateTime) = feedTable.getAllOutdated(outdatedThreshold)
|
2019-12-16 08:36:04 +01:00
|
|
|
|
2020-01-28 06:59:49 +01:00
|
|
|
fun notLoadedCount(groupId: Long = FeedGroupEntity.GROUP_ALL_ID): Flowable<Long> {
|
|
|
|
return when (groupId) {
|
|
|
|
FeedGroupEntity.GROUP_ALL_ID -> feedTable.notLoadedCount()
|
|
|
|
else -> feedTable.notLoadedCountForGroup(groupId)
|
2019-12-16 08:36:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-18 08:16:55 +02:00
|
|
|
fun outdatedSubscriptionsForGroup(groupId: Long = FeedGroupEntity.GROUP_ALL_ID, outdatedThreshold: OffsetDateTime) =
|
2020-10-31 21:55:45 +01:00
|
|
|
feedTable.getAllOutdatedForGroup(groupId, outdatedThreshold)
|
2019-12-16 08:36:04 +01:00
|
|
|
|
|
|
|
fun markAsOutdated(subscriptionId: Long) = feedTable
|
2020-10-31 21:55:45 +01:00
|
|
|
.setLastUpdatedForSubscription(FeedLastUpdatedEntity(subscriptionId, null))
|
2019-12-16 08:36:04 +01:00
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
fun upsertAll(
|
|
|
|
subscriptionId: Long,
|
|
|
|
items: List<StreamInfoItem>,
|
2020-10-18 08:16:55 +02:00
|
|
|
oldestAllowedDate: OffsetDateTime = FEED_OLDEST_ALLOWED_DATE
|
2020-05-01 20:13:21 +02:00
|
|
|
) {
|
2019-04-28 22:43:54 +02:00
|
|
|
val itemsToInsert = ArrayList<StreamInfoItem>()
|
|
|
|
loop@ for (streamItem in items) {
|
|
|
|
val uploadDate = streamItem.uploadDate
|
|
|
|
|
|
|
|
itemsToInsert += when {
|
|
|
|
uploadDate == null && streamItem.streamType == StreamType.LIVE_STREAM -> streamItem
|
2020-10-18 08:16:55 +02:00
|
|
|
uploadDate != null && uploadDate.offsetDateTime() >= oldestAllowedDate -> streamItem
|
2019-04-28 22:43:54 +02:00
|
|
|
else -> continue@loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
feedTable.unlinkOldLivestreams(subscriptionId)
|
|
|
|
|
|
|
|
if (itemsToInsert.isNotEmpty()) {
|
|
|
|
val streamEntities = itemsToInsert.map { StreamEntity(it) }
|
|
|
|
val streamIds = streamTable.upsertAll(streamEntities)
|
|
|
|
val feedEntities = streamIds.map { FeedEntity(it, subscriptionId) }
|
|
|
|
|
|
|
|
feedTable.insertAll(feedEntities)
|
|
|
|
}
|
|
|
|
|
2020-11-04 18:07:40 +01:00
|
|
|
feedTable.setLastUpdatedForSubscription(
|
|
|
|
FeedLastUpdatedEntity(
|
|
|
|
subscriptionId,
|
|
|
|
OffsetDateTime.now(ZoneOffset.UTC)
|
|
|
|
)
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2020-10-18 08:16:55 +02:00
|
|
|
fun removeOrphansOrOlderStreams(oldestAllowedDate: OffsetDateTime = FEED_OLDEST_ALLOWED_DATE) {
|
2019-04-28 22:43:54 +02:00
|
|
|
feedTable.unlinkStreamsOlderThan(oldestAllowedDate)
|
|
|
|
streamTable.deleteOrphans()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clear() {
|
|
|
|
feedTable.deleteAll()
|
|
|
|
val deletedOrphans = streamTable.deleteOrphans()
|
|
|
|
if (DEBUG) Log.d(this::class.java.simpleName, "clear() → streamTable.deleteOrphans() → $deletedOrphans")
|
|
|
|
}
|
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
// Feed Groups
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
fun subscriptionIdsForGroup(groupId: Long): Flowable<List<Long>> {
|
|
|
|
return feedGroupTable.getSubscriptionIdsFor(groupId)
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun updateSubscriptionsForGroup(groupId: Long, subscriptionIds: List<Long>): Completable {
|
|
|
|
return Completable.fromCallable { feedGroupTable.updateSubscriptionsForGroup(groupId, subscriptionIds) }
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun createGroup(name: String, icon: FeedGroupIcon): Maybe<Long> {
|
|
|
|
return Maybe.fromCallable { feedGroupTable.insert(FeedGroupEntity(0, name, icon)) }
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun getGroup(groupId: Long): Maybe<FeedGroupEntity> {
|
|
|
|
return feedGroupTable.getGroup(groupId)
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun updateGroup(feedGroupEntity: FeedGroupEntity): Completable {
|
|
|
|
return Completable.fromCallable { feedGroupTable.update(feedGroupEntity) }
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun deleteGroup(groupId: Long): Completable {
|
|
|
|
return Completable.fromCallable { feedGroupTable.delete(groupId) }
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
2019-12-16 08:36:04 +01:00
|
|
|
|
2020-02-26 03:01:23 +01:00
|
|
|
fun updateGroupsOrder(groupIdList: List<Long>): Completable {
|
|
|
|
var index = 0L
|
|
|
|
val orderMap = groupIdList.associateBy({ it }, { index++ })
|
|
|
|
|
|
|
|
return Completable.fromCallable { feedGroupTable.updateOrder(orderMap) }
|
2020-10-31 21:55:45 +01:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2020-02-26 03:01:23 +01:00
|
|
|
}
|
|
|
|
|
2020-10-18 08:16:55 +02:00
|
|
|
fun oldestSubscriptionUpdate(groupId: Long): Flowable<List<OffsetDateTime>> {
|
2020-01-28 06:59:49 +01:00
|
|
|
return when (groupId) {
|
|
|
|
FeedGroupEntity.GROUP_ALL_ID -> feedTable.oldestSubscriptionUpdateFromAll()
|
|
|
|
else -> feedTable.oldestSubscriptionUpdate(groupId)
|
2019-12-16 08:36:04 +01:00
|
|
|
}
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|