mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Apply combined continue/next up, if enabled, on library recommended tabs (#533)
## Description Respect the combine Continue Watching & Next Up setting on TV Show library recommended tabs. This uses the same implementation on the home screen, but only includes items for that particular tv show library. ### Related issues Fixes #532
This commit is contained in:
parent
11dda19b8a
commit
6df89fe8c9
2 changed files with 96 additions and 59 deletions
|
|
@ -9,14 +9,15 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.DatePlayedService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.data.RowColumn
|
||||
import com.github.damontecres.wholphin.ui.main.buildCombinedNextUp
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.ui.toBaseItems
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
|
|
@ -57,6 +58,7 @@ class RecommendedTvShowViewModel
|
|||
private val api: ApiClient,
|
||||
private val serverRepository: ServerRepository,
|
||||
private val preferencesDataStore: DataStore<AppPreferences>,
|
||||
private val datePlayedService: DatePlayedService,
|
||||
@Assisted val parentId: UUID,
|
||||
navigationManager: NavigationManager,
|
||||
favoriteWatchManager: FavoriteWatchManager,
|
||||
|
|
@ -78,17 +80,17 @@ class RecommendedTvShowViewModel
|
|||
|
||||
override fun init() {
|
||||
viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
|
||||
val itemsPerRow =
|
||||
preferencesDataStore.data
|
||||
.firstOrNull()
|
||||
?.homePagePreferences
|
||||
?.maxItemsPerRow
|
||||
?: AppPreference.HomePageItems.defaultValue.toInt()
|
||||
val preferences =
|
||||
preferencesDataStore.data.firstOrNull() ?: AppPreferences.getDefaultInstance()
|
||||
val combineNextUp = preferences.homePagePreferences.combineContinueNext
|
||||
val itemsPerRow = preferences.homePagePreferences.maxItemsPerRow
|
||||
val userId = serverRepository.currentUser.value?.id
|
||||
try {
|
||||
val resumeItemsDeferred =
|
||||
viewModelScope.async(Dispatchers.IO) {
|
||||
val resumeItemsRequest =
|
||||
GetResumeItemsRequest(
|
||||
userId = userId,
|
||||
parentId = parentId,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.EPISODE),
|
||||
|
|
@ -106,12 +108,14 @@ class RecommendedTvShowViewModel
|
|||
viewModelScope.async(Dispatchers.IO) {
|
||||
val nextUpRequest =
|
||||
GetNextUpRequest(
|
||||
parentId = parentId,
|
||||
userId = userId,
|
||||
fields = SlimItemFields,
|
||||
enableUserData = true,
|
||||
startIndex = 0,
|
||||
imageTypeLimit = 1,
|
||||
parentId = parentId,
|
||||
limit = itemsPerRow,
|
||||
enableTotalRecordCount = false,
|
||||
enableResumable = false,
|
||||
enableUserData = true,
|
||||
enableRewatching = preferences.homePagePreferences.enableRewatchingNextUp,
|
||||
)
|
||||
|
||||
GetNextUpRequestHandler
|
||||
|
|
@ -119,21 +123,45 @@ class RecommendedTvShowViewModel
|
|||
.toBaseItems(api, true)
|
||||
}
|
||||
val resumeItems = resumeItemsDeferred.await()
|
||||
update(
|
||||
R.string.continue_watching,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.continue_watching),
|
||||
resumeItems,
|
||||
),
|
||||
)
|
||||
val nextUpItems = nextUpItemsDeferred.await()
|
||||
update(
|
||||
R.string.next_up,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.next_up),
|
||||
nextUpItems,
|
||||
),
|
||||
)
|
||||
if (combineNextUp) {
|
||||
val combined =
|
||||
buildCombinedNextUp(
|
||||
viewModelScope,
|
||||
datePlayedService,
|
||||
resumeItems,
|
||||
nextUpItems,
|
||||
)
|
||||
update(
|
||||
R.string.continue_watching,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.continue_watching),
|
||||
combined,
|
||||
),
|
||||
)
|
||||
update(
|
||||
R.string.next_up,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.next_up),
|
||||
listOf(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
update(
|
||||
R.string.continue_watching,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.continue_watching),
|
||||
resumeItems,
|
||||
),
|
||||
)
|
||||
update(
|
||||
R.string.next_up,
|
||||
HomeRowLoadingState.Success(
|
||||
context.getString(R.string.next_up),
|
||||
nextUpItems,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (resumeItems.isNotEmpty() || nextUpItems.isNotEmpty()) {
|
||||
loading.setValueOnMain(LoadingState.Success)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.github.damontecres.wholphin.util.LoadingState
|
|||
import com.github.damontecres.wholphin.util.supportItemKinds
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -109,7 +110,13 @@ class HomeViewModel
|
|||
val watching =
|
||||
buildList {
|
||||
if (prefs.combineContinueNext) {
|
||||
val items = buildCombined(resume, nextUp)
|
||||
val items =
|
||||
buildCombinedNextUp(
|
||||
viewModelScope,
|
||||
datePlayedService,
|
||||
resume,
|
||||
nextUp,
|
||||
)
|
||||
add(
|
||||
HomeRowLoadingState.Success(
|
||||
title = context.getString(R.string.continue_watching),
|
||||
|
|
@ -267,39 +274,6 @@ class HomeViewModel
|
|||
latestRows.setValueOnMain(rows)
|
||||
}
|
||||
|
||||
private suspend fun buildCombined(
|
||||
resume: List<BaseItem>,
|
||||
nextUp: List<BaseItem>,
|
||||
): List<BaseItem> =
|
||||
withContext(Dispatchers.IO) {
|
||||
val start = System.currentTimeMillis()
|
||||
val semaphore = Semaphore(3)
|
||||
val deferred =
|
||||
nextUp
|
||||
.filter { it.data.seriesId != null }
|
||||
.map { item ->
|
||||
viewModelScope.async(Dispatchers.IO) {
|
||||
try {
|
||||
semaphore.withPermit {
|
||||
datePlayedService.getLastPlayed(item)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error fetching %s", item.id)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val nextUpLastPlayed = deferred.awaitAll()
|
||||
val timestamps = mutableMapOf<UUID, LocalDateTime?>()
|
||||
nextUp.map { it.id }.zip(nextUpLastPlayed).toMap(timestamps)
|
||||
resume.forEach { timestamps[it.id] = it.data.userData?.lastPlayedDate }
|
||||
val result = (resume + nextUp).sortedByDescending { timestamps[it.id] }
|
||||
val duration = (System.currentTimeMillis() - start).milliseconds
|
||||
Timber.v("buildCombined took %s", duration)
|
||||
return@withContext result
|
||||
}
|
||||
|
||||
fun setWatched(
|
||||
itemId: UUID,
|
||||
played: Boolean,
|
||||
|
|
@ -340,3 +314,38 @@ data class LatestData(
|
|||
val title: String,
|
||||
val request: GetLatestMediaRequest,
|
||||
)
|
||||
|
||||
suspend fun buildCombinedNextUp(
|
||||
scope: CoroutineScope,
|
||||
datePlayedService: DatePlayedService,
|
||||
resume: List<BaseItem>,
|
||||
nextUp: List<BaseItem>,
|
||||
): List<BaseItem> =
|
||||
withContext(Dispatchers.IO) {
|
||||
val start = System.currentTimeMillis()
|
||||
val semaphore = Semaphore(3)
|
||||
val deferred =
|
||||
nextUp
|
||||
.filter { it.data.seriesId != null }
|
||||
.map { item ->
|
||||
scope.async(Dispatchers.IO) {
|
||||
try {
|
||||
semaphore.withPermit {
|
||||
datePlayedService.getLastPlayed(item)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error fetching %s", item.id)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val nextUpLastPlayed = deferred.awaitAll()
|
||||
val timestamps = mutableMapOf<UUID, LocalDateTime?>()
|
||||
nextUp.map { it.id }.zip(nextUpLastPlayed).toMap(timestamps)
|
||||
resume.forEach { timestamps[it.id] = it.data.userData?.lastPlayedDate }
|
||||
val result = (resume + nextUp).sortedByDescending { timestamps[it.id] }
|
||||
val duration = (System.currentTimeMillis() - start).milliseconds
|
||||
Timber.v("buildCombined took %s", duration)
|
||||
return@withContext result
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue