mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Sort names, static home rows, & only show supported content
This commit is contained in:
parent
ead2431bc4
commit
1a4ddabff9
10 changed files with 203 additions and 74 deletions
|
|
@ -50,6 +50,7 @@ import com.github.damontecres.dolphin.ui.ifElse
|
||||||
import com.github.damontecres.dolphin.util.seasonEpisode
|
import com.github.damontecres.dolphin.util.seasonEpisode
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ItemCard(
|
fun ItemCard(
|
||||||
|
|
@ -167,6 +168,12 @@ fun ItemCardImage(
|
||||||
contentDescription = name,
|
contentDescription = name,
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
alignment = Alignment.Center,
|
alignment = Alignment.Center,
|
||||||
|
// TODO error/fallback images
|
||||||
|
error = null,
|
||||||
|
fallback = null,
|
||||||
|
onError = {
|
||||||
|
Timber.e(it.result.throwable, "Error loading image: $imageUrl")
|
||||||
|
},
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import com.github.damontecres.dolphin.R
|
||||||
import com.github.damontecres.dolphin.ui.FontAwesome
|
import com.github.damontecres.dolphin.ui.FontAwesome
|
||||||
import com.github.damontecres.dolphin.ui.data.SortAndDirection
|
import com.github.damontecres.dolphin.ui.data.SortAndDirection
|
||||||
import com.github.damontecres.dolphin.ui.data.flip
|
import com.github.damontecres.dolphin.ui.data.flip
|
||||||
|
import com.github.damontecres.dolphin.ui.data.getStringRes
|
||||||
import org.jellyfin.sdk.model.api.ItemSortBy
|
import org.jellyfin.sdk.model.api.ItemSortBy
|
||||||
import org.jellyfin.sdk.model.api.SortOrder
|
import org.jellyfin.sdk.model.api.SortOrder
|
||||||
|
|
||||||
|
|
@ -32,6 +33,7 @@ fun SortByButton(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val currentSort = current.sort
|
val currentSort = current.sort
|
||||||
|
val name = stringResource(getStringRes(currentSort))
|
||||||
val currentDirection = current.direction
|
val currentDirection = current.direction
|
||||||
var sortByDropDown by remember { mutableStateOf(false) }
|
var sortByDropDown by remember { mutableStateOf(false) }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
@ -58,7 +60,7 @@ fun SortByButton(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
append(" ")
|
append(" ")
|
||||||
append(currentSort.name) // TODO names
|
append(name)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +71,7 @@ fun SortByButton(
|
||||||
onDismissRequest = { sortByDropDown = false },
|
onDismissRequest = { sortByDropDown = false },
|
||||||
) {
|
) {
|
||||||
sortOptions
|
sortOptions
|
||||||
.sortedBy { it.name }
|
// .sortedBy { it.name }
|
||||||
.forEach { sortOption ->
|
.forEach { sortOption ->
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
|
|
@ -91,7 +93,7 @@ fun SortByButton(
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
text = sortOption.name,
|
text = stringResource(getStringRes(sortOption)),
|
||||||
color = MaterialTheme.colorScheme.onSecondaryContainer,
|
color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.github.damontecres.dolphin.ui.data
|
package com.github.damontecres.dolphin.ui.data
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.github.damontecres.dolphin.R
|
||||||
import org.jellyfin.sdk.model.api.ItemSortBy
|
import org.jellyfin.sdk.model.api.ItemSortBy
|
||||||
import org.jellyfin.sdk.model.api.SortOrder
|
import org.jellyfin.sdk.model.api.SortOrder
|
||||||
|
|
||||||
|
|
@ -15,13 +17,9 @@ fun SortOrder.flip() = if (this == SortOrder.ASCENDING) SortOrder.DESCENDING els
|
||||||
val MovieSortOptions =
|
val MovieSortOptions =
|
||||||
listOf(
|
listOf(
|
||||||
ItemSortBy.SORT_NAME,
|
ItemSortBy.SORT_NAME,
|
||||||
ItemSortBy.PRODUCTION_YEAR,
|
ItemSortBy.PREMIERE_DATE,
|
||||||
ItemSortBy.COMMUNITY_RATING,
|
|
||||||
ItemSortBy.DATE_CREATED,
|
ItemSortBy.DATE_CREATED,
|
||||||
ItemSortBy.DATE_PLAYED,
|
ItemSortBy.DATE_PLAYED,
|
||||||
ItemSortBy.PLAY_COUNT,
|
|
||||||
ItemSortBy.STUDIO,
|
|
||||||
ItemSortBy.OFFICIAL_RATING,
|
|
||||||
ItemSortBy.RANDOM,
|
ItemSortBy.RANDOM,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,12 +27,9 @@ val SeriesSortOptions =
|
||||||
listOf(
|
listOf(
|
||||||
ItemSortBy.SORT_NAME,
|
ItemSortBy.SORT_NAME,
|
||||||
ItemSortBy.PREMIERE_DATE,
|
ItemSortBy.PREMIERE_DATE,
|
||||||
ItemSortBy.COMMUNITY_RATING,
|
|
||||||
ItemSortBy.DATE_CREATED,
|
ItemSortBy.DATE_CREATED,
|
||||||
ItemSortBy.DATE_LAST_CONTENT_ADDED,
|
ItemSortBy.DATE_LAST_CONTENT_ADDED,
|
||||||
ItemSortBy.DATE_PLAYED,
|
ItemSortBy.DATE_PLAYED,
|
||||||
ItemSortBy.STUDIO,
|
|
||||||
ItemSortBy.OFFICIAL_RATING,
|
|
||||||
ItemSortBy.RANDOM,
|
ItemSortBy.RANDOM,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -45,3 +40,15 @@ val VideoSortOptions =
|
||||||
ItemSortBy.DATE_PLAYED,
|
ItemSortBy.DATE_PLAYED,
|
||||||
ItemSortBy.RANDOM,
|
ItemSortBy.RANDOM,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@StringRes
|
||||||
|
fun getStringRes(sort: ItemSortBy): Int =
|
||||||
|
when (sort) {
|
||||||
|
ItemSortBy.SORT_NAME -> R.string.sort_by_name
|
||||||
|
ItemSortBy.PREMIERE_DATE -> R.string.sort_by_date_released
|
||||||
|
ItemSortBy.DATE_CREATED -> R.string.sort_by_date_added
|
||||||
|
ItemSortBy.DATE_LAST_CONTENT_ADDED -> R.string.sort_by_date_episode_added
|
||||||
|
ItemSortBy.DATE_PLAYED -> R.string.sort_by_date_played
|
||||||
|
ItemSortBy.RANDOM -> R.string.sort_by_random
|
||||||
|
else -> throw IllegalArgumentException("Unsupported sort option: $sort")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import androidx.compose.ui.input.key.KeyEventType
|
||||||
import androidx.compose.ui.input.key.key
|
import androidx.compose.ui.input.key.key
|
||||||
import androidx.compose.ui.input.key.onKeyEvent
|
import androidx.compose.ui.input.key.onKeyEvent
|
||||||
import androidx.compose.ui.input.key.type
|
import androidx.compose.ui.input.key.type
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.tv.material3.Button
|
import androidx.tv.material3.Button
|
||||||
|
|
@ -46,7 +45,6 @@ import com.github.damontecres.dolphin.ui.AppColors
|
||||||
import com.github.damontecres.dolphin.ui.FontAwesome
|
import com.github.damontecres.dolphin.ui.FontAwesome
|
||||||
import com.github.damontecres.dolphin.ui.cards.ItemCard
|
import com.github.damontecres.dolphin.ui.cards.ItemCard
|
||||||
import com.github.damontecres.dolphin.ui.ifElse
|
import com.github.damontecres.dolphin.ui.ifElse
|
||||||
import com.github.damontecres.dolphin.ui.nav.NavigationManager
|
|
||||||
import com.github.damontecres.dolphin.ui.playback.isBackwardButton
|
import com.github.damontecres.dolphin.ui.playback.isBackwardButton
|
||||||
import com.github.damontecres.dolphin.ui.playback.isForwardButton
|
import com.github.damontecres.dolphin.ui.playback.isForwardButton
|
||||||
import com.github.damontecres.dolphin.ui.playback.isPlayKeyUp
|
import com.github.damontecres.dolphin.ui.playback.isPlayKeyUp
|
||||||
|
|
@ -66,7 +64,7 @@ fun CardGrid(
|
||||||
letterPosition: suspend (Char) -> Int,
|
letterPosition: suspend (Char) -> Int,
|
||||||
requestFocus: Boolean,
|
requestFocus: Boolean,
|
||||||
gridFocusRequester: FocusRequester,
|
gridFocusRequester: FocusRequester,
|
||||||
navigationManager: NavigationManager,
|
showJumpButtons: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
initialPosition: Int = 0,
|
initialPosition: Int = 0,
|
||||||
positionCallback: ((columns: Int, position: Int) -> Unit)? = null,
|
positionCallback: ((columns: Int, position: Int) -> Unit)? = null,
|
||||||
|
|
@ -120,9 +118,6 @@ fun CardGrid(
|
||||||
// hasRun = true
|
// hasRun = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val context = LocalContext.current
|
|
||||||
val showJumpButtons = true
|
|
||||||
|
|
||||||
var alphabetFocus by remember { mutableStateOf(false) }
|
var alphabetFocus by remember { mutableStateOf(false) }
|
||||||
val focusOn = { index: Int ->
|
val focusOn = { index: Int ->
|
||||||
if (DEBUG) Timber.v("focusOn: focusedIndex=$focusedIndex, index=$index")
|
if (DEBUG) Timber.v("focusOn: focusedIndex=$focusedIndex, index=$index")
|
||||||
|
|
@ -237,7 +232,7 @@ fun CardGrid(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
if (showJumpButtons && pager.size > 0) {
|
if (showJumpButtons && pager.isNotEmpty()) {
|
||||||
JumpButtons(
|
JumpButtons(
|
||||||
jump1 = jump1,
|
jump1 = jump1,
|
||||||
jump2 = jump2,
|
jump2 = jump2,
|
||||||
|
|
@ -286,8 +281,7 @@ fun CardGrid(
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
}
|
}
|
||||||
// TODO
|
val item = pager[index]
|
||||||
val item = pager[index] // ?.let { convertModel(it, api) }
|
|
||||||
if (!hasRequestFocusRun && requestFocus && initialPosition >= 0) {
|
if (!hasRequestFocusRun && requestFocus && initialPosition >= 0) {
|
||||||
// On very first composition, if parent wants to focus on the grid, do so
|
// On very first composition, if parent wants to focus on the grid, do so
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
|
@ -328,7 +322,7 @@ fun CardGrid(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pager.size == 0) {
|
if (pager.isEmpty()) {
|
||||||
// focusedIndex = -1
|
// focusedIndex = -1
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -87,20 +87,11 @@ class CollectionFolderViewModel
|
||||||
}
|
}
|
||||||
val includeItemTypes =
|
val includeItemTypes =
|
||||||
when (item.data.collectionType) {
|
when (item.data.collectionType) {
|
||||||
CollectionType.UNKNOWN -> TODO()
|
|
||||||
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
||||||
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
||||||
CollectionType.MUSIC -> TODO()
|
|
||||||
CollectionType.MUSICVIDEOS -> TODO()
|
|
||||||
CollectionType.TRAILERS -> TODO()
|
|
||||||
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
||||||
CollectionType.BOXSETS -> TODO()
|
|
||||||
CollectionType.BOOKS -> TODO()
|
else -> listOf()
|
||||||
CollectionType.PHOTOS -> TODO()
|
|
||||||
CollectionType.LIVETV -> TODO()
|
|
||||||
CollectionType.PLAYLISTS -> TODO()
|
|
||||||
CollectionType.FOLDERS -> TODO()
|
|
||||||
null -> listOf()
|
|
||||||
}
|
}
|
||||||
val request =
|
val request =
|
||||||
GetItemsRequest(
|
GetItemsRequest(
|
||||||
|
|
@ -110,7 +101,12 @@ class CollectionFolderViewModel
|
||||||
// recursive = true,
|
// recursive = true,
|
||||||
enableImageTypes = listOf(ImageType.PRIMARY, ImageType.THUMB),
|
enableImageTypes = listOf(ImageType.PRIMARY, ImageType.THUMB),
|
||||||
includeItemTypes = includeItemTypes,
|
includeItemTypes = includeItemTypes,
|
||||||
sortBy = listOf(sortAndDirection.sort),
|
sortBy =
|
||||||
|
listOf(
|
||||||
|
sortAndDirection.sort,
|
||||||
|
ItemSortBy.SORT_NAME,
|
||||||
|
ItemSortBy.PRODUCTION_YEAR,
|
||||||
|
),
|
||||||
sortOrder = listOf(sortAndDirection.direction),
|
sortOrder = listOf(sortAndDirection.direction),
|
||||||
fields = DefaultItemFields,
|
fields = DefaultItemFields,
|
||||||
)
|
)
|
||||||
|
|
@ -225,7 +221,7 @@ fun CollectionDetails(
|
||||||
letterPosition = { 0 },
|
letterPosition = { 0 },
|
||||||
requestFocus = true,
|
requestFocus = true,
|
||||||
gridFocusRequester = gridFocusRequester,
|
gridFocusRequester = gridFocusRequester,
|
||||||
navigationManager = navigationManager,
|
showJumpButtons = false, // TODO add preference
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
initialPosition = 0,
|
initialPosition = 0,
|
||||||
positionCallback = { _, _ -> },
|
positionCallback = { _, _ -> },
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ import org.jellyfin.sdk.model.extensions.ticks
|
||||||
|
|
||||||
data class HomeRow(
|
data class HomeRow(
|
||||||
val section: HomeSection,
|
val section: HomeSection,
|
||||||
val items: List<BaseItem>,
|
val items: List<BaseItem?>,
|
||||||
val title: String? = null,
|
val title: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -82,13 +82,13 @@ fun HomePage(
|
||||||
|
|
||||||
LoadingState.Success -> {
|
LoadingState.Success -> {
|
||||||
val homeRows by viewModel.homeRows.observeAsState(listOf())
|
val homeRows by viewModel.homeRows.observeAsState(listOf())
|
||||||
MainPageContent(navigationManager, homeRows, modifier)
|
HomePageContent(navigationManager, homeRows, modifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainPageContent(
|
fun HomePageContent(
|
||||||
navigationManager: NavigationManager,
|
navigationManager: NavigationManager,
|
||||||
homeRows: List<HomeRow>,
|
homeRows: List<HomeRow>,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,15 @@ import androidx.lifecycle.viewModelScope
|
||||||
import com.github.damontecres.dolphin.data.model.BaseItem
|
import com.github.damontecres.dolphin.data.model.BaseItem
|
||||||
import com.github.damontecres.dolphin.preferences.UserPreferences
|
import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.dolphin.ui.DefaultItemFields
|
import com.github.damontecres.dolphin.ui.DefaultItemFields
|
||||||
import com.github.damontecres.dolphin.ui.isNotNullOrBlank
|
|
||||||
import com.github.damontecres.dolphin.util.LoadingExceptionHandler
|
import com.github.damontecres.dolphin.util.LoadingExceptionHandler
|
||||||
import com.github.damontecres.dolphin.util.LoadingState
|
import com.github.damontecres.dolphin.util.LoadingState
|
||||||
|
import com.github.damontecres.dolphin.util.supportItemKinds
|
||||||
|
import com.github.damontecres.dolphin.util.supportedCollectionTypes
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi
|
|
||||||
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||||
import org.jellyfin.sdk.api.client.extensions.tvShowsApi
|
import org.jellyfin.sdk.api.client.extensions.tvShowsApi
|
||||||
import org.jellyfin.sdk.api.client.extensions.userApi
|
import org.jellyfin.sdk.api.client.extensions.userApi
|
||||||
|
|
@ -44,19 +44,33 @@ class HomeViewModel
|
||||||
"Error loading home page",
|
"Error loading home page",
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
val user = api.userApi.getCurrentUser().content
|
val user by api.userApi.getCurrentUser()
|
||||||
val displayPrefs =
|
// val displayPrefs =
|
||||||
api.displayPreferencesApi
|
// api.displayPreferencesApi
|
||||||
.getDisplayPreferences(
|
// .getDisplayPreferences(
|
||||||
displayPreferencesId = "usersettings",
|
// displayPreferencesId = "usersettings",
|
||||||
client = "emby",
|
// client = "emby",
|
||||||
).content
|
// ).content
|
||||||
val homeSections =
|
val homeSections =
|
||||||
displayPrefs.customPrefs.entries
|
listOf(
|
||||||
.filter { it.key.startsWith("homesection") && it.value.isNotNullOrBlank() }
|
HomeSection.RESUME,
|
||||||
.sortedBy { it.key }
|
HomeSection.NEXT_UP,
|
||||||
.map { HomeSection.fromKey(it.value ?: "") }
|
HomeSection.LATEST_MEDIA,
|
||||||
.filterNot { it == HomeSection.NONE }
|
)
|
||||||
|
// TODO use display preferences?
|
||||||
|
|
||||||
|
// displayPrefs.customPrefs.entries
|
||||||
|
// .filter { it.key.startsWith("homesection") && it.value.isNotNullOrBlank() }
|
||||||
|
// .sortedBy { it.key }
|
||||||
|
// .map { HomeSection.fromKey(it.value ?: "") }
|
||||||
|
// .filter {
|
||||||
|
// it in
|
||||||
|
// setOf(
|
||||||
|
// HomeSection.LATEST_MEDIA,
|
||||||
|
// HomeSection.NEXT_UP,
|
||||||
|
// HomeSection.RESUME,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
val latestMediaIncludes =
|
val latestMediaIncludes =
|
||||||
user.configuration?.orderedViews.orEmpty().toMutableList().apply {
|
user.configuration?.orderedViews.orEmpty().toMutableList().apply {
|
||||||
|
|
@ -71,29 +85,38 @@ class HomeViewModel
|
||||||
Timber.Forest.v("Loading section: %s", section.name)
|
Timber.Forest.v("Loading section: %s", section.name)
|
||||||
when (section) {
|
when (section) {
|
||||||
HomeSection.LATEST_MEDIA -> {
|
HomeSection.LATEST_MEDIA -> {
|
||||||
latestMediaIncludes.map { viewId ->
|
latestMediaIncludes.mapNotNull { viewId ->
|
||||||
val title =
|
val view =
|
||||||
views.items.firstOrNull { it.id == viewId }?.name?.let {
|
views.items
|
||||||
"Recently Added in $it"
|
.firstOrNull { it.id == viewId }
|
||||||
}
|
if (view?.collectionType in supportedCollectionTypes) {
|
||||||
val request =
|
val title =
|
||||||
GetLatestMediaRequest(
|
view
|
||||||
fields = DefaultItemFields,
|
?.name
|
||||||
imageTypeLimit = 1,
|
?.let {
|
||||||
parentId = viewId,
|
"Recently Added in $it"
|
||||||
groupItems = true,
|
}
|
||||||
limit = limit,
|
val request =
|
||||||
|
GetLatestMediaRequest(
|
||||||
|
fields = DefaultItemFields,
|
||||||
|
imageTypeLimit = 1,
|
||||||
|
parentId = viewId,
|
||||||
|
groupItems = true,
|
||||||
|
limit = limit,
|
||||||
|
)
|
||||||
|
val latest =
|
||||||
|
api.userLibraryApi
|
||||||
|
.getLatestMedia(request)
|
||||||
|
.content
|
||||||
|
.map { BaseItem.from(it, api, true) }
|
||||||
|
HomeRow(
|
||||||
|
section = section,
|
||||||
|
items = latest,
|
||||||
|
title = title,
|
||||||
)
|
)
|
||||||
val latest =
|
} else {
|
||||||
api.userLibraryApi
|
null
|
||||||
.getLatestMedia(request)
|
}
|
||||||
.content
|
|
||||||
.map { BaseItem.from(it, api, true) }
|
|
||||||
HomeRow(
|
|
||||||
section = section,
|
|
||||||
items = latest,
|
|
||||||
title = title,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +126,7 @@ class HomeViewModel
|
||||||
userId = user.id,
|
userId = user.id,
|
||||||
fields = DefaultItemFields,
|
fields = DefaultItemFields,
|
||||||
limit = limit,
|
limit = limit,
|
||||||
// TODO, more params?
|
includeItemTypes = supportItemKinds,
|
||||||
)
|
)
|
||||||
val items =
|
val items =
|
||||||
api.itemsApi
|
api.itemsApi
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,14 @@ import kotlinx.coroutines.sync.withLock
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.Response
|
import org.jellyfin.sdk.api.client.Response
|
||||||
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||||
|
import org.jellyfin.sdk.api.client.extensions.suggestionsApi
|
||||||
import org.jellyfin.sdk.api.client.extensions.tvShowsApi
|
import org.jellyfin.sdk.api.client.extensions.tvShowsApi
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDtoQueryResult
|
import org.jellyfin.sdk.model.api.BaseItemDtoQueryResult
|
||||||
import org.jellyfin.sdk.model.api.request.GetEpisodesRequest
|
import org.jellyfin.sdk.model.api.request.GetEpisodesRequest
|
||||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||||
|
import org.jellyfin.sdk.model.api.request.GetNextUpRequest
|
||||||
|
import org.jellyfin.sdk.model.api.request.GetResumeItemsRequest
|
||||||
|
import org.jellyfin.sdk.model.api.request.GetSuggestionsRequest
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
|
@ -76,6 +80,63 @@ val GetEpisodesRequestHandler =
|
||||||
): Response<BaseItemDtoQueryResult> = api.tvShowsApi.getEpisodes(request)
|
): Response<BaseItemDtoQueryResult> = api.tvShowsApi.getEpisodes(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val GetResumeItemsRequestHandler =
|
||||||
|
object : RequestHandler<GetResumeItemsRequest> {
|
||||||
|
override fun prepare(
|
||||||
|
request: GetResumeItemsRequest,
|
||||||
|
startIndex: Int,
|
||||||
|
limit: Int,
|
||||||
|
enableTotalRecordCount: Boolean,
|
||||||
|
): GetResumeItemsRequest =
|
||||||
|
request.copy(
|
||||||
|
startIndex = startIndex,
|
||||||
|
limit = limit,
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun execute(
|
||||||
|
api: ApiClient,
|
||||||
|
request: GetResumeItemsRequest,
|
||||||
|
): Response<BaseItemDtoQueryResult> = api.itemsApi.getResumeItems(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
val GetNextUpRequestHandler =
|
||||||
|
object : RequestHandler<GetNextUpRequest> {
|
||||||
|
override fun prepare(
|
||||||
|
request: GetNextUpRequest,
|
||||||
|
startIndex: Int,
|
||||||
|
limit: Int,
|
||||||
|
enableTotalRecordCount: Boolean,
|
||||||
|
): GetNextUpRequest =
|
||||||
|
request.copy(
|
||||||
|
startIndex = startIndex,
|
||||||
|
limit = limit,
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun execute(
|
||||||
|
api: ApiClient,
|
||||||
|
request: GetNextUpRequest,
|
||||||
|
): Response<BaseItemDtoQueryResult> = api.tvShowsApi.getNextUp(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
val GetSuggestionsRequestHandler =
|
||||||
|
object : RequestHandler<GetSuggestionsRequest> {
|
||||||
|
override fun prepare(
|
||||||
|
request: GetSuggestionsRequest,
|
||||||
|
startIndex: Int,
|
||||||
|
limit: Int,
|
||||||
|
enableTotalRecordCount: Boolean,
|
||||||
|
): GetSuggestionsRequest =
|
||||||
|
request.copy(
|
||||||
|
startIndex = startIndex,
|
||||||
|
limit = limit,
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun execute(
|
||||||
|
api: ApiClient,
|
||||||
|
request: GetSuggestionsRequest,
|
||||||
|
): Response<BaseItemDtoQueryResult> = api.suggestionsApi.getSuggestions(request)
|
||||||
|
}
|
||||||
|
|
||||||
class ApiRequestPager<T>(
|
class ApiRequestPager<T>(
|
||||||
val api: ApiClient,
|
val api: ApiClient,
|
||||||
val request: T,
|
val request: T,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.github.damontecres.dolphin.util
|
||||||
|
|
||||||
|
import com.github.damontecres.dolphin.ui.main.HomeSection
|
||||||
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
|
import org.jellyfin.sdk.model.api.CollectionType
|
||||||
|
|
||||||
|
val supportedHomeSection =
|
||||||
|
setOf(
|
||||||
|
HomeSection.LATEST_MEDIA,
|
||||||
|
HomeSection.NEXT_UP,
|
||||||
|
HomeSection.RESUME,
|
||||||
|
)
|
||||||
|
|
||||||
|
val supportItemKinds =
|
||||||
|
setOf(
|
||||||
|
BaseItemKind.MOVIE,
|
||||||
|
BaseItemKind.EPISODE,
|
||||||
|
BaseItemKind.SERIES,
|
||||||
|
BaseItemKind.VIDEO,
|
||||||
|
BaseItemKind.SEASON,
|
||||||
|
BaseItemKind.COLLECTION_FOLDER,
|
||||||
|
BaseItemKind.USER_VIEW,
|
||||||
|
)
|
||||||
|
|
||||||
|
val supportedCollectionTypes =
|
||||||
|
setOf(
|
||||||
|
CollectionType.MOVIES,
|
||||||
|
CollectionType.TVSHOWS,
|
||||||
|
CollectionType.HOMEVIDEOS,
|
||||||
|
)
|
||||||
|
|
@ -47,4 +47,13 @@
|
||||||
<string name="playback_debug_info">Show playback debug info</string>
|
<string name="playback_debug_info">Show playback debug info</string>
|
||||||
<string name="auto_play_next_delay">Delay before playing next up</string>
|
<string name="auto_play_next_delay">Delay before playing next up</string>
|
||||||
<string name="auto_play_next">Auto play next up</string>
|
<string name="auto_play_next">Auto play next up</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="sort_by_name">Name</string>
|
||||||
|
<string name="sort_by_random">Random</string>
|
||||||
|
<string name="sort_by_date_episode_added">Date Episode Added</string>
|
||||||
|
<string name="sort_by_date_added">Date Added</string>
|
||||||
|
<string name="sort_by_date_played">Date Played</string>
|
||||||
|
<string name="sort_by_date_released">Date Released</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue