@@ -162,6 +162,7 @@ object PlayerStreamsRepository {
162162 val installedAddonNames = installedAddons.map { it.displayTitle }.toSet()
163163 PlayerSettingsRepository .ensureLoaded()
164164 val playerSettings = PlayerSettingsRepository .uiState.value
165+ val debridSettings = DebridSettingsRepository .snapshot()
165166 val pluginScrapers = if (AppFeaturePolicy .pluginsEnabled) {
166167 PluginRepository .initialize()
167168 PluginRepository .getEnabledScrapersForType(type)
@@ -234,6 +235,61 @@ object PlayerStreamsRepository {
234235 val job = scope.launch {
235236 val pendingStreamAddons = streamAddons.filterNot { it.addonId in warmedAddonIds }
236237 val installedAddonIds = streamAddons.map { it.addonId }.toSet()
238+ val debridAvailabilityJobs = mutableListOf<Job >()
239+ fun emptyStateReason (groups : List <AddonStreamGroup >, anyLoading : Boolean ) =
240+ if (! anyLoading && groups.all { it.streams.isEmpty() }) {
241+ if (groups.all { ! it.error.isNullOrBlank() }) {
242+ com.nuvio.app.features.streams.StreamsEmptyStateReason .StreamFetchFailed
243+ } else {
244+ com.nuvio.app.features.streams.StreamsEmptyStateReason .NoStreamsFound
245+ }
246+ } else {
247+ null
248+ }
249+
250+ fun presentDebridGroup (group : AddonStreamGroup ): AddonStreamGroup =
251+ DebridStreamPresentation .apply (
252+ groups = listOf (group),
253+ settings = debridSettings,
254+ ).firstOrNull() ? : group
255+
256+ fun publishStreamGroup (group : AddonStreamGroup ) {
257+ stateFlow.update { current ->
258+ val updated = StreamAutoPlaySelector .orderAddonStreams(
259+ groups = current.groups.map { currentGroup ->
260+ if (currentGroup.addonId == group.addonId) group else currentGroup
261+ },
262+ installedOrder = installedAddonOrder,
263+ )
264+ val anyLoading = updated.any { it.isLoading }
265+ current.copy(
266+ groups = updated,
267+ isAnyLoading = anyLoading,
268+ emptyStateReason = emptyStateReason(updated, anyLoading),
269+ )
270+ }
271+ }
272+
273+ fun launchDebridAvailability (group : AddonStreamGroup ) {
274+ if (group.addonId !in installedAddonIds || group.streams.isEmpty()) return
275+
276+ val eligibleGroupIds = setOf (group.addonId)
277+ val checkingGroup = TorboxAvailabilityService .markChecking(
278+ groups = listOf (group),
279+ eligibleGroupIds = eligibleGroupIds,
280+ ).firstOrNull() ? : group
281+ publishStreamGroup(checkingGroup)
282+
283+ val availabilityJob = launch {
284+ val availabilityGroup = TorboxAvailabilityService .annotateCachedAvailability(
285+ groups = listOf (checkingGroup),
286+ eligibleGroupIds = eligibleGroupIds,
287+ ).firstOrNull() ? : checkingGroup
288+ publishStreamGroup(presentDebridGroup(availabilityGroup))
289+ }
290+ debridAvailabilityJobs + = availabilityJob
291+ }
292+
237293 val addonJobs = pendingStreamAddons.map { addon ->
238294 async {
239295 val url = buildAddonResourceUrl(
@@ -301,64 +357,33 @@ object PlayerStreamsRepository {
301357 completions.send(deferred.await())
302358 }
303359 }
304- var debridPreparationLaunched = false
305360 repeat(jobs.size) {
306361 val result = completions.receive()
307- stateFlow.update { current ->
308- val updated = StreamAutoPlaySelector .orderAddonStreams(
309- groups = current.groups.map { g -> if (g.addonId == result.addonId) result else g },
310- installedOrder = installedAddonOrder,
311- )
312- val anyLoading = updated.any { it.isLoading }
313- current.copy(
314- groups = updated,
315- isAnyLoading = anyLoading,
316- emptyStateReason = if (! anyLoading && updated.all { it.streams.isEmpty() }) {
317- if (updated.all { ! it.error.isNullOrBlank() }) {
318- com.nuvio.app.features.streams.StreamsEmptyStateReason .StreamFetchFailed
319- } else {
320- com.nuvio.app.features.streams.StreamsEmptyStateReason .NoStreamsFound
321- }
322- } else null ,
323- )
324- }
362+ publishStreamGroup(result)
363+ launchDebridAvailability(result)
325364 }
326- if (! debridPreparationLaunched) {
327- debridPreparationLaunched = true
328- val checkingGroups = TorboxAvailabilityService .markChecking(
329- groups = stateFlow.value.groups,
330- eligibleGroupIds = installedAddonIds,
331- )
332- stateFlow.update { current -> current.copy(groups = checkingGroups) }
333- val availabilityGroups = TorboxAvailabilityService .annotateCachedAvailability(
334- groups = stateFlow.value.groups,
335- eligibleGroupIds = installedAddonIds,
336- )
337- val presentedGroups = DebridStreamPresentation .apply (
338- groups = availabilityGroups,
339- settings = DebridSettingsRepository .snapshot(),
340- )
341- stateFlow.update { current -> current.copy(groups = presentedGroups) }
342- launch {
343- DirectDebridStreamPreparer .prepare(
344- streams = stateFlow.value.groups
345- .filter { it.addonId in installedAddonIds }
346- .flatMap { it.streams },
347- season = season,
348- episode = episode,
349- playerSettings = playerSettings,
350- installedAddonNames = installedAddonNames,
351- ) { original, prepared ->
352- stateFlow.update { current ->
353- current.copy(
354- groups = DirectDebridStreamPreparer .replacePreparedStream(
355- groups = current.groups,
356- original = original,
357- prepared = prepared,
358- eligibleGroupIds = installedAddonIds,
359- ),
360- )
361- }
365+ for (availabilityJob in debridAvailabilityJobs) {
366+ availabilityJob.join()
367+ }
368+ launch {
369+ DirectDebridStreamPreparer .prepare(
370+ streams = stateFlow.value.groups
371+ .filter { it.addonId in installedAddonIds }
372+ .flatMap { it.streams },
373+ season = season,
374+ episode = episode,
375+ playerSettings = playerSettings,
376+ installedAddonNames = installedAddonNames,
377+ ) { original, prepared ->
378+ stateFlow.update { current ->
379+ current.copy(
380+ groups = DirectDebridStreamPreparer .replacePreparedStream(
381+ groups = current.groups,
382+ original = original,
383+ prepared = prepared,
384+ eligibleGroupIds = installedAddonIds,
385+ ),
386+ )
362387 }
363388 }
364389 }
0 commit comments