Reduce card image transfers and list metadata payloads
This commit is contained in:
parent
f4fb6e22c9
commit
e340d470c1
10 changed files with 152 additions and 31 deletions
|
|
@ -51,7 +51,7 @@ class LibraryReadFacadeTest {
|
|||
val offsets = mutableListOf<Int>()
|
||||
coEvery { items.getItems(userId = user, parentId = library.id, recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
fields = listOf(ItemFields.PROVIDER_IDS, ItemFields.SORT_NAME, ItemFields.DATE_CREATED),
|
||||
fields = listOf(ItemFields.PROVIDER_IDS, ItemFields.DATE_CREATED),
|
||||
sortBy = listOf(ItemSortBy.SORT_NAME), startIndex = capture(offsets), limit = 200) } coAnswers {
|
||||
if (offsets.last() == 0) successQueryResult(firstChunk, 202) else {
|
||||
assertEquals(200, offsets.last())
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ import com.github.damontecres.wholphin.test.TestTracks
|
|||
import org.jellyfin.sdk.model.api.MediaStreamType
|
||||
import org.jellyfin.sdk.model.api.request.GetEpisodesRequest
|
||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||
import org.jellyfin.sdk.model.api.ItemFields
|
||||
import org.jellyfin.sdk.model.api.request.GetNextUpRequest
|
||||
import org.junit.Assert.*
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
|
|
@ -219,6 +221,43 @@ class TitleReadFacadeTest {
|
|||
assertEquals(2, TitleState(data, ShellPerson("justin", "Justin", "J", false)) {}.season)
|
||||
}
|
||||
|
||||
@Test fun leanEpisodeListsKeepSingleItemPlaybackTracksEvenWithoutNextUp() = runTest {
|
||||
val series = BaseItemDto(id = seriesId, name = "Series", type = BaseItemKind.SERIES, people = emptyList(), providerIds = mapOf("Tmdb" to "42"))
|
||||
val episode = file(firstId, BaseItemKind.EPISODE).copy(seriesId = seriesId, parentIndexNumber = 3, indexNumber = 1)
|
||||
coEvery { library.getItem(seriesId) } returns successResponse(series)
|
||||
coEvery { library.getItem(firstId) } returns successResponse(episode)
|
||||
coEvery { shows.getNextUp(any<GetNextUpRequest>()) } coAnswers {
|
||||
assertTrue(firstArg<GetNextUpRequest>().fields.orEmpty().isEmpty())
|
||||
successQueryResult(emptyList())
|
||||
}
|
||||
coEvery { items.getItems(any<GetItemsRequest>()) } returns successQueryResult(
|
||||
listOf(BaseItemDto(id = seasonId, type = BaseItemKind.SEASON, indexNumber = 3)))
|
||||
coEvery { shows.getEpisodes(any<GetEpisodesRequest>()) } coAnswers {
|
||||
val fields = firstArg<GetEpisodesRequest>().fields.orEmpty()
|
||||
assertFalse(fields.any { it in listOf(ItemFields.MEDIA_SOURCES, ItemFields.MEDIA_STREAMS, ItemFields.PEOPLE, ItemFields.PARENT_ID) })
|
||||
successQueryResult(listOf(episode.copy(mediaSources = null, overview = "Episode synopsis")))
|
||||
}
|
||||
val page = facade.read(seriesId, 3, preferences)
|
||||
assertEquals(firstId.toString(), page.playTarget?.id)
|
||||
assertEquals("MKV", page.versions.single().container)
|
||||
assertEquals(listOf(3), page.versions.single().audio.map { it.index })
|
||||
val saved = requireNotNull(facade.readSaved(seriesId, preferences))
|
||||
assertEquals(page.versions, saved.versions)
|
||||
}
|
||||
|
||||
@Test fun performerCreditListsOmitStreamsButKeepCharacterRoles() = runTest {
|
||||
coEvery { library.getItem(firstId) } returns successResponse(
|
||||
BaseItemDto(id = firstId, type = BaseItemKind.PERSON, name = "Actor"))
|
||||
coEvery { items.getItems(any<GetItemsRequest>()) } coAnswers {
|
||||
val fields = firstArg<GetItemsRequest>().fields.orEmpty()
|
||||
assertFalse(fields.any { it in listOf(ItemFields.MEDIA_SOURCES, ItemFields.MEDIA_STREAMS, ItemFields.PARENT_ID) })
|
||||
assertTrue(ItemFields.PEOPLE in fields)
|
||||
successQueryResult(listOf(file(secondId).copy(people = listOf(
|
||||
org.jellyfin.sdk.model.api.BaseItemPerson(id = firstId, name = "Actor", role = "Chef")))))
|
||||
}
|
||||
assertEquals("Chef", facade.readPerson(firstId, 0).credits.single().character)
|
||||
}
|
||||
|
||||
@Test fun compactJellyfinSourceIdUsesTheSameVersionPersistenceKey() = runTest {
|
||||
coEvery { library.getItem(firstId) } returns successResponse(file(firstId))
|
||||
coEvery { playback.savePlayVersion(any(), any()) } returns null
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class LibraryReadFacade @Inject constructor(private val api: ApiClient) {
|
|||
val response = api.itemsApi.getItems(
|
||||
userId = userId, parentId = library.id, recursive = true,
|
||||
includeItemTypes = listOf(if (destination == "movies") BaseItemKind.MOVIE else BaseItemKind.SERIES),
|
||||
fields = listOf(ItemFields.PROVIDER_IDS, ItemFields.SORT_NAME, ItemFields.DATE_CREATED),
|
||||
fields = listOf(ItemFields.PROVIDER_IDS, ItemFields.DATE_CREATED),
|
||||
sortBy = listOf(ItemSortBy.SORT_NAME), startIndex = offset,
|
||||
limit = WolfskinTokens.Behaviour.libraryChunk.toInt(),
|
||||
).content
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ class TitleReadFacade @Inject constructor(
|
|||
@param:ApplicationContext private val context: Context,
|
||||
) {
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
private val fields = listOf(ItemFields.PROVIDER_IDS, ItemFields.MEDIA_SOURCES, ItemFields.MEDIA_STREAMS, ItemFields.OVERVIEW, ItemFields.PEOPLE, ItemFields.PARENT_ID)
|
||||
private val episodeFields = listOf(ItemFields.PROVIDER_IDS, ItemFields.OVERVIEW)
|
||||
private val creditFields = listOf(ItemFields.PROVIDER_IDS, ItemFields.OVERVIEW, ItemFields.PEOPLE)
|
||||
|
||||
/** Resolve through this user's Jellyfin permissions before granting a catalogue card playback. */
|
||||
suspend fun findHeld(tmdb: Long, media: String): UUID? {
|
||||
|
|
@ -88,12 +89,12 @@ class TitleReadFacade @Inject constructor(
|
|||
val series = if (opened.type == BaseItemKind.EPISODE && opened.seriesId != null) readItem(opened.seriesId!!) else opened
|
||||
val seasons = if (series.type == BaseItemKind.SERIES) api.itemsApi.getItems(GetItemsRequest(parentId = series.id, includeItemTypes = listOf(BaseItemKind.SEASON), recursive = false, sortBy = listOf(ItemSortBy.INDEX_NUMBER))).content.items.orEmpty() else emptyList()
|
||||
val next = if (opened.type == BaseItemKind.EPISODE || opened.type == BaseItemKind.MOVIE) opened else {
|
||||
api.tvShowsApi.getNextUp(GetNextUpRequest(seriesId = series.id, userId = repository.currentUser?.id, limit = 1, fields = fields, enableResumable = true)).content.items.firstOrNull()?.let { api.userLibraryApi.getItem(it.id).content }
|
||||
api.tvShowsApi.getNextUp(GetNextUpRequest(seriesId = series.id, userId = repository.currentUser?.id, limit = 1, enableResumable = true)).content.items.firstOrNull()?.let { readItem(it.id) }
|
||||
}
|
||||
val selectedNumber = season ?: next?.parentIndexNumber ?: seasons.firstOrNull()?.indexNumber
|
||||
val selected = seasons.firstOrNull { it.indexNumber == selectedNumber } ?: seasons.firstOrNull()
|
||||
val episodes = selected?.let { api.tvShowsApi.getEpisodes(GetEpisodesRequest(seriesId = series.id, seasonId = it.id, fields = fields)).content.items.orEmpty() }.orEmpty()
|
||||
val target = next ?: episodes.firstOrNull { it.type == BaseItemKind.EPISODE }
|
||||
val episodes = selected?.let { api.tvShowsApi.getEpisodes(GetEpisodesRequest(seriesId = series.id, seasonId = it.id, fields = episodeFields)).content.items.orEmpty() }.orEmpty()
|
||||
val target = next ?: episodes.firstOrNull { it.type == BaseItemKind.EPISODE }?.let { readItem(it.id) }
|
||||
val rows = (listOf(series, opened) + listOfNotNull(target) + episodes).distinctBy { it.id }
|
||||
val numbers = seasons.mapNotNull { it.indexNumber }
|
||||
val result = build(rows, numbers, selected?.indexNumber, opened.id.toString(), target?.id?.toString(), preferences)
|
||||
|
|
@ -165,7 +166,7 @@ class TitleReadFacade @Inject constructor(
|
|||
} else emptyList()
|
||||
val person = previous.firstOrNull() ?: api.userLibraryApi.getItem(id).content
|
||||
val credits = api.itemsApi.getItems(GetItemsRequest(personIds = listOf(id), recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES), fields = fields, startIndex = start, limit = 200,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES), fields = creditFields, startIndex = start, limit = 200,
|
||||
sortBy = listOf(ItemSortBy.PRODUCTION_YEAR, ItemSortBy.SORT_NAME))).content.items.orEmpty()
|
||||
val rows = listOf(person) + (previous.drop(1) + credits).distinctBy { it.id }
|
||||
if (personCacheFile(id) != file) throw kotlinx.coroutines.CancellationException("Performer identity changed")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue