mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-23 01:37:19 +02:00
Backend - Add podcast data model (PodcastChannel, PodcastEpisode) with migrations - Implement Subsonic API endpoints: getPodcasts, getNewestPodcasts, createPodcastChannel, refreshPodcasts, deletePodcastChannel, deletePodcastEpisode, downloadPodcastEpisode, getPodcastEpisode - Add native REST API endpoints: GET/DELETE /api/podcast, GET /api/podcast/preview (feed info without creating channel) - Inject events.Broker into podcast service for SSE support - Emit PodcastEpisodeProgress SSE events during download (every 512 KB) and on completion/error with status field - Use HTTP Content-Length as fallback when RSS feed omits enclosure size - Write ID3 tags (title, album, genre=Podcast) to downloaded files via ffmpeg so the library scanner reads correct metadata - Set MediaFile fields (Title, Album, AlbumID=channelId, AlbumArtist, Genre) on episode registration - Add duplicate URL check in AddChannel - Add ExistsByURL to PodcastChannelRepository Frontend - Podcast list - Add grid/list view toggle (Redux podcastViewReducer) matching album list - New PodcastGridView component with responsive column count (2-6 cols) - Cover image 100px in table view - Remove Feed URL column; add inline copy-to-clipboard button Frontend - Podcast show (episode list) - Real-time download progress (%) in Status column via SSE, no polling - Spinner only before first SSE event; N% once data arrives - Size column removed; Downloading badge replaced with progress - Completed episodes play on row click; separate play button removed - Play / Shuffle / Play Next / Add to Queue buttons above episode list (only shown when completed episodes exist) - On download completion, reload episodes to obtain streamId for immediate playback without page refresh - Clicking album name in AudioTitle navigates to podcast channel page Frontend - Podcast create - Full-width URL input with Fetch Feed Info button and Enter key support - Preview card (cover image, title, episode count, description) before committing channel creation - Add Channel button appears only after preview; shows already-registered message if channel URL exists Frontend - Playlist - Album link navigates to podcast channel page for podcast tracks (identified by genre=Podcast) - Artist column shows '-' for podcast tracks with empty artist field Closes #5420 Signed-off-by: ji-ho lee <search5@gmail.com>
53 lines
1.7 KiB
Go
53 lines
1.7 KiB
Go
package model
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/Masterminds/squirrel"
|
|
"github.com/deluan/rest"
|
|
)
|
|
|
|
type QueryOptions struct {
|
|
Sort string
|
|
Order string
|
|
Max int
|
|
Offset int
|
|
Filters squirrel.Sqlizer
|
|
Seed string // for random sorting
|
|
}
|
|
|
|
type ResourceRepository interface {
|
|
rest.Repository
|
|
}
|
|
|
|
type DataStore interface {
|
|
Library(ctx context.Context) LibraryRepository
|
|
Folder(ctx context.Context) FolderRepository
|
|
Album(ctx context.Context) AlbumRepository
|
|
Artist(ctx context.Context) ArtistRepository
|
|
MediaFile(ctx context.Context) MediaFileRepository
|
|
Genre(ctx context.Context) GenreRepository
|
|
Tag(ctx context.Context) TagRepository
|
|
Playlist(ctx context.Context) PlaylistRepository
|
|
PlayQueue(ctx context.Context) PlayQueueRepository
|
|
Transcoding(ctx context.Context) TranscodingRepository
|
|
Player(ctx context.Context) PlayerRepository
|
|
Radio(ctx context.Context) RadioRepository
|
|
Share(ctx context.Context) ShareRepository
|
|
Property(ctx context.Context) PropertyRepository
|
|
User(ctx context.Context) UserRepository
|
|
UserProps(ctx context.Context) UserPropsRepository
|
|
ScrobbleBuffer(ctx context.Context) ScrobbleBufferRepository
|
|
Scrobble(ctx context.Context) ScrobbleRepository
|
|
Plugin(ctx context.Context) PluginRepository
|
|
Artwork(ctx context.Context) ArtworkRepository
|
|
ArtworkQueue(ctx context.Context) ArtworkQueueRepository
|
|
PodcastChannel(ctx context.Context) PodcastChannelRepository
|
|
PodcastEpisode(ctx context.Context) PodcastEpisodeRepository
|
|
|
|
Resource(ctx context.Context, model any) ResourceRepository
|
|
|
|
WithTx(block func(tx DataStore) error, scope ...string) error
|
|
WithTxImmediate(block func(tx DataStore) error, scope ...string) error
|
|
GC(ctx context.Context, libraryIDs ...int) error
|
|
}
|