Update Seerr integration version & start blocklist handling logic (#1671)

## Description
Start testing against Seerr `3.3.0` which has been out for over a month.
The only significant change is that the new "blocklisted" status is
added, but it uses the same code as the previous "deleted" status. So
generally, Seerr `3.2.0` will still work.

This starts work on supporting Seerr's blocklist which, unfortunately,
is expected to be enforced on the client side. For now, blocklisted
items still show, but the request button is disabled and shows
"Unavailable" instead.

Finally, some Seerr parent permissions I missed in #1631 are added.

### Related issues
Related to #1626

### Testing
Emulator testing

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-07-07 13:56:22 -04:00 • committed by GitHub
parent f6e00c7820
commit 013755208d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 81 additions and 13 deletions

View file

@ -103,7 +103,7 @@ Requires Android 6+ (or Fire TV OS 6+) and Jellyfin server `10.10.x` or `10.11.x
The app is tested on a variety of Android TV/Fire TV OS devices, but if you encounter issues, please file an issue!
Seerr integration is tested with `v3.2.0`. Older versions may not work.
Seerr integration is tested with `v3.3.0`. Older versions may not work.
## Contributions

View file

@ -56,12 +56,14 @@ enum class SeerrItemType(
enum class SeerrAvailability(
val status: Int,
) {
// https://github.com/seerr-team/seerr/blob/develop/server/constants/media.ts#L14
UNKNOWN(1),
PENDING(2),
PROCESSING(3),
PARTIALLY_AVAILABLE(4),
AVAILABLE(5),
DELETED(6),
BLOCKLISTED(6),
DELETED(7),
;
companion object {

View file

@ -23,8 +23,8 @@ enum class SeerrPermission(
REQUEST_4K(1024),
REQUEST_4K_MOVIE(2048, REQUEST_4K),
REQUEST_4K_TV(4096, REQUEST_4K),
REQUEST_ADVANCED(8192),
REQUEST_VIEW(16384),
REQUEST_ADVANCED(8192, MANAGE_REQUESTS),
REQUEST_VIEW(16384, MANAGE_REQUESTS),
AUTO_APPROVE_4K(32768),
AUTO_APPROVE_4K_MOVIE(65536, AUTO_APPROVE_4K),
AUTO_APPROVE_4K_TV(131072, AUTO_APPROVE_4K),
@ -36,10 +36,10 @@ enum class SeerrPermission(
AUTO_REQUEST(8388608),
AUTO_REQUEST_MOVIE(16777216, AUTO_REQUEST),
AUTO_REQUEST_TV(33554432, AUTO_REQUEST),
RECENT_VIEW(67108864),
WATCHLIST_VIEW(134217728),
MANAGE_BLACKLIST(268435456),
VIEW_BLACKLIST(1073741824, MANAGE_BLACKLIST),
RECENT_VIEW(67108864, MANAGE_REQUESTS),
WATCHLIST_VIEW(134217728, MANAGE_REQUESTS),
MANAGE_BLOCKLIST(268435456),
VIEW_BLOCKLIST(1073741824, MANAGE_BLOCKLIST),
;
internal fun hasPermission(permissions: Int) = flag.and(permissions) == flag

View file

@ -38,6 +38,7 @@ object AppColors {
val Purple = Color(147, 51, 234)
val Green = Color(74, 222, 128)
val Yellow = Color(234, 179, 8)
val Red = Color(204, 38, 38)
}
}

View file

@ -130,7 +130,16 @@ fun DiscoverItemCard(
AvailableIndicator(Modifier.align(Alignment.TopEnd))
}
else -> {}
SeerrAvailability.BLOCKLISTED -> {
// TODO handle block listed
// BlocklistedIndicator(Modifier.align(Alignment.TopEnd))
}
SeerrAvailability.UNKNOWN,
SeerrAvailability.DELETED,
null,
-> {
}
}
if (showOverlay) {
val color =
@ -284,6 +293,31 @@ fun PartiallyAvailableIndicator(modifier: Modifier = Modifier) {
}
}
@Composable
fun BlocklistedIndicator(modifier: Modifier = Modifier) {
Box(
modifier =
modifier
.padding(4.dp)
.border(
width = .5.dp,
color = Color.White,
shape = CircleShape,
).background(
color = AppColors.Discover.Red.copy(alpha = .85f),
shape = CircleShape,
).size(16.dp),
) {
Text(
text = stringResource(R.string.fa_xmark),
fontFamily = FontAwesome,
fontSize = 10.sp,
color = Color.White,
modifier = Modifier.align(Alignment.Center),
)
}
}
@PreviewTvSpec
@Composable
private fun Preview() {
@ -292,6 +326,7 @@ private fun Preview() {
PendingIndicator()
AvailableIndicator()
PartiallyAvailableIndicator()
BlocklistedIndicator()
}
}
}

View file

@ -60,7 +60,11 @@ fun ExpandableDiscoverButtons(
SeerrAvailability.AVAILABLE,
-> R.string.go_to
SeerrAvailability.DELETED -> R.string.delete // TODO
// TODO
SeerrAvailability.DELETED -> R.string.delete
// TODO Blocklist
SeerrAvailability.BLOCKLISTED -> R.string.unavailable
}
val icon =
when (availability) {
@ -74,13 +78,29 @@ fun ExpandableDiscoverButtons(
SeerrAvailability.AVAILABLE,
-> R.string.fa_play
SeerrAvailability.DELETED -> R.string.fa_video // TODO
SeerrAvailability.DELETED -> R.string.fa_video
// TODO
SeerrAvailability.BLOCKLISTED -> R.string.fa_xmark
}
item("first") {
ExpandableFaButton(
title = text,
iconStringRes = icon,
enabled = if (availability == SeerrAvailability.UNKNOWN) canRequest else true,
enabled =
when (availability) {
SeerrAvailability.UNKNOWN -> canRequest
SeerrAvailability.PENDING,
SeerrAvailability.PROCESSING,
SeerrAvailability.PARTIALLY_AVAILABLE,
SeerrAvailability.AVAILABLE,
-> true
SeerrAvailability.BLOCKLISTED,
SeerrAvailability.DELETED,
-> false
},
onClick = {
when (availability) {
SeerrAvailability.UNKNOWN -> {
@ -99,7 +119,9 @@ fun ExpandableDiscoverButtons(
goToOnClick.invoke()
}
SeerrAvailability.DELETED -> {
SeerrAvailability.DELETED,
SeerrAvailability.BLOCKLISTED,
-> {
// TODO
}
}

View file

@ -282,6 +282,11 @@ fun SeasonListItem(
SeerrAvailability.AVAILABLE -> {
AvailableIndicator()
}
SeerrAvailability.BLOCKLISTED -> {
// TODO handle block listed
// BlocklistedIndicator()
}
}
},
trailingContent = {

View file

@ -56,4 +56,5 @@
<string name="fa_compass" translatable="false">&#xf14e;</string>
<string name="fa_repeat" translatable="false">&#xf363;</string>
<string name="fa_compact_disc" translatable="false">&#xf51f;</string>
<string name="fa_xmark" translatable="false">&#xf00d;</string>
</resources>

View file

@ -840,4 +840,6 @@
<string name="confirm_enable_experimental_title">Enable experimental settings?</string>
<string name="confirm_enable_experimental_body">Experimental settings may be unstable!\n\n These may removed or changed in any release.</string>
<string name="video_tunneling">Video tunneling</string>
<string name="blocklisted">Blocklisted</string>
<string name="unavailable">Unavailable</string>
</resources>