mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Fix some image issues (#926)
## Description Fixes/improves thumb image handling by falling back to backdrop images if available. Episodes without a parent thumb/backdrop will fall back to their primary image. Also fixes the nav drawer selected item not updating (bug introduced by #886). ### Related issues Fixes #642 Fixes #914 ### Testing Emulator in various situations with missing thumbs ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
f57cba85f2
commit
9daf679f7d
5 changed files with 132 additions and 3 deletions
|
|
@ -30,6 +30,9 @@ class ImageUrlService
|
|||
useSeriesForPrimary: Boolean,
|
||||
imageTags: Map<ImageType, String?>,
|
||||
imageType: ImageType,
|
||||
parentThumbId: UUID? = null,
|
||||
parentBackdropId: UUID? = null,
|
||||
backdropTags: List<String> = emptyList(),
|
||||
fillWidth: Int? = null,
|
||||
fillHeight: Int? = null,
|
||||
): String? =
|
||||
|
|
@ -54,8 +57,65 @@ class ImageUrlService
|
|||
}
|
||||
}
|
||||
|
||||
ImageType.THUMB -> {
|
||||
if (useSeriesForPrimary && parentThumbId != null &&
|
||||
(itemType == BaseItemKind.EPISODE || itemType == BaseItemKind.SEASON)
|
||||
) {
|
||||
// Use parent's thumb
|
||||
getItemImageUrl(
|
||||
itemId = parentThumbId,
|
||||
imageType = imageType,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
} else if (useSeriesForPrimary && parentBackdropId != null &&
|
||||
(itemType == BaseItemKind.EPISODE || itemType == BaseItemKind.SEASON)
|
||||
) {
|
||||
// No parent thumb, so use backdrop instead
|
||||
getItemImageUrl(
|
||||
itemId = parentBackdropId,
|
||||
imageType = ImageType.BACKDROP,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
} else if (parentThumbId != null && itemType == BaseItemKind.SEASON && imageType !in imageTags) {
|
||||
getItemImageUrl(
|
||||
itemId = parentThumbId,
|
||||
imageType = imageType,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
} else if (useSeriesForPrimary &&
|
||||
parentThumbId == null &&
|
||||
itemType == BaseItemKind.EPISODE &&
|
||||
imageType !in imageTags
|
||||
) {
|
||||
// Workaround to fall back to episode image if no parent thumb
|
||||
getItemImageUrl(
|
||||
itemId = itemId,
|
||||
imageType = ImageType.PRIMARY,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
} else if (imageType !in imageTags && backdropTags.isNotEmpty()) {
|
||||
// If no thumb, use backdrop if available
|
||||
getItemImageUrl(
|
||||
itemId = itemId,
|
||||
imageType = ImageType.BACKDROP,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
} else {
|
||||
getItemImageUrl(
|
||||
itemId = itemId,
|
||||
imageType = imageType,
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ImageType.PRIMARY,
|
||||
ImageType.THUMB,
|
||||
ImageType.BANNER,
|
||||
-> {
|
||||
if (useSeriesForPrimary && seriesId != null &&
|
||||
|
|
@ -108,6 +168,9 @@ class ImageUrlService
|
|||
useSeriesForPrimary = item.useSeriesForPrimary,
|
||||
imageTags = item.data.imageTags.orEmpty(),
|
||||
imageType = imageType,
|
||||
parentThumbId = item.data.parentThumbItemId,
|
||||
parentBackdropId = item.data.parentBackdropItemId,
|
||||
backdropTags = item.data.backdropImageTags.orEmpty(),
|
||||
fillWidth = fillWidth,
|
||||
fillHeight = fillHeight,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
|||
import org.jellyfin.sdk.api.client.extensions.userViewsApi
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
import org.jellyfin.sdk.model.api.UserDto
|
||||
import org.jellyfin.sdk.model.api.request.GetLatestMediaRequest
|
||||
import org.jellyfin.sdk.model.api.request.GetNextUpRequest
|
||||
|
|
@ -60,6 +61,12 @@ class LatestNextUpService
|
|||
remove(BaseItemKind.EPISODE)
|
||||
}
|
||||
},
|
||||
enableImageTypes =
|
||||
listOf(
|
||||
ImageType.PRIMARY,
|
||||
ImageType.THUMB,
|
||||
ImageType.BACKDROP,
|
||||
),
|
||||
)
|
||||
val items =
|
||||
api.itemsApi
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ fun BannerCard(
|
|||
null
|
||||
}
|
||||
}
|
||||
var imageError by remember { mutableStateOf(false) }
|
||||
var imageError by remember(imageUrl) { mutableStateOf(false) }
|
||||
Card(
|
||||
modifier = modifier.size(cardHeight * aspectRatio, cardHeight),
|
||||
onClick = onClick,
|
||||
|
|
|
|||
|
|
@ -346,7 +346,12 @@ class CollectionFolderViewModel
|
|||
filter.applyTo(
|
||||
GetItemsRequest(
|
||||
parentId = item?.id,
|
||||
enableImageTypes = listOf(ImageType.PRIMARY, ImageType.THUMB),
|
||||
enableImageTypes =
|
||||
listOf(
|
||||
ImageType.PRIMARY,
|
||||
ImageType.THUMB,
|
||||
ImageType.BACKDROP,
|
||||
),
|
||||
includeItemTypes = includeItemTypes,
|
||||
recursive = recursive,
|
||||
excludeItemIds = item?.let { listOf(item.id) },
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import androidx.compose.material.icons.filled.KeyboardArrowLeft
|
|||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -54,6 +55,7 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.findViewTreeViewModelStoreOwner
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.tv.material3.DrawerState
|
||||
import androidx.tv.material3.DrawerValue
|
||||
import androidx.tv.material3.Icon
|
||||
|
|
@ -77,7 +79,9 @@ import com.github.damontecres.wholphin.services.SetupNavigationManager
|
|||
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||
import com.github.damontecres.wholphin.ui.components.TimeDisplay
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.preferences.PreferenceScreenOption
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.ui.setup.UserIconCardImage
|
||||
import com.github.damontecres.wholphin.ui.spacedByWithFooter
|
||||
import com.github.damontecres.wholphin.ui.theme.LocalTheme
|
||||
|
|
@ -87,6 +91,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.imageApi
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -145,6 +150,54 @@ class NavDrawerViewModel
|
|||
}
|
||||
|
||||
fun getUserImage(user: JellyfinUser): String = api.imageApi.getUserImageUrl(user.id)
|
||||
|
||||
fun updateSelectedIndex() {
|
||||
viewModelScope.launchDefault {
|
||||
val asDestinations =
|
||||
(
|
||||
state.value.items +
|
||||
listOf(
|
||||
NavDrawerItem.More,
|
||||
NavDrawerItem.Discover,
|
||||
) + state.value.moreItems
|
||||
).map {
|
||||
if (it is ServerNavDrawerItem) {
|
||||
it.destination
|
||||
} else if (it is NavDrawerItem.Favorites) {
|
||||
Destination.Favorites
|
||||
} else if (it is NavDrawerItem.Discover) {
|
||||
Destination.Discover
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val backstack = navigationManager.backStack.toList().reversed()
|
||||
for (i in 0..<backstack.size) {
|
||||
val key = backstack[i]
|
||||
if (key is Destination) {
|
||||
val index =
|
||||
if (key is Destination.Home) {
|
||||
-1
|
||||
} else if (key is Destination.Search) {
|
||||
-2
|
||||
} else {
|
||||
val idx = asDestinations.indexOf(key)
|
||||
if (idx >= 0) {
|
||||
idx
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
Timber.v("Found $index => $key")
|
||||
if (index != null) {
|
||||
selectedIndex.setValueOnMain(index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface NavDrawerItem {
|
||||
|
|
@ -208,6 +261,7 @@ fun NavDrawer(
|
|||
key = "${server.id}_${user.id}", // Keyed to the server & user to ensure its reset when switching either
|
||||
),
|
||||
) {
|
||||
LaunchedEffect(Unit) { viewModel.updateSelectedIndex() }
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val density = LocalDensity.current
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue