mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
A few small UI fixes (#1012)
## Description - Restores corner text for episode cards - Always show end time on playback overlay instead of it being controlled by the "Show Clock" setting - Better logic to determine person's role in media ### Related issues Fixes #1010 Fixes #1004 Fixes #975 ### Testing Emulator ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
9b995bf6ba
commit
b65e55f4ed
6 changed files with 99 additions and 26 deletions
|
|
@ -95,7 +95,11 @@ data class BaseItem(
|
||||||
data.indexNumber?.let { "E$it" }
|
data.indexNumber?.let { "E$it" }
|
||||||
?: data.premiereDate?.let(::formatDateTime),
|
?: data.premiereDate?.let(::formatDateTime),
|
||||||
episodeUnplayedCornerText =
|
episodeUnplayedCornerText =
|
||||||
if (type == BaseItemKind.SERIES || type == BaseItemKind.SEASON || type == BaseItemKind.BOX_SET) {
|
if (type == BaseItemKind.SERIES ||
|
||||||
|
type == BaseItemKind.SEASON ||
|
||||||
|
type == BaseItemKind.EPISODE ||
|
||||||
|
type == BaseItemKind.BOX_SET
|
||||||
|
) {
|
||||||
data.indexNumber?.let { "E$it" }
|
data.indexNumber?.let { "E$it" }
|
||||||
?: data.userData
|
?: data.userData
|
||||||
?.unplayedItemCount
|
?.unplayedItemCount
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package com.github.damontecres.wholphin.data.model
|
package com.github.damontecres.wholphin.data.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.github.damontecres.wholphin.R
|
||||||
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.imageApi
|
import org.jellyfin.sdk.api.client.extensions.imageApi
|
||||||
import org.jellyfin.sdk.model.UUID
|
import org.jellyfin.sdk.model.UUID
|
||||||
|
|
@ -19,19 +23,21 @@ data class Person(
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
fun fromDto(
|
fun fromDto(
|
||||||
|
context: Context,
|
||||||
dto: BaseItemPerson,
|
dto: BaseItemPerson,
|
||||||
api: ApiClient,
|
api: ApiClient,
|
||||||
): Person =
|
): Person =
|
||||||
Person(
|
Person(
|
||||||
id = dto.id,
|
id = dto.id,
|
||||||
name = dto.name,
|
name = dto.name,
|
||||||
role = dto.role,
|
role = personRole(context, dto.role, dto.type),
|
||||||
type = dto.type,
|
type = dto.type,
|
||||||
imageUrl = api.imageApi.getItemImageUrl(dto.id, ImageType.PRIMARY),
|
imageUrl = api.imageApi.getItemImageUrl(dto.id, ImageType.PRIMARY),
|
||||||
favorite = false,
|
favorite = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun fromDto(
|
fun fromDto(
|
||||||
|
context: Context,
|
||||||
dto: BaseItemPerson,
|
dto: BaseItemPerson,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
api: ApiClient,
|
api: ApiClient,
|
||||||
|
|
@ -39,10 +45,51 @@ data class Person(
|
||||||
Person(
|
Person(
|
||||||
id = dto.id,
|
id = dto.id,
|
||||||
name = dto.name,
|
name = dto.name,
|
||||||
role = dto.role,
|
role = personRole(context, dto.role, dto.type),
|
||||||
type = dto.type,
|
type = dto.type,
|
||||||
imageUrl = api.imageApi.getItemImageUrl(dto.id, ImageType.PRIMARY),
|
imageUrl = api.imageApi.getItemImageUrl(dto.id, ImageType.PRIMARY),
|
||||||
favorite = favorite,
|
favorite = favorite,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun personRole(
|
||||||
|
context: Context,
|
||||||
|
role: String?,
|
||||||
|
type: PersonKind,
|
||||||
|
): String? =
|
||||||
|
if (type == PersonKind.ACTOR || type == PersonKind.GUEST_STAR || type == PersonKind.UNKNOWN) {
|
||||||
|
role
|
||||||
|
} else if (role.equals(type.name, ignoreCase = true)) {
|
||||||
|
type.stringRes?.let { context.getString(it) }
|
||||||
|
} else if (role.isNotNullOrBlank() && role.lowercase().contains(type.name.lowercase())) {
|
||||||
|
role
|
||||||
|
} else {
|
||||||
|
listOfNotNull(
|
||||||
|
role?.takeIf { it.isNotNullOrBlank() },
|
||||||
|
type.stringRes?.let { context.getString(it) },
|
||||||
|
).takeIf { it.isNotEmpty() }?.joinToString(" - ")
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:StringRes
|
||||||
|
private val PersonKind.stringRes: Int?
|
||||||
|
get() =
|
||||||
|
when (this) {
|
||||||
|
PersonKind.UNKNOWN -> R.string.unknown
|
||||||
|
PersonKind.ACTOR -> R.string.actor
|
||||||
|
PersonKind.DIRECTOR -> R.string.director
|
||||||
|
PersonKind.COMPOSER -> R.string.composer
|
||||||
|
PersonKind.WRITER -> R.string.writer
|
||||||
|
PersonKind.GUEST_STAR -> R.string.guest_star
|
||||||
|
PersonKind.PRODUCER -> R.string.producer
|
||||||
|
PersonKind.CONDUCTOR -> R.string.conductor
|
||||||
|
PersonKind.LYRICIST -> R.string.lyricist
|
||||||
|
PersonKind.ARRANGER -> R.string.arranger
|
||||||
|
PersonKind.ENGINEER -> R.string.engineer
|
||||||
|
PersonKind.MIXER -> R.string.mixer
|
||||||
|
PersonKind.REMIXER -> R.string.mixer
|
||||||
|
PersonKind.CREATOR -> R.string.creator
|
||||||
|
PersonKind.ARTIST -> R.string.artist
|
||||||
|
PersonKind.ALBUM_ARTIST -> R.string.artist
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package com.github.damontecres.wholphin.services
|
package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.Person
|
import com.github.damontecres.wholphin.data.model.Person
|
||||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -12,6 +14,7 @@ import javax.inject.Singleton
|
||||||
class PeopleFavorites
|
class PeopleFavorites
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
|
@param:ApplicationContext private val context: Context,
|
||||||
private val api: ApiClient,
|
private val api: ApiClient,
|
||||||
) {
|
) {
|
||||||
suspend fun getPeopleFor(item: BaseItem): List<Person> =
|
suspend fun getPeopleFor(item: BaseItem): List<Person> =
|
||||||
|
|
@ -27,7 +30,14 @@ class PeopleFavorites
|
||||||
val people =
|
val people =
|
||||||
item.data.people
|
item.data.people
|
||||||
?.letNotEmpty { people ->
|
?.letNotEmpty { people ->
|
||||||
people.map { Person.fromDto(it, favorites[it.id] ?: false, api) }
|
people.map {
|
||||||
|
Person.fromDto(
|
||||||
|
context,
|
||||||
|
it,
|
||||||
|
favorites[it.id] ?: false,
|
||||||
|
api,
|
||||||
|
)
|
||||||
|
}
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
people
|
people
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -528,7 +528,7 @@ class SeriesViewModel
|
||||||
api.userLibraryApi
|
api.userLibraryApi
|
||||||
.getItem(item.id)
|
.getItem(item.id)
|
||||||
.content.people
|
.content.people
|
||||||
?.map { Person.fromDto(it, api) }
|
?.map { Person.fromDto(context, it, api) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
PeopleInItem(item.id, list)
|
PeopleInItem(item.id, list)
|
||||||
|
|
|
||||||
|
|
@ -612,29 +612,28 @@ fun Controller(
|
||||||
fontSize = subtitleTextSize,
|
fontSize = subtitleTextSize,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (showClock) {
|
|
||||||
var endTimeStr by remember { mutableStateOf("...") }
|
var endTimeStr by remember { mutableStateOf("...") }
|
||||||
LaunchedEffect(playerControls) {
|
LaunchedEffect(playerControls) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val remaining =
|
val remaining =
|
||||||
(playerControls.duration - playerControls.currentPosition)
|
(playerControls.duration - playerControls.currentPosition)
|
||||||
.div(playerControls.playbackParameters.speed)
|
.div(playerControls.playbackParameters.speed)
|
||||||
.toLong()
|
.toLong()
|
||||||
.milliseconds
|
.milliseconds
|
||||||
val endTime = LocalTime.now().plusSeconds(remaining.inWholeSeconds)
|
val endTime = LocalTime.now().plusSeconds(remaining.inWholeSeconds)
|
||||||
endTimeStr = TimeFormatter.format(endTime)
|
endTimeStr = TimeFormatter.format(endTime)
|
||||||
delay(1.seconds)
|
delay(1.seconds)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Text(
|
|
||||||
text = "Ends $endTimeStr",
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.padding(end = 32.dp),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
Text(
|
||||||
|
text = "Ends $endTimeStr",
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.padding(end = 32.dp),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO need to move these up a level?
|
// TODO need to move these up a level?
|
||||||
|
|
|
||||||
|
|
@ -704,4 +704,17 @@
|
||||||
<item>@string/photos</item>
|
<item>@string/photos</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="actor">Actor</string>
|
||||||
|
<string name="composer">Composer</string>
|
||||||
|
<string name="writer">Writer</string>
|
||||||
|
<string name="guest_star">Guest star</string>
|
||||||
|
<string name="producer">Producer</string>
|
||||||
|
<string name="conductor">Conductor</string>
|
||||||
|
<string name="lyricist">Lyricist</string>
|
||||||
|
<string name="arranger">Arranger</string>
|
||||||
|
<string name="engineer">Engineer</string>
|
||||||
|
<string name="mixer">Mixer</string>
|
||||||
|
<string name="creator">Creator</string>
|
||||||
|
<string name="artist">Artist</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue