11package org.schabi.newpipe.local.feed.service
22
33import android.content.Context
4+ import android.content.SharedPreferences
45import androidx.preference.PreferenceManager
56import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
67import io.reactivex.rxjava3.core.Completable
@@ -13,6 +14,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers
1314import org.schabi.newpipe.R
1415import org.schabi.newpipe.database.feed.model.FeedGroupEntity
1516import org.schabi.newpipe.database.subscription.NotificationMode
17+ import org.schabi.newpipe.database.subscription.SubscriptionEntity
1618import org.schabi.newpipe.extractor.Info
1719import org.schabi.newpipe.extractor.NewPipe
1820import org.schabi.newpipe.extractor.feed.FeedInfo
@@ -108,99 +110,7 @@ class FeedLoadManager(private val context: Context) {
108110 .runOn(Schedulers .io(), PARALLEL_EXTRACTIONS * 2 )
109111 .filter { ! cancelSignal.get() }
110112 .map { subscriptionEntity ->
111- var error: Throwable ? = null
112- val storeOriginalErrorAndRethrow = { e: Throwable ->
113- // keep original to prevent blockingGet() from wrapping it into RuntimeException
114- error = e
115- throw e
116- }
117-
118- try {
119- // check for and load new streams
120- // either by using the dedicated feed method or by getting the channel info
121- var originalInfo: Info ? = null
122- var streams: List <StreamInfoItem >? = null
123- val errors = ArrayList <Throwable >()
124-
125- if (useFeedExtractor) {
126- NewPipe .getService(subscriptionEntity.serviceId)
127- .getFeedExtractor(subscriptionEntity.url)
128- ?.also { feedExtractor ->
129- // the user wants to use a feed extractor and there is one, use it
130- val feedInfo = FeedInfo .getInfo(feedExtractor)
131- errors.addAll(feedInfo.errors)
132- originalInfo = feedInfo
133- streams = feedInfo.relatedItems
134- }
135- }
136-
137- if (originalInfo == null ) {
138- // use the normal channel tabs extractor if either the user wants it, or
139- // the current service does not have a dedicated feed extractor
140-
141- val channelInfo = getChannelInfo(
142- subscriptionEntity.serviceId,
143- subscriptionEntity.url, true
144- )
145- .onErrorReturn(storeOriginalErrorAndRethrow)
146- .blockingGet()
147- errors.addAll(channelInfo.errors)
148- originalInfo = channelInfo
149-
150- streams = channelInfo.tabs
151- .filter { tab ->
152- ChannelTabHelper .fetchFeedChannelTab(
153- context,
154- defaultSharedPreferences,
155- tab
156- )
157- }
158- .map {
159- Pair (
160- getChannelTab(subscriptionEntity.serviceId, it, true )
161- .onErrorReturn(storeOriginalErrorAndRethrow)
162- .blockingGet(),
163- it
164- )
165- }
166- .flatMap { (channelTabInfo, linkHandler) ->
167- errors.addAll(channelTabInfo.errors)
168- if (channelTabInfo.relatedItems.isEmpty() &&
169- channelTabInfo.nextPage != null
170- ) {
171- val infoItemsPage = getMoreChannelTabItems(
172- subscriptionEntity.serviceId,
173- linkHandler, channelTabInfo.nextPage
174- )
175- .blockingGet()
176-
177- errors.addAll(infoItemsPage.errors)
178- return @flatMap infoItemsPage.items
179- } else {
180- return @flatMap channelTabInfo.relatedItems
181- }
182- }
183- .filterIsInstance<StreamInfoItem >()
184- }
185-
186- return @map Notification .createOnNext(
187- FeedUpdateInfo (
188- subscriptionEntity,
189- originalInfo!! ,
190- streams!! ,
191- errors,
192- )
193- )
194- } catch (e: Throwable ) {
195- val request = " ${subscriptionEntity.serviceId} :${subscriptionEntity.url} "
196- val wrapper = FeedLoadService .RequestException (
197- subscriptionEntity.uid,
198- request,
199- // do this to prevent blockingGet() from wrapping into RuntimeException
200- error ? : e
201- )
202- return @map Notification .createOnError<FeedUpdateInfo >(wrapper)
203- }
113+ loadStreams(subscriptionEntity, useFeedExtractor, defaultSharedPreferences)
204114 }
205115 .sequential()
206116 .observeOn(AndroidSchedulers .mainThread())
@@ -226,6 +136,107 @@ class FeedLoadManager(private val context: Context) {
226136 )
227137 }
228138
139+ private fun loadStreams (
140+ subscriptionEntity : SubscriptionEntity ,
141+ useFeedExtractor : Boolean ,
142+ defaultSharedPreferences : SharedPreferences
143+ ):
144+ Notification <FeedUpdateInfo > {
145+ var error: Throwable ? = null
146+ val storeOriginalErrorAndRethrow = { e: Throwable ->
147+ // keep original to prevent blockingGet() from wrapping it into RuntimeException
148+ error = e
149+ throw e
150+ }
151+
152+ try {
153+ // check for and load new streams
154+ // either by using the dedicated feed method or by getting the channel info
155+ var originalInfo: Info ? = null
156+ var streams: List <StreamInfoItem >? = null
157+ val errors = ArrayList <Throwable >()
158+
159+ if (useFeedExtractor) {
160+ NewPipe .getService(subscriptionEntity.serviceId)
161+ .getFeedExtractor(subscriptionEntity.url)
162+ ?.also { feedExtractor ->
163+ // the user wants to use a feed extractor and there is one, use it
164+ val feedInfo = FeedInfo .getInfo(feedExtractor)
165+ errors.addAll(feedInfo.errors)
166+ originalInfo = feedInfo
167+ streams = feedInfo.relatedItems
168+ }
169+ }
170+
171+ if (originalInfo == null ) {
172+ // use the normal channel tabs extractor if either the user wants it, or
173+ // the current service does not have a dedicated feed extractor
174+
175+ val channelInfo = getChannelInfo(
176+ subscriptionEntity.serviceId,
177+ subscriptionEntity.url, true
178+ )
179+ .onErrorReturn(storeOriginalErrorAndRethrow)
180+ .blockingGet()
181+ errors.addAll(channelInfo.errors)
182+ originalInfo = channelInfo
183+
184+ streams = channelInfo.tabs
185+ .filter { tab ->
186+ ChannelTabHelper .fetchFeedChannelTab(
187+ context,
188+ defaultSharedPreferences,
189+ tab
190+ )
191+ }
192+ .map {
193+ Pair (
194+ getChannelTab(subscriptionEntity.serviceId, it, true )
195+ .onErrorReturn(storeOriginalErrorAndRethrow)
196+ .blockingGet(),
197+ it
198+ )
199+ }
200+ .flatMap { (channelTabInfo, linkHandler) ->
201+ errors.addAll(channelTabInfo.errors)
202+ if (channelTabInfo.relatedItems.isEmpty() &&
203+ channelTabInfo.nextPage != null
204+ ) {
205+ val infoItemsPage = getMoreChannelTabItems(
206+ subscriptionEntity.serviceId,
207+ linkHandler, channelTabInfo.nextPage
208+ )
209+ .blockingGet()
210+
211+ errors.addAll(infoItemsPage.errors)
212+ return @flatMap infoItemsPage.items
213+ } else {
214+ return @flatMap channelTabInfo.relatedItems
215+ }
216+ }
217+ .filterIsInstance<StreamInfoItem >()
218+ }
219+
220+ return Notification .createOnNext(
221+ FeedUpdateInfo (
222+ subscriptionEntity,
223+ originalInfo!! ,
224+ streams!! ,
225+ errors,
226+ )
227+ )
228+ } catch (e: Throwable ) {
229+ val request = " ${subscriptionEntity.serviceId} :${subscriptionEntity.url} "
230+ val wrapper = FeedLoadService .RequestException (
231+ subscriptionEntity.uid,
232+ request,
233+ // do this to prevent blockingGet() from wrapping into RuntimeException
234+ error ? : e
235+ )
236+ return Notification .createOnError(wrapper)
237+ }
238+ }
239+
229240 /* *
230241 * Keep the feed and the stream tables small
231242 * to reduce loading times when trying to display the feed.
0 commit comments