Share playlists

This commit is contained in:
Deluan 2023-01-22 01:12:08 -05:00
parent 65174d3fb2
commit 58fc271864
3 changed files with 60 additions and 15 deletions

View File

@ -10,6 +10,7 @@ import (
gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/model/request"
"github.com/navidrome/navidrome/utils/slice"
)
@ -44,22 +45,17 @@ func (s *shareService) Load(ctx context.Context, id string) (*model.Share, error
}
idList := strings.Split(share.ResourceIDs, ",")
var mfs model.MediaFiles
switch share.ResourceType {
case "album":
share.Tracks, err = s.loadMediafiles(ctx, squirrel.Eq{"album_id": idList}, "album")
mfs, err = s.loadMediafiles(ctx, squirrel.Eq{"album_id": idList}, "album")
case "playlist":
mfs, err = s.loadPlaylistTracks(ctx, share.ResourceIDs)
}
if err != nil {
return nil, err
}
return entity.(*model.Share), nil
}
func (s *shareService) loadMediafiles(ctx context.Context, filter squirrel.Eq, sort string) ([]model.ShareTrack, error) {
all, err := s.ds.MediaFile(ctx).GetAll(model.QueryOptions{Filters: filter, Sort: sort})
if err != nil {
return nil, err
}
return slice.Map(all, func(mf model.MediaFile) model.ShareTrack {
share.Tracks = slice.Map(mfs, func(mf model.MediaFile) model.ShareTrack {
return model.ShareTrack{
ID: mf.ID,
Title: mf.Title,
@ -68,7 +64,23 @@ func (s *shareService) loadMediafiles(ctx context.Context, filter squirrel.Eq, s
Duration: mf.Duration,
UpdatedAt: mf.UpdatedAt,
}
}), nil
})
return entity.(*model.Share), nil
}
func (s *shareService) loadMediafiles(ctx context.Context, filter squirrel.Eq, sort string) (model.MediaFiles, error) {
return s.ds.MediaFile(ctx).GetAll(model.QueryOptions{Filters: filter, Sort: sort})
}
func (s *shareService) loadPlaylistTracks(ctx context.Context, id string) (model.MediaFiles, error) {
// Create a context with a fake admin user, to be able to access playlists
ctx = request.WithUser(context.TODO(), model.User{IsAdmin: true})
tracks, err := s.ds.Playlist(ctx).Tracks(id, true).GetAll(model.QueryOptions{Sort: "id"})
if err != nil {
return nil, err
}
return tracks.MediaFiles(), nil
}
func (s *shareService) NewRepository(ctx context.Context) rest.Repository {
@ -117,8 +129,11 @@ func (r *shareRepositoryWrapper) Save(entity interface{}) (string, error) {
if s.ExpiresAt.IsZero() {
s.ExpiresAt = time.Now().Add(365 * 24 * time.Hour)
}
if s.ResourceType == "album" {
switch s.ResourceType {
case "album":
s.Contents = r.shareContentsFromAlbums(s.ID, s.ResourceIDs)
case "playlist":
s.Contents = r.shareContentsFromPlaylist(s.ID, s.ResourceIDs)
}
id, err = r.Persistable.Save(s)
return id, err
@ -141,3 +156,15 @@ func (r *shareRepositoryWrapper) shareContentsFromAlbums(shareID string, ids str
}
return content
}
func (r *shareRepositoryWrapper) shareContentsFromPlaylist(shareID string, id string) string {
pls, err := r.ds.Playlist(r.ctx).Get(id)
if err != nil {
log.Error(r.ctx, "Error retrieving album names for share", "share", shareID, err)
return ""
}
content := pls.Name
if len(content) > 30 {
content = content[:26] + "..."
}
return content
}

View File

@ -109,7 +109,7 @@ const AlbumActions = ({
{config.devEnableShare && (
<Button
onClick={shareDialog.openDialog}
label={translate('resources.album.actions.share')}
label={translate('ra.action.share')}
>
<ShareIcon />
</Button>
@ -118,7 +118,7 @@ const AlbumActions = ({
<Button
onClick={handleDownload}
label={
translate('resources.album.actions.download') +
translate('ra.action.download') +
(isDesktop ? ` (${formatBytes(record.size)})` : '')
}
>

View File

@ -28,6 +28,9 @@ import { formatBytes } from '../utils'
import { useMediaQuery, makeStyles } from '@material-ui/core'
import config from '../config'
import { ToggleFieldsMenu } from '../common'
import { ShareDialog } from '../dialogs/ShareDialog'
import { useDialog } from '../dialogs/useDialog'
import ShareIcon from '@material-ui/icons/Share'
const useStyles = makeStyles({
toolbar: { display: 'flex', justifyContent: 'space-between', width: '100%' },
@ -41,6 +44,7 @@ const PlaylistActions = ({ className, ids, data, record, ...rest }) => {
const notify = useNotify()
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
const isNotSmall = useMediaQuery((theme) => theme.breakpoints.up('sm'))
const shareDialog = useDialog()
const getAllSongsAndDispatch = React.useCallback(
(action) => {
@ -133,11 +137,19 @@ const PlaylistActions = ({ className, ids, data, record, ...rest }) => {
>
<RiPlayListAddFill />
</Button>
{config.devEnableShare && (
<Button
onClick={shareDialog.openDialog}
label={translate('ra.action.share')}
>
<ShareIcon />
</Button>
)}
{config.enableDownloads && (
<Button
onClick={handleDownload}
label={
translate('resources.album.actions.download') +
translate('ra.action.download') +
(isDesktop ? ` (${formatBytes(record.size)})` : '')
}
>
@ -153,6 +165,12 @@ const PlaylistActions = ({ className, ids, data, record, ...rest }) => {
</div>
<div>{isNotSmall && <ToggleFieldsMenu resource="playlistTrack" />}</div>
</div>
<ShareDialog
{...shareDialog.props}
ids={[record.id]}
resource={'playlist'}
name={record.name}
/>
</TopToolbar>
)
}