diff --git a/frontend-v2/src/lib/components/media/PodcastPlayer.svelte b/frontend-v2/src/lib/components/media/PodcastPlayer.svelte new file mode 100644 index 0000000..b00b2ac --- /dev/null +++ b/frontend-v2/src/lib/components/media/PodcastPlayer.svelte @@ -0,0 +1,1551 @@ + + +
+ + + + + + + +
+ {#if selectedShow} +
+
+ {#if selectedShow.artwork_url} + + {/if} + + +
+
+ {/if} + + {#if loading} +
+ {#each Array(6) as _, i} +
+
+
+
+
+
+
+ {/each} +
+ {:else if episodes.length === 0} +
+ +

{shows.length === 0 ? 'No podcasts yet. Add a show to get started.' : 'No episodes found.'}

+
+ {:else} +
+ {#each episodes as ep (ep.id)} + {@const art = artworkFor(ep)} + {@const pct = progressPct(ep)} +
+ + +
playEpisode(ep)} role="button" tabindex="0" onkeydown={(e) => { if (e.key === 'Enter') playEpisode(ep); }}> +
+ {ep.title} + {#if !selectedShowId} + {ep.show_title} + {/if} +
+
+ {formatDate(ep.published_at)} + · + {formatDuration(ep.duration)} + {#if ep.status === 'in-progress' && pct > 0} + · + {Math.round(pct)}% + {/if} +
+ {#if ep.status === 'in-progress' && pct > 0} +
+
+
+ {/if} +
+ +
+ + +
+
+ {/each} +
+ {/if} +
+
+ + +{#if currentEpisode} + {@const playerArt = artworkFor(currentEpisode)} +
+
+ +
+ {#if playerArt} + + {:else} +
+ +
+ {/if} +
+ {currentEpisode.title} + {currentEpisode.show_title} +
+
+ + +
+ + + + + +
+ + +
+ {formatTime(currentTime)} +
+
+
+
+
+ {formatTime(duration)} +
+ + +
+
+ + {#if showRateMenu} +
+ {#each rates as rate} + + {/each} +
+ {/if} +
+ + +
+
+
+{/if} + + +{#if showQueue} +
showQueue = false} role="presentation">
+ +{/if} + + diff --git a/frontend-v2/src/routes/(app)/media/+page.svelte b/frontend-v2/src/routes/(app)/media/+page.svelte index f893ff2..ffeec28 100644 --- a/frontend-v2/src/routes/(app)/media/+page.svelte +++ b/frontend-v2/src/routes/(app)/media/+page.svelte @@ -3,11 +3,17 @@ import BookSearch from '$lib/components/media/BookSearch.svelte'; import MusicSearch from '$lib/components/media/MusicSearch.svelte'; import BookLibrary from '$lib/components/media/BookLibrary.svelte'; + import PodcastPlayer from '$lib/components/media/PodcastPlayer.svelte'; - type MediaTab = 'books' | 'music' | 'library'; + type MediaTab = 'books' | 'music' | 'library' | 'podcasts'; const urlMode = page.url.searchParams.get('mode'); - let activeTab = $state(urlMode === 'music' ? 'music' : urlMode === 'library' ? 'library' : 'books'); + let activeTab = $state( + urlMode === 'music' ? 'music' + : urlMode === 'library' ? 'library' + : urlMode === 'podcasts' ? 'podcasts' + : 'books' + );
@@ -17,6 +23,7 @@
{#if activeTab === 'books'}Book Downloads {:else if activeTab === 'music'}Music Downloads + {:else if activeTab === 'podcasts'}Podcast Player {:else}Book Library{/if}
@@ -30,6 +37,10 @@ Music +