diff --git a/src/app/Nav.vue b/src/app/Nav.vue index 4cd329c..013788e 100644 --- a/src/app/Nav.vue +++ b/src/app/Nav.vue @@ -38,6 +38,10 @@ Starred + + Podcasts + + Radio diff --git a/src/library/TrackList.vue b/src/library/TrackList.vue index 962085c..f295557 100644 --- a/src/library/TrackList.vue +++ b/src/library/TrackList.vue @@ -54,9 +54,14 @@ - + + {{ $formatDuration(item.duration) }} diff --git a/src/library/podcast/PodcastDetails.vue b/src/library/podcast/PodcastDetails.vue new file mode 100644 index 0000000..0e10c28 --- /dev/null +++ b/src/library/podcast/PodcastDetails.vue @@ -0,0 +1,88 @@ + + diff --git a/src/library/podcast/PodcastLibrary.vue b/src/library/podcast/PodcastLibrary.vue new file mode 100644 index 0000000..da4f6af --- /dev/null +++ b/src/library/podcast/PodcastLibrary.vue @@ -0,0 +1,42 @@ + + diff --git a/src/player/Player.vue b/src/player/Player.vue index 0f77e2c..04d1634 100644 --- a/src/player/Player.vue +++ b/src/player/Player.vue @@ -25,7 +25,7 @@ {{ track.title }}
- {{ track.artist }} + {{ track.artist || track.album || track.description }}
diff --git a/src/shared/api.ts b/src/shared/api.ts index 26c1737..7f24cc7 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -318,6 +318,20 @@ export class API { return this.get('rest/deleteInternetRadioStation', { id }) } + async getPodcasts(): Promise { + const response = await this.get('rest/getPodcasts') + return (response?.podcasts?.channel || []).map(this.normalizePodcast, this) + } + + async getPodcast(id: string): Promise { + const response = await this.get('rest/getPodcasts', { id }) + return this.normalizePodcast(response?.podcasts?.channel[0]) + } + + async refreshPodcasts(): Promise { + return this.get('rest/refreshPodcasts') + } + async scan(): Promise { return this.get('rest/startScan') } @@ -387,6 +401,33 @@ export class API { } } + private normalizePodcast(podcast: any): any { + const image = podcast.originalImageUrl + return { + id: podcast.id, + name: podcast.title, + description: podcast.description, + image: image, + url: podcast.url, + trackCount: podcast.episode.length, + tracks: podcast.episode.map((episode: any, index: number) => ({ + id: episode.id, + title: episode.title, + duration: episode.duration, + starred: false, + track: podcast.episode.length - index, + album: podcast.title, + albumId: null, + artist: '', + artistId: null, + image, + url: episode.streamId ? this.getStreamUrl(episode.streamId) : null, + description: podcast.description, + playable: episode.status === 'completed', + })), + } + } + private getCoverArtUrl(item: any) { if (!item.coverArt) { return undefined diff --git a/src/shared/components/Icon.vue b/src/shared/components/Icon.vue index 67881f1..cd0277b 100644 --- a/src/shared/components/Icon.vue +++ b/src/shared/components/Icon.vue @@ -26,6 +26,7 @@ BIconBoxArrowRight, BIconPersonFill, BIconPersonCircle, + BIconRss, BIconX, } from 'bootstrap-vue' @@ -53,6 +54,7 @@ BIconBoxArrowRight, BIconPersonFill, BIconPersonCircle, + BIconRss, BIconX, }, props: { diff --git a/src/shared/router.ts b/src/shared/router.ts index 97e6d21..203930c 100644 --- a/src/shared/router.ts +++ b/src/shared/router.ts @@ -10,6 +10,8 @@ import GenreDetails from '@/library/genre/GenreDetails.vue' import GenreLibrary from '@/library/genre/GenreLibrary.vue' import Starred from '@/library/starred/Starred.vue' import RadioStations from '@/library/radio/RadioStations.vue' +import PodcastDetails from '@/library/podcast/PodcastDetails.vue' +import PodcastLibrary from '@/library/podcast/PodcastLibrary.vue' import Playlist from '@/playlist/Playlist.vue' import PlaylistList from '@/playlist/PlaylistList.vue' import SearchResult from '@/search/SearchResult.vue' @@ -86,6 +88,17 @@ export function setupRouter(auth: AuthService) { path: '/radio', component: RadioStations, }, + { + name: 'podcasts', + path: '/podcasts', + component: PodcastLibrary, + }, + { + name: 'podcast', + path: '/podcast/:id', + component: PodcastDetails, + props: true, + }, { name: 'playlists', path: '/playlists',