mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-06 10:50:58 +01:00
Several small fixes (#1612)
## Description - Fixes showing "null" in the subtitle for some tv episodes (usually daily shows like Jeopardy) - Partially fix holding back to return to the previous grid position (still has focus issues) - Show/hide tabs on the discover page similar to other pages in the app - Prevent a warning server-side if a negative playback timestamp is sent ### Related issues N/A ### Testing Emulator ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
77d7571276
commit
c945e1a472
9 changed files with 44 additions and 18 deletions
|
|
@ -12,6 +12,7 @@ import com.github.damontecres.wholphin.ui.detail.series.SeasonEpisodeIds
|
|||
import com.github.damontecres.wholphin.ui.dot
|
||||
import com.github.damontecres.wholphin.ui.formatDateTime
|
||||
import com.github.damontecres.wholphin.ui.getDateFormatter
|
||||
import com.github.damontecres.wholphin.ui.joinNotBlank
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.playback.playable
|
||||
import com.github.damontecres.wholphin.ui.roundMinutes
|
||||
|
|
@ -57,14 +58,14 @@ data class BaseItem(
|
|||
|
||||
val title get() = if (type == BaseItemKind.EPISODE) data.seriesName else name
|
||||
|
||||
val subtitle
|
||||
get() =
|
||||
when (type) {
|
||||
BaseItemKind.EPISODE -> data.seasonEpisode + " - " + name
|
||||
BaseItemKind.SERIES -> data.seriesProductionYears
|
||||
BaseItemKind.AUDIO -> listOfNotNull(data.album, artistsString).joinToString(" - ")
|
||||
else -> data.productionYear?.toString()
|
||||
}
|
||||
val subtitle: String? by lazy {
|
||||
when (type) {
|
||||
BaseItemKind.EPISODE -> listOf(data.seasonEpisode, name).joinNotBlank(" - ")
|
||||
BaseItemKind.SERIES -> data.seriesProductionYears
|
||||
BaseItemKind.AUDIO -> listOf(data.album, artistsString).joinNotBlank(" - ")
|
||||
else -> data.productionYear?.toString()
|
||||
}
|
||||
}
|
||||
|
||||
val subtitleLong: String? by lazy {
|
||||
if (type == BaseItemKind.EPISODE) {
|
||||
|
|
@ -72,7 +73,7 @@ data class BaseItem(
|
|||
add(data.seasonEpisodePadded)
|
||||
add(data.name)
|
||||
add(data.premiereDate?.let { formatDateTime(it) })
|
||||
}.filterNotNull().joinToString(" - ")
|
||||
}.joinNotBlank(" - ")
|
||||
} else {
|
||||
data.productionYear?.toString()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ inline fun <T> List<T>.indexOfFirstOrNull(predicate: (T) -> Boolean): Int? {
|
|||
return if (index >= 0) index else null
|
||||
}
|
||||
|
||||
fun Iterable<CharSequence?>.joinNotBlank(sep: String): String? = filter { it.isNotNullOrBlank() }.letNotEmpty { it.joinToString(sep) }
|
||||
|
||||
/**
|
||||
* Try to call [FocusRequester.requestFocus], but catch & log the exception if something is not configured properly
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ fun <T : CardGridItem> CardGrid(
|
|||
{ index: Int ->
|
||||
if (DEBUG) Timber.v("focusOn: focusedIndex=$currentFocusedIndex, index=$index")
|
||||
if (index != currentFocusedIndex) {
|
||||
previouslyFocusedIndex = focusedIndex
|
||||
previouslyFocusedIndex = currentFocusedIndex
|
||||
}
|
||||
focusedIndex = index
|
||||
}
|
||||
|
|
@ -257,10 +257,11 @@ fun <T : CardGridItem> CardGrid(
|
|||
val newPosition = previouslyFocusedIndex
|
||||
if (DEBUG) Timber.d("Back long pressed: newPosition=$newPosition")
|
||||
if (newPosition > 0) {
|
||||
focusOn(newPosition)
|
||||
scope.launch(ExceptionHandler()) {
|
||||
gridState.scrollToItem(newPosition, -columns)
|
||||
firstFocus.tryRequestFocus()
|
||||
pager.getOrNull(newPosition)
|
||||
gridState.scrollToItem(newPosition)
|
||||
focusOn(newPosition)
|
||||
alphabetFocus = true
|
||||
}
|
||||
}
|
||||
return@onKeyEvent true
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ fun DiscoverPage(
|
|||
0 -> {
|
||||
SeerrDiscoverPage(
|
||||
preferences = preferences,
|
||||
positionCallback = { showHeader = it.row < 1 },
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
|
|
@ -53,6 +54,7 @@ fun DiscoverPage(
|
|||
1 -> {
|
||||
SeerrRequestsPage(
|
||||
focusRequesterOnEmpty = tabDetails.tabFocusRequester,
|
||||
positionCallback = { columns, index -> showHeader = index < columns },
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
|
|
@ -64,6 +66,7 @@ fun DiscoverPage(
|
|||
2 -> {
|
||||
DiscoverSearchPage(
|
||||
preferences = preferences,
|
||||
positionCallback = { columns, index -> showHeader = index < columns },
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ class DiscoverSearchViewModel
|
|||
@Composable
|
||||
fun DiscoverSearchPage(
|
||||
preferences: UserPreferences,
|
||||
positionCallback: (columns: Int, position: Int) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: DiscoverSearchViewModel = hiltViewModel(),
|
||||
) {
|
||||
|
|
@ -241,7 +242,10 @@ fun DiscoverSearchPage(
|
|||
onPlayItem = { _, _ -> },
|
||||
onClickPosition = { position = it.column },
|
||||
onClickDiscover = onClickDiscover,
|
||||
positionCallback = { columns, index -> position = index },
|
||||
positionCallback = { columns, index ->
|
||||
position = index
|
||||
positionCallback.invoke(columns, index)
|
||||
},
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ data class DiscoverState(
|
|||
@Composable
|
||||
fun SeerrDiscoverPage(
|
||||
preferences: UserPreferences,
|
||||
positionCallback: (RowColumn) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SeerrDiscoverViewModel = hiltViewModel(),
|
||||
) {
|
||||
|
|
@ -335,12 +336,16 @@ fun SeerrDiscoverPage(
|
|||
viewModel.navigationManager.navigateTo(item.destination)
|
||||
},
|
||||
onLongClickItem = { index, item -> },
|
||||
onCardFocus = { index -> position = RowColumn(rowIndex, index) },
|
||||
onCardFocus = { index ->
|
||||
position = RowColumn(rowIndex, index)
|
||||
positionCallback.invoke(position)
|
||||
},
|
||||
focusRequester = focusRequesters[rowIndex],
|
||||
enableViewMore = row.type != DiscoverRequestType.UNKNOWN,
|
||||
onClickViewMore = {
|
||||
(row.items as? DataLoadingState.Success<List<DiscoverItem>>)?.data?.size?.let {
|
||||
position = RowColumn(rowIndex, it)
|
||||
positionCallback.invoke(position)
|
||||
}
|
||||
viewModel.navigationManager.navigateTo(
|
||||
Destination.DiscoverMoreResult(row.type),
|
||||
|
|
|
|||
|
|
@ -148,10 +148,12 @@ data class RequestGridItem(
|
|||
@Composable
|
||||
fun SeerrRequestsPage(
|
||||
focusRequesterOnEmpty: FocusRequester?,
|
||||
positionCallback: (columns: Int, position: Int) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SeerrRequestsViewModel = hiltViewModel(),
|
||||
) {
|
||||
val state by viewModel.state.collectAsState(SeerrRequestsState.EMPTY)
|
||||
val columns = 6
|
||||
|
||||
when (val state = state.requests) {
|
||||
is DataLoadingState.Error -> {
|
||||
|
|
@ -213,7 +215,8 @@ fun SeerrRequestsPage(
|
|||
modifier = mod,
|
||||
)
|
||||
},
|
||||
columns = 6,
|
||||
columns = columns,
|
||||
positionCallback = positionCallback,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,12 +338,15 @@ class PlayExternalViewModel
|
|||
}
|
||||
}
|
||||
Timber.v("Result position: %s", position?.milliseconds)
|
||||
if (position != null && position < 0L) {
|
||||
Timber.w("Unknown stop position for external playback")
|
||||
}
|
||||
if (position != null || result.data?.action != null) {
|
||||
api.playStateApi.reportPlaybackStopped(
|
||||
PlaybackStopInfo(
|
||||
itemId = itemId,
|
||||
mediaSourceId = mediaSourceId,
|
||||
positionTicks = position?.milliseconds?.inWholeTicks,
|
||||
positionTicks = position?.milliseconds?.inWholeTicks?.takeIf { it >= 0 },
|
||||
failed = false,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import timber.log.Timber
|
|||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import java.util.UUID
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
|
|
@ -84,10 +85,13 @@ class TrackActivityPlaybackListener(
|
|||
launch("reportPlaybackStopped") {
|
||||
getState.invoke()?.let { state ->
|
||||
Timber.v("reportPlaybackStopped for ${state.itemId} at $position")
|
||||
if (position < Duration.ZERO) {
|
||||
Timber.w("Negative position when reporting playback stopped: %s", position)
|
||||
}
|
||||
api.playStateApi.reportPlaybackStopped(
|
||||
PlaybackStopInfo(
|
||||
itemId = state.itemId,
|
||||
positionTicks = position.inWholeTicks,
|
||||
positionTicks = position.inWholeTicks.takeIf { it >= 0 },
|
||||
failed = false,
|
||||
playSessionId = state.playSessionId,
|
||||
liveStreamId = state.liveStreamId,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue