mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Support collections
This commit is contained in:
parent
a93f183f5f
commit
b40db0074f
11 changed files with 64 additions and 14 deletions
|
|
@ -98,7 +98,7 @@ fun GridCard(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = item?.name ?: "",
|
text = item?.title ?: "",
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -109,7 +109,7 @@ fun GridCard(
|
||||||
.enableMarquee(focusedAfterDelay),
|
.enableMarquee(focusedAfterDelay),
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = item?.data?.productionYear?.toString() ?: "",
|
text = item?.subtitle ?: "",
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier =
|
modifier =
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ class CollectionFolderViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
potential: BaseItem?,
|
potential: BaseItem?,
|
||||||
sortAndDirection: SortAndDirection,
|
sortAndDirection: SortAndDirection,
|
||||||
|
recursive: Boolean,
|
||||||
): Job =
|
): Job =
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
LoadingExceptionHandler(
|
LoadingExceptionHandler(
|
||||||
|
|
@ -80,10 +81,13 @@ class CollectionFolderViewModel
|
||||||
) + Dispatchers.IO,
|
) + Dispatchers.IO,
|
||||||
) {
|
) {
|
||||||
fetchItem(itemId, potential)
|
fetchItem(itemId, potential)
|
||||||
loadResults(sortAndDirection)
|
loadResults(sortAndDirection, recursive)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadResults(sortAndDirection: SortAndDirection) {
|
fun loadResults(
|
||||||
|
sortAndDirection: SortAndDirection,
|
||||||
|
recursive: Boolean,
|
||||||
|
) {
|
||||||
item.value?.let { item ->
|
item.value?.let { item ->
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
|
@ -96,6 +100,15 @@ class CollectionFolderViewModel
|
||||||
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
CollectionType.MOVIES -> listOf(BaseItemKind.MOVIE)
|
||||||
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
CollectionType.TVSHOWS -> listOf(BaseItemKind.SERIES)
|
||||||
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
CollectionType.HOMEVIDEOS -> listOf(BaseItemKind.VIDEO)
|
||||||
|
CollectionType.MUSIC ->
|
||||||
|
listOf(
|
||||||
|
BaseItemKind.AUDIO,
|
||||||
|
BaseItemKind.MUSIC_ARTIST,
|
||||||
|
BaseItemKind.MUSIC_ALBUM,
|
||||||
|
)
|
||||||
|
|
||||||
|
CollectionType.BOXSETS -> listOf(BaseItemKind.BOX_SET)
|
||||||
|
CollectionType.PLAYLISTS -> listOf(BaseItemKind.PLAYLIST)
|
||||||
|
|
||||||
else -> listOf()
|
else -> listOf()
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +117,8 @@ class CollectionFolderViewModel
|
||||||
parentId = item.id,
|
parentId = item.id,
|
||||||
enableImageTypes = listOf(ImageType.PRIMARY, ImageType.THUMB),
|
enableImageTypes = listOf(ImageType.PRIMARY, ImageType.THUMB),
|
||||||
includeItemTypes = includeItemTypes,
|
includeItemTypes = includeItemTypes,
|
||||||
recursive = true,
|
recursive = recursive,
|
||||||
|
excludeItemIds = listOf(item.id),
|
||||||
sortBy =
|
sortBy =
|
||||||
listOf(
|
listOf(
|
||||||
sortAndDirection.sort,
|
sortAndDirection.sort,
|
||||||
|
|
@ -120,7 +134,13 @@ class CollectionFolderViewModel
|
||||||
fields = DefaultItemFields,
|
fields = DefaultItemFields,
|
||||||
)
|
)
|
||||||
val newPager =
|
val newPager =
|
||||||
ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope)
|
ApiRequestPager(
|
||||||
|
api,
|
||||||
|
request,
|
||||||
|
GetItemsRequestHandler,
|
||||||
|
viewModelScope,
|
||||||
|
useSeriesForPrimary = true,
|
||||||
|
)
|
||||||
newPager.init()
|
newPager.init()
|
||||||
if (newPager.isNotEmpty()) newPager.getBlocking(0)
|
if (newPager.isNotEmpty()) newPager.getBlocking(0)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
|
@ -164,6 +184,7 @@ class CollectionFolderViewModel
|
||||||
fun CollectionFolderGrid(
|
fun CollectionFolderGrid(
|
||||||
preferences: UserPreferences,
|
preferences: UserPreferences,
|
||||||
destination: Destination.MediaItem,
|
destination: Destination.MediaItem,
|
||||||
|
recursive: Boolean,
|
||||||
onClickItem: (BaseItem) -> Unit,
|
onClickItem: (BaseItem) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
viewModel: CollectionFolderViewModel = hiltViewModel(),
|
viewModel: CollectionFolderViewModel = hiltViewModel(),
|
||||||
|
|
@ -176,7 +197,7 @@ fun CollectionFolderGrid(
|
||||||
positionCallback: ((columns: Int, position: Int) -> Unit)? = null,
|
positionCallback: ((columns: Int, position: Int) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
OneTimeLaunchedEffect {
|
OneTimeLaunchedEffect {
|
||||||
viewModel.init(destination.itemId, destination.item, initialSortAndDirection)
|
viewModel.init(destination.itemId, destination.item, initialSortAndDirection, recursive)
|
||||||
}
|
}
|
||||||
val sortAndDirection by viewModel.sortAndDirection.observeAsState(initialSortAndDirection)
|
val sortAndDirection by viewModel.sortAndDirection.observeAsState(initialSortAndDirection)
|
||||||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||||
|
|
@ -198,7 +219,7 @@ fun CollectionFolderGrid(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onClickItem = onClickItem,
|
onClickItem = onClickItem,
|
||||||
onSortChange = {
|
onSortChange = {
|
||||||
viewModel.loadResults(it)
|
viewModel.loadResults(it, recursive)
|
||||||
},
|
},
|
||||||
showTitle = showTitle,
|
showTitle = showTitle,
|
||||||
positionCallback = positionCallback,
|
positionCallback = positionCallback,
|
||||||
|
|
@ -263,7 +284,7 @@ fun CollectionFolderGridContent(
|
||||||
CardGrid(
|
CardGrid(
|
||||||
pager = pager,
|
pager = pager,
|
||||||
onClickItem = onClickItem,
|
onClickItem = onClickItem,
|
||||||
longClicker = {},
|
onLongClickItem = {},
|
||||||
letterPosition = letterPosition,
|
letterPosition = letterPosition,
|
||||||
gridFocusRequester = gridFocusRequester,
|
gridFocusRequester = gridFocusRequester,
|
||||||
showJumpButtons = false, // TODO add preference
|
showJumpButtons = false, // TODO add preference
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ private const val DEBUG = false
|
||||||
fun CardGrid(
|
fun CardGrid(
|
||||||
pager: List<BaseItem?>,
|
pager: List<BaseItem?>,
|
||||||
onClickItem: (BaseItem) -> Unit,
|
onClickItem: (BaseItem) -> Unit,
|
||||||
longClicker: (BaseItem) -> Unit,
|
onLongClickItem: (BaseItem) -> Unit,
|
||||||
letterPosition: suspend (Char) -> Int,
|
letterPosition: suspend (Char) -> Int,
|
||||||
gridFocusRequester: FocusRequester,
|
gridFocusRequester: FocusRequester,
|
||||||
showJumpButtons: Boolean,
|
showJumpButtons: Boolean,
|
||||||
|
|
@ -257,7 +257,7 @@ fun CardGrid(
|
||||||
onClickItem.invoke(item)
|
onClickItem.invoke(item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = { if (item != null) longClicker.invoke(item) },
|
onLongClick = { if (item != null) onLongClickItem.invoke(item) },
|
||||||
modifier =
|
modifier =
|
||||||
mod
|
mod
|
||||||
.ifElse(index == 0, Modifier.focusRequester(zeroFocus))
|
.ifElse(index == 0, Modifier.focusRequester(zeroFocus))
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import com.github.damontecres.dolphin.ui.preferences.PreferencesViewModel
|
||||||
fun CollectionFolderGeneric(
|
fun CollectionFolderGeneric(
|
||||||
preferences: UserPreferences,
|
preferences: UserPreferences,
|
||||||
destination: Destination.MediaItem,
|
destination: Destination.MediaItem,
|
||||||
|
recursive: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
preferencesViewModel: PreferencesViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
|
|
@ -27,6 +28,7 @@ fun CollectionFolderGeneric(
|
||||||
onClickItem = { preferencesViewModel.navigationManager.navigateTo(it.destination()) },
|
onClickItem = { preferencesViewModel.navigationManager.navigateTo(it.destination()) },
|
||||||
destination = destination,
|
destination = destination,
|
||||||
showTitle = showHeader,
|
showTitle = showHeader,
|
||||||
|
recursive = recursive,
|
||||||
modifier =
|
modifier =
|
||||||
modifier
|
modifier
|
||||||
.padding(start = 16.dp),
|
.padding(start = 16.dp),
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ fun CollectionFolderMovie(
|
||||||
onClickItem = onClickItem,
|
onClickItem = onClickItem,
|
||||||
destination = destination,
|
destination = destination,
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
|
recursive = true,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(start = 16.dp)
|
.padding(start = 16.dp)
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ fun CollectionFolderTv(
|
||||||
preferences = preferences,
|
preferences = preferences,
|
||||||
destination = destination,
|
destination = destination,
|
||||||
showTitle = false,
|
showTitle = false,
|
||||||
|
recursive = true,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(start = 16.dp)
|
.padding(start = 16.dp)
|
||||||
|
|
|
||||||
|
|
@ -61,13 +61,14 @@ abstract class ItemViewModel<T>(
|
||||||
abstract class LoadingItemViewModel<T>(
|
abstract class LoadingItemViewModel<T>(
|
||||||
api: ApiClient,
|
api: ApiClient,
|
||||||
) : ItemViewModel<T>(api) {
|
) : ItemViewModel<T>(api) {
|
||||||
val loading = MutableLiveData<LoadingState>(LoadingState.Loading)
|
val loading = MutableLiveData<LoadingState>(LoadingState.Pending)
|
||||||
|
|
||||||
open fun init(
|
open fun init(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
potential: BaseItem?,
|
potential: BaseItem?,
|
||||||
): Job? =
|
): Job? {
|
||||||
viewModelScope.launch(
|
loading.value = LoadingState.Loading
|
||||||
|
return viewModelScope.launch(
|
||||||
LoadingExceptionHandler(
|
LoadingExceptionHandler(
|
||||||
loading,
|
loading,
|
||||||
"Error loading item $itemId",
|
"Error loading item $itemId",
|
||||||
|
|
@ -86,3 +87,4 @@ abstract class LoadingItemViewModel<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,14 @@ fun DestinationContent(
|
||||||
modifier,
|
modifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
BaseItemKind.BOX_SET ->
|
||||||
|
CollectionFolderGeneric(
|
||||||
|
preferences,
|
||||||
|
destination,
|
||||||
|
false,
|
||||||
|
modifier,
|
||||||
|
)
|
||||||
|
|
||||||
BaseItemKind.COLLECTION_FOLDER -> {
|
BaseItemKind.COLLECTION_FOLDER -> {
|
||||||
when (destination.item?.data?.collectionType) {
|
when (destination.item?.data?.collectionType) {
|
||||||
CollectionType.TVSHOWS ->
|
CollectionType.TVSHOWS ->
|
||||||
|
|
@ -122,10 +130,19 @@ fun DestinationContent(
|
||||||
modifier,
|
modifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CollectionType.BOXSETS ->
|
||||||
|
CollectionFolderGeneric(
|
||||||
|
preferences,
|
||||||
|
destination,
|
||||||
|
true,
|
||||||
|
modifier,
|
||||||
|
)
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
CollectionFolderGeneric(
|
CollectionFolderGeneric(
|
||||||
preferences,
|
preferences,
|
||||||
destination,
|
destination,
|
||||||
|
false,
|
||||||
modifier,
|
modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +158,7 @@ fun DestinationContent(
|
||||||
CollectionFolderGeneric(
|
CollectionFolderGeneric(
|
||||||
preferences,
|
preferences,
|
||||||
destination,
|
destination,
|
||||||
|
true,
|
||||||
modifier,
|
modifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,8 @@ fun NavigationDrawerScope.LibraryNavItem(
|
||||||
CollectionType.HOMEVIDEOS -> R.string.fa_video
|
CollectionType.HOMEVIDEOS -> R.string.fa_video
|
||||||
CollectionType.LIVETV -> R.string.fa_tv
|
CollectionType.LIVETV -> R.string.fa_tv
|
||||||
CollectionType.MUSIC -> R.string.fa_music
|
CollectionType.MUSIC -> R.string.fa_music
|
||||||
|
CollectionType.BOXSETS -> R.string.fa_open_folder
|
||||||
|
CollectionType.PLAYLISTS -> R.string.fa_list_ul
|
||||||
else -> R.string.fa_film
|
else -> R.string.fa_film
|
||||||
}
|
}
|
||||||
val isFocused = interactionSource.collectIsFocusedAsState().value
|
val isFocused = interactionSource.collectIsFocusedAsState().value
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,5 @@ val supportedCollectionTypes =
|
||||||
CollectionType.TVSHOWS,
|
CollectionType.TVSHOWS,
|
||||||
CollectionType.HOMEVIDEOS,
|
CollectionType.HOMEVIDEOS,
|
||||||
CollectionType.PLAYLISTS,
|
CollectionType.PLAYLISTS,
|
||||||
|
CollectionType.BOXSETS,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,6 @@
|
||||||
<string name="fa_eye_slash" translatable="false"></string>
|
<string name="fa_eye_slash" translatable="false"></string>
|
||||||
<string name="fa_arrow_left_arrow_right" translatable="false"></string>
|
<string name="fa_arrow_left_arrow_right" translatable="false"></string>
|
||||||
<string name="fa_shuffle" translatable="false"></string>
|
<string name="fa_shuffle" translatable="false"></string>
|
||||||
|
<string name="fa_open_folder" translatable="false"></string>
|
||||||
|
<string name="fa_list_ul" translatable="false"></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue