mirror of
https://github.com/jellyfin/jellyfin-android.git
synced 2026-10-26 16:45:26 +00:00
Add audiobook support to Android Auto
This commit is contained in:
1 parent
0055b5a808
commit
deabcafd49
7 files changed
+109
-29
No files matched your search
@@ -60,6 +60,12 @@ sealed interface LibraryPageElement {
|
||||
tag = albumPrimaryImageTag,
|
||||
).toUri()
|
||||
|
||||
parentId != null && parentPrimaryImageTag != null -> api.imageApi.getItemImageUrl(
|
||||
itemId = requireNotNull(parentId),
|
||||
imageType = ImageType.PRIMARY,
|
||||
tag = parentPrimaryImageTag,
|
||||
).toUri()
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package org.jellyfin.mobile.sessionbrowser
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UseSerializers
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
import org.jellyfin.sdk.model.serializer.UUIDSerializer
|
||||
import java.util.UUID
|
||||
|
||||
@@ -22,7 +23,7 @@ sealed interface LibraryRoute {
|
||||
data class Search(val query: String? = null) : LibraryRoute
|
||||
|
||||
@Serializable
|
||||
data class Library(val libraryId: UUID) : LibraryRoute
|
||||
data class Library(val libraryId: UUID, val collectionType: CollectionType? = null) : LibraryRoute
|
||||
|
||||
@Serializable
|
||||
data class Albums(val libraryId: UUID, val startLetter: String? = null) : LibraryRoute
|
||||
@@ -30,6 +31,9 @@ sealed interface LibraryRoute {
|
||||
@Serializable
|
||||
data class Album(val albumId: UUID) : LibraryRoute
|
||||
|
||||
@Serializable
|
||||
data class AudioBooks(val libraryId: UUID, val startLetter: String? = null) : LibraryRoute
|
||||
|
||||
@Serializable
|
||||
data class Artists(val libraryId: UUID, val startLetter: String? = null) : LibraryRoute
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jellyfin.mobile.sessionbrowser.page.AlbumLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.AlbumsLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.ArtistLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.ArtistsLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.AudioBooksLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.FavoritesLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.GenreLibraryPage
|
||||
import org.jellyfin.mobile.sessionbrowser.page.GenresLibraryPage
|
||||
@@ -54,6 +55,7 @@ class SessionBrowserCallback(
|
||||
UserViewLibraryPage(context),
|
||||
AlbumsLibraryPage(api),
|
||||
AlbumLibraryPage(api),
|
||||
AudioBooksLibraryPage(api),
|
||||
ArtistsLibraryPage(api),
|
||||
ArtistLibraryPage(api),
|
||||
FavoritesLibraryPage(api),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.jellyfin.mobile.sessionbrowser.page
|
||||
|
||||
import org.jellyfin.mobile.sessionbrowser.LibraryItemAction
|
||||
import org.jellyfin.mobile.sessionbrowser.LibraryPageElement
|
||||
import org.jellyfin.mobile.sessionbrowser.LibraryRoute
|
||||
import org.jellyfin.mobile.sessionbrowser.libraryPage
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
import org.jellyfin.sdk.model.api.ItemSortBy
|
||||
|
||||
val AudioBooksLibraryPage = { api: ApiClient ->
|
||||
libraryPage<LibraryRoute.AudioBooks>(grid = true) { route, offset, limit ->
|
||||
if (route.startLetter == null) return@libraryPage createAlphaBrowser { route.copy(startLetter = it) }
|
||||
|
||||
val result by api.itemsApi.getItems(
|
||||
parentId = route.libraryId,
|
||||
includeItemTypes = listOf(BaseItemKind.AUDIO_BOOK),
|
||||
sortBy = listOf(ItemSortBy.SORT_NAME),
|
||||
recursive = true,
|
||||
imageTypeLimit = 1,
|
||||
enableImageTypes = listOf(ImageType.PRIMARY),
|
||||
nameLessThan = if (route.startLetter == ALPHA_BROWSER_OTHER) ALPHA_BROWSER_LETTERS[0].toString() else null,
|
||||
nameStartsWith = if (route.startLetter == ALPHA_BROWSER_OTHER) null else route.startLetter,
|
||||
startIndex = offset,
|
||||
limit = limit,
|
||||
)
|
||||
|
||||
result.items.map {
|
||||
LibraryPageElement.baseItem(
|
||||
api = api,
|
||||
item = it,
|
||||
action = LibraryItemAction.Play(it),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.userViewsApi
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
|
||||
private val collectionTypes = setOf(CollectionType.MUSIC, CollectionType.BOOKS)
|
||||
|
||||
/**
|
||||
* Root library page that returns the available libraries (user views) for Android Auto playback.
|
||||
* Note that this should ideally not exceed 4 items.
|
||||
@@ -17,7 +19,7 @@ val RootLibraryPage = { api: ApiClient ->
|
||||
val userViews by api.userViewsApi.getUserViews()
|
||||
userViews
|
||||
.items
|
||||
.filter { it.collectionType == CollectionType.MUSIC }
|
||||
.filter { collectionTypes.contains(it.collectionType) }
|
||||
.drop(offset)
|
||||
.take(limit)
|
||||
.map {
|
||||
@@ -25,7 +27,7 @@ val RootLibraryPage = { api: ApiClient ->
|
||||
api = api,
|
||||
item = it,
|
||||
image = null,
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Library(it.id)),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Library(it.id, it.collectionType)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,39 +6,66 @@ import org.jellyfin.mobile.sessionbrowser.LibraryItemAction
|
||||
import org.jellyfin.mobile.sessionbrowser.LibraryPageElement
|
||||
import org.jellyfin.mobile.sessionbrowser.LibraryRoute
|
||||
import org.jellyfin.mobile.sessionbrowser.libraryPage
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
|
||||
val UserViewLibraryPage = { context: Context ->
|
||||
libraryPage<LibraryRoute.Library> { route, offset, limit ->
|
||||
listOf(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_albums),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Albums(route.libraryId)),
|
||||
),
|
||||
buildList {
|
||||
val isMusic = route.collectionType == CollectionType.MUSIC
|
||||
val isBooks = route.collectionType == CollectionType.BOOKS
|
||||
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_artists),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Artists(route.libraryId)),
|
||||
),
|
||||
if (isMusic) {
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_albums),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Albums(route.libraryId)),
|
||||
),
|
||||
)
|
||||
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_favorites),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Favorites(route.libraryId)),
|
||||
),
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_artists),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Artists(route.libraryId)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_genres),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Genres(route.libraryId)),
|
||||
),
|
||||
if (isBooks) {
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_audiobooks),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.AudioBooks(route.libraryId)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_playlists),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Playlists(route.libraryId)),
|
||||
),
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_favorites),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Favorites(route.libraryId)),
|
||||
),
|
||||
)
|
||||
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_recents),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Recent(route.libraryId)),
|
||||
),
|
||||
).drop(offset).take(limit)
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_genres),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Genres(route.libraryId)),
|
||||
),
|
||||
)
|
||||
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_playlists),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Playlists(route.libraryId)),
|
||||
),
|
||||
)
|
||||
|
||||
add(
|
||||
LibraryPageElement.Item(
|
||||
title = context.getString(R.string.media_service_car_section_recents),
|
||||
action = LibraryItemAction.Navigate(LibraryRoute.Recent(route.libraryId)),
|
||||
),
|
||||
)
|
||||
}.drop(offset).take(limit)
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@
|
||||
<string name="media_service_car_section_recents">Recently played</string>
|
||||
<string name="media_service_car_section_favorites">Favorites</string>
|
||||
<string name="media_service_car_section_albums">Albums</string>
|
||||
<string name="media_service_car_section_audiobooks">Audiobooks</string>
|
||||
<string name="media_service_car_section_artists">Artists</string>
|
||||
<string name="media_service_car_section_songs">Songs</string>
|
||||
<string name="media_service_car_section_genres">Genres</string>
|
||||
|
||||
Reference in new issue
Block a user