From cefc93990984db96382557de1e7aeebec51e721b Mon Sep 17 00:00:00 2001 From: Deluan Date: Thu, 10 Jun 2021 12:20:52 -0400 Subject: [PATCH] Trigger UI refresh on media annotation events: `star`, `setRating` and `scrobble` --- cmd/wire_gen.go | 5 +++-- cmd/wire_injectors.go | 3 +-- server/subsonic/api.go | 5 ++++- server/subsonic/media_annotation.go | 22 +++++++++++++++++----- server/subsonic/wire_gen.go | 5 +++-- server/subsonic/wire_injectors.go | 2 +- ui/src/album/AlbumSongs.js | 2 ++ ui/src/playlist/PlaylistSongs.js | 2 ++ 8 files changed, 33 insertions(+), 13 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index c75239e24..107357ea0 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -47,7 +47,8 @@ func CreateSubsonicAPIRouter() *subsonic.Router { players := core.NewPlayers(dataStore) externalMetadata := core.NewExternalMetadata(dataStore) scanner := GetScanner() - router := subsonic.New(dataStore, artwork, mediaStreamer, archiver, players, externalMetadata, scanner) + broker := GetBroker() + router := subsonic.New(dataStore, artwork, mediaStreamer, archiver, players, externalMetadata, scanner, broker) return router } @@ -73,7 +74,7 @@ func createScheduler() scheduler.Scheduler { // wire_injectors.go: -var allProviders = wire.NewSet(core.Set, subsonic.New, app.New, persistence.New) +var allProviders = wire.NewSet(core.Set, subsonic.New, app.New, persistence.New, GetBroker) // Scanner must be a Singleton var ( diff --git a/cmd/wire_injectors.go b/cmd/wire_injectors.go index 364e1c7a9..4851ee619 100644 --- a/cmd/wire_injectors.go +++ b/cmd/wire_injectors.go @@ -21,6 +21,7 @@ var allProviders = wire.NewSet( subsonic.New, app.New, persistence.New, + GetBroker, ) func CreateServer(musicFolder string) *server.Server { @@ -33,7 +34,6 @@ func CreateServer(musicFolder string) *server.Server { func CreateAppRouter() *app.Router { panic(wire.Build( allProviders, - GetBroker, )) } @@ -60,7 +60,6 @@ func GetScanner() scanner.Scanner { func createScanner() scanner.Scanner { panic(wire.Build( allProviders, - GetBroker, scanner.New, )) } diff --git a/server/subsonic/api.go b/server/subsonic/api.go index 8c27b8321..903485ce3 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -14,6 +14,7 @@ import ( "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/scanner" + "github.com/navidrome/navidrome/server/events" "github.com/navidrome/navidrome/server/subsonic/responses" "github.com/navidrome/navidrome/utils" ) @@ -30,12 +31,13 @@ type Router struct { Players core.Players ExternalMetadata core.ExternalMetadata Scanner scanner.Scanner + Broker events.Broker mux http.Handler } func New(ds model.DataStore, artwork core.Artwork, streamer core.MediaStreamer, archiver core.Archiver, players core.Players, - externalMetadata core.ExternalMetadata, scanner scanner.Scanner) *Router { + externalMetadata core.ExternalMetadata, scanner scanner.Scanner, broker events.Broker) *Router { r := &Router{ DataStore: ds, Artwork: artwork, @@ -44,6 +46,7 @@ func New(ds model.DataStore, artwork core.Artwork, streamer core.MediaStreamer, Players: players, ExternalMetadata: externalMetadata, Scanner: scanner, + Broker: broker, } r.mux = r.routes() return r diff --git a/server/subsonic/media_annotation.go b/server/subsonic/media_annotation.go index e59daec5a..b18d96ee4 100644 --- a/server/subsonic/media_annotation.go +++ b/server/subsonic/media_annotation.go @@ -10,6 +10,7 @@ import ( "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model/request" + "github.com/navidrome/navidrome/server/events" "github.com/navidrome/navidrome/server/subsonic/responses" "github.com/navidrome/navidrome/utils" ) @@ -17,10 +18,11 @@ import ( type MediaAnnotationController struct { ds model.DataStore npRepo core.NowPlaying + broker events.Broker } -func NewMediaAnnotationController(ds model.DataStore, npr core.NowPlaying) *MediaAnnotationController { - return &MediaAnnotationController{ds: ds, npRepo: npr} +func NewMediaAnnotationController(ds model.DataStore, npr core.NowPlaying, broker events.Broker) *MediaAnnotationController { + return &MediaAnnotationController{ds: ds, npRepo: npr, broker: broker} } func (c *MediaAnnotationController) SetRating(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { @@ -55,16 +57,22 @@ func (c *MediaAnnotationController) setRating(ctx context.Context, id string, ra if exist, err = c.ds.Artist(ctx).Exists(id); err != nil { return err } else if exist { - return c.ds.Artist(ctx).SetRating(rating, id) + err = c.ds.Artist(ctx).SetRating(rating, id) + c.broker.SendMessage(&events.RefreshResource{Resource: "artist"}) + return err } if exist, err = c.ds.Album(ctx).Exists(id); err != nil { return err } else if exist { - return c.ds.Album(ctx).SetRating(rating, id) + err = c.ds.Album(ctx).SetRating(rating, id) + c.broker.SendMessage(&events.RefreshResource{Resource: "album"}) + return err } - return c.ds.MediaFile(ctx).SetRating(rating, id) + err = c.ds.MediaFile(ctx).SetRating(rating, id) + c.broker.SendMessage(&events.RefreshResource{Resource: "song"}) + return err } func (c *MediaAnnotationController) Star(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { @@ -166,6 +174,7 @@ func (c *MediaAnnotationController) scrobblerRegister(ctx context.Context, playe if err != nil { log.Error("Error while scrobbling", "trackId", trackId, "user", username, err) } else { + c.broker.SendMessage(&events.RefreshResource{}) log.Info("Scrobbled", "title", mf.Title, "artist", mf.Artist, "user", username) } @@ -209,6 +218,7 @@ func (c *MediaAnnotationController) setStar(ctx context.Context, star bool, ids if err != nil { return err } + c.broker.SendMessage(&events.RefreshResource{Resource: "album"}) continue } exist, err = tx.Artist(ctx).Exists(id) @@ -220,12 +230,14 @@ func (c *MediaAnnotationController) setStar(ctx context.Context, star bool, ids if err != nil { return err } + c.broker.SendMessage(&events.RefreshResource{Resource: "artist"}) continue } err = tx.MediaFile(ctx).SetStar(star, ids...) if err != nil { return err } + c.broker.SendMessage(&events.RefreshResource{}) } return nil }) diff --git a/server/subsonic/wire_gen.go b/server/subsonic/wire_gen.go index 2f4a0c78e..bc9f46c8a 100644 --- a/server/subsonic/wire_gen.go +++ b/server/subsonic/wire_gen.go @@ -34,7 +34,8 @@ func initAlbumListController(router *Router) *AlbumListController { func initMediaAnnotationController(router *Router) *MediaAnnotationController { dataStore := router.DataStore nowPlaying := core.NewNowPlayingRepository() - mediaAnnotationController := NewMediaAnnotationController(dataStore, nowPlaying) + broker := router.Broker + mediaAnnotationController := NewMediaAnnotationController(dataStore, nowPlaying, broker) return mediaAnnotationController } @@ -95,5 +96,5 @@ var allProviders = wire.NewSet( NewMediaRetrievalController, NewStreamController, NewBookmarksController, - NewLibraryScanningController, core.NewNowPlayingRepository, wire.FieldsOf(new(*Router), "DataStore", "Artwork", "Streamer", "Archiver", "ExternalMetadata", "Scanner"), + NewLibraryScanningController, core.NewNowPlayingRepository, wire.FieldsOf(new(*Router), "DataStore", "Artwork", "Streamer", "Archiver", "ExternalMetadata", "Scanner", "Broker"), ) diff --git a/server/subsonic/wire_injectors.go b/server/subsonic/wire_injectors.go index 59e6d13da..3a736e960 100644 --- a/server/subsonic/wire_injectors.go +++ b/server/subsonic/wire_injectors.go @@ -20,7 +20,7 @@ var allProviders = wire.NewSet( NewBookmarksController, NewLibraryScanningController, core.NewNowPlayingRepository, - wire.FieldsOf(new(*Router), "DataStore", "Artwork", "Streamer", "Archiver", "ExternalMetadata", "Scanner"), + wire.FieldsOf(new(*Router), "DataStore", "Artwork", "Streamer", "Archiver", "ExternalMetadata", "Scanner", "Broker"), ) func initSystemController(router *Router) *SystemController { diff --git a/ui/src/album/AlbumSongs.js b/ui/src/album/AlbumSongs.js index 08bcf3b46..958c50b1f 100644 --- a/ui/src/album/AlbumSongs.js +++ b/ui/src/album/AlbumSongs.js @@ -23,6 +23,7 @@ import { RatingField, QualityInfo, useSelectedFields, + useResourceRefresh, } from '../common' import { AddToPlaylistDialog } from '../dialogs' import config from '../config' @@ -88,6 +89,7 @@ const AlbumSongs = (props) => { const classes = useStyles({ isDesktop }) const dispatch = useDispatch() const version = useVersion() + useResourceRefresh('song', 'album') const toggleableFields = useMemo(() => { return { diff --git a/ui/src/playlist/PlaylistSongs.js b/ui/src/playlist/PlaylistSongs.js index eebbc2fc4..b3c6fec00 100644 --- a/ui/src/playlist/PlaylistSongs.js +++ b/ui/src/playlist/PlaylistSongs.js @@ -24,6 +24,7 @@ import { SongTitleField, QualityInfo, useSelectedFields, + useResourceRefresh, } from '../common' import { AddToPlaylistDialog } from '../dialogs' import { AlbumLinkField } from '../song/AlbumLinkField' @@ -91,6 +92,7 @@ const PlaylistSongs = ({ playlistId, readOnly, actions, ...props }) => { const refresh = useRefresh() const notify = useNotify() const version = useVersion() + useResourceRefresh('song', 'playlist') const onAddToPlaylist = useCallback( (pls) => {