mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Show overlay for extra items (#1320)
## Description Shows the overlay (watched, progress bar) for extras appearing as single items. Grouped extras individually show the overlay when clicking into. If all of the grouped are played, the group is show with the watched indicator. Also very slightly optimizations the UI by offloading the title/subtitle/imageUrl to object creation time instead of when they're shown on screen. ### Related issues Closes #1311 ### Testing Shield testing with different extras ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
8cf99900e5
commit
5571654a22
3 changed files with 69 additions and 42 deletions
|
|
@ -15,7 +15,11 @@ sealed interface ExtrasItem {
|
|||
val parentId: UUID
|
||||
val type: ExtraType
|
||||
val destination: Destination
|
||||
val title: String?
|
||||
val imageUrl: String?
|
||||
val title: String
|
||||
val subtitle: String?
|
||||
val isPlayed: Boolean
|
||||
val playedPercentage: Double
|
||||
|
||||
/**
|
||||
* Represents multiple extras of the same type
|
||||
|
|
@ -24,11 +28,16 @@ sealed interface ExtrasItem {
|
|||
override val parentId: UUID,
|
||||
override val type: ExtraType,
|
||||
val items: List<BaseItem>,
|
||||
override val imageUrl: String?,
|
||||
override val title: String,
|
||||
override val subtitle: String,
|
||||
override val isPlayed: Boolean,
|
||||
) : ExtrasItem {
|
||||
override val destination: Destination =
|
||||
Destination.ItemGrid(null, type.stringRes, items.map { it.id })
|
||||
|
||||
override val title: String? = null
|
||||
override val playedPercentage
|
||||
get() = -1.0
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,12 +47,18 @@ sealed interface ExtrasItem {
|
|||
override val parentId: UUID,
|
||||
override val type: ExtraType,
|
||||
val item: BaseItem,
|
||||
override val imageUrl: String?,
|
||||
override val title: String,
|
||||
override val subtitle: String?,
|
||||
) : ExtrasItem {
|
||||
override val destination: Destination =
|
||||
Destination.Playback(
|
||||
item = item,
|
||||
)
|
||||
override val title: String? get() = item.title
|
||||
override val isPlayed: Boolean
|
||||
get() = item.played
|
||||
override val playedPercentage
|
||||
get() = item.data.userData?.playedPercentage ?: 0.0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
package com.github.damontecres.wholphin.services
|
||||
|
||||
import android.content.Context
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ExtrasItem
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.pluralRes
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||
import org.jellyfin.sdk.model.api.ExtraType
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -19,6 +24,8 @@ class ExtrasService
|
|||
@Inject
|
||||
constructor(
|
||||
private val api: ApiClient,
|
||||
@param:ApplicationContext private val context: Context,
|
||||
private val imageUrlService: ImageUrlService,
|
||||
) {
|
||||
/**
|
||||
* Get the [ExtrasItem]s for the given item
|
||||
|
|
@ -39,9 +46,45 @@ class ExtrasService
|
|||
extrasMap
|
||||
.mapNotNull { (type, items) ->
|
||||
if (items.size == 1) {
|
||||
ExtrasItem.Single(itemId, type, items.first())
|
||||
val item = items.first()
|
||||
val title =
|
||||
item.title ?: context.resources.getQuantityString(type.pluralRes, 1)
|
||||
val subtitle =
|
||||
if (item.title == null) {
|
||||
context.resources.getQuantityString(type.pluralRes, 1)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
ExtrasItem.Single(
|
||||
parentId = itemId,
|
||||
type = type,
|
||||
item = item,
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
imageUrl = imageUrlService.getItemImageUrl(item, ImageType.PRIMARY),
|
||||
)
|
||||
} else if (items.size > 1) {
|
||||
ExtrasItem.Group(itemId, type, items)
|
||||
val title =
|
||||
context.resources.getQuantityString(type.pluralRes, items.size)
|
||||
val subtitle =
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.items,
|
||||
items.size,
|
||||
items.size,
|
||||
)
|
||||
ExtrasItem.Group(
|
||||
parentId = itemId,
|
||||
type = type,
|
||||
items = items,
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
isPlayed = items.all { it.played },
|
||||
imageUrl =
|
||||
imageUrlService.getItemImageUrl(
|
||||
items.random(),
|
||||
ImageType.PRIMARY,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
package com.github.damontecres.wholphin.ui.cards
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ExtrasItem
|
||||
import com.github.damontecres.wholphin.data.pluralRes
|
||||
import com.github.damontecres.wholphin.ui.AspectRatios
|
||||
import com.github.damontecres.wholphin.ui.Cards
|
||||
import com.github.damontecres.wholphin.ui.LocalImageUrlService
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
|
||||
@Composable
|
||||
fun ExtrasRow(
|
||||
|
|
@ -22,52 +16,27 @@ fun ExtrasRow(
|
|||
onLongClickItem: (Int, ExtrasItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val resources = LocalResources.current
|
||||
ItemRow(
|
||||
title = stringResource(R.string.extras),
|
||||
items = extras,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = onLongClickItem,
|
||||
cardContent = { index, item, mod, onClick, onLongClick ->
|
||||
val imageUrlService = LocalImageUrlService.current
|
||||
val imageUrl =
|
||||
remember {
|
||||
val item =
|
||||
when (item) {
|
||||
is ExtrasItem.Group -> item.items.random()
|
||||
is ExtrasItem.Single -> item.item
|
||||
null -> null
|
||||
}
|
||||
imageUrlService.getItemImageUrl(item, ImageType.PRIMARY)
|
||||
}
|
||||
SeasonCard(
|
||||
title =
|
||||
when (item) {
|
||||
is ExtrasItem.Group -> item.type.pluralRes.let { resources.getQuantityString(it, item.items.size) }
|
||||
is ExtrasItem.Single -> item.title ?: item.type.pluralRes.let { resources.getQuantityString(it, 1) }
|
||||
null -> null
|
||||
},
|
||||
title = item?.title,
|
||||
name = null,
|
||||
subtitle =
|
||||
if (item is ExtrasItem.Single && item.title != null) {
|
||||
item.type.pluralRes.let { resources.getQuantityString(it, 1) }
|
||||
} else if (item is ExtrasItem.Group) {
|
||||
resources.getQuantityString(R.plurals.items, item.items.size, item.items.size)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
subtitle = item?.subtitle,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
modifier = mod,
|
||||
showImageOverlay = true,
|
||||
imageHeight = Cards.height2x3 * .75f,
|
||||
imageHeight = Cards.heightEpisode,
|
||||
imageWidth = Dp.Unspecified,
|
||||
imageUrl = imageUrl,
|
||||
imageUrl = item?.imageUrl,
|
||||
isFavorite = false,
|
||||
isPlayed = false,
|
||||
isPlayed = item?.isPlayed == true,
|
||||
unplayedItemCount = -1,
|
||||
playedPercentage = -1.0,
|
||||
playedPercentage = item?.playedPercentage ?: 0.0,
|
||||
numberOfVersions = -1,
|
||||
aspectRatio = AspectRatios.FOUR_THREE, // TODO
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue