mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-22 17:52:06 +00:00
feat: save resolved links in memory
This commit is contained in:
parent
2e35652e81
commit
e85ea4f322
2 changed files with 119 additions and 3 deletions
|
|
@ -64,6 +64,13 @@ internal class CloudLibraryStore(
|
|||
?: return CloudLibraryPlaybackResult.MissingCredentials
|
||||
val api = providerApis.firstOrNull { it.provider.id == item.providerId }
|
||||
?: return CloudLibraryPlaybackResult.Failed()
|
||||
file.playbackUrl?.takeIf { it.isNotBlank() }?.let { url ->
|
||||
return CloudLibraryPlaybackResult.Success(
|
||||
url = url,
|
||||
filename = file.name.takeIf { it.isNotBlank() },
|
||||
videoSizeBytes = file.sizeBytes,
|
||||
)
|
||||
}
|
||||
return api.resolvePlayback(
|
||||
apiKey = credential.apiKey,
|
||||
item = item,
|
||||
|
|
@ -186,7 +193,26 @@ object CloudLibraryRepository {
|
|||
if (!DebridSettingsRepository.snapshot().cloudLibraryEnabled) {
|
||||
return CloudLibraryPlaybackResult.Failed("Cloud library is disabled.")
|
||||
}
|
||||
return store.resolvePlayback(item, file)
|
||||
val result = store.resolvePlayback(item, file)
|
||||
if (result is CloudLibraryPlaybackResult.Success) {
|
||||
rememberResolvedPlaybackUrl(item = item, file = file, url = result.url)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun rememberResolvedPlaybackUrl(
|
||||
item: CloudLibraryItem,
|
||||
file: CloudLibraryFile,
|
||||
url: String,
|
||||
) {
|
||||
if (url.isBlank()) return
|
||||
_uiState.update { current ->
|
||||
current.withResolvedPlaybackUrl(
|
||||
item = item,
|
||||
file = file,
|
||||
url = url,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun connectedCloudCredentials(): List<DebridServiceCredential> =
|
||||
|
|
@ -248,3 +274,35 @@ internal fun CloudLibraryUiState.findPlaybackTargetForProgress(
|
|||
val singleFile = singleItem.playableFiles.singleOrNull() ?: return null
|
||||
return CloudLibraryPlaybackTarget(item = singleItem, file = singleFile)
|
||||
}
|
||||
|
||||
internal fun CloudLibraryUiState.withResolvedPlaybackUrl(
|
||||
item: CloudLibraryItem,
|
||||
file: CloudLibraryFile,
|
||||
url: String,
|
||||
): CloudLibraryUiState {
|
||||
val normalizedUrl = url.trim().takeIf { it.isNotBlank() } ?: return this
|
||||
val targetItemKey = item.stableKey
|
||||
val targetFileKey = file.stableKey
|
||||
var didUpdate = false
|
||||
val updatedProviders = providers.map { providerState ->
|
||||
if (providerState.providerId != item.providerId) return@map providerState
|
||||
val updatedItems = providerState.items.map { candidateItem ->
|
||||
if (candidateItem.stableKey != targetItemKey) return@map candidateItem
|
||||
val updatedFiles = candidateItem.files.map { candidateFile ->
|
||||
if (candidateFile.stableKey != targetFileKey) {
|
||||
candidateFile
|
||||
} else {
|
||||
didUpdate = true
|
||||
candidateFile.copy(playbackUrl = normalizedUrl)
|
||||
}
|
||||
}
|
||||
candidateItem.copy(files = updatedFiles)
|
||||
}
|
||||
providerState.copy(items = updatedItems)
|
||||
}
|
||||
return if (didUpdate) {
|
||||
copy(providers = updatedProviders)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,59 @@ class CloudLibraryStoreTest {
|
|||
assertEquals(item.playableFiles.single(), target.file)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolve playback reuses already resolved file url`() = runBlocking {
|
||||
val provider = cloudProvider(id = "premiumize", name = "Premiumize")
|
||||
val api = FakeCloudProviderApi(
|
||||
provider = provider,
|
||||
items = emptyList(),
|
||||
)
|
||||
val store = CloudLibraryStore(
|
||||
credentialsProvider = {
|
||||
listOf(DebridServiceCredential(provider, "token"))
|
||||
},
|
||||
providerApis = listOf(api),
|
||||
)
|
||||
val item = cloudItem(provider, "ready")
|
||||
val file = item.playableFiles.single().copy(playbackUrl = "https://cached.example/video.mkv")
|
||||
|
||||
val result = store.resolvePlayback(item = item, file = file)
|
||||
|
||||
assertTrue(result is CloudLibraryPlaybackResult.Success)
|
||||
assertEquals("https://cached.example/video.mkv", result.url)
|
||||
assertEquals(0, api.resolvePlaybackCalls)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolved playback url is remembered in cloud library state`() {
|
||||
val provider = cloudProvider(id = "torbox", name = "TorBox")
|
||||
val item = cloudItem(provider, "29773238")
|
||||
val file = item.playableFiles.single()
|
||||
val state = CloudLibraryUiState(
|
||||
isLoaded = true,
|
||||
providers = listOf(
|
||||
CloudLibraryProviderState(
|
||||
provider = provider,
|
||||
items = listOf(item),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val updated = state.withResolvedPlaybackUrl(
|
||||
item = item,
|
||||
file = file,
|
||||
url = "https://resolved.example/movie.mkv",
|
||||
)
|
||||
|
||||
val target = assertNotNull(
|
||||
updated.findPlaybackTargetForProgress(
|
||||
contentId = item.stableKey,
|
||||
videoId = item.playbackVideoId(file),
|
||||
),
|
||||
)
|
||||
assertEquals("https://resolved.example/movie.mkv", target.file.playbackUrl)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `provider poster urls are mapped for cloud services`() {
|
||||
assertEquals(
|
||||
|
|
@ -155,6 +208,9 @@ private class FakeCloudProviderApi(
|
|||
override val provider: DebridProvider,
|
||||
private val items: List<CloudLibraryItem>,
|
||||
) : CloudLibraryProviderApi {
|
||||
var resolvePlaybackCalls: Int = 0
|
||||
private set
|
||||
|
||||
override suspend fun listItems(apiKey: String): Result<List<CloudLibraryItem>> =
|
||||
Result.success(items)
|
||||
|
||||
|
|
@ -162,8 +218,10 @@ private class FakeCloudProviderApi(
|
|||
apiKey: String,
|
||||
item: CloudLibraryItem,
|
||||
file: CloudLibraryFile,
|
||||
): CloudLibraryPlaybackResult =
|
||||
CloudLibraryPlaybackResult.Success(url = "https://example.test/${item.id}/${file.id}")
|
||||
): CloudLibraryPlaybackResult {
|
||||
resolvePlaybackCalls += 1
|
||||
return CloudLibraryPlaybackResult.Success(url = "https://example.test/${item.id}/${file.id}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun cloudProvider(id: String, name: String): DebridProvider =
|
||||
|
|
|
|||
Loading…
Reference in a new issue